Stripped from the internal repo: per-box deploy trees, Go services (nodelist/astmeta/proxy/svxdr), deploy/sync scripts and all secrets. Config templates for nginx, PHP-FPM, Redis and tmpfiles live in install/ with CHANGEME placeholders. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
102 lines
4.0 KiB
Plaintext
102 lines
4.0 KiB
Plaintext
# SvxPortal web — nginx server block.
|
|
# Install: sudo cp install/nginx-svxportal.conf /etc/nginx/sites-available/svxportal
|
|
# sudo ln -s /etc/nginx/sites-available/svxportal /etc/nginx/sites-enabled/
|
|
# sudo nginx -t && sudo systemctl reload nginx
|
|
# Replace: svxportal.example.com, the certificate paths, and the PHP version in the socket names.
|
|
|
|
server {
|
|
listen 80;
|
|
listen [::]:80;
|
|
server_name svxportal.example.com;
|
|
|
|
# Let's Encrypt HTTP challenge (certbot --webroot -w /var/www/letsencrypt)
|
|
location ^~ /.well-known/acme-challenge/ {
|
|
default_type "text/plain";
|
|
root /var/www/letsencrypt;
|
|
allow all;
|
|
}
|
|
location / { return 301 https://$host$request_uri; }
|
|
}
|
|
|
|
server {
|
|
listen 443 ssl;
|
|
listen [::]:443 ssl;
|
|
http2 on;
|
|
server_name svxportal.example.com;
|
|
|
|
root /var/www/html/svxportal;
|
|
index index.html index.php;
|
|
|
|
ssl_certificate /etc/letsencrypt/live/svxportal.example.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/svxportal.example.com/privkey.pem;
|
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
|
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
|
|
|
access_log /var/log/nginx/svxportal-access.log;
|
|
error_log /var/log/nginx/svxportal-error.log;
|
|
|
|
add_header X-Content-Type-Options nosniff always;
|
|
add_header X-Frame-Options SAMEORIGIN always;
|
|
add_header Referrer-Policy strict-origin-when-cross-origin always;
|
|
# The UI loads Bootstrap/icons from cdn.jsdelivr.net; everything else is same-origin.
|
|
add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; style-src 'self' https://cdn.jsdelivr.net 'unsafe-inline'; img-src 'self' data:; font-src 'self' https://cdn.jsdelivr.net data:; connect-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self'; object-src 'none'" always;
|
|
|
|
location = /robots.txt { default_type text/plain; alias /var/www/html/svxportal/robots.txt; }
|
|
location = /sitemap.xml { default_type application/xml; alias /var/www/html/svxportal/sitemap.xml; }
|
|
location = /privacy { default_type text/plain; alias /var/www/html/svxportal/privacy; }
|
|
|
|
# Reflector admin API runs in its own PHP-FPM pool (see install/php-fpm-svxadmin.conf).
|
|
# It needs exec() for the sudo helpers; the normal pool should keep exec disabled.
|
|
location = /auth/admin_reflector_api.php {
|
|
include /etc/nginx/fastcgi.conf;
|
|
try_files $uri =404;
|
|
fastcgi_hide_header X-Powered-By;
|
|
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
|
fastcgi_pass unix:/run/php/php8.4-fpm-svxadmin.sock;
|
|
fastcgi_index index.php;
|
|
fastcgi_read_timeout 30;
|
|
}
|
|
|
|
# Never serve dotfiles (.git, .gitignore ...) or editor/backup files.
|
|
location ~ /\.(?!well-known) { deny all; access_log off; log_not_found off; }
|
|
location ~* \.(bak|orig|save|old|swp|inc|sql|dist|tpl)(\.[0-9]+)?$ { deny all; access_log off; log_not_found off; }
|
|
|
|
# Server-Sent Events endpoint: must not be buffered.
|
|
location = /auth/events.php {
|
|
include /etc/nginx/fastcgi.conf;
|
|
try_files $uri =404;
|
|
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
|
|
fastcgi_buffering off;
|
|
fastcgi_read_timeout 3600;
|
|
gzip off;
|
|
}
|
|
|
|
location ~ \.php$ {
|
|
include /etc/nginx/fastcgi.conf;
|
|
try_files $uri =404;
|
|
fastcgi_hide_header X-Powered-By;
|
|
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
|
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
|
|
fastcgi_index index.php;
|
|
fastcgi_read_timeout 25;
|
|
}
|
|
|
|
location = / { try_files /index.html =404; }
|
|
location / { try_files $uri $uri/ =404; }
|
|
|
|
# Live data API (/svxportal/api/status, /stream, /lastheard, /monitor-nodes,
|
|
# /local-trunks). The web UI expects a JSON/SSE backend here on 127.0.0.1:8098.
|
|
# That backend is NOT part of this repository — see INSTALL.md, section 8.
|
|
location ^~ /svxportal/api/ {
|
|
proxy_pass http://127.0.0.1:8098/api/;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header Connection "";
|
|
proxy_buffering off;
|
|
proxy_cache off;
|
|
proxy_read_timeout 3600s;
|
|
gzip off;
|
|
add_header X-Accel-Buffering no;
|
|
}
|
|
}
|