Files
hantim-server/CLAUDE.md
T
2026-03-20 11:28:36 -04:00

4.2 KiB

CLAUDE.md

Project overview

Server provisioning and app management for the hantim webserver. This repo lives at /opt/hantim on the production server (Rocky Linux 9 on Vultr) and manages Docker Compose configs, deploy scripts, nginx configs, and Gitea Actions workflows.

Key files

  • scripts/bootstrap.sh -- First-time server setup (manual, uses Bitwarden)
  • scripts/configure.sh -- Idempotent server config (firewall, certbot, start services; CI-safe)
  • scripts/deploy.sh -- SSH-triggered deploy + cert issuance + provision (deploy-, cert-, provision commands)
  • tools/new-app.sh -- Single-command new static site (DNS + Gitea repo + cert + deploy + verify)
  • tools/new-service.sh -- Scaffold a new Docker Compose service (compose + workflow)
  • tools/remove-app.sh -- Remove a static site (local files + Gitea repo)
  • docker/nginx/ -- Reverse proxy (nginx:alpine + certbot on host)
  • docker/<domain>/compose.yml -- Per-app compose files
  • .gitea/workflows/deploy-<app>.yml -- Per-app deploy workflows
  • .gitea/workflows/provision.yml -- Triggers configure.sh on setup changes

Conventions

  • App name = domain (e.g., example.com)
  • Container name = domain with dots replaced by underscores (e.g., example_com)
  • Image = git.timothykim.net/hantim/<domain>:latest
  • Cert name = config filename without .conf (at /etc/letsencrypt/live/<name>/)
  • One domain per conf file -- deploy.sh derives cert name from filename
  • All HTTP redirects to HTTPS; bare domain redirects to www.<domain>
  • The shared Docker network is created by nginx compose and used by all apps

Secrets

Bitwarden Secrets Manager (project: hantim, fetched via bws CLI):

  • hantim-ci-registry-push -- Gitea registry token (used by bootstrap.sh)
  • hantim-deploy-ssh-private-key -- deploy user SSH private key (used by new-app.sh)
  • hantim-deploy-ssh-public-key -- deploy user SSH public key (used by bootstrap.sh)
  • hantim-new-app-script -- Gitea API token for creating repos (used by new-app.sh)
  • hantim-vultr-api-key -- Vultr API key for DNS management (used by new-app.sh)
  • hantim-garage-rpc-secret -- Garage cluster RPC secret (used by deploy.sh)
  • hantim-garage-argento-node-id -- Argento's Garage node ID + address (used by deploy.sh)
  • hantim-garage-admin-token -- Garage admin API token (used by deploy.sh, new-app.sh)
  • hantim-garage-media-key-id -- S3 access key ID for media uploads (used by new-app.sh)
  • hantim-garage-media-secret-key -- S3 secret key for media uploads (used by aws CLI)

Machine accounts:

  • hantim-server -- access token stored at /etc/bws-token on hantim
  • hantim-ci -- access token stored as Gitea secret (reserved for future use)

Gitea org-level (hantim) secrets/variables:

  • DEPLOY_HOST -- Variable (server IP)
  • DEPLOY_SSH_KEY -- Secret (deploy SSH private key)
  • CI_REGISTRY_TOKEN -- Secret (registry token)

Working with this repo

Adding a new static site

Run ./tools/new-app.sh <domain> from dev machine. Handles everything: DNS, Gitea repo, SSL cert, commit/push, build trigger, and verification. See USECASES.md for full details.

Adding a new Docker service

Run ./tools/new-service.sh <name> to scaffold the compose file and deploy workflow, then edit the compose file and commit.

Editing scripts

All shell scripts use set -euo pipefail. Keep all steps idempotent. configure.sh must be safe to re-run from CI.

Deploy flow

App repo push -> build.yml builds image, pushes to registry, SSHes to server -> deploy.sh pulls repo, pulls image, restarts container.

Infrastructure push (this repo) -> deploy-<app>.yml triggers on path match -> same deploy.sh flow. nginx deploys test config with nginx -t first.

Setup change push -> provision.yml triggers -> deploy.sh provision -> configure.sh (firewall, certbot, start services).

Build and test

No build step. No tests. Verify changes by:

  1. Reading scripts and checking idempotency
  2. Walking through each use case in USECASES.md
  3. Cross-checking documentation (README.md, ARCHITECTURE.md, USECASES.md) against scripts

Commit style

  • Short, lowercase commit messages (e.g., "add example.com", "fix deploy command")
  • Do NOT include "Co-Authored-By" lines
  • Commit only when explicitly asked