# Example nginx config # for serving tkr as a subdomain with SSL # e.g. https://tkr.my-domain.com/ # # Use SSL in production. # This is a minimal SSL confiuration # For more robust SSL configuration, refer to https://ssl-config.mozilla.org/ server { listen 443 ssl; listen [::]:443 ssl; # CONFIG: replace "localhost" with your subdomain (e.g. tkr.my-domain.com) server_name localhost; # CONFIG: # replace "/var/www/tkr" with the directory you extracted the .zip file to (if different) root /var/www/tkr/public; index index.php; # CONFIG: # Assumes you're using letsencrypt for cert generation # Replace with the actual paths to your cert and key ssl_certificate /etc/letsencrypt/live/tkr.my-domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/tkr.my-domain.com/privkey.pem; # Security headers # The first rule is to prevent including in a frame on a different domain. # Remove it if you want to do that. add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; # Deny access to hidden files location ~ /\. { deny all; access_log off; log_not_found off; } # PHP routing - everything goes through index.php location / { # Cache static files # Note that I don't actually serve most of this (just css) # but this prevents requests for static content from getting to the PHP handler. # # I've excluded /css/custom so that requests for uploaded css can be handled by the PHP app. # That lets me store uploaded content outside of the document root, # so it isn't served directly. location ~* ^/(?!css/custom/).+\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control "public, immutable"; try_files $uri =404; } # index.php is the entry point # It needs to be sent to php-fpm # But if someone tries to directly access index.php, that file will throw a 404 # so bots and scanners can't tell this is a php app location = /index.php { # CONFIG: # If you're running php-fpm on the same server as nginx, # then change this to the local php-fpm socket # e.g. fastcgi_pass unix:/run/php/php8.2-fpm.sock; fastcgi_pass php:9000; # CONFIG: # replace "/var/www/tkr" with the directory you extracted the .zip file to (if different) fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; include fastcgi_params; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param REQUEST_URI $request_uri; fastcgi_param QUERY_STRING $query_string; } # Block attempts to access all other .php files directly # (these are bots and scanners) location ~ ^/.+\.php$ { return 404; } # forward other requests to the fallback block, # which sends them to php-fpm for handling try_files $uri $uri/ @tkr_fallback; } # Fallback for /tkr routing - all non-file requests (e.g. /login) go to index.php location @tkr_fallback { # CONFIG: # If you're running php-fpm on the same server as nginx, # then change this to the local php-fpm socket # e.g. fastcgi_pass unix:/run/php/php8.2-fpm.sock; fastcgi_pass php:9000; # CONFIG: # replace "/var/www/tkr" with the directory you extracted the .zip file to (if different) fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; include fastcgi_params; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param REQUEST_URI $request_uri; fastcgi_param QUERY_STRING $query_string; } # Deny access to sensitive directories location ~ ^/(storage|src|templates|uploads|config) { deny all; return 404; } } server { listen 80 default_server; listen [::]:80 default_server; return 301 https://$host$request_uri; }