Home

Bluesky

GitHub

Setup Legacy NGINX on Debian/Ubuntu.

Poorly written by Billy on April 8, 2025

There is no warranty or liability, this is my own setup notes!

  1. Install the latest Ubuntu Server LTS, update/upgrade all packages, don't install normal NGINX.
  2. Install legacy-nginx following instructions at https://github.com/rem-verse/legacy-nginx.
  3. Create a DS certificate using https://github.com/KaeruTeam/nds-constraint - ensure you concatenate nwc.crt, as Nginx doesn't let you add a chain file unlike Apache. (Also, maybe a Wii certificate using https://github.com/shutterbug2000/wii-ssl-bug)
  4. Copy NGINX config to /usr/local/nginx/conf/nginx.conf.

Configs!

nginx.conf

load_module /usr/local/nginx/modules/ngx_stream_module.so;

events
{
	worker_connections 768; # Copied, should probably be worth working out a 'sane' default here?
}

stream
{
	# This server block will handle TLS 1.2/1.3 - assuming 1.0.2u has 1.3 support? - maybe have a normal website here?
	upstream https_default_backend
	{
		server 127.0.0.1:8443;
	}
	# This server block will handle any/all SSLv3 connections.
	upstream ds_backend
	{
		server 127.0.0.1:8003;
	}

	# Same idea, but for TLSv1
	upstream wii_backend
	{
		server 127.0.0.1:8010;
	}

	map $ssl_preread_protocol $upstream
	{
		default https_default_backend; # NB: This will also handle TLSv1.1 - which I hope your website isn't using!
		"TLSv1" wii_backend;
		"SSLv3" ds_backend;
	}

	server
	{
		listen 443;
		listen [::]:443;
		ssl_preread on;
		proxy_protocol on; # Passes along IP/etc, https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/
		proxy_pass $upstream;
	}

}

http
{
	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 65;
	types_hash_max_size 2048;
	include /usr/local/nginx/conf/mime.types;
	default_type application/octet-stream;
	ssl_prefer_server_ciphers on;
	gzip on;
	underscores_in_headers on;
	keepalive_requests 256;

	ssl_protocols SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
	ssl_ciphers "ALL:!aNULL:";

	# load configs
	include /usr/local/nginx/conf.d/*.conf;
	include /usr/local/nginx/sites-enabled/*;
}

sites-available/dls1.conf

server
	{
		listen 127.0.0.1:8003 ssl proxy_protocol;

        # Remember, DS doesn't send SNI - this is more for your own peace of mind/NGINX SSL cert checking.
		server_name dls1.ilostmymind.xyz;

		ssl_certificate /usr/local/nginx/ssl/dls1-ds/server.crt;
		ssl_certificate_key /usr/local/nginx/ssl/dls1-ds/server.key;

		ssl_protocols SSLv3;
		ssl_ciphers "ALL:!aNULL:";
		underscores_in_headers on;
		keepalive_requests 256;

		location /
		{
			proxy_buffering off;
			proxy_pass http://127.0.0.1:9000;
			proxy_set_header X-Forwarded-For $proxy_protocol_addr;
			proxy_set_header X-Forwarded-Port $proxy_protocol_port;
			keepalive_requests 256;
		}
	}
server
	{
		listen 127.0.0.1:8010 ssl proxy_protocol;

        # Remember, DS doesn't send SNI - this is more for your own peace of mind/NGINX SSL cert checking.
		server_name dls1.ilostmymind.xyz;

		ssl_certificate /usr/local/nginx/ssl/dls1-wii/server.crt;
		ssl_certificate_key /usr/local/nginx/ssl/dls1-wii/server.key;

		ssl_protocols TLSv1;
		ssl_ciphers "ALL:!aNULL:";
		underscores_in_headers on;
		keepalive_requests 256;

		location /
		{
			proxy_buffering off;
			proxy_pass http://127.0.0.1:9000;
			proxy_set_header X-Forwarded-For $proxy_protocol_addr;
			proxy_set_header X-Forwarded-Port $proxy_protocol_port;
			keepalive_requests 256;
		}
	}

server {
	listen 80;
	listen [::]:80;

	server_name dls1.ilostmymind.xyz dls1.wiimmfi.de;

	location /
		{
			proxy_buffering off;
			proxy_pass http://127.0.0.1:9000;
			proxy_set_header X-Forwarded-For $proxy_protocol_addr;
			proxy_set_header X-Forwarded-Port $proxy_protocol_port;
			keepalive_requests 256;
		}

}

sites-available/gamestats.conf

server {
	listen 80;
	listen [::]:80;

	server_name gamestats.gs.wiimmfi.de gamestats2.gs.wiimmfi.de gamestats.gs.nintendowifi.net gamestats2.gs.nintendowifi.net *.gamestats.gs.wiimmfi.de *.gamestats2.gs.wiimmfi.de *.gamestats.gs.nintendowifi.net *.gamestats2.gs.nintendowifi.net;

	location /
		{
			proxy_buffering off;
			proxy_pass http://127.0.0.1:9090;
			proxy_set_header X-Forwarded-For $remote_addr;
			proxy_set_header X-Forwarded-Port $remote_port;
			keepalive_requests 256;
		}

		location /syachi2ds/
		{
			proxy_buffering off;
			proxy_pass http://gamestats2.gs.pkmnclassic.net/syachi2ds/;
			proxy_set_header X-Forwarded-For $remote_addr;
			proxy_set_header X-Forwarded-Port $remote_port;
			keepalive_requests 256;
		}

		location /pokemondpds/
		{
			proxy_buffering off;
			proxy_pass http://gamestats2.gs.pkmnclassic.net/pokemondpds/;
			proxy_set_header X-Forwarded-For $remote_addr;
			proxy_set_header X-Forwarded-Port $remote_port;
			keepalive_requests 256;
		}

		location /pokedungeonds/
		{
			proxy_buffering off;
			proxy_pass http://gamestats2.gs.pkmnclassic.net/pokedungeonds/;
			proxy_set_header X-Forwarded-For $remote_addr;
			proxy_set_header X-Forwarded-Port $remote_port;
			keepalive_requests 256;
		}

		location /pokedngnwii/
		{
			proxy_buffering off;
			proxy_pass http://gamestats2.gs.pkmnclassic.net/pokedngnwii/;
			proxy_set_header X-Forwarded-For $remote_addr;
			proxy_set_header X-Forwarded-Port $remote_port;
			keepalive_requests 256;
		}
}

sites-available/000-html.conf

server
{
	listen 80;
	listen [::]:80;
	#server_name services.billy.wales;
	set $base /var/www;
	root $base/html;
	index index.html;

        location /
        {
                #try_files $uri;
        }
        # . files
        location ~ /\.(?!well-known)
        {
                deny all;
        }
}

server
{
	listen 127.0.0.1:8443 ssl proxy_protocol;
	server_name services.billy.wales;
	http2 on;

	ssl_certificate /etc/letsencrypt/live/services.billy.wales/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/services.billy.wales/privkey.pem;
	#ssl_certificate_key /usr/local/nginx/ssl/services-moderntls/server.key;

	ssl_session_timeout 1d;
	ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
	ssl_session_tickets off;
	ssl_dhparam /usr/local/nginx/ssl/dhparam.pem;

	# old configuration
	ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
	ssl_ciphers 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:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA;
	ssl_prefer_server_ciphers on;

	# security headers
	add_header X-Frame-Options "SAMEORIGIN" always;
	add_header X-XSS-Protection "1; mode=block" always;
	add_header X-Content-Type-Options "nosniff" always;
	add_header Referrer-Policy "no-referrer-when-downgrade" always;
	add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
	add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

	set $base /var/www;
	root $base/html;

	index index.html;

	location /
	{
		#try_files $uri;
	}
	# . files
	location ~ /\.(?!well-known)
	{
		deny all;
	}

	# favicon.ico
	location = /favicon.ico
	{
		log_not_found off;
		access_log off;
	}

	# robots.txt
	location = /robots.txt
	{
		log_not_found off;
		access_log off;
	}

	# assets, media
	location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$
	{
		expires 7d;
		access_log off;
	}

	# svg, fonts
	location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$
	{
		add_header Access-Control-Allow-Origin "*";
		expires 7d;
		access_log off;
	}

	location ~ \.php$ {
	    include fastcgi.conf;  # Use the existing fastcgi.conf file
	    fastcgi_pass unix:/run/php/php8.3-fpm.sock;  # Adjust the path according to your PHP version
	    fastcgi_index index.php;
	    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
	}


	# gzip
	gzip on;
	gzip_vary on;
	gzip_proxied any;
	gzip_comp_level 6;
	gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;

}