No description
  • Shell 56.3%
  • HCL 21.7%
  • Dockerfile 15.6%
  • Makefile 6.4%
Find a file
2026-06-22 00:53:39 +08:00
caddy feat: setup for lawnet 2026-06-22 00:53:39 +08:00
docs refactor: update environment variable names for R2 compatibility across services 2026-05-17 18:34:08 +08:00
etc/ssh 2026-05-17 17:04:45 +08:00
forgejo feat: forgejo runner setup 2026-06-21 23:39:27 +08:00
immich refactor: update environment variable names for R2 compatibility across services 2026-05-17 18:34:08 +08:00
linkwarden feat: remove linkwarden 2026-05-17 17:36:54 +08:00
mailserver feat: mailserver 2026-06-14 12:25:44 +08:00
offline-notion@21326cd93a feat: remove linkwarden 2026-05-17 17:36:54 +08:00
openbao refactor: update environment variable names for R2 compatibility across services 2026-05-17 18:34:08 +08:00
outline refactor: update environment variable names for R2 compatibility across services 2026-05-17 18:34:08 +08:00
tofu-infra feat: setup for lawnet 2026-06-22 00:53:39 +08:00
vaultwarden refactor: update environment variable names for R2 compatibility across services 2026-05-17 18:34:08 +08:00
.env.example feat: forgejo runner setup 2026-06-14 12:41:34 +08:00
.gitignore 2026-05-17 17:04:45 +08:00
ARCHITECTURE.md feat: remove nextcloud 2026-05-17 17:56:13 +08:00
ARCHITECTURE.puml feat: remove nextcloud 2026-05-17 17:56:13 +08:00
BACKUPS.md feat: mailserver 2026-06-14 12:25:44 +08:00
docker-compose.yaml feat: forgejo runner setup 2026-06-14 12:41:34 +08:00
Makefile feat: remove nextcloud 2026-05-17 17:56:13 +08:00
README.md feat: setup for lawnet 2026-06-22 00:53:39 +08:00
source.sh 2026-05-17 17:04:45 +08:00

Hetzner Auction Ubuntu 24.04 Server

Config and helpers for a Hetzner auction server running Ubuntu 24.04.

See all the services @ ARCHITECTURE.md.

Set Up

1. SSH config: /etc/ssh/sshd_config

This is a hardened OpenSSH server config. It:

  • Disables root SSH: PermitRootLogin no
  • Key-only auth: password and keyboard-interactive are off; only PubkeyAuthentication is used
  • Restricts login: AllowUsers server
  • Keeps PAM for account/session handling
  • Disables X11 forwarding because I don't need it and ChatGPT suggested it

Services

From the Internet

Service Port Subdomain
Vaultwarden 2407 pw.yongbeom.net
OpenBao 2408 bao.yongbeom.net
Immich 2409 photos.yongbeom.net
Forgejo 2410 git.yongbeom.net
Forgejo SSH 222 git@git.yongbeom.net (SSH)
Stalwart admin/web 2412 local mail.yongbeom.com
Stalwart SMTP 25, 465, 587 mail.yongbeom.com
Stalwart IMAP 993 mail.yongbeom.com

Mine

Service Port Subdomain
Offline Notion (TODO) 3404 notion.yongbeom.net
Lobster 3405 lobster.yongbeom.net
LawNet 3410 lawnet.yongbeom.com
LawNet staging 3411 lawnet-staging.yongbeom.com

Senpailearn

Service Port Subdomain
Hydragen (V2) (TODO) 3504 hydragen.senpailearn.com

Service removal runbooks:

Mailserver

The mailserver profile runs Stalwart Mail Server. Caddy serves the admin/web UI at https://mail.yongbeom.com, while SMTP and IMAP ports are exposed directly by Docker:

MAILSERVER_HOSTNAME=mail.yongbeom.com
STALWART_HTTP_PORT=2412
SMTP2GO_USERNAME=...
SMTP2GO_PASSWORD=...
MAILSERVER_BACKUP_ON_STARTUP=false
MAILSERVER_B2_REPO=b2:backup-mail-yongbeom-com
MAILSERVER_R2_REPO=s3:https://<account-id>.r2.cloudflarestorage.com/backup-mail-yongbeom-com

The Stalwart config and data paths are Compose named volumes backed by ${VOLUME_BASE_DIR}/mailserver/..., matching the OpenBao volume pattern. On a fresh host, create the backing directories before starting:

mkdir -p "${VOLUME_BASE_DIR}/mailserver/config" "${VOLUME_BASE_DIR}/mailserver/data"

On first start, get the temporary admin password and finish setup in the web UI:

docker logs mailserver 2>&1 | grep -A8 'bootstrap mode'

Open https://mail.yongbeom.com/admin. Use mail.yongbeom.com as the server hostname and yongbeom.com as the default email domain. Keep DNS management manual unless you intentionally wire Stalwart to Route53. Stalwart can generate DKIM keys during setup; after setup, view the generated zone file from the domain menu in the admin UI and copy the DKIM/SPF/DMARC records into Route53.

For mail client TLS on IMAP/SMTP, configure Stalwart to use Caddy's Let's Encrypt certificate. The Caddy data directory is mounted read-only at /certs/caddy; add a Stalwart TLS certificate object using:

Certificate file: /certs/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/mail.yongbeom.com/mail.yongbeom.com.crt
Private key file: /certs/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/mail.yongbeom.com/mail.yongbeom.com.key

Set that certificate as Stalwart's default certificate so IMAP on 993 and SMTP submission on 465/587 present a trusted certificate.

For outbound delivery through SMTP2GO, configure an outbound relay in the Stalwart admin UI using mail.smtp2go.com, port 2525 or 587, and the SMTP2GO credentials from the environment.

The mailserver-backup sidecar runs daily at 04:35. It briefly stops the mailserver container, backs up Stalwart config and data with restic, then starts the container again.

DNS is managed in Terraform for:

mail.yongbeom.com. A     <server ipv4>
mail.yongbeom.com. AAAA  <server ipv6>
yongbeom.com.      MX 10 mail.yongbeom.com.

Also set the server reverse DNS/PTR at Hetzner to mail.yongbeom.com.

LawNet

Caddy proxies LawNet to apps already listening on the host. These two routes are hardcoded in caddy/Caddyfile, so no .env changes are needed:

lawnet.yongbeom.com         -> localhost:3410
lawnet-staging.yongbeom.com -> localhost:3411

DNS is managed in Terraform through the shared aws-dns-record module, which creates A/AAAA records for each hostname and its www alias:

lawnet.yongbeom.com.             A     <server ipv4>
lawnet.yongbeom.com.             AAAA  <server ipv6>
www.lawnet.yongbeom.com.         A     <server ipv4>
www.lawnet.yongbeom.com.         AAAA  <server ipv6>
lawnet-staging.yongbeom.com.     A     <server ipv4>
lawnet-staging.yongbeom.com.     AAAA  <server ipv6>
www.lawnet-staging.yongbeom.com. A     <server ipv4>
www.lawnet-staging.yongbeom.com. AAAA  <server ipv6>