Files
hantim-server/README.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

3.9 KiB

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
scripts/
  deploy.sh            # Deploy script (validates command, git pull, docker compose up)
  new-app.sh           # Scaffolding script to add a new app
setup.sh               # Server provisioning script (idempotent)
.gitea/workflows/      # Per-app deploy workflows triggered by path changes

Provisioning a new server

On a fresh Rocky Linux 9 install:

dnf install -y git
git clone https://git.timothykim.net/hantim/hantim-server.git /opt/hantim
bash /opt/hantim/setup.sh

setup.sh is fully automated and idempotent. It:

  1. Installs system dependencies (git-crypt, jq, certbot, Node.js 20, Docker)
  2. Installs and authenticates the Bitwarden CLI
  3. Unlocks git-crypt using a key stored in Bitwarden
  4. Fetches the Docker registry token and deploy SSH public key from Bitwarden
  5. Logs into the Gitea Docker registry
  6. Creates the deploy user with restricted SSH access and sudo
  7. Issues SSL certificates via certbot for all configured domains
  8. Starts all services (nginx first, then all apps)

Prerequisites: DNS for all configured domains must point to the server before running setup.

Adding a new app

./scripts/new-app.sh <domain>

Example: ./scripts/new-app.sh hcsuzuki.net

This creates:

  • A Gitea repo (hantim/<domain>) from the static-site-template
  • docker/<domain>/compose.yml -- app compose file
  • .gitea/workflows/deploy-<domain>.yml -- deploy workflow
  • docker/nginx/conf.d/<domain>.conf -- nginx proxy config (HTTP->HTTPS, bare domain->www)

After running the script:

  1. Issue the SSL cert on the server (before pushing):
    docker stop nginx
    certbot certonly --standalone --non-interactive --agree-tos \
      --register-unsafely-without-email --cert-name <domain> \
      -d <domain> -d www.<domain>
    docker start nginx
    
  2. Commit and push this repo to deploy
  3. Clone the new app repo, customize it, and push to build/deploy

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/<app>/ 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. setup.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 setup.sh:

Bitwarden item Type Purpose
hantim-git-crypt-key Secure Note git-crypt symmetric key (base64)
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 is 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