- 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
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
sharedDocker 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:
- Reading scripts and checking idempotency
- Walking through each use case in USECASES.md
- 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