Files
hantim-server/CLAUDE.md
T
timothykim 5c38b0631a
Deploy nginx / deploy (push) Failing after 3s
Deploy timothykim.net / deploy (push) Successful in 3s
replace NPM with vanilla nginx + certbot
- nginx:alpine replaces nginx-proxy-manager
- certbot on host with standalone issuance and auto-renewal
- per-site nginx configs in conf.d/ (HTTP->HTTPS, bare->www)
- container names use underscores (timothykim_net)
- setup.sh: automated cert issuance, dynamic app startup
- deploy.sh: nginx -t guard, graceful image-not-found
- new-app.sh: Gitea API repo creation, nginx conf generation
- add ARCHITECTURE.md, USECASES.md, CLAUDE.md
- remove old NPM data/certs from tracking
2026-03-16 00:55:13 -04:00

2.7 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

  • setup.sh -- Server provisioning (idempotent, run as root)
  • scripts/deploy.sh -- SSH-triggered deploy (validates command, pulls, restarts)
  • scripts/new-app.sh -- Scaffolds a new static site (Gitea repo + compose + workflow + nginx conf)
  • 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

Conventions

  • App name = domain (e.g., hcsuzuki.net)
  • Container name = domain with dots replaced by underscores (e.g., hcsuzuki_net)
  • Image = git.timothykim.net/hantim/<domain>:latest
  • Cert name = domain (at /etc/letsencrypt/live/<domain>/)
  • 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

Stored in Bitwarden (free tier), fetched via bw CLI:

  • hantim-git-crypt-key -- Secure Note (base64)
  • hantim-ci-registry-push -- Secure Note (Gitea registry token)
  • hantim-server-deploy -- SSH Key (deploy user key pair)
  • hantim-new-app-script -- Secure Note (Gitea API token for creating repos)

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 app

Run ./scripts/new-app.sh <domain> from dev machine, then issue SSL cert on server before pushing. See USECASES.md for full steps.

Editing scripts

All shell scripts use set -euo pipefail. Keep all steps idempotent. setup.sh must be safe to re-run on an existing server.

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.

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 hcsuzuki.net", "fix deploy command")
  • Do NOT include "Co-Authored-By" lines
  • Commit only when explicitly asked