server { listen 80 default_server; listen [::]:80 default_server; server_name _; # Web root is public/ — app/, storage/, secrets/ are NOT web-accessible root /var/www/html/public; index index.php index.html; # Logging access_log /var/log/nginx/teampass-access.log; error_log /var/log/nginx/teampass-error.log warn; # Maximum upload size — must be >= PHP post_max_size / upload_max_filesize # (see docker/php/php.ini). Without this, nginx rejects uploads >1M with 413. client_max_body_size 100M; # Security: Deny access to hidden files and directories location ~ /\. { deny all; access_log off; log_not_found off; } # Main location location / { try_files $uri $uri/ /index.php?$args; } # API location — proxied through public/api/index.php → app/api/index.php location /api/ { try_files $uri $uri/ /api/index.php?$args; } # PHP-FPM configuration location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; include fastcgi_params; # Timeouts fastcgi_read_timeout 300; fastcgi_send_timeout 300; # Buffer sizes fastcgi_buffer_size 128k; fastcgi_buffers 256 16k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; } # Static files caching location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml|svg|woff|woff2|ttf|eot)$ { expires 30d; add_header Cache-Control "public, immutable"; access_log off; } # Deny access to specific files location ~ /(\.|composer\.json|composer\.lock|package\.json|README\.md|CHANGELOG\.md) { deny all; return 404; } # Health check endpoint location /health { access_log off; return 200 "healthy\n"; add_header Content-Type text/plain; } }