deploy/deploy.sh you would run by hand. The server builds its own images, so CI
needs no registry and holds no application secrets. Two repository secrets cover it,
SSH_KEY for the deploy@ private key and SSH_HOST.
.github/workflows/deploy.yml
Hardening the CI key
A key that can run any command is a key that can read your.env. Lock it to one command
with a forced command in the server’s ~deploy/.ssh/authorized_keys:
ssh argument is then ignored, and the key cannot open a shell.
Add
feather check and feather security-check to the test job. Both exit non-zero on
failure, so a convention violation or a weak secret stops the deploy rather than
shipping.