1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
# Download page
`index.php` scans `bin/client` and `bin/server` on every request and renders
whatever builds it finds, with version, size and SHA-256. No database, no
JavaScript, no CSS, no dependencies. The page is plain browser defaults:
black text, blue links, monospace checksums. PHP 8.0+.
## Layout
```
web/
index.php
bin/client/ served at /bin/client/...
bin/server/ served at /bin/server/...
```
Serve `web/` as the document root. Binaries in `bin/` are gitignored.
## Naming
The page only lists files that match the release pattern; anything else in
those directories is ignored.
```
zagan-bet-client-<version>-<platform>-<arch>[.exe]
zagan-bet-server-<version>-<platform>-<arch>
```
`<version>` is `MAJOR.MINOR.PATCH`, `<platform>` is `linux`, `windows` or
`macos`, `<arch>` is `x86_64`, `i686` or `aarch64`.
## Publishing a build
From the repository root:
```sh
./scripts/publish.sh
```
It reads the version from `Cargo.toml`, builds all four artifacts and installs
them under `web/bin` with the names above. Override the destination with
`DEST=/srv/www/bin ./scripts/publish.sh`.
Builds are per target triple, so these must be installed:
`x86_64-unknown-linux-gnu`, `i686-unknown-linux-gnu` and
`x86_64-pc-windows-gnu`, plus the mingw linker for the Windows build. Client
builds always pass `--no-default-features`, which drops the server's OpenSSL
dependency; the client is rustls-only.
Cargo itself cannot produce these names: it always writes
`target/<triple>/release/<bin>`. 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
php -S 127.0.0.1:8899 -t web
```
Then open <http://127.0.0.1:8899/>.
## Deploying
```sh
./scripts/publish.sh
./scripts/deploy.sh user@host:/srv/zagan.bet https://zagan.bet/
```
`deploy.sh` rsyncs `web/` with `--delay-updates`, so a visitor never sees a
half-written binary, then fetches the live page and every artifact it lists and
compares the downloaded bytes with the local SHA-256. `--verify-only` skips the
upload and only checks the live site. Old versions are left on the server;
prune them by hand.
A local directory works as a target, which is how the verification itself is
tested:
```sh
php -S 127.0.0.1:8899 -t /srv/staging
./scripts/deploy.sh /srv/staging http://127.0.0.1:8899/
```
## Notes
- Hashes are cached in a JSON file keyed on size and mtime, so a file is only
read once until it changes. The cache lives in the system temp directory by
default because the web root is often not writable by the PHP user; set
`ZAGAN_HASH_CACHE` to put it elsewhere. If the cache cannot be written, the
page simply hashes every request.
- The page lists every build it finds, newest version first, so old releases
stay downloadable until you remove them from `bin/`.
- The checksum block is in `sha256sum` format, so visitors can save it as
`SHA256SUMS` and run `sha256sum -c SHA256SUMS`.
|