Files
hantim-server/USECASES.md
T

4.6 KiB

Use Cases

1. Provision a new server

Set up a fresh Rocky Linux 9 server from scratch.

dnf install -y git
git clone https://git.timothykim.net/hantim/hantim-server.git /opt/hantim
bash /opt/hantim/scripts/bootstrap.sh

What happens:

  • Installs all dependencies (jq, certbot, Node.js 20, Docker, bw CLI)
  • Fetches secrets from Bitwarden (registry token, deploy SSH key)
  • Logs into Docker registry
  • Creates deploy user with restricted SSH + sudo
  • Runs configure.sh:
    • Opens firewall ports (HTTP, HTTPS, Garage RPC)
    • Issues SSL certs for all domains in docker/nginx/conf.d/
    • Starts nginx and all app containers

Prerequisites:

  • DNS for all configured domains must point to the server
  • Bitwarden vault must contain: hantim-ci-registry-push, hantim-server-deploy
  • Docker images must exist in the Gitea registry (or apps will start on next push)

2. Restore from backup

Identical to provisioning a new server. Run the same three commands on a fresh server.

  • bootstrap.sh and configure.sh are idempotent -- safe to re-run
  • SSL certs are re-issued automatically (Let's Encrypt)
  • Docker images are pulled from the Gitea registry
  • No data migration needed for stateless static sites

3. Add a new static site

From your dev machine (single command):

./scripts/new-app.sh hcsuzuki.net

Prerequisites:

  • Bitwarden vault must contain hantim-new-app-script, hantim-vultr-api-key, and hantim-server-deploy
  • Domain nameservers must be pointed to Vultr (configured on directnic.com)
  • Dependencies: bw, jq, dig

What happens (fully automated):

  1. Resolves server IP from hantim.net
  2. Fetches Gitea API token, Vultr API key, and deploy SSH key from Bitwarden
  3. Creates DNS zone on Vultr (if needed) and A records for bare + www
  4. Waits for DNS to propagate
  5. Creates Gitea repo hantim/hcsuzuki.net from static-site-template
  6. Creates local files:
    • docker/hcsuzuki.net/compose.yml (container name: hcsuzuki_net)
    • .gitea/workflows/deploy-hcsuzuki.net.yml
    • docker/nginx/conf.d/hcsuzuki.net.conf (HTTP->HTTPS, bare->www, proxy)
  7. SSHes to server as deploy user, issues SSL cert via webroot (zero downtime)
  8. Commits and pushes hantim-server (triggers deploy)
  9. Triggers initial build of the app repo via Gitea API
  10. Polls https://www.hcsuzuki.net until it responds (up to 3 minutes)

After the site is live, clone the app repo and customize:

git clone git@git.timothykim.net:hantim/hcsuzuki.net.git
cd hcsuzuki.net
# edit static/index.html, etc.
git add . && git commit -m "initial content" && git push

4. Update app code

Push a change to the app repo (e.g., timothykim.net):

cd timothykim.net
# make changes
git add . && git commit -m "update content" && git push

What happens:

  1. Gitea Actions runs build.yml: builds Docker image, pushes to registry
  2. SSHes into server, runs deploy-timothykim.net
  3. deploy.sh pulls latest hantim-server, pulls new image, restarts container

No manual steps needed.

5. Update Docker Compose config

Edit a compose file in this repo and push:

vim docker/timothykim.net/compose.yml
git add docker/timothykim.net/compose.yml
git commit -m "update timothykim.net config"
git push

What happens:

  1. deploy-timothykim.yml workflow triggers (path match)
  2. deploy.sh pulls latest code, pulls image, runs docker compose up -d

6. Update nginx config

Edit an nginx config in this repo and push:

vim docker/nginx/conf.d/timothykim.net.conf
git add docker/nginx/conf.d/timothykim.net.conf
git commit -m "update nginx config"
git push

What happens:

  1. deploy-nginx.yml workflow triggers (path match)
  2. deploy.sh pulls latest code
  3. If any conf files reference certs that don't exist yet, nginx is briefly stopped and certs are issued via standalone certbot (auto-restarts on failure)
  4. Tests nginx config with nginx -t -- if it fails, deploy aborts and the running nginx is untouched
  5. Runs docker compose up -d and reloads nginx

Note: Each conf file must contain server blocks for only one domain. The cert name is derived from the filename (e.g. hcsuzuki.net.conf -> cert hcsuzuki.net). Redirect-only domains like hcsuzukiviolin.com get their own conf file.

7. Re-run configure on existing server

Safe to do at any time, manually or via CI:

cd /opt/hantim
git pull
bash scripts/configure.sh

Or push a change to scripts/configure.sh — the provision.yml workflow triggers automatically.

  • All steps are idempotent
  • Existing certs are skipped
  • Brief nginx downtime (seconds) while certbot checks run
  • Services are restarted