3.3 KiB
hantim-server
Server provisioning and app management for the hantim webserver. This repo
lives at /opt/hantim on the server and contains Docker Compose configs, deploy
scripts, and Gitea Actions workflows for each app.
Repo structure
docker/ # One directory per app, each with a compose.yml
nginx/ # Nginx Proxy Manager (reverse proxy + TLS)
timothykim.net/ # timothykim.net static site
scripts/
deploy-dispatch.sh # SSH command dispatcher (routes to per-app deploy scripts)
deploy-nginx.sh # Deploy script for nginx
deploy-timothykim.sh # Deploy script for timothykim.net
new-app.sh # Scaffolding script to add a new app
setup.sh # One-time server provisioning script
.gitea/workflows/ # Per-app deploy workflows triggered by path changes
Initial server setup
On a fresh Rocky Linux 9 (or compatible) install:
dnf install -y git
git clone https://git.timothykim.net/timothykim/hantim-server.git /opt/hantim
bash /opt/hantim/setup.sh
setup.sh handles everything else: installs git-crypt and the Bitwarden CLI,
fetches the git-crypt key from your Bitwarden vault (stored as a base64-encoded
secure note named hantim-git-crypt-key), unlocks the repo, installs Docker,
creates the deploy user, and starts all services.
To save the git-crypt key to Bitwarden (one-time, from your dev machine):
base64 /path/to/git-crypt-key
# Save the output as a Bitwarden secure note named "hantim-git-crypt-key"
How deploys work
Each app has three components:
- Deploy script (
scripts/deploy-<app>.sh) -- pulls the latest repo changes, then runsdocker compose pull && up -dfor that app. - Gitea Actions workflow (
.gitea/workflows/deploy-<app>.yml) -- triggers on pushes tomainwhen files underdocker/<app>/change. SSHes into the server as thedeployuser to trigger the deploy. - SSH dispatcher (
scripts/deploy-dispatch.sh) -- thedeployuser'sauthorized_keysis locked to this script via acommand=directive. It readsSSH_ORIGINAL_COMMANDto route to the correct per-app deploy script.
This means:
- Pushing a change to
docker/nginx/compose.ymlonly deploys nginx. - Pushing a change to
scripts/orsetup.shdoes not trigger any deploy. - Each app deploys independently.
Adding a new app
Run the scaffolding script:
./scripts/new-app.sh <app-name>
This creates:
docker/<app-name>/compose.yml-- a starter compose file on thesharednetworkscripts/deploy-<app-name>.sh-- the deploy script.gitea/workflows/deploy-<app-name>.yml-- the Gitea Actions workflow- A new case in
scripts/deploy-dispatch.sh
After running the script:
- Edit
docker/<app-name>/compose.ymlto fit your app (image, ports, volumes, environment variables, etc.). - Commit and push to
main. - Configure the proxy host in Nginx Proxy Manager to route traffic to the new service.
Secrets
Nginx Proxy Manager certs and Let's Encrypt account keys are encrypted with
git-crypt (see .gitattributes). You need the git-crypt key to unlock them.
The following secrets must be configured in the Gitea repo settings for deploys to work:
DEPLOY_HOST-- the server's IP or hostnameDEPLOY_KEY-- the SSH private key for thedeployuser