From 753be86ca4ce2a62addc4c3f0a41e313ad89e06f Mon Sep 17 00:00:00 2001 From: Chun Li Date: Fri, 17 Apr 2026 15:40:46 -0700 Subject: [PATCH] Initial commit; setting up raine to serve simple static site plus gitea. --- .gitignore | 1 + README.md | 119 ++++++++++++++++++++++++++++ caddy/Caddyfile | 21 +++++ caddy/compose.yml | 18 +++++ caddy/site/chunli.net/index.html | 1 + caddy/site/oversteep.com/index.html | 1 + gitea/compose.yml | 12 +++ 7 files changed, 173 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 caddy/Caddyfile create mode 100644 caddy/compose.yml create mode 100644 caddy/site/chunli.net/index.html create mode 100644 caddy/site/oversteep.com/index.html create mode 100644 gitea/compose.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a6428d8 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +gitea/data/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..b237aba --- /dev/null +++ b/README.md @@ -0,0 +1,119 @@ +# raine - home server + +Home server running on Ubuntu (hostname: `raine`, local IP: `10.0.0.100`). +Hosts personal websites, Gitea, and a NAS for local file sharing. + +## Architecture + +``` + Internet + │ + ▼ + ┌─────────────┐ + │ Cloudflare │ (terminates TLS, hides home IP) + └──────┬──────┘ + │ + encrypted tunnel + │ + ▼ + ┌─────────────┐ + │ cloudflared │ (native systemd service) + │ (raine) │ + └──────┬──────┘ + │ HTTP :80 + ▼ + ┌─────────────┐ + │ Caddy │ (Docker, reverse proxy) + │ │ + └──┬───┬───┬──┘ + │ │ │ + oversteep.com│ │ │git.chunli.net + │ │ └──────┐ + ▼ ▼ ▼ + /srv/oversteep.com ┌──────┐ + /srv/chunli.net │Gitea │ (Docker, :3000) + (static sites) └──────┘ +``` + +Local-only services (not exposed via tunnel): +- **Samba** — serves `/mnt/nas` over the LAN for file sharing between Linux/Mac clients +- **SSH** — on port 22, key auth only +- **Gitea SSH** — on port 2222, for local git operations + +## Services + +### Native (systemd) + +| Service | Purpose | +|--------------|--------------------------------------| +| cloudflared | Cloudflare tunnel to the internet | +| smbd | Samba file sharing on LAN | +| ssh | Remote shell access on LAN | + +### Docker (managed per-directory) + +| Service | Directory | Ports | Notes | +|---------|----------------|-------------|--------------------------------| +| caddy | `./caddy/` | 80, 443 | Reverse proxy, serves sites | +| gitea | `./gitea/` | 3000, 2222 | Self-hosted git, SQLite | + +Each service has its own `compose.yml` for independent management. They communicate +over the Docker host network via `host.docker.internal` (configured in caddy's +`extra_hosts`). + +## Domains + +| Domain | Points to | +|------------------|------------------------------| +| oversteep.com | Static site (Madison's) | +| chunli.net | Static site (personal) | +| git.chunli.net | Gitea via Caddy proxy | + +All domains go through the Cloudflare tunnel. Cloudflare handles TLS, so Caddy +serves plain HTTP internally (the `http://` prefix in the Caddyfile disables +Caddy's automatic HTTPS). + +## Storage + +- `/mnt/nas` — 2TB ext4 drive (`sda2`), shared via Samba + - Owned by `chun:nas`, mode 775 + - Users in the `nas` group have full read/write + - Folder layout: `photos/`, `media/`, `files/` +- Future: add more drives + mergerfs + snapraid when prices drop + +## Backups + +**Important:** Gitea's `data/` directory contains repos, the SQLite database, and +config. It's gitignored but needs a separate backup strategy. + +(TODO: set up backup scheme) + +## Common tasks + +```bash +# Restart a service +cd ~/docker/ +docker compose restart + +# View logs +docker logs + +# Update a service to the latest image +cd ~/docker/ +docker compose pull +docker compose up -d + +# Check what's running +docker ps +``` + +## Gotchas + +- **Caddy can't reach containers in other compose projects via `localhost`.** Use + `host.docker.internal:` instead (requires `extra_hosts: ["host.docker.internal:host-gateway"]`). +- **Caddy must pass `X-Forwarded-Proto: https`** to Gitea so it generates correct + URLs (since Cloudflare terminates TLS, not Caddy). +- **Group changes don't apply to existing shell sessions.** After `usermod -aG`, + log out and back in. +- **NTFS/exFAT drives auto-mount as root.** If you need user-level access, either + `sudo` or remount with `uid=1000,gid=1000`. diff --git a/caddy/Caddyfile b/caddy/Caddyfile new file mode 100644 index 0000000..a55df2a --- /dev/null +++ b/caddy/Caddyfile @@ -0,0 +1,21 @@ +# All sites are served over HTTP because Cloudflare tunnel handles TLS termination. +# http:// prefix disables Caddy's automatic HTTPS since certs are managed upstream. + +http://oversteep.com { + encode zstd gzip + root * /srv/oversteep.com + file_server +} + +http://chunli.net { + encode zstd gzip + root * /srv/chunli.net + file_server +} + +http://git.chunli.net { + encode zstd gzip + reverse_proxy host.docker.internal:3000 { + header_up X-Forwarded-Proto https + } +} diff --git a/caddy/compose.yml b/caddy/compose.yml new file mode 100644 index 0000000..086d2a7 --- /dev/null +++ b/caddy/compose.yml @@ -0,0 +1,18 @@ +services: + caddy: + container_name: caddy + image: caddy:latest + restart: unless-stopped + ports: + - "80:80" + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile + - ./site:/srv + - caddy_data:/data + - caddy_config:/config + extra_hosts: + - "host.docker.internal:host-gateway" + +volumes: + caddy_data: + caddy_config: diff --git a/caddy/site/chunli.net/index.html b/caddy/site/chunli.net/index.html new file mode 100644 index 0000000..008e34a --- /dev/null +++ b/caddy/site/chunli.net/index.html @@ -0,0 +1 @@ +

Hello this is chunli.net

diff --git a/caddy/site/oversteep.com/index.html b/caddy/site/oversteep.com/index.html new file mode 100644 index 0000000..505ba28 --- /dev/null +++ b/caddy/site/oversteep.com/index.html @@ -0,0 +1 @@ +

Hello from raine! This is oversteep.com

diff --git a/gitea/compose.yml b/gitea/compose.yml new file mode 100644 index 0000000..7a277e3 --- /dev/null +++ b/gitea/compose.yml @@ -0,0 +1,12 @@ +services: + gitea: + container_name: gitea + image: gitea/gitea:latest + restart: unless-stopped + environment: + - USER_UID=1000 + - USER_GID=1000 + volumes: + - ./data:/data + ports: + - "3000:3000"