fly-hermes#
Fly.io deployment config for a Hermes agent with a custom convenience image.
This repo follows the official Hermes-on-Fly setup, but builds a local Docker image on top of nousresearch/hermes-agent:latest so extra tools are available every time the machine is redeployed.
Included additions#
gnupg2passunzipjqlsofneovim/nvimbunpinned viaBUN_VERSIONinDockerfilepi, the pi coding agent from https://pi.dev- Playwright with Chromium browser dependencies
- Tailscale CLI/daemon
jj- GitHub CLI,
gh
Deploy#
fly deploy
Tailscale#
The image includes a small entrypoint that starts Tailscale only when TS_AUTHKEY is present.
fly secrets set TS_AUTHKEY=tskey-auth-...
Optional settings:
fly secrets set TS_HOSTNAME=fly-hermes
fly secrets set TS_EXTRA_ARGS="--advertise-tags=tag:dev"
Tailscale state is stored on the Fly volume at /opt/data/tailscale, so the node can survive redeploys.
To expose a dev server to your tailnet, start the server on the machine and use Tailscale Serve, for example:
tailscale --socket=/tmp/tailscale/tailscaled.sock serve --bg 3000
Password manager#
pass is installed for secure credential storage. Initialize a GPG key at runtime, then store passwords under /opt/data/.password-store (or the default ~/.password-store, which lives on the Fly volume since the home directory is under /opt/data).
This means passwords survive redeploys as long as the GPG key is also backed up or regenerated with the same identity.
GitHub / PR workflow#
gh is installed, but authentication should be provided at runtime, not committed to this repo. Use either gh auth login over SSH or a Fly secret such as GH_TOKEN.
Browser testing#
Playwright and Chromium are installed in the image. Example:
npx playwright test
Updating tools#
To add apt packages, edit the apt-get install list in Dockerfile.
To update pinned tools, change the relevant build args:
ARG BUN_VERSION=...
ARG JJ_VERSION=...
Then redeploy.
Notes#
The Fly machine has a persistent volume mounted at /opt/data. Tooling installed through the Docker image is reproducible; anything installed manually over SSH should be treated as temporary machine state.