2026-03-13 17:09:11 -04:00
2026-03-12 21:16:59 -04:00
2026-03-12 21:16:59 -04:00
2026-03-12 21:16:59 -04:00

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.sh          # Deploy script (validates command, 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:

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 two components:

  1. Gitea Actions workflow (.gitea/workflows/deploy-<app>.yml) -- triggers on pushes to main when files under docker/<app>/ change. SSHes into the server as the deploy user to trigger the deploy.
  2. Deploy script (scripts/deploy.sh) -- the deploy user's authorized_keys is locked to this script via a command= directive. It validates the command, 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:

./scripts/new-app.sh <app-name>

This creates:

  • docker/<app-name>/compose.yml -- a starter compose file on the shared network
  • .gitea/workflows/deploy-<app-name>.yml -- the Gitea Actions workflow

After running the script:

  1. Edit docker/<app-name>/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
S
Description
No description provided
Readme 500 KiB
Languages
Shell 65.2%
Python 33.5%
Assembly 0.5%
Dockerfile 0.4%
HTML 0.4%