Setting up reverse proxy with nginx

Posted April 26, 2024 by smnd ‐ 3 min read

Set up nginx as reverse proxy

Why nginx?

What is a reverse proxy? Cloudflare has an amazing article describing the basics of it.

So what did I need to do?

First let's create the needed container file in the /etc/containers/systemd/ directory.

/etc/containers/systemd/nginx.container:

[Container]
Image=docker.io/library/nginx:latest
AutoUpdate=registry
PublishPort=443:443/tcp
PublishPort=443:443/udp
PublishPort=80:80
Volume=/path/to/nginx/etc/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
Volume=/path/to/nginx/etc/nginx/conf.d/:/etc/nginx/conf.d/:z
Volume=/path/to/certs/:/etc/ssl/:ro
[Service]
Restart=always

[Install]
WantedBy=default.target

Once this is done let's create also the nginx.conf file of ours.:

/path/to/nginx/etc/nginx/nginx.conf:


user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    # hide who we are, don't show nginx version to clients
    server_tokens                   off; 
    # buffering causes issues, disable it
    # increase buffer size. still useful even when buffering is off
    proxy_buffering off;
    proxy_buffer_size 4k;

    # allow the server to close the connection after a client stops responding. Frees up socket-associated memory.
    reset_timedout_connection on;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #added because of immich, default is 1M, immich recommendation is 50000M
    client_max_body_size 5000M;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

also create the folder conf.d which contains http3.conf, and our future configs. Some guidance can be found in the Mozilla SSL-config generator.

/path/to/nginx/etc/nginx/conf.d/http3.conf

ssl_protocols TLSv1.3;
quic_retry on;
ssl_early_data on;

ssl_prefer_server_ciphers off;
#ssl_prefer_server_ciphers on; # Let the client choose, as of 2022-05 these ciphers are all still secure.
#ssl_dhparam /etc/nginx/dhparam2048.pem; # generate with 'openssl dhparam -out dhparam.pem 2048'
#ssl_ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
#ssl_ecdh_curve X25519:prime256v1:secp384r1;

ssl_session_cache shared:SSL:5m;
ssl_session_timeout 1h;
ssl_session_tickets off;

ssl_stapling on;
ssl_stapling_verify on;

resolver 1.1.1.1 1.0.0.1 valid=300s; # Use whichever resolvers you'd like, these are Cloudflare's and is one of the fastest DNS resolvers.
resolver_timeout 5s;

add_header alt-svc 'h3=":443"; ma=86400'; # Absolutely necessary header. This informs the client that HTTP/3 is available.
add_header Strict-Transport-Security max-age=15768000; # Optional but good, client should always try to use HTTPS, even for initial requests.
add_header X-protocol $server_protocol always;        

gzip off; #https://en.wikipedia.org/wiki/BREACH

then we can add the firewall exception for the ports to be used:

sudo firewall-cmd --add-port 80/tcp -- permanent
sudo firewall-cmd --add-port 443/tcp -- permanent
sudo firewall-cmd --add-port 443/udp -- permanent

for starting the container run these commands:

sudo systemctl daemon-reload
sudo systemctl start nginx

Then in the Podman containers view we should see the container up and running.