From 8f8cabeaa533e4f4f8156ff8f4f001f9e4228698 Mon Sep 17 00:00:00 2001 From: salmonik Date: Fri, 30 Oct 2026 00:52:25 +0100 Subject: add nginx + php-fpm deployment example --- web/README.md | 34 +++++++++++++++++++++++++++++++ web/nginx.conf.example | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 web/nginx.conf.example diff --git a/web/README.md b/web/README.md index a82c492..e79abd4 100644 --- a/web/README.md +++ b/web/README.md @@ -50,6 +50,40 @@ dependency; the client is rustls-only. Cargo itself cannot produce these names: it always writes `target//release/`. The script renames after each build. +## nginx + +`web/nginx.conf.example` is a working server block for a subdomain with an +existing certificate. On Arch-based systems: + +```sh +sudo pacman -S nginx php-fpm +sudo install -d -o "$USER" -g http -m 0755 /srv/zagan.bet +sudo cp web/nginx.conf.example /etc/nginx/conf.d/zagan.bet.conf +# edit server_name, root and the certificate paths, then: +sudo nginx -t && sudo systemctl enable --now nginx php-fpm +``` + +The pool socket and user are Arch defaults (`http`, +`/run/php-fpm/php-fpm.sock`). Check them and adjust `fastcgi_pass` if your +distribution differs: + +```sh +grep -E '^(user|group|listen)' /etc/php/php-fpm.d/www.conf +``` + +`rsync` publishes files as `0755`/`0644`, so the `http` worker and the php-fpm +pool can read them without extra group juggling. `index.php` is the only +script; any other `.php` request 404s instead of executing. + +PHP's opcache is enabled by default and revalidates timestamps every two +seconds, so a deployed `index.php` takes effect without reloading php-fpm. If +you ever set `opcache.validate_timestamps=0`, reload php-fpm after a deploy. + +The php-fpm unit on Arch uses `PrivateTmp=`, so the hash cache in `/tmp` lives +in the service's private tmp. It still works; point `ZAGAN_HASH_CACHE` at a +writable path such as `/var/cache/zagan-bet-hashes.json` if you want it to +survive a service restart. + ## Preview locally ```sh diff --git a/web/nginx.conf.example b/web/nginx.conf.example new file mode 100644 index 0000000..ad001d1 --- /dev/null +++ b/web/nginx.conf.example @@ -0,0 +1,55 @@ +# zagan.bet download page — nginx + php-fpm example. +# +# Install at /etc/nginx/conf.d/zagan.bet.conf (the packaged nginx.conf includes +# conf.d/*.conf). Replace the server name, root and certificate paths. +# +# Only index.php is PHP; everything under /bin/ is served as static files. +# The binaries are versioned, so they can be cached forever — which means you +# must bump the version (Cargo.toml) instead of overwriting a published file. + +server { + listen 80; + listen [::]:80; + server_name dl.example.com; + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl; + listen [::]:443 ssl; + http2 on; + server_name dl.example.com; + + root /srv/zagan.bet; + index index.php; + + ssl_certificate /etc/letsencrypt/live/dl.example.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/dl.example.com/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers off; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 1d; + + # Published binaries: static, versioned, never rewritten. + location /bin/ { + try_files $uri =404; + add_header Cache-Control "public, max-age=31536000, immutable"; + } + + # The page rescans bin/ on every request, so don't cache it. + location = /index.php { + include fastcgi_params; + fastcgi_pass unix:/run/php-fpm/php-fpm.sock; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + add_header Cache-Control "no-cache"; + } + + location / { + try_files $uri $uri/ =404; + } + + # Never serve dotfiles (.gitignore, editor leftovers). + location ~ /\. { + deny all; + } +} -- cgit v1.2.3