# hantim-server Server provisioning and app management for the hantim webserver. This repo lives at `/opt/hantim` on the server and contains Docker Compose configs, deploy scripts, nginx configs, and Gitea Actions workflows for each app. ## Repo structure ``` docker/ nginx/ # Reverse proxy (nginx:alpine) + SSL config nginx.conf # Main nginx config conf.d/ # Per-app server blocks (e.g. timothykim.net.conf) compose.yml timothykim.net/ # timothykim.net static site compose.yml garage/ # Garage S3-compatible object storage compose.yml garage.toml.template scripts/ bootstrap.sh # First-time server setup (manual, uses Bitwarden) configure.sh # Idempotent server config (CI-safe) deploy.sh # Deploy + cert issuance + provision (called via SSH) new-app.sh # Scaffolding script to add a new static site new-service.sh # Scaffolding script to add a new Docker service .gitea/workflows/ # Per-app deploy workflows triggered by path changes ``` ## Provisioning a new server On a fresh Rocky Linux 9 install: ```bash dnf install -y git git clone https://git.timothykim.net/hantim/hantim-server.git /opt/hantim bash /opt/hantim/scripts/bootstrap.sh ``` `bootstrap.sh` runs once manually. It: 1. Installs system dependencies (jq, certbot, Node.js 20, Docker) 2. Installs and authenticates the Bitwarden CLI 3. Fetches the Docker registry token and deploy SSH public key from Bitwarden 4. Logs into the Gitea Docker registry 5. Creates the `deploy` user with restricted SSH access and sudo 6. Runs `configure.sh` (firewall, certbot, start services) `configure.sh` is idempotent and CI-safe. It: 1. Opens firewall ports (HTTP, HTTPS, Garage RPC) 2. Sets up certbot and issues SSL certificates for all configured domains 3. Starts all services (nginx first, then all apps) **Prerequisites**: DNS for all configured domains must point to the server before running bootstrap. ## Adding a new app ```bash ./scripts/new-app.sh ``` Example: `./scripts/new-app.sh hcsuzuki.net` This single command handles everything: creates DNS records on Vultr, creates the Gitea repo from `static-site-template`, generates all config files, issues the SSL cert (zero downtime), commits and pushes, triggers the first build, and verifies the site is live. **Prerequisites:** domain nameservers pointed to Vultr, `bw`/`jq`/`dig` installed. Uses the deploy SSH key from Bitwarden -- no personal server access needed. See USECASES.md for full details. After the site is live, clone the app repo and customize it: ```bash git clone git@git.timothykim.net:hantim/.git cd # edit content git add . && git commit -m "initial content" && git push ``` ## Deploying changes **App code change** (push to an app repo like `timothykim.net`): - The app's `build.yml` builds the Docker image, pushes to the registry, and SSHes into the server to trigger a deploy **Compose or nginx config change** (push to this repo): - Gitea Actions workflows trigger based on which `docker//` paths changed - `deploy.sh` pulls the latest code and runs `docker compose up -d` - For nginx deploys, the config is tested before applying to prevent downtime ## Restoring from backup Run the same three commands as provisioning. `bootstrap.sh` is idempotent: - Existing packages are skipped - Existing certs are skipped (or re-issued if the server is new) - All services are started ## Secrets The following are stored in Bitwarden and fetched automatically by `bootstrap.sh`: | Bitwarden item | Type | Purpose | |---|---|---| | `hantim-ci-registry-push` | Secure Note | Gitea token for Docker registry | | `hantim-server-deploy` | SSH Key | Deploy user's SSH key | The following are configured in the `hantim` Gitea org settings: | Name | Type | Purpose | |---|---|---| | `DEPLOY_HOST` | Variable | Server IP or hostname | | `DEPLOY_SSH_KEY` | Secret | SSH private key for the deploy user | | `CI_REGISTRY_TOKEN` | Secret | Gitea token for Docker registry login | The following are stored in Bitwarden and used by `new-app.sh`: | Bitwarden item | Type | Purpose | |---|---|---| | `hantim-new-app-script` | Secure Note | Gitea API token for creating repos | | `hantim-vultr-api-key` | Secure Note | Vultr API key for DNS management |