diff options
| author | salmonik <salmonik@tuta.io> | 2026-10-30 00:52:25 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-10-30 00:52:25 +0100 |
| commit | 8f8cabeaa533e4f4f8156ff8f4f001f9e4228698 (patch) | |
| tree | 60f3445ab7a303d7be10bcb45d51a27042fc5e99 | |
| parent | add deploy script with live verification; cache file hashes by size and mtime (diff) | |
| download | zagan-bet-8f8cabeaa533e4f4f8156ff8f4f001f9e4228698.tar.gz zagan-bet-8f8cabeaa533e4f4f8156ff8f4f001f9e4228698.zip | |
add nginx + php-fpm deployment example
| -rw-r--r-- | web/README.md | 34 | ||||
| -rw-r--r-- | web/nginx.conf.example | 55 |
2 files changed, 89 insertions, 0 deletions
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. | |||
| 50 | Cargo itself cannot produce these names: it always writes | 50 | Cargo itself cannot produce these names: it always writes |
| 51 | `target/<triple>/release/<bin>`. The script renames after each build. | 51 | `target/<triple>/release/<bin>`. The script renames after each build. |
| 52 | 52 | ||
| 53 | ## nginx | ||
| 54 | |||
| 55 | `web/nginx.conf.example` is a working server block for a subdomain with an | ||
| 56 | existing certificate. On Arch-based systems: | ||
| 57 | |||
| 58 | ```sh | ||
| 59 | sudo pacman -S nginx php-fpm | ||
| 60 | sudo install -d -o "$USER" -g http -m 0755 /srv/zagan.bet | ||
| 61 | sudo cp web/nginx.conf.example /etc/nginx/conf.d/zagan.bet.conf | ||
| 62 | # edit server_name, root and the certificate paths, then: | ||
| 63 | sudo nginx -t && sudo systemctl enable --now nginx php-fpm | ||
| 64 | ``` | ||
| 65 | |||
| 66 | The pool socket and user are Arch defaults (`http`, | ||
| 67 | `/run/php-fpm/php-fpm.sock`). Check them and adjust `fastcgi_pass` if your | ||
| 68 | distribution differs: | ||
| 69 | |||
| 70 | ```sh | ||
| 71 | grep -E '^(user|group|listen)' /etc/php/php-fpm.d/www.conf | ||
| 72 | ``` | ||
| 73 | |||
| 74 | `rsync` publishes files as `0755`/`0644`, so the `http` worker and the php-fpm | ||
| 75 | pool can read them without extra group juggling. `index.php` is the only | ||
| 76 | script; any other `.php` request 404s instead of executing. | ||
| 77 | |||
| 78 | PHP's opcache is enabled by default and revalidates timestamps every two | ||
| 79 | seconds, so a deployed `index.php` takes effect without reloading php-fpm. If | ||
| 80 | you ever set `opcache.validate_timestamps=0`, reload php-fpm after a deploy. | ||
| 81 | |||
| 82 | The php-fpm unit on Arch uses `PrivateTmp=`, so the hash cache in `/tmp` lives | ||
| 83 | in the service's private tmp. It still works; point `ZAGAN_HASH_CACHE` at a | ||
| 84 | writable path such as `/var/cache/zagan-bet-hashes.json` if you want it to | ||
| 85 | survive a service restart. | ||
| 86 | |||
| 53 | ## Preview locally | 87 | ## Preview locally |
| 54 | 88 | ||
| 55 | ```sh | 89 | ```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 @@ | |||
| 1 | # zagan.bet download page — nginx + php-fpm example. | ||
| 2 | # | ||
| 3 | # Install at /etc/nginx/conf.d/zagan.bet.conf (the packaged nginx.conf includes | ||
| 4 | # conf.d/*.conf). Replace the server name, root and certificate paths. | ||
| 5 | # | ||
| 6 | # Only index.php is PHP; everything under /bin/ is served as static files. | ||
| 7 | # The binaries are versioned, so they can be cached forever — which means you | ||
| 8 | # must bump the version (Cargo.toml) instead of overwriting a published file. | ||
| 9 | |||
| 10 | server { | ||
| 11 | listen 80; | ||
| 12 | listen [::]:80; | ||
| 13 | server_name dl.example.com; | ||
| 14 | return 301 https://$host$request_uri; | ||
| 15 | } | ||
| 16 | |||
| 17 | server { | ||
| 18 | listen 443 ssl; | ||
| 19 | listen [::]:443 ssl; | ||
| 20 | http2 on; | ||
| 21 | server_name dl.example.com; | ||
| 22 | |||
| 23 | root /srv/zagan.bet; | ||
| 24 | index index.php; | ||
| 25 | |||
| 26 | ssl_certificate /etc/letsencrypt/live/dl.example.com/fullchain.pem; | ||
| 27 | ssl_certificate_key /etc/letsencrypt/live/dl.example.com/privkey.pem; | ||
| 28 | ssl_protocols TLSv1.2 TLSv1.3; | ||
| 29 | ssl_prefer_server_ciphers off; | ||
| 30 | ssl_session_cache shared:SSL:10m; | ||
| 31 | ssl_session_timeout 1d; | ||
| 32 | |||
| 33 | # Published binaries: static, versioned, never rewritten. | ||
| 34 | location /bin/ { | ||
| 35 | try_files $uri =404; | ||
| 36 | add_header Cache-Control "public, max-age=31536000, immutable"; | ||
| 37 | } | ||
| 38 | |||
| 39 | # The page rescans bin/ on every request, so don't cache it. | ||
| 40 | location = /index.php { | ||
| 41 | include fastcgi_params; | ||
| 42 | fastcgi_pass unix:/run/php-fpm/php-fpm.sock; | ||
| 43 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; | ||
| 44 | add_header Cache-Control "no-cache"; | ||
| 45 | } | ||
| 46 | |||
| 47 | location / { | ||
| 48 | try_files $uri $uri/ =404; | ||
| 49 | } | ||
| 50 | |||
| 51 | # Never serve dotfiles (.gitignore, editor leftovers). | ||
| 52 | location ~ /\. { | ||
| 53 | deny all; | ||
| 54 | } | ||
| 55 | } | ||
