summaryrefslogtreecommitdiffstats
path: root/web/README.md
blob: bd87e11f14aad8ee52e47e1d423eec46339d23fa (plain) (blame)
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# Download page

`index.php` scans `bin/gui`, `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/gui/       served at /bin/gui/... (app and installers)
  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.

```
bin/gui/zagan-bet-gui-<version>-<platform>-<arch>[.exe]
bin/gui/zagan-bet-gui-<version>-<platform>-<arch>-install.sh
bin/gui/zagan-bet-gui-<version>-<platform>-<arch>-install.ps1
bin/client/zagan-bet-client-<version>-<platform>-<arch>[.exe]
bin/server/zagan-bet-server-<version>-<platform>-<arch>[.exe]
```

`<version>` is `MAJOR.MINOR.PATCH`, `<platform>` is `linux`, `windows` or
`macos`, `<arch>` is `x86_64`, `i686` or `aarch64`.

The installers are generated next to their app. They embed the app's SHA-256,
check the file (or download it) and install it for the current user: Linux
writes `~/.local/bin/zagan-bet-gui` plus a `.desktop` launcher, Windows writes
`%LOCALAPPDATA%\Programs\Zagan-Bet` plus a Start-menu shortcut. The source
archives satisfy the GPL's corresponding-source requirement.

## Publishing a build

From the repository root:

```sh
./scripts/publish.sh
```

It reads the version from `Cargo.toml`, builds every artifact and installs
them under `web/bin` with the names above. The GUI is built with the
workspace's `gui-release` profile (LTO, stripped) and the installers are
rendered with Python 3 and the published SHA-256. Run it from a clean tree so
the release commit is the source the page links to. Override the destination
with `DEST=/srv/www/bin ./scripts/publish.sh`, and the download origin baked
into the installers with `URL_BASE=https://staging.example/ ./scripts/publish.sh`.
`ALLOW_DIRTY=1` skips the clean-tree check for a preview.

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. The GUI needs Python 3 at publish time
for the installer templates in `scripts/installers/`.

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 —
GUI apps, installers, terminal clients and servers — 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`.
- The page links <https://git.2137697.xyz/zagan-bet.git> for the GPL
  corresponding source; publish only from a committed release so that link
  contains the exact source.