Additional notes on NGINX

install | source | nginx | advanced | analyze | php | redirect

static vs. reverse-proxy

static pages

    location / {
        root /var/www/html;
        index index.html index.htm;
        try_files $uri $uri/ =404;


    location / {
        proxy_pass http://x.x.x.x/;

More on reverse-proxy

To setup an http reverse proxy, simply change location in the server stanza

location / {
    proxy_pass http://APPLICATION_ADDRESS:PORT;

Be careful, some applications need to know about the vhost and port that are called. So you shall play with those settings. Here is some specific conf for GitLab

    proxy_set_header Host $http_host;

here’s a working specific conf for Gollum, assuming you’re running SSL only on the nginx side

location / {
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Proto https;

also jenkins conf

some other possible configs

    #proxy_set_header Host $host; #instead of http_host
            #proxy_set_header X-Real-IP $remote_addr;
    #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

and to deal with backend’s 301s

    #proxy_redirect off;


in location or server

    ssi on;

then use as such

<!--# include file="HTML-FILE-TO-INCLUDE-HERE" -->


custom format & compression – enable compression and define a custom log format to display the compression ratio

gzip  on;
log_format compression '$remote_addr - $remote_user [$time_local] '
    '"$request" $status $body_bytes_sent '
    '"$http_referer" "$http_user_agent" "$gzip_ratio"';

separate files

server {
        access_log logs/DOMAIN.TLD.access.log compression;
        error_log  logs/DOMAIN.TLD.error.log warn;


in the server or http stanza

    location ^~ /private/ {
        auth_basic "restricted area";
        auth_basic_user_file passwd;

–either– build and install THTTPD –or– get the tool from apache

apt install apache2-utils

then create or edit a password file

cd /etc/nginx/
htpasswd -c passwd NEW_USER

# DO NOT chmod 600 htpasswd as the www-data / nginx user needs to read it

if files exists already

htpasswd htpasswd EXISTING_USER

apply with systemctl restart nginx or /usr/local/nginx/sbin/nginx -s reload


Install and run the FastCGI helper

apt -y install fcgiwrap
systemctl list-unit-files | grep fcgi
systemctl status fcgiwrap.socket
ls -lhF /var/run/fcgiwrap.socket
systemctl status fcgiwrap.service

Make sure NGINX is ready for that

ls -lhF $confdir/../fastcgi_params
ls -lhF $confdir/../fastcgi.conf

Make sure your script is executable and test it

mkdir -p /data/www/$vhost/

cat > /data/www/$vhost/index.cgi <<-EOF9

cat <<EOF
Content-type: text/html

<p>hello \`host \$REMOTE_ADDR | awk '{print \$NF}'\` (\$REMOTE_ADDR)

chmod +x /data/www/$vhost/index.cgi
ls -lhF /bin/ksh
export REMOTE_ADDR=::1

and setup those parms into the vhost server stanza e.g.

vi $confdir/$vhost.conf

root /data/www/$server_name;
    index index.cgi maintenance.html;

location ~ (\.cgi|\.py|\.sh|\.pl|\.lua)$ {
    gzip off;
    fastcgi_pass unix:/var/run/fcgiwrap.socket;
    include fastcgi_params;
    fastcgi_param DOCUMENT_ROOT /data/www/$server_name;
    fastcgi_param SCRIPT_FILENAME /data/www/$server_name$fastcgi_script_name;

Note. Be careful with $server_name in the fastcgi parameters: if you do not use a vhost the server name becomes _

Note. include fastcgi_params points to conf/fastcgi_params already

apply with systemctl restart nginx or /usr/local/nginx/sbin/nginx -s reload

HTTP additions

    #add_before_body /css/header.html;
    sub_filter '<head><title>Index of $uri</title></head>' '<head><title>TITLE-HERE - $uri</title></head>';
    sub_filter '<h1>Index of $uri</h1>' '<h1 style="font-family:Courier;font-style:italic;text-transform:uppercase;">TITLE-HERE - $uri</h1>';
    sub_filter_once on;

    #add_after_body  /css/footer.html;
    sub_filter '</body>' '<div>SOME FOOTER HERE</div></body>';

Note: not adding a footer as some /body and /html would remain – the filter would not differenciate those I added and those from the directory listing.

Additional notes

robots.txt & favicon.ico

vi /etc/nginx/drop.conf

location = /robots.txt          { access_log off; log_not_found off; }
location = /favicon.ico         { access_log off; log_not_found off; }
location ~ /apple-touch-icon    { access_log off; log_not_found off; }
#location ~ /\.                  { access_log off; log_not_found off; deny all; }
#location ~ ~$                   { access_log off; log_not_found off; deny all; }

then onto the vhost’s server stanza

include drop.conf;

cache control

into the http stanza and before the Virtual Host Configs server stanzas

vi nginx.conf

# Expires map
map $sent_http_content_type $expires {
    default                    off;
    text/html                  epoch;
    text/css                   max;
    application/javascript     max;
    ~image/                    max;

as docker container

to run as Docker container on foreground,

nginx -g 'daemon off;'



Nginx proxy_redirect: Change response-header Location and Refresh in the response of the server

Moodle behind ssl reverse proxy: “Reverse proxy enabled, server can not be accessed directly, sorry.”

favicon and robots ignore



How to Implement Browser Caching with Nginx’s header Module on CentOS 7



phases and why not use variables everywhere

Nginx directive execution order (01)

HTTP request processing phases in Nginx


Module ngx_http_ssi_module


Configuring Logging


nginx listen on specific interface [closed]

NGINX bind to a specific network interface, regardless of IP address

Copyright © 2024 Pierre-Philipp Braun