# Unified nginx configuration # Routes traffic based on domain: # - host.uk.com → Laravel Host Hub (PHP-FPM) # - *.host.uk.com → WordPress (PHP-FPM) # Map for allowed CORS origins (WordPress REST API) map $http_origin $cors_origin { default ""; "~^https?://host\.uk\.com$" $http_origin; "~^https?://social\.host\.uk\.com$" $http_origin; "~^https?://link\.host\.uk\.com$" $http_origin; "~^https?://analytics\.host\.uk\.com$" $http_origin; "~^https?://trust\.host\.uk\.com$" $http_origin; "~^https?://notify\.host\.uk\.com$" $http_origin; "~^https?://localhost(:[0-9]+)?$" $http_origin; "~^https?://127\.0\.0\.1(:[0-9]+)?$" $http_origin; } # ============================================ # LARAVEL HOST HUB - Apex Domain # ============================================ server { listen 80; listen [::]:80; server_name host.uk.com www.host.uk.com; root /app/public; index index.php; client_max_body_size 64M; # Security headers add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; # Health check - returns 200 if nginx is up (no PHP needed) location = /healthz { access_log off; add_header Content-Type text/plain; return 200 "ok\n"; } # WordPress REST API proxy # host.uk.com/api/wordpress/* → WordPress /wp-json/* # Same-origin, no CORS needed location ~ ^/api/wordpress/(.*)$ { # Pass to WordPress index.php with rest_route fastcgi_pass unix:/run/php-fpm.sock; fastcgi_param SCRIPT_FILENAME /var/www/html/index.php; fastcgi_param REQUEST_URI /wp-json/$1$is_args$args; fastcgi_param HTTP_X_FORWARDED_PROTO $http_x_forwarded_proto; fastcgi_index index.php; fastcgi_buffering off; fastcgi_read_timeout 300; include fastcgi_params; } # Laravel routing location / { try_files $uri $uri/ /index.php?$query_string; } # PHP-FPM for Laravel location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/run/php-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param HTTP_X_FORWARDED_PROTO $http_x_forwarded_proto; fastcgi_index index.php; fastcgi_buffering off; fastcgi_read_timeout 300; include fastcgi_params; } # Livewire and Flux - must go to Laravel (not static files) location ~ ^/(admin|flux)/ { try_files $uri $uri/ /index.php?$query_string; } # Laravel static assets (build, vendor directories only) location ~* ^/(build|vendor)/.*\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires max; add_header Cache-Control "public, immutable"; log_not_found off; access_log off; } # Deny hidden files location ~ /\. { deny all; } # PHP-FPM status (internal only) location ~ ^/(fpm-status|fpm-ping)$ { access_log off; allow 127.0.0.1; deny all; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; fastcgi_pass unix:/run/php-fpm.sock; } } # ============================================ # LARAVEL SATELLITES - Subdomains # ============================================ server { listen 80 default_server; listen [::]:80 default_server; server_name *.host.uk.com; root /app/public; index index.php; client_max_body_size 64M; # Security headers add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; # Health check location = /healthz { access_log off; add_header Content-Type text/plain; return 200 "ok\n"; } # WordPress REST API (for internal content sync) # Routes /wp-json/* requests to WordPress # Host header determines which multisite blog to serve location ~ ^/wp-json/(.*)$ { fastcgi_pass unix:/run/php-fpm.sock; fastcgi_param SCRIPT_FILENAME /var/www/html/index.php; fastcgi_param REQUEST_URI /wp-json/$1$is_args$args; fastcgi_param HTTP_X_FORWARDED_PROTO $http_x_forwarded_proto; fastcgi_index index.php; fastcgi_buffering off; fastcgi_read_timeout 300; include fastcgi_params; } # Laravel routing location / { try_files $uri $uri/ /index.php?$query_string; } # PHP-FPM for Laravel location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/run/php-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param HTTP_X_FORWARDED_PROTO $http_x_forwarded_proto; fastcgi_index index.php; fastcgi_buffering off; fastcgi_read_timeout 300; include fastcgi_params; } # Livewire and Flux location ~ ^/(admin|flux)/ { try_files $uri $uri/ /index.php?$query_string; } # Static assets location ~* ^/(build|vendor)/.*\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires max; add_header Cache-Control "public, immutable"; log_not_found off; access_log off; } # Deny hidden files location ~ /\. { deny all; } }