summaryrefslogtreecommitdiffstats
path: root/web/README.md
blob: 81346fda52196c8dbec0381e1d6528dfe5c892b2 (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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# 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      the download page
  latest.php     newest-version feed for the installers
  releases.php   shared scanner and hash cache
  install.sh     stable Linux installer
  install.ps1    stable Windows installer
  bin/gui/       apps, served at /bin/gui/...
  bin/client/    terminal clients
  bin/server/    servers
```

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/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 not versioned. They read `latest.php`, pick the newest build
for the machine, verify its SHA-256 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. Updating the
site only needs `publish.sh`; the installer links never change. Set
`ZAGAN_SITE` (Linux) or `-Site` (Windows) to test against a staging site. The
Windows installer waits for Enter before closing (`-NoPause` for automation).
The page links the public git repository for the GPL corresponding source.

## 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). 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`; `ALLOW_DIRTY=1` skips the
clean-tree check for a preview. The installers are static and need no
regeneration.

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. Debian/Ubuntu and Arch install it the same way:

```sh
# Debian / Ubuntu
sudo apt install nginx php-fpm
sudo install -d -o "$USER" -g www-data -m 0755 /srv/zagan.bet

# Arch
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, socket and certificate paths, then:
sudo nginx -t && sudo systemctl enable --now nginx php-fpm
```

The example uses Debian/Ubuntu's pool socket (`/run/php/php-fpm.sock`); Arch
uses `/run/php-fpm/php-fpm.sock`. Check the pool's user and socket and adjust
`fastcgi_pass` if your distribution differs:

```sh
grep -E '^(user|group|listen)' /etc/php/*/fpm/pool.d/www.conf /etc/php-fpm.d/www.conf 2>/dev/null
```

`rsync` publishes files as `0755`/`0644`, so the PHP worker can read them
without extra group juggling. `index.php` and `latest.php` are the only
scripts; `releases.php` is an include, and the example returns 404 for every
other `.php` request instead of serving it as source.

The example sends `/latest.php` with `no-store` and the two installers with
`no-cache`, so a new release is picked up immediately without giving up the
immutable caching on `/bin/`.

PHP's opcache is enabled by default and revalidates timestamps every two
seconds, so a deployed `index.php` or `latest.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 often 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.