# Cloud Elves Infrastructure Overview ## Architecture All services run on a single DigitalOcean VPS (`box.cloud-elves.eu`, Debian 13) managed by Ansible and deployed as Docker Compose containers. ### Services | Service | URL | Purpose | |---|---|---| | Caddy | (internal) | Reverse proxy, automatic HTTPS via Let's Encrypt | | Gitea | https://git.cloud-elves.eu | Git hosting, SSH clone on port 2222 | | Outline | https://docs.cloud-elves.eu | Wiki and documentation | | Dex | https://auth.cloud-elves.eu | OIDC identity provider | | LLDAP | https://ldap.cloud-elves.eu | User directory with web UI | | Static site | https://cloud-elves.eu | Company website (also www) | ### Supporting Services (internal only) | Service | Used by | |---|---| | Gitea Runner (act_runner) | Gitea Actions CI/CD — runs pipelines | | Postgres (gitea-db) | Gitea | | Postgres (outline-db) | Outline | | Redis | Outline (caching/sessions) | ### How a request reaches your app ```mermaid sequenceDiagram participant Browser participant Caddy participant App as Gitea / Outline / etc. Browser->>Caddy: HTTPS request (port 443) Note over Caddy: Terminates TLS
Auto-issued Let's Encrypt cert Caddy->>App: Forward to internal port App-->>Caddy: Response Caddy-->>Browser: HTTPS response ``` ## Authentication All authentication flows through a centralized identity stack. ### SSO Login Flow ```mermaid sequenceDiagram participant User participant App as Gitea / Outline participant Dex as Dex (OIDC) participant LLDAP as LLDAP (Directory) User->>App: Visit app App->>Dex: Redirect to SSO Dex->>User: Show login form User->>Dex: Enter credentials Dex->>LLDAP: Verify credentials LLDAP-->>Dex: OK Dex-->>App: Auth token App-->>User: Logged in ``` ### Onboarding a new team member 1. Create their account in LLDAP (https://ldap.cloud-elves.eu) 2. They can immediately log into all services via SSO — accounts are auto-created on first login ### Removing a team member 1. Delete or disable the user in LLDAP 2. Their SSO sessions will expire (existing sessions may persist until token expiry) ## Networking ### Exposed Ports | Port | Protocol | Service | |---|---|---| | 22 | TCP | SSH (host access) | | 80 | TCP | HTTP (redirects to HTTPS) | | 443 | TCP + UDP | HTTPS (all web services) | | 2222 | TCP | Gitea SSH (git clone) | All other communication happens over internal Docker networks. UFW firewall blocks everything else. ### Internal Networks | Network | Connects | |---|---| | frontend | Caddy to all web-facing services | | identity | Dex to LLDAP | | gitea-backend | Gitea to its Postgres | | outline-backend | Outline to its Postgres and Redis | ## DNS Records | Record | Type | Points to | |---|---|---| | `cloud-elves.eu` | A | 188.166.60.12 | | `box.cloud-elves.eu` | A | 188.166.60.12 | | `www.cloud-elves.eu` | CNAME | box.cloud-elves.eu | | `git.cloud-elves.eu` | CNAME | box.cloud-elves.eu | | `auth.cloud-elves.eu` | CNAME | box.cloud-elves.eu | | `ldap.cloud-elves.eu` | CNAME | box.cloud-elves.eu | | `docs.cloud-elves.eu` | CNAME | box.cloud-elves.eu | ## Data & Persistence All persistent data is in Docker named volumes under `/var/lib/docker/volumes/` on the host. Docker Compose prefixes them with `services_` (e.g. `services_gitea-data`). | Volume | Contains | Backed up? | |---|---|---| | `lldap-data` | User directory (SQLite) | Yes | | `dex-data` | Dex auth database (SQLite) | Yes | | `gitea-data` | Git repositories, Gitea config | Yes | | `gitea-db` | Gitea Postgres data | Yes | | `outline-data` | Uploaded files/attachments | Yes | | `outline-db` | Outline Postgres data | Yes | | `caddy-data` | TLS certificates | No — re-issued automatically | | `caddy-config` | Caddy runtime config | No — regenerated from Caddyfile | | `gitea-runner-data` | Runner registration state | No — regenerated on deploy |