112 lines
4.6 KiB
Markdown
112 lines
4.6 KiB
Markdown
# Deployment notes — Family Home Lab
|
||
|
||
## Domains
|
||
- Public zone `lab.audasmedia.com.au` → `144.6.86.11` (router) → `.35` Caddy.
|
||
- **No Pi-hole local records needed.** `*.home.lab` is deprecated (not a registered TLD).
|
||
|
||
## Caddy (.35)
|
||
1. SSH: `ssh sam@192.168.20.35`
|
||
2. Locate the running Caddy config (Docker container on .35).
|
||
3. Append `deploy/caddy/Caddyfile.snippet` contents to the Caddyfile.
|
||
4. Reload: `docker exec <caddy> caddy reload --config /etc/caddy/Caddyfile`
|
||
5. Verify Caddy can obtain Let's Encrypt certs (ports 80/443 forwarded on router — already working for omniroute/gitea domains).
|
||
|
||
## Host (.13)
|
||
1. Compose project: `/home/sam/Docker/Containers/family-home-lab/` (created during build).
|
||
2. Data: `/mnt/data/family-home-lab/` (garage-data, garage-meta, shared-media, dsh/).
|
||
3. Backup: add `/mnt/data/family-home-lab/` to Borg sources in `/etc/nixos/backup.nix`.
|
||
|
||
## Ports (on .13)
|
||
| Port | Service |
|
||
|---|---|
|
||
| 8500 | Portal (FastAPI) |
|
||
| 8487 | Photopea (→ container 8887) |
|
||
| 8083 | Video editor (kdenlive) — 8081 was taken by airflow-webserver |
|
||
| 8084 | Audio editor (audacity) — 3000 was taken by a NixOS service |
|
||
| 3900/3902 | Garage (S3/admin) |
|
||
| 3081–3084 | dsh instances (other agent) |
|
||
|
||
## Order of operations
|
||
1. Build portal + compose stack (this repo) → `docker compose up -d` on .13
|
||
2. Apply Caddy snippet on .35
|
||
3. Test `https://console.lab.audasmedia.com.au`
|
||
4. Deploy tool containers one at a time, verifying each URL
|
||
5. dsh agent deploys its instances and coordinates token handoff
|
||
|
||
## First run (portal)
|
||
Portal auto-creates the DB tables and, if the users table is empty, seeds the
|
||
admin from `ADMIN_USERNAME`/`ADMIN_PASSWORD` in `.env` (Sam, by default).
|
||
|
||
```bash
|
||
cd /home/sam/Docker/Containers/family-home-lab
|
||
docker compose up -d
|
||
# first admin already created on startup; create the rest in the UI at /admin
|
||
```
|
||
|
||
## Garage provisioning (S3 buckets + access keys)
|
||
After Garage is up, create buckets/keys from inside the container:
|
||
|
||
```bash
|
||
# env for the garage CLI
|
||
G=('docker compose exec -T garage garage --config /etc/garage.toml')
|
||
|
||
# main service key for the portal
|
||
KEY_ID=$($G key import --name portal - <<< "$(cat .env | grep S3_ACCESS | cut -d= -f2)")
|
||
|
||
# buckets
|
||
for b in sam jo harry finn shared-media; do $G bucket create "$b"; done
|
||
# allow the portal key to access every bucket
|
||
for b in sam jo harry finn shared-media; do $G bucket allow --read --write "$b" --key portal; done
|
||
```
|
||
|
||
> Symmetry: ensure S3_ACCESS_KEY/S3_SECRET_KEY in `.env` match what `key import`
|
||
> registers, else portal uploads will 403.
|
||
|
||
## ON/OFF service-controller (ON_OFF.md)
|
||
|
||
Host-side on/off API on `.13`, port **8443** (chosen because it is already in the
|
||
NixOS `networking.firewall.allowedTCPPorts` allowlist — 8091/8092 were taken by
|
||
langgraph-service / photo-dashboard, and 8099 was blocked by the firewall).
|
||
|
||
Files live in `deploy/service-controller/` and copy to `/home/sam/service-controller/` on .13.
|
||
|
||
Install / update:
|
||
|
||
```bash
|
||
# on .27 (this repo), then:
|
||
scp -q deploy/service-controller/service_controller.py \
|
||
deploy/service-controller/services.toml \
|
||
deploy/service-controller/run.sh \
|
||
deploy/service-controller/family-service-controller.service \
|
||
sam@192.168.20.13:/home/sam/service-controller/
|
||
|
||
# on .13:
|
||
cd /home/sam/service-controller
|
||
python3 -m venv .venv # first time only
|
||
./.venv/bin/pip install -q -r requirements.txt # first time only
|
||
cp family-service-controller.service ~/.config/systemd/user/
|
||
systemctl --user daemon-reload
|
||
systemctl --user enable --now family-service-controller.service
|
||
```
|
||
|
||
Secrets:
|
||
- `SC_TOKEN` lives in `/home/sam/.config/environment.d/10-secrets.conf` (git-ignored; run.sh sources it).
|
||
- The portal gets `SC_TOKEN` from its `.env` on .13 (injected at deploy; never committed).
|
||
|
||
Firewall note: the controller binds `0.0.0.0:8443` and is protected by the token.
|
||
Binding only to the docker bridge gateway was dropped because this NixOS box drops
|
||
INPUT from containers to non-allowlisted host listeners; `0.0.0.0` on the already-
|
||
allowed port 8443 is the workable, token-gated compromise.
|
||
|
||
Portal wiring: `docker-compose.yml` sets `SC_URL=http://host.docker.internal:8443`
|
||
and `SC_TOKEN=${SC_TOKEN:-}` on the portal service, with
|
||
`extra_hosts: ["host.docker.internal:192.168.144.1"]` (host-gateway resolves to the
|
||
DOWN docker0 bridge on this box; pinning to the fhl-net gateway works).
|
||
|
||
Verify:
|
||
```bash
|
||
curl -s http://127.0.0.1:8443/health # {"ok":true,...}
|
||
curl -s -H "X-Controller-Token: $SC_TOKEN" http://127.0.0.1:8443/services
|
||
curl -s -X POST -H "X-Controller-Token: $SC_TOKEN" http://127.0.0.1:8443/services/lmms/stop
|
||
```
|