diff --git a/README.md b/README.md index 53f2d78..196780a 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,11 @@ | Container | Image | Purpose | |-----------|-------|---------| | `duckdns` | `lscr.io/linuxserver/duckdns` | Dynamic DNS — keeps `*.duckdns.org` pointed at the home IP | -| `homeassistant` | `homeassistant/home-assistant` | Home automation, reachable at `:8123` | +| `caddy` | `caddy` (custom build) | HTTPS reverse proxy with automatic Let's Encrypt certificates via DuckDNS DNS-01 | +| `homeassistant` | `homeassistant/home-assistant` | Home automation, reachable at `https://ha-padriano.duckdns.org` | | `timemachine` | `mbentley/timemachine:smb` | Time Machine backup server over SMB | | `samba` | `dperson/samba` | General SMB file share for Mac and Linux clients | -| `forgejo` | `codeberg.org/forgejo/forgejo` | Self-hosted Git server, web UI at `:3000`, SSH at `:2222` | +| `forgejo` | `codeberg.org/forgejo/forgejo` | Self-hosted Git server at `https://git-padriano.duckdns.org`, SSH at `:2222` | ## Initial Setup @@ -19,7 +20,9 @@ nano .env ``` -2. Create the required host directories if they don't exist: +2. Register the required DuckDNS subdomains at [duckdns.org](https://www.duckdns.org): `ha-padriano`, `padrianoha`, `padriano`, `git-padriano`. + +3. Create the required host directories if they don't exist: ```bash mkdir -p /home/padriano/projects/forgejo @@ -32,11 +35,23 @@ sudo chown 1001:1001 /home/padriano/share ``` -3. Bring the full stack up: +4. Add the reverse proxy trusted header config to Home Assistant: + + ```bash + sudo tee -a /home/padriano/projects/ha/config/configuration.yaml > /dev/null << 'EOF' + + http: + use_x_forwarded_for: true + trusted_proxies: + - 172.16.0.0/12 + EOF + ``` + +5. Bring the full stack up (first run builds the custom Caddy image): ```bash cd /home/padriano/projects/composer - docker compose up -d + docker compose up -d --build ``` --- @@ -115,14 +130,26 @@ docker inspect forgejo ### duckdns - Config stored at `/home/padriano/projects/duckdns/config` -- Uses `network_mode: host` — required for Avahi/mDNS broadcast -- Domains managed: `ha-padriano`, `padrianoha`, `padriano` (all `.duckdns.org`) +- Domains managed: `ha-padriano`, `padrianoha`, `padriano`, `git-padriano` (all `.duckdns.org`) +- Subdomains must be registered manually at [duckdns.org](https://www.duckdns.org) before they can be updated + +### caddy + +- Custom image built from `caddy/Dockerfile` — adds the [DuckDNS DNS provider plugin](https://github.com/caddy-dns/duckdns) to the official Caddy image +- Config at `caddy/Caddyfile`; TLS certificates stored in the `caddy_data` Docker volume +- Obtains free Let's Encrypt certificates via **DNS-01 challenge** (no extra ports needed, no cost) +- Listens on `:80` (redirects to HTTPS) and `:443` +- Routes: + - `ha-padriano.duckdns.org` → Home Assistant `:8123` + - `git-padriano.duckdns.org` → Forgejo `:3000` +- To reload config without restarting: `docker exec caddy caddy reload --config /etc/caddy/Caddyfile` ### homeassistant - Config stored at `/home/padriano/projects/ha/config` -- Web UI: `http://server:8123` or `http://ha-padriano.duckdns.org` -- Uses `network_mode: host` for device discovery (mDNS, Zigbee, etc.) +- Web UI: `https://ha-padriano.duckdns.org` (via Caddy) or `http://server:8123` on the LAN +- Runs on the `internal` bridge network so Caddy can reach it by container name +- `configuration.yaml` must include `http.use_x_forwarded_for: true` and `trusted_proxies` for the Docker bridge range so HA accepts forwarded headers from Caddy - Has a healthcheck — status shows `(health: starting)` for ~60s on first boot ### timemachine @@ -145,35 +172,36 @@ docker inspect forgejo - All data (repos, config, SQLite DB) stored at `/home/padriano/projects/forgejo` - Backing up this single directory is sufficient for a full restore +- Port 3000 is no longer exposed on the host — access is via Caddy only #### First-run setup -Visit `http://server:3000` on first start and complete the install wizard: +Visit `http://server:3000` on first start (LAN only) and complete the install wizard: -- **Base URL**: `http://padriano.duckdns.org:3000` -- **SSH domain**: `padriano.duckdns.org` +- **Base URL**: `https://git-padriano.duckdns.org` +- **SSH domain**: `git-padriano.duckdns.org` - **SSH port**: `2222` #### Access | Method | Local network | External (via DuckDNS) | |--------|---------------|------------------------| -| Web UI | `http://server:3000` | `http://padriano.duckdns.org:3000` | -| Git SSH | `ssh://git@server:2222` | `ssh://git@padriano.duckdns.org:2222` | +| Web UI | `http://server:3000` | `https://git-padriano.duckdns.org` | +| Git SSH | `ssh://git@server:2222` | `ssh://git@git-padriano.duckdns.org:2222` | -For external access, forward these ports on your router to `192.168.1.116`: +For external access, forward these ports on your router to the server IP: -- TCP `3000` → Forgejo web UI +- TCP `443` → Caddy (HTTPS — serves both HA and Forgejo) - TCP `2222` → Forgejo SSH #### Git remote URL examples ```bash -# Add remote via HTTP -git remote add origin http://padriano.duckdns.org:3000/padriano/my-repo.git +# Add remote via HTTPS +git remote add origin https://git-padriano.duckdns.org/padriano/my-repo.git # Add remote via SSH -git remote add origin ssh://git@padriano.duckdns.org:2222/padriano/my-repo.git +git remote add origin ssh://git@git-padriano.duckdns.org:2222/padriano/my-repo.git # Clone via SSH (local) git clone ssh://git@server:2222/padriano/my-repo.git @@ -201,6 +229,7 @@ du -sh /home/padriano/projects/* /home/padriano/backup/* | Service | Host path | Notes | |---------|-----------|-------| | `duckdns` | `/home/padriano/projects/duckdns/config` | Token cache, not critical | +| `caddy` | Docker volume `caddy_data` | Issued TLS certificates — auto-reissued if lost | | `homeassistant` | `/home/padriano/projects/ha/config` | All HA config and automations | | `timemachine` | `/home/padriano/backup/timemachine` | Mac backup sparsebundles | | `samba` | `/home/padriano/share` | General file share — back up as needed | diff --git a/caddy/Caddyfile b/caddy/Caddyfile new file mode 100644 index 0000000..7890be1 --- /dev/null +++ b/caddy/Caddyfile @@ -0,0 +1,13 @@ +ha-padriano.duckdns.org { + reverse_proxy homeassistant:8123 + tls { + dns duckdns {env.DUCKDNS_TOKEN} + } +} + +git-padriano.duckdns.org { + reverse_proxy forgejo:3000 + tls { + dns duckdns {env.DUCKDNS_TOKEN} + } +} diff --git a/caddy/Dockerfile b/caddy/Dockerfile new file mode 100644 index 0000000..302e873 --- /dev/null +++ b/caddy/Dockerfile @@ -0,0 +1,5 @@ +FROM caddy:builder AS builder +RUN xcaddy build --with github.com/caddy-dns/duckdns + +FROM caddy:latest +COPY --from=builder /usr/bin/caddy /usr/bin/caddy diff --git a/docker-compose.yml b/docker-compose.yml index 63d4203..97aed90 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,7 +18,8 @@ services: image: homeassistant/home-assistant:2024.5.4 container_name: homeassistant restart: unless-stopped - network_mode: host + networks: + - internal depends_on: - duckdns environment: @@ -38,8 +39,9 @@ services: hostname: forgejo restart: unless-stopped ports: - - "3000:3000" - "2222:22" + networks: + - internal environment: - USER_UID=${PUID} - USER_GID=${PGID} @@ -48,6 +50,25 @@ services: - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro + caddy: + build: ./caddy + container_name: caddy + restart: unless-stopped + ports: + - "80:80" + - "443:443" + environment: + - DUCKDNS_TOKEN=${DUCKDNS_TOKEN} + volumes: + - ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro + - caddy_data:/data + - caddy_config:/config + networks: + - internal + depends_on: + - homeassistant + - forgejo + samba: image: dperson/samba:latest container_name: samba @@ -93,5 +114,11 @@ services: - /home/padriano/projects/composer/timemachine/smb.conf:/etc/samba/smb.conf:ro networks: + internal: + driver: bridge macvlan_lan: external: true + +volumes: + caddy_data: + caddy_config: