919c5353bc
Provision server / provision (push) Failing after 2s
bootstrap.sh handles first-time setup (manual, Bitwarden). configure.sh handles idempotent config (CI-safe). Add provision workflow, deploy-garage workflow, new-service.sh. Remove git-crypt references and empty .gitattributes.
86 lines
3.4 KiB
Markdown
86 lines
3.4 KiB
Markdown
# 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)
|
|
- `scripts/new-app.sh` -- Single-command new static site (DNS + Gitea repo + cert + deploy + verify)
|
|
- `scripts/new-service.sh` -- Scaffold a new Docker Compose service (compose + workflow)
|
|
- `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., `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-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)
|
|
- `hantim-vultr-api-key` -- Secure Note (Vultr API key for DNS management)
|
|
- `argento-garage` -- Secure Note (Garage rpc_secret, argento_node_id, S3 keys)
|
|
|
|
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 `./scripts/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 `./scripts/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 hcsuzuki.net", "fix deploy command")
|
|
- Do NOT include "Co-Authored-By" lines
|
|
- Commit only when explicitly asked
|