# 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 (validates and routes deploy commands) deploy.sh # Generic deploy script (git pull + docker compose up) 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: ```bash 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): ```bash 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 two components: 1. **Gitea Actions workflow** (`.gitea/workflows/deploy-.yml`) -- triggers on pushes to `main` when files under `docker//` change. SSHes into the server as the `deploy` user to trigger the deploy. 2. **SSH dispatcher** (`scripts/deploy-dispatch.sh`) -- the `deploy` user's `authorized_keys` is locked to this script via a `command=` directive. It validates the command and runs `scripts/deploy.sh`, which pulls the latest repo changes and runs `docker compose pull && up -d` for that app. This means: - Pushing a change to `docker/nginx/compose.yml` only deploys nginx. - Pushing a change to `scripts/` or `setup.sh` does not trigger any deploy. - Each app deploys independently. ## Adding a new app Run the scaffolding script: ```bash ./scripts/new-app.sh ``` This creates: - `docker//compose.yml` -- a starter compose file on the `shared` network - `.gitea/workflows/deploy-.yml` -- the Gitea Actions workflow After running the script: 1. Edit `docker//compose.yml` to fit your app (image, ports, volumes, environment variables, etc.). 2. Commit and push to `main`. 3. 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 hostname - `DEPLOY_KEY` -- the SSH private key for the `deploy` user