server { # Listen only on port 81 for localhost, and nothing else. server_name 127.0.0.1; listen 127.0.0.1:81 default_server; charset utf-8; # Certbot's folder used for the ACME challenge response. location ^~ /.well-known/acme-challenge { default_type text/plain; root /var/www/certbot; try_files $uri =404; } } server { listen [::]:80; listen 80; server_name %hostname%; location '/.well-known/acme-challenge' { proxy_pass http://localhost:81; } # redirect all traffic to HTTPS rewrite ^ https://$host$request_uri? permanent; } server { listen [::]:443 ssl http2; listen 443 ssl http2; ssl_certificate /etc/letsencrypt/live/%hostname%/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/%hostname%/privkey.pem; # Let's Encrypt best practices include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; root /var/www/social/public; # Server name server_name %hostname%; # Index index index.php; # X-Accel/X-Sendfile. Still needs to be enabled in the config location /file { internal; root /var/www/social; } location /.well-known/acme-challenge/ { allow all; root /var/www/certbot; try_files $uri =404; break; } # PHP location ~ ^/(index|install)\.php(/.*)?$ { include fastcgi_params; fastcgi_split_path_info ^(.+?\.php)(/.*)$; set $path_info $fastcgi_path_info; try_files $fastcgi_script_name =404; fastcgi_pass php:9000; fastcgi_index index.php; fastcgi_param PATH_INFO $path_info; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } # Don't allow any PHP file other than index.php to be executed # This will ensure that nor config.php nor plugin files with eventual hardcoded security information are downloadable # And this is better than allowing php files to be executed in case of forgotten `if (!defined('GNUSOCIAL')) { exit(1); }` location ~ \.php$ { deny all; } # Location location / { try_files $uri $uri/ @index_handler; } # Fancy URLs error_page 404 @index_handler; location @index_handler { rewrite ^(.*)$ /index.php?p=$1 last; } # Restrict access that is unnecessary anyway location ~ /\.(ht|git) { deny all; } # # Hardening (optional) # add_header Strict-Transport-Security "max-age=15768000; preload;"; add_header X-Content-Type-Options nosniff; add_header Referrer-Policy strict-origin-when-cross-origin; add_header Content-Security-Policy "default-src 'self' 'unsafe-inline'; frame-ancestors 'self'; form-action 'self'; style-src 'self' 'unsafe-inline'; img-src * blob: data:;"; add_header X-Permitted-Cross-Domain-Policies none; add_header X-Robots-Tag all; # Not really hardening, just here for strictness purposes client_max_body_size 15M; client_body_buffer_size 128k; gzip_vary on; location ~* \.(?:css|js|woff|svg|gif|png|webp|ttf|ico|jpe?g)$ { gzip on; gzip_comp_level 4; add_header Cache-Control "public"; expires 30d; access_log off; log_not_found off; } }