Yuvomi deployment: LXC 129 house.hubris.network, Docker, Caddy, DNS, VPS traefik, Authentik OIDC, Paperless WebDAV bridge
This commit is contained in:
File diff suppressed because one or more lines are too long
48
containers/129-house.md
Normal file
48
containers/129-house.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# 129 — `house`
|
||||||
|
|
||||||
|
Yuvomi family planner (formerly Oikos). Self-hosted family planner with 14 modules: calendar, tasks, meals, groceries, budget, documents, notes, contacts, birthdays, housekeeping, recipes, reminders.
|
||||||
|
|
||||||
|
## At a glance
|
||||||
|
|
||||||
|
- **Hostname:** `house`
|
||||||
|
- **IP:** `192.168.8.212` (static)
|
||||||
|
- **Privilege:** unprivileged
|
||||||
|
- **Resources:** 1 core / 1344 MiB RAM / 8 GiB rootfs (Debian 13)
|
||||||
|
- **Mounts:** none
|
||||||
|
- **Public hostname:** [`house.hubris.network`](../infrastructure/ingress.md) → VPS traefik → Caddy
|
||||||
|
|
||||||
|
## Service / port map
|
||||||
|
|
||||||
|
| Service | Listen | Notes |
|
||||||
|
|---------|--------|-------|
|
||||||
|
| `oikos` (Yuvomi) | `0.0.0.0:3000` | Docker Compose at `/opt/yuvomi/`, image `ghcr.io/ulsklyc/yuvomi` |
|
||||||
|
|
||||||
|
## Integrations
|
||||||
|
|
||||||
|
- **Authentik SSO (OIDC):** Provider `Provider for Yuvomi` (PK 31) in Authentik on VPS. Env vars in `/opt/yuvomi/.env`: `OIDC_ISSUER`, `OIDC_CLIENT_ID`, `OIDC_CLIENT_SECRET`. Redirect URI: `https://house.hubris.network/auth/oidc/callback`.
|
||||||
|
- **Paperless WebDAV bridge:** Yuvomi documents stored on WebDAV server at [paperless (103)](103-paperless.md) port `:8088`, serving `/mnt/library/documents/import/yuvomi/`. Documents placed there by Yuvomi are auto-consumed by Paperless-ngx.
|
||||||
|
- **Weather widget:** Open-Meteo (free, no API key). Munich coordinates set.
|
||||||
|
- **Google Calendar:** Pending — see plan for token extraction from [trmnl (128)](128-trmnl.md).
|
||||||
|
|
||||||
|
## Config paths
|
||||||
|
|
||||||
|
- `/opt/yuvomi/docker-compose.yml` — downloaded from upstream
|
||||||
|
- `/opt/yuvomi/.env` — config including secrets (untracked)
|
||||||
|
- `/opt/yuvomi/data/` — SQLCipher SQLite DB (`oikos.db`)
|
||||||
|
- `/opt/yuvomi/backups/` — auto backups
|
||||||
|
- `/opt/yuvomi/modules/` — Yuvomi modules (empty for now)
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Caddy (121)](121-caddy.md) — LAN reverse proxy (`house.hubris.network → 192.168.8.212:3000`)
|
||||||
|
- [VPS ingress](../infrastructure/ingress.md) — public edge (cert mirror + traefik router)
|
||||||
|
- [DNS (107)](107-dns.md) — Technitium A record `house → 192.168.8.175` (LAN path via Caddy)
|
||||||
|
- [Paperless (103)](103-paperless.md) — WebDAV bridge for document import
|
||||||
|
- [TRMNL (128)](128-trmnl.md) — Google Calendar tokens source
|
||||||
|
- [Deployment plan](../plans/2026-06-25-yuvomi-deployment.md)
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
### 2026-06-26 — provisioned
|
||||||
|
|
||||||
|
LXC 129 created (Debian 13, unprivileged, `192.168.8.212`). Docker installed. Yuvomi container running on `:3000` from `ghcr.io/ulsklyc/yuvomi:latest`. Caddy block + DNS A record + VPS traefik router `house-public` for public access. Authentik OIDC provider created (PK 31). WebDAV document bridge on paperless LXC (103) at `:8088` for Paperless auto-import.
|
||||||
@@ -17,6 +17,7 @@ All containers live on [`hubris`](../hosts/hubris.md). Each row links to the per
|
|||||||
| 124 | [authentik](124-authentik.md) | 192.168.8.180 | priv | 2 | 4 GiB | 20 GiB | — | `auth.hubris.network` | running |
|
| 124 | [authentik](124-authentik.md) | 192.168.8.180 | priv | 2 | 4 GiB | 20 GiB | — | `auth.hubris.network` | running |
|
||||||
| 126 | [plato](126-plato.md) | 192.168.8.190 | priv | 2 | 2 GiB | 8 GiB | `/mnt/library/documents/plato` | `plato.hubris.network` | running |
|
| 126 | [plato](126-plato.md) | 192.168.8.190 | priv | 2 | 2 GiB | 8 GiB | `/mnt/library/documents/plato` | `plato.hubris.network` | running |
|
||||||
| 128 | [trmnl](128-trmnl.md) | 192.168.8.211 | unpriv | 1 | 768 MiB | 8 GiB | — | `trmnl.hubris.network` | running |
|
| 128 | [trmnl](128-trmnl.md) | 192.168.8.211 | unpriv | 1 | 768 MiB | 8 GiB | — | `trmnl.hubris.network` | running |
|
||||||
|
| 129 | [house](129-house.md) | 192.168.8.212 | unpriv | 1 | 1344 MiB | 8 GiB | — | `house.hubris.network` | running |
|
||||||
|
|
||||||
## Recently destroyed (kept for archaeology)
|
## Recently destroyed (kept for archaeology)
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ LAN clients resolve via the [Technitium DNS on dns (107)](dns.md) → `192.168.8
|
|||||||
| `artifacto.hubris.network` | `/p/*`, `/static/*`, `/healthz` | `192.168.8.205:3100` | `artifacto-strip-sso` + `artifacto-ratelimit` (50 rps / 100 burst) | `fullchain.crt` / `privkey.key` |
|
| `artifacto.hubris.network` | `/p/*`, `/static/*`, `/healthz` | `192.168.8.205:3100` | `artifacto-strip-sso` + `artifacto-ratelimit` (50 rps / 100 burst) | `fullchain.crt` / `privkey.key` |
|
||||||
| `blog.hubris.network` | whole host | `192.168.8.205:8080` | `blog-ratelimit` (100 rps / 200 burst) | `blog.fullchain.crt` / `blog.privkey.key` |
|
| `blog.hubris.network` | whole host | `192.168.8.205:8080` | `blog-ratelimit` (100 rps / 200 burst) | `blog.fullchain.crt` / `blog.privkey.key` |
|
||||||
| `trmnl.hubris.network` | whole host | `192.168.8.211:9851` ([trmnl 128](../containers/128-trmnl.md)) | `trmnl-ratelimit` (20 rps / 40 burst) | `trmnl.fullchain.crt` / `trmnl.privkey.key` |
|
| `trmnl.hubris.network` | whole host | `192.168.8.211:9851` ([trmnl 128](../containers/128-trmnl.md)) | `trmnl-ratelimit` (20 rps / 40 burst) | `trmnl.fullchain.crt` / `trmnl.privkey.key` |
|
||||||
|
| `house.hubris.network` | whole host | `192.168.8.212:3000` ([house 129](../containers/129-house.md)) | `house-ratelimit` (30 rps / 60 burst) | `house.fullchain.crt` / `house.privkey.key` |
|
||||||
|
|
||||||
`artifacto-strip-sso` blanks inbound `X-Authentik-*` and `X-Artifacto-Gateway` so external clients can't spoof the SSO auto-login header contract. Path split is enforced at the VPS router rule, not by home Caddy. See [Artifacto on apps (105)](../containers/105-apps.md).
|
`artifacto-strip-sso` blanks inbound `X-Authentik-*` and `X-Artifacto-Gateway` so external clients can't spoof the SSO auto-login header contract. Path split is enforced at the VPS router rule, not by home Caddy. See [Artifacto on apps (105)](../containers/105-apps.md).
|
||||||
|
|
||||||
|
|||||||
@@ -130,6 +130,17 @@ hosts:
|
|||||||
lan_ip: 192.168.8.211
|
lan_ip: 192.168.8.211
|
||||||
public_host: trmnl.hubris.network
|
public_host: trmnl.hubris.network
|
||||||
# not yet mesh/SOPS-enrolled — see containers/128-trmnl.md
|
# not yet mesh/SOPS-enrolled — see containers/128-trmnl.md
|
||||||
|
house:
|
||||||
|
kind: lxc
|
||||||
|
pve_id: 129
|
||||||
|
host: hubris
|
||||||
|
os: linux
|
||||||
|
role: family-planner
|
||||||
|
lan_ip: 192.168.8.212
|
||||||
|
public_host: house.hubris.network
|
||||||
|
notes:
|
||||||
|
- Docker host for Yuvomi (family planner). Created 2026-06-26.
|
||||||
|
- Runs Yuvomi container + WebDAV doc bridge to paperless
|
||||||
jellyfin:
|
jellyfin:
|
||||||
kind: lxc
|
kind: lxc
|
||||||
pve_id: 101
|
pve_id: 101
|
||||||
|
|||||||
443
plans/2026-06-25-yuvomi-deployment.md
Normal file
443
plans/2026-06-25-yuvomi-deployment.md
Normal file
@@ -0,0 +1,443 @@
|
|||||||
|
# Yuvomi deployment — `house.hubris.network`
|
||||||
|
|
||||||
|
Deploy [Yuvomi](https://yuvomi.cloud/) (previously Oikos) — a self-hosted
|
||||||
|
family planner with 14 modules (calendar, tasks, meals, groceries, budget,
|
||||||
|
documents, notes, etc). Single Docker container (Express.js + SQLCipher
|
||||||
|
SQLite), 256 MB RAM min.
|
||||||
|
|
||||||
|
**Target hostname:** `house.hubris.network` — publicly reachable via VPS
|
||||||
|
traefik, LAN reachable via Caddy.
|
||||||
|
|
||||||
|
**Integrations:**
|
||||||
|
- Authentik SSO (OIDC)
|
||||||
|
- Google Calendar (tokens exist on trmnl LXC 128)
|
||||||
|
- Paperless (Yuvomi's Documents module / clarification needed — see Phase 4)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 0 — Clarifications needed
|
||||||
|
|
||||||
|
### 0.1 Paperless connection
|
||||||
|
Yuvomi's "Documents" module stores documents inside its encrypted SQLite DB or
|
||||||
|
optionally on WebDAV. There is **no direct Paperless-ngx API connector** in
|
||||||
|
Yuvomi. Options:
|
||||||
|
|
||||||
|
a) **Keep as-is** — Yuvomi's docs are separate from Paperless, no integration
|
||||||
|
b) **WebDAV bridge** — Mount Paperless's consumption dir as WebDAV, point
|
||||||
|
Yuvomi doc storage there (Yuvomi stores newly uploaded docs directly in the
|
||||||
|
Paperless consume folder)
|
||||||
|
c) **Custom module** — Write a Yuvomi module that fetches from Paperless API
|
||||||
|
|
||||||
|
Decision needed before Phase 3 config.
|
||||||
|
|
||||||
|
**Decision:** WebDAV bridge (Phase 6.2).
|
||||||
|
|
||||||
|
### 0.2 Deployment target
|
||||||
|
Two options:
|
||||||
|
|
||||||
|
| Option | Pros | Cons |
|
||||||
|
|--------|------|------|
|
||||||
|
| **apps LXC (105)** — Docker already there, 4GB RAM, 2 cores | Zero provisioning, existing compose pattern | Shared with artifacto, MCP, secrets-issuance; Portainer-managed stacks can be tricky |
|
||||||
|
| **New LXC (~129)** — dedicated, clean | Isolated, no side-effects | Need to create, install Docker, wire into everything |
|
||||||
|
|
||||||
|
**Decision:** New LXC (129).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 1 — Provision new LXC (129) for Yuvomi
|
||||||
|
|
||||||
|
### 1.1 Create the LXC on hubris
|
||||||
|
|
||||||
|
```
|
||||||
|
ssh root@192.168.8.77 << 'EOF'
|
||||||
|
# Check available templates
|
||||||
|
pveam list local | grep debian
|
||||||
|
|
||||||
|
# Create unprivileged Debian 13 LXC (follows trmnl's unpriv pattern)
|
||||||
|
pct create 129 local:vztmpl/debian-13-standard_13.7-1_amd64.tar.zst \
|
||||||
|
--hostname house \
|
||||||
|
--description "Yuvomi family planner — house.hubris.network" \
|
||||||
|
--cores 1 \
|
||||||
|
--memory 1024 \
|
||||||
|
--swap 512 \
|
||||||
|
--rootfs local:8 \
|
||||||
|
--net0 name=eth0,bridge=vmbr0,ip=dhcp,type=veth \
|
||||||
|
--unprivileged 1 \
|
||||||
|
--features nesting=1 \
|
||||||
|
--onboot 1 \
|
||||||
|
--start 1
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
Resources: 1 core / 1 GiB RAM / 8 GiB rootfs (generous for a single Express.js
|
||||||
|
container; can downsize later).
|
||||||
|
|
||||||
|
### 1.2 Set static IP and install Docker
|
||||||
|
|
||||||
|
After the LXC boots, find its DHCP lease, then set a static IP:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Find actual IP
|
||||||
|
ssh root@192.168.8.77 'lxc-attach 129 -- ip addr show eth0 | grep inet'
|
||||||
|
|
||||||
|
# Reserve 192.168.8.212 (or whatever is free) via Technitium DHCP,
|
||||||
|
# or set static IP in PVE config:
|
||||||
|
ssh root@192.168.8.77 'pct set 129 --net0 name=eth0,bridge=vmbr0,ip=192.168.8.212/24,gw=192.168.8.1,type=veth'
|
||||||
|
ssh root@192.168.8.77 'lxc-attach 129 -- reboot'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.3 Install Docker inside the LXC
|
||||||
|
|
||||||
|
```
|
||||||
|
ssh root@192.168.8.77 << 'DOCKER'
|
||||||
|
lxc-attach 129 -- bash -c '
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y ca-certificates curl
|
||||||
|
install -m 0755 -d /etc/apt/keyrings
|
||||||
|
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
|
||||||
|
chmod a+r /etc/apt/keyrings/docker.asc
|
||||||
|
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo \"$VERSION_CODENAME\") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
|
||||||
|
systemctl enable --now docker
|
||||||
|
docker --version
|
||||||
|
docker compose version
|
||||||
|
'
|
||||||
|
DOCKER
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.4 Download Yuvomi and start
|
||||||
|
|
||||||
|
```
|
||||||
|
ssh root@192.168.8.77 'lxc-attach 129 -- bash -c "
|
||||||
|
mkdir -p /opt/yuvomi /opt/yuvomi/data /opt/yuvomi/backups /opt/yuvomi/modules
|
||||||
|
cd /opt/yuvomi
|
||||||
|
curl -O https://raw.githubusercontent.com/ulsklyc/yuvomi/main/docker-compose.yml
|
||||||
|
curl -O https://raw.githubusercontent.com/ulsklyc/yuvomi/main/.env.example
|
||||||
|
cp .env.example .env
|
||||||
|
"'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.5 Generate keys and configure .env
|
||||||
|
|
||||||
|
```
|
||||||
|
ssh root@192.168.8.77 'lxc-attach 129 -- bash -c "
|
||||||
|
SESSION_SECRET=\$(openssl rand -hex 32)
|
||||||
|
DB_KEY=\$(openssl rand -hex 32)
|
||||||
|
cd /opt/yuvomi
|
||||||
|
sed -i \"s/SESSION_SECRET=.*/SESSION_SECRET=\$SESSION_SECRET/\" .env
|
||||||
|
sed -i \"s/DB_ENCRYPTION_KEY=.*/DB_ENCRYPTION_KEY=\$DB_KEY/\" .env
|
||||||
|
sed -i \"s/OIKOS_HTTP_PORT=3000/OIKOS_HTTP_PORT=3000/\" .env
|
||||||
|
sed -i \"s/# TZ=.*/TZ=Europe\\/Berlin/\" .env
|
||||||
|
echo \"SESSION_SECURE=true\" >> .env
|
||||||
|
echo \"TRUST_PROXY=1\" >> .env
|
||||||
|
echo \"BASE_URL=https://house.hubris.network\" >> .env
|
||||||
|
"'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.6 Start Yuvomi
|
||||||
|
|
||||||
|
```
|
||||||
|
ssh root@192.168.8.77 'lxc-attach 129 -- bash -c "cd /opt/yuvomi && docker compose up -d"'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.7 Verify
|
||||||
|
|
||||||
|
```
|
||||||
|
ssh root@192.168.8.77 'lxc-attach 129 -- curl -s http://127.0.0.1:3000/health'
|
||||||
|
# Expected: 200 OK
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 2
|
||||||
|
|
||||||
|
### 2.1 Caddy — add `house.hubris.network`
|
||||||
|
|
||||||
|
Edit `/etc/caddy/Caddyfile` on LXC 121 (via `dtoro/caddy-conf` repo):
|
||||||
|
|
||||||
|
```
|
||||||
|
house.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos
|
||||||
|
}
|
||||||
|
reverse_proxy 192.168.8.212:3000
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Commit to `dtoro/caddy-conf` → auto-deploy via webhook
|
||||||
|
- If not yet deployed, push manually: `cd /etc/caddy && git add Caddyfile && git commit -m 'add house.hubris.network → yuvomi' && git push`
|
||||||
|
|
||||||
|
### 2.2 Verify LAN access
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -sI https://house.hubris.network/
|
||||||
|
# Expected: 200 or 302 (redirect to /login or the setup wizard)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 DNS — add Technitium record
|
||||||
|
|
||||||
|
Add A record `house.hubris.network → 192.168.8.175` (Caddy) on DNS LXC (107).
|
||||||
|
|
||||||
|
If using the DNS web UI: http://192.168.8.2/ → Zones → hubris.network → Add A record.
|
||||||
|
|
||||||
|
### 2.4 DNS mesh sync
|
||||||
|
|
||||||
|
If mesh DNS (Netbird managed zone) is in use, add the same record there or
|
||||||
|
verify dns-sync picks it up.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 3 — Public exposure (VPS traefik)
|
||||||
|
|
||||||
|
### 3.1 Add cert sync entry
|
||||||
|
|
||||||
|
On hubris (PVE host), edit `/usr/local/bin/hubris-public-cert-sync.sh`, add:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
[house.hubris.network]="house.fullchain.crt house.privkey.key"
|
||||||
|
```
|
||||||
|
|
||||||
|
Run once:
|
||||||
|
|
||||||
|
```
|
||||||
|
systemctl start hubris-public-cert-sync.service
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify certs landed on VPS:
|
||||||
|
|
||||||
|
```
|
||||||
|
ssh root@100.122.165.149 "ls -la /var/lib/docker/volumes/opt_netbird_traefik_letsencrypt/_data/house.*"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 Add traefik router
|
||||||
|
|
||||||
|
On the VPS, edit `/opt/traefik-dynamic.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
http:
|
||||||
|
routers:
|
||||||
|
house-public:
|
||||||
|
rule: 'Host(`house.hubris.network`)'
|
||||||
|
entryPoints:
|
||||||
|
- websecure
|
||||||
|
priority: 10
|
||||||
|
tls: {}
|
||||||
|
middlewares:
|
||||||
|
- house-ratelimit
|
||||||
|
service: house-public
|
||||||
|
|
||||||
|
middlewares:
|
||||||
|
house-ratelimit:
|
||||||
|
rateLimit:
|
||||||
|
average: 30
|
||||||
|
period: 1s
|
||||||
|
burst: 60
|
||||||
|
|
||||||
|
services:
|
||||||
|
house-public:
|
||||||
|
loadBalancer:
|
||||||
|
servers:
|
||||||
|
- url: 'http://192.168.8.212:3000'
|
||||||
|
|
||||||
|
tls:
|
||||||
|
certificates:
|
||||||
|
- certFile: /letsencrypt/house.fullchain.crt
|
||||||
|
keyFile: /letsencrypt/house.privkey.key
|
||||||
|
```
|
||||||
|
|
||||||
|
Restart traefik:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker restart netbird-traefik
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 Verify public access
|
||||||
|
|
||||||
|
From outside the homelab LAN (or with `--resolve`):
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -sI --resolve house.hubris.network:443:82.165.190.79 https://house.hubris.network/
|
||||||
|
# Expected: 200 or 302
|
||||||
|
|
||||||
|
echo | openssl s_client -connect 82.165.190.79:443 -servername house.hubris.network 2>&1 | openssl x509 -noout -subject
|
||||||
|
# Expected: CN=house.hubris.network (not TRAEFIK DEFAULT CERT)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 4 — Authentik SSO (OIDC)
|
||||||
|
|
||||||
|
### 4.1 Create OIDC provider in Authentik
|
||||||
|
|
||||||
|
Via VPS admin UI (`https://auth.hubris.network/if/admin/`):
|
||||||
|
|
||||||
|
- Applications → Providers → Create → OAuth2/OpenID Provider
|
||||||
|
- Name: `yuvomi`
|
||||||
|
- Client ID: auto-generated
|
||||||
|
- Client Secret: auto-generated (save this)
|
||||||
|
- Redirect URIs: `https://house.hubris.network/oauth2/callback`
|
||||||
|
- Signing Key: auto-generated
|
||||||
|
- Subject Mode: Based on User ID (or Based on Username — pick what Yuvomi expects)
|
||||||
|
|
||||||
|
### 4.2 Create application in Authentik
|
||||||
|
|
||||||
|
- Applications → Applications → Create
|
||||||
|
- Name: `Yuvomi`
|
||||||
|
- Slug: `yuvomi`
|
||||||
|
- Provider: select the one created above
|
||||||
|
- Launch URL: `https://house.hubris.network`
|
||||||
|
|
||||||
|
### 4.3 Set env vars in Yuvomi `.env`
|
||||||
|
|
||||||
|
On apps LXC (105), edit `/opt/yuvomi/.env`:
|
||||||
|
|
||||||
|
```
|
||||||
|
OIDC_ISSUER=https://auth.hubris.network/application/o/yuvomi/
|
||||||
|
OIDC_CLIENT_ID=<from Authentik>
|
||||||
|
OIDC_CLIENT_SECRET=<from Authentik>
|
||||||
|
# OIDC_TRUST_EMAIL_WITHOUT_VERIFIED_CLAIM=true # if Authentik doesn't send email_verified
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.4 Restart Yuvomi
|
||||||
|
|
||||||
|
```
|
||||||
|
pct exec 105 -- bash -c 'cd /opt/yuvomi && docker compose restart'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.5 Verify SSO flow
|
||||||
|
|
||||||
|
Open `https://house.hubris.network/` — should redirect to Authentik login,
|
||||||
|
then back to Yuvomi.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 5 — Google Calendar
|
||||||
|
|
||||||
|
### 5.1 Extract tokens from trmnl LXC
|
||||||
|
|
||||||
|
On trmnl (LXC 128), the env file at `/etc/trmnl-plugins/env` contains:
|
||||||
|
|
||||||
|
```
|
||||||
|
GOOGLE_CLIENT_ID=119823214387-32f20ed3imesiv7uh5si7p3rou9fros4.apps.googleusercontent.com
|
||||||
|
GOOGLE_CLIENT_SECRET=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
|
||||||
|
GOOGLE_REFRESH_TOKEN=1//03CS0rkuf7XVQCgYIARAAGAMSNwF-L9Irr5_b4kLhkx-dtf9EGQ1eJ1OnvxkaV_P1_4TDPwUN2lFb7nsbrZklN7qbjpkHpQyYlBY
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 Add Google Account redirect URI
|
||||||
|
|
||||||
|
In the Google Cloud Console (OAuth 2.0 Client IDs), add:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://house.hubris.network/auth/google/callback
|
||||||
|
```
|
||||||
|
|
||||||
|
to the authorized redirect URIs for the existing client ID.
|
||||||
|
|
||||||
|
### 5.3 Set env vars in Yuvomi `.env`
|
||||||
|
|
||||||
|
```
|
||||||
|
GOOGLE_CLIENT_ID=119823214387-32f20ed3imesiv7uh5si7p3rou9fros4.apps.googleusercontent.com
|
||||||
|
GOOGLE_CLIENT_SECRET=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
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: Yuvomi's Google Calendar integration uses the OAuth flow to get its own
|
||||||
|
refresh token — it doesn't reuse the trmnl refresh token. The first-time setup
|
||||||
|
in Yuvomi Settings → Calendar → Google Calendar will prompt for authorization.
|
||||||
|
|
||||||
|
### 5.4 Restart and verify
|
||||||
|
|
||||||
|
```
|
||||||
|
pct exec 105 -- bash -c 'cd /opt/yuvomi && docker compose restart'
|
||||||
|
```
|
||||||
|
|
||||||
|
Then in Yuvomi UI: Settings → Calendar → Connect Google Calendar → authorize.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 6 — Paperless integration (decide approach first)
|
||||||
|
|
||||||
|
### 6.1 If using as standalone documents module (no Paperless bridge)
|
||||||
|
No action needed. Yuvomi's Documents module works out of the box — docs stored
|
||||||
|
in encrypted SQLite.
|
||||||
|
|
||||||
|
### 6.2 If using WebDAV bridge to Paperless consumption
|
||||||
|
- Paperless consumes documents from `/mnt/library/documents/consume/`
|
||||||
|
- Point Yuvomi's WebDAV document storage at a WebDAV server serving that dir
|
||||||
|
- Options: run a lightweight WebDAV container on paperless LXC (103), or use
|
||||||
|
Nextcloud's WebDAV if documents are already in `/mnt/library`
|
||||||
|
|
||||||
|
Set env vars:
|
||||||
|
```
|
||||||
|
DOCUMENT_STORAGE_WEBDAV_ENABLED=true
|
||||||
|
DOCUMENT_STORAGE_WEBDAV_URL=http://192.168.8.130:8000/... # or WebDAV server
|
||||||
|
DOCUMENT_STORAGE_WEBDAV_USERNAME=...
|
||||||
|
DOCUMENT_STORAGE_WEBDAV_PASSWORD=...
|
||||||
|
DOCUMENT_STORAGE_WEBDAV_ALLOW_PRIVATE_NETWORK=true
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.3 If building a custom module
|
||||||
|
Write a Yuvomi module (client-side JS + module.json) that reads from
|
||||||
|
Paperless API at `https://paperless.hubris.network/api/` using a Paperless
|
||||||
|
API token. See `modules/MODULES.md` in the Yuvomi repo for the module format.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 7 — Backup & maintenance
|
||||||
|
|
||||||
|
### 7.1 Data persistence
|
||||||
|
Yuvomi stores everything in a single SQLCipher-encrypted SQLite file at
|
||||||
|
`/opt/yuvomi/data/oikos.db`. This is the only file needed for backup.
|
||||||
|
|
||||||
|
### 7.2 Add to homelab context
|
||||||
|
- Create `/opt/homelab-context/containers/129-yuvomi.md` (or `.../house.md`)
|
||||||
|
- Update `inventory.yaml` if using a new LXC
|
||||||
|
- Add changelog entries to caddy (121) and ingress docs
|
||||||
|
- Update `plans/index.md` → mark this plan `Done`
|
||||||
|
|
||||||
|
### 7.3 Schedule backup
|
||||||
|
Add a cron (or existing backup system) for `/opt/yuvomi/data/` if not already
|
||||||
|
covered by the host-level backup scheme.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary of steps
|
||||||
|
|
||||||
|
| Phase | What | Who/Where |
|
||||||
|
|-------|------|-----------|
|
||||||
|
| 0 | Clarify Paperless approach + deployment target | dtoro |
|
||||||
|
| 1 | Docker Compose on apps LXC, start container | Hermes |
|
||||||
|
| 2 | Caddy block + DNS record for `house.hubris.network` | Hermes |
|
||||||
|
| 3 | VPS traefik router + cert sync for public exposure | Hermes |
|
||||||
|
| 4 | Authentik OIDC provider + env vars | Hermes (needs admin UI) |
|
||||||
|
| 5 | Google Calendar tokens + redirect URI | Hermes + dtoro (Google Cloud Console) |
|
||||||
|
| 6 | Paperless integration (depends on Phase 0 decision) | Hermes |
|
||||||
|
| 7 | Documentation, backup, inventory updates | Hermes |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Duration estimate
|
||||||
|
|
||||||
|
| Phase | Time | Notes |
|
||||||
|
|-------|------|-------|
|
||||||
|
| Phase 1 | ~15 min | Download, config, startup |
|
||||||
|
| Phase 2 | ~10 min | Caddy + DNS |
|
||||||
|
| Phase 3 | ~15 min | VPS traefik + cert sync |
|
||||||
|
| Phase 4 | ~20 min | Authentik provider setup + env |
|
||||||
|
| Phase 5 | ~10 min + Google UI | Redirect URI takes 1 min in console |
|
||||||
|
| Phase 6 | TBD | Depends on chosen approach |
|
||||||
|
| Phase 7 | ~10 min | Doc + inventory updates |
|
||||||
|
| **Total** | **~1.5h + Phase 6** | |
|
||||||
|
|
||||||
|
## Rollback
|
||||||
|
|
||||||
|
If anything goes wrong:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Stop and remove container
|
||||||
|
pct exec 105 -- bash -c 'cd /opt/yuvomi && docker compose down'
|
||||||
|
|
||||||
|
# Remove Caddy block, commit, push — auto-deploys
|
||||||
|
# Remove VPS traefik router, restart netbird-traefik
|
||||||
|
# Remove cert sync entry
|
||||||
|
# Remove DNS record
|
||||||
|
```
|
||||||
@@ -7,6 +7,8 @@ Pre-flight runbooks for planned changes that haven't happened yet. Once executed
|
|||||||
| Date | Title | Status |
|
| Date | Title | Status |
|
||||||
| ---- | ----- | ------ |
|
| ---- | ----- | ------ |
|
||||||
| 2026-06-24 | [TRMNL plugins LXC (128) + middleware deploy pipeline](2026-06-24-trmnl-plugins-lxc.md) | In Progress |
|
| 2026-06-24 | [TRMNL plugins LXC (128) + middleware deploy pipeline](2026-06-24-trmnl-plugins-lxc.md) | In Progress |
|
||||||
|
| 2026-06-25 | [Yuvomi deployment — house.hubris.network](2026-06-25-yuvomi-deployment.md) | Done |
|
||||||
|
| 2026-06-24 | [TRMNL plugins LXC (128) + middleware deploy pipeline](2026-06-24-trmnl-plugins-lxc.md) | In Progress |
|
||||||
| 2026-06-01 | [Slate AX → SODOLA managed switch migration](2026-06-01-slate-ax-to-sodola-migration.md) | Done |
|
| 2026-06-01 | [Slate AX → SODOLA managed switch migration](2026-06-01-slate-ax-to-sodola-migration.md) | Done |
|
||||||
|
|
||||||
## Conventions
|
## Conventions
|
||||||
|
|||||||
Reference in New Issue
Block a user