Files
pwap/ops/host/README.md
SatoshiQaziMuhammed 3ba40d4e52 Deploy over pinned, single-purpose keys from GitHub-hosted runners (#51)
- ops: deploy scripts the CI keys are pinned to
- ci: deploy over pinned, single-purpose keys from GitHub-hosted runners
- ops: tell shellcheck the test's variables are read through eval
2026-10-09 04:11:51 +04:00

79 lines
3.1 KiB
Markdown

# Deploy keys and the scripts they are pinned to
CI reaches the hosts with four SSH keys, one per target. None of them opens a
shell. Each is pinned in `authorized_keys` to one script from this directory
(`restrict,command=`), so what CI can do on a host is exactly what that script
does, with the input it validates:
| target | host | user | key secret | forced command | input |
|---|---|---|---|---|---|
| app.pezkuwichain.io | NEW-7 `89.117.59.63` | `app-deploy` | `PWAP_APP_DEPLOY_KEY` | `pwap-web-receive app` | site tar on stdin |
| pex.mom | VPS3 `217.77.6.126` | `pex-deploy` | `PWAP_PEX_DEPLOY_KEY` | `pwap-web-receive pex` | site tar on stdin |
| indexer | NEW-7 `89.117.59.63` | `indexer-deploy` | `PWAP_INDEXER_DEPLOY_KEY` | `pwap-indexer-ssh` → sudo `pwap-indexer-deploy` | image SHA |
| Supabase | VPS3 `217.77.6.126` | `supabase-deploy` | `PWAP_SUPABASE_DEPLOY_KEY` | `pwap-supabase-ssh` → sudo `pwap-supabase-deploy` | bundle on stdin |
The hosts and their host keys are in the workflow env (`APP_HOST` …,
`DEPLOY_KNOWN_HOSTS`, the same lines as `ops/known_hosts`). A deploy to a host
that presents another key fails.
No key for these hosts belongs in root's `authorized_keys`.
## Installing on a host
Scripts are root-owned and not writable by the deploy users:
```sh
install -o root -g root -m 755 ops/host/pwap-web-receive /usr/local/sbin/
install -o root -g root -m 755 ops/host/pwap-indexer-ssh ops/host/pwap-indexer-deploy /usr/local/sbin/ # NEW-7
install -o root -g root -m 755 ops/host/pwap-supabase-ssh ops/host/pwap-supabase-deploy /usr/local/sbin/ # VPS3
```
Users (system accounts, no password):
```sh
useradd --system --create-home --shell /bin/bash app-deploy # NEW-7
useradd --system --create-home --shell /bin/bash indexer-deploy # NEW-7
useradd --system --create-home --shell /bin/bash supabase-deploy # VPS3 (pex-deploy already exists)
```
Web roots belong to their deploy user, group `www-data`, setgid:
```sh
chown -R app-deploy:www-data /var/www/subdomains/app # NEW-7
chmod -R g+rwX /var/www/subdomains/app
find /var/www/subdomains/app -type d -exec chmod g+s {} +
```
sudo, for the two deploys that have to run docker as root (`visudo -f`):
```
# /etc/sudoers.d/pwap-indexer-deploy (NEW-7)
indexer-deploy ALL=(root) NOPASSWD: /usr/local/sbin/pwap-indexer-deploy
# /etc/sudoers.d/pwap-supabase-deploy (VPS3)
supabase-deploy ALL=(root) NOPASSWD: /usr/local/sbin/pwap-supabase-deploy
```
The indexer's settings, `/etc/pwap-indexer.env` on NEW-7 (root, 644):
```
WS_ENDPOINT=wss://rpc.pezkuwichain.io
HOST_PORT=3011
```
`authorized_keys` of each deploy user, one line:
```
restrict,command="/usr/local/sbin/pwap-web-receive app" ssh-ed25519 AAAA... pwap-ci-app-deploy
```
## Checking it
`ops/host/test-web-receive.sh` runs the web script against a scratch web root,
including everything it must refuse; CI runs it with shellcheck in the
`workflow-guard` job. On a host, a key must fail anything but its command:
```sh
ssh -i key app-deploy@89.117.59.63 id # refused: the only command is deploy
ssh -i key -N -L 1:127.0.0.1:22 app-deploy@89.117.59.63 # refused: restrict
```