diff --git a/12_euro_office_deployment.md b/12_euro_office_deployment.md new file mode 100644 index 0000000..9624e54 --- /dev/null +++ b/12_euro_office_deployment.md @@ -0,0 +1,279 @@ +# 12 — Euro-Office Deployment (CT 114) + +> Status: **Planned** +> Last updated: 2026-06-12 + +--- + +## Overview + +Euro-Office is an open-source, self-hosted online office suite (compatible with .docx, .xlsx, .pptx). +Docker image: `ghcr.io/euro-office/documentserver:latest` +Released: June 9, 2026. + +Deployed in CT 114 as a privileged Docker LXC, following the standard homelab pattern. +Exposed via nginx (CT 101) at `office.spendlik.sk`, protected by Authelia (CT 102). + +--- + +## Container Spec + +| Property | Value | +|---|---| +| **CT ID** | 114 | +| **Hostname** | euro-office | +| **IP** | 192.168.1.114 | +| **Gateway** | 192.168.1.1 | +| **CPU** | 2 cores | +| **RAM** | 2 GB | +| **Disk** | 20 GB | +| **OS Template** | `debian-13-standard_13.1-2_amd64.tar.zst` | +| **Privileged** | Yes (Docker requirement) | +| **Domain** | office.spendlik.sk | + +--- + +## Phase 1 — Create the LXC Container + +In Proxmox web UI or via `pct` on the Proxmox host: + +```bash +pct create 114 local:vztmpl/debian-13-standard_13.1-2_amd64.tar.zst \ + --hostname euro-office \ + --cores 2 \ + --memory 2048 \ + --swap 512 \ + --net0 name=eth0,bridge=vmbr0,ip=192.168.1.114/24,gw=192.168.1.1 \ + --rootfs local-lvm:20 \ + --unprivileged 0 \ + --features nesting=1 \ + --start 1 \ + --onboot 1 +``` + +> `nesting=1` is required for Docker inside LXC. +> `unprivileged 0` = privileged container. + +--- + +## Phase 2 — Base System Setup + +Enter the container: + +```bash +pct enter 114 +``` + +Update and install essentials: + +```bash +apt update && apt upgrade -y +apt install -y curl nano ca-certificates gnupg lsb-release +``` + +--- + +## Phase 3 — Install Docker + +```bash +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg + +echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \ + https://download.docker.com/linux/debian \ + $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null + +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +Verify: + +```bash +docker run hello-world +``` + +--- + +## Phase 4 — Deploy Euro-Office + +Create the service directory: + +```bash +mkdir -p /opt/euro-office +cd /opt/euro-office +``` + +Create `docker-compose.yml`: + +```yaml +services: + euro-office: + image: ghcr.io/euro-office/documentserver:latest + container_name: euro-office + restart: unless-stopped + ports: + - "80:80" + environment: + - JWT_ENABLED=true + - JWT_SECRET=CHANGE_ME_STRONG_SECRET + volumes: + - ./data:/var/lib/euro-office + - ./logs:/var/log/euro-office +``` + +> ⚠️ Replace `CHANGE_ME_STRONG_SECRET` with a strong random secret before starting. +> Generate one with: `openssl rand -hex 32` + +Start the service: + +```bash +docker compose up -d +docker compose logs -f +``` + +Verify it responds locally: + +```bash +curl -s http://localhost/healthcheck +``` + +Expected: HTTP 200 or a JSON health response (check Euro-Office docs for exact endpoint). + +--- + +## Phase 5 — nginx Reverse Proxy (CT 101) + +On CT 101 (`192.168.1.10`), create `/etc/nginx/sites-available/office.spendlik.sk`: + +```nginx +server { + listen 80; + server_name office.spendlik.sk; + + location / { + proxy_pass http://192.168.1.114:80; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # Euro-Office requires WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # Large file uploads (documents) + client_max_body_size 100m; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} +``` + +Enable and reload: + +```bash +ln -s /etc/nginx/sites-available/office.spendlik.sk /etc/nginx/sites-enabled/ +nginx -t && nginx -s reload +``` + +Test HTTP before adding SSL: + +```bash +curl -I http://office.spendlik.sk # from mobile data only (hairpin NAT limitation) +``` + +--- + +## Phase 6 — SSL Certificate (CT 101) + +```bash +certbot --nginx -d office.spendlik.sk +``` + +⚠️ **Always manually inspect the config after certbot runs:** + +```bash +nano /etc/nginx/sites-available/office.spendlik.sk +``` + +Check for: +- Duplicate `server_name` directives +- Missing closing braces +- Correct `proxy_pass` still pointing to `192.168.1.114:80` +- WebSocket headers (`Upgrade`, `Connection`) preserved in both HTTP and HTTPS blocks + +Reload after any manual fix: + +```bash +nginx -t && nginx -s reload +``` + +--- + +## Phase 7 — Authelia Protection (CT 102) + +Add `office.spendlik.sk` to Authelia's access control rules in CT 102. + +In `/etc/authelia/configuration.yml` on CT 102, add under `access_control.rules`: + +```yaml +- domain: office.spendlik.sk + policy: two_factor +``` + +Restart Authelia: + +```bash +systemctl restart authelia +``` + +Add the Authelia middleware to the nginx vhost in CT 101. +Refer to the existing pattern used for `automation.spendlik.sk` (CT 100) or `email.spendlik.sk` (CT 104) as the template. + +--- + +## Phase 8 — DNS Record (WebSupport) + +Add an A record for `office.spendlik.sk` pointing to the public IP (`178.41.205.8`) via the WebSupport DNS panel. + +⚠️ WebSupport has **two separate DNS management pages** — update both to avoid a repeat of the previous outage. + +Service ID for API operations: `15056760` + +--- + +## Post-Deployment Checklist + +- [ ] Container starts on boot (`onboot=1` confirmed in Proxmox) +- [ ] Docker service starts on container boot (`restart: unless-stopped`) +- [ ] `office.spendlik.sk` loads over HTTPS from mobile data +- [ ] Authelia 2FA prompt appears before reaching the office suite +- [ ] Document open/edit/save works end-to-end +- [ ] JWT secret changed from placeholder value +- [ ] nginx config inspected post-certbot (no duplicates, no missing braces) +- [ ] `homelab-overview.md` updated with CT 114 entry +- [ ] `00_index.md` updated — CT 114 row and next available ID bumped + +--- + +## Troubleshooting + +| Symptom | Likely Cause | Fix | +|---|---|---| +| WebSocket errors / real-time editing broken | Missing `Upgrade`/`Connection` headers in nginx | Re-add WebSocket proxy headers, reload nginx | +| 502 Bad Gateway | Euro-Office container not responding | `docker compose logs` in CT 114; check if container is up | +| Large file upload fails | `client_max_body_size` too small | Increase to `200m` or higher in nginx vhost | +| Slow document loading | Insufficient RAM | Increase CT 114 RAM allocation in Proxmox | +| certbot breaks config | Known issue on this setup | Manually restore WebSocket headers and proxy_pass after cert issuance | + +--- + +## Notes + +- Euro-Office is a relatively new project (released June 2026) — check the [GitHub repo](https://github.com/euro-office/documentserver) for breaking changes before upgrading the Docker image. +- The JWT secret must match if you integrate Euro-Office with other tools (e.g., Nextcloud or a future document portal). Keep the secret backed up. +- Docker image tag: always pull `latest` for now; consider pinning to a specific version tag once the project stabilises.