No description
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHKVLXH3jJnu5YRKxVcqyF |
||
| docs | ||
| .gitignore | ||
| README.md | ||
Server documentation
Documentation for a small self-hosted setup: video calls, file sharing, a website and monitoring, run on a home server and exposed to the internet through a small EU VPS.
This repository is public. Never commit passwords, API keys, tokens,
.envfiles, private keys, public IP addresses or other secrets. See Security notes.
Goals
- Open source only. Every component can be self-hosted and inspected.
- EU only. All hosting, DNS and storage stay in the EU. (Exception: Backblaze is US-owned but the bucket is in its EU region, and data is encrypted before upload.)
- Cheap. Target under €14/month in total, including VAT.
- Low maintenance. As few moving parts and servers as possible.
Architecture
flowchart LR
user([Visitors / call participants])
subgraph vps[EU VPS - netcup]
pangolin[Pangolin<br/>reverse proxy + TLS]
gerbil[Gerbil<br/>WireGuard server]
kuma[Uptime Kuma]
end
subgraph home[Home network]
router[UniFi Dream Router 7<br/>no inbound port forwards]
subgraph pve[Proxmox host]
subgraph dmz[DMZ VLAN 20]
vm103[VM103 'public'<br/>Docker: Newt, Jitsi, OpenCloud,<br/>Forgejo, website]
end
lan[Main LAN<br/>other homelab VMs]
end
end
user -- HTTPS 443 / UDP 10000 --> pangolin
pangolin --- gerbil
vm103 -- outbound WireGuard tunnel --> gerbil
lan -- allowed --> dmz
dmz -. blocked .-> lan
The home server dials out to the VPS over WireGuard, so nothing at home is exposed. The ISP uses CGNAT for IPv4 anyway. Visitors connect to the VPS, and Pangolin forwards their traffic through the tunnel. The home IP address is never published.
Stack
| Layer | Choice | Where |
|---|---|---|
| Hypervisor | Proxmox VE | Home (Minisforum UM790 Pro) |
| Public-services VM | Ubuntu Server 26.04, Docker, managed by Coolify | VM103 in the DMZ VLAN |
| Network / firewall | UniFi Dream Router 7, zone-based firewall | Home |
| Tunnel + reverse proxy | Pangolin (+ Newt on VM103) | VPS + VM103 |
| Video calls | Jitsi Meet | VM103, see docs/jitsi.md |
| Files | OpenCloud | VM103, see docs/opencloud.md |
| Website | Astro static site, edited with Sveltia CMS | VM103, deployed by Coolify |
| Metrics | Beszel (hub on the main LAN, agent on VM103) | Home |
| Logs | Dozzle | VM103 (behind Pangolin login) |
| External uptime checks | Uptime Kuma, public status page | VPS, see docs/monitoring.md |
| Backups | vzdump nightly + rclone crypt; Pangolin archive nightly | Proxmox host and VPS → Backblaze B2 (EU region) |
| DNS / registrar | deSEC / Domænehajen | EU |
| Code hosting | Forgejo | VM103 (git.<domain>), see docs/forgejo.md |
Status
- DMZ network (VLAN 20) and zone policies on the UDR7, see docs/network.md
- VM103 created, Ubuntu installed and hardened, Docker installed, see docs/vm-public.md
- VPS provisioned and hardened, see docs/vps.md
- Domain moved to a Danish registrar, DNS moved to deSEC, DNSSEC active, see docs/dns.md
- Pangolin installed on the VPS, Newt on VM103, tunnel tested from outside
- Website live: Forgejo → auto-deploy → Coolify → Pangolin, Sveltia CMS with Forgejo login, see docs/website.md
- OpenCloud live, see docs/opencloud.md
- Jitsi live with auth and ITPU branding, see docs/jitsi.md
- Jitsi tested with three participants (proves the UDP path through the VPS)
- Self-hosted Forgejo replaces Codeberg, see docs/forgejo.md
- Nightly encrypted backup of the VPS (Pangolin) to B2, see docs/backups.md
- Uptime Kuma on the VPS: admin UI behind Pangolin's login, public status page, see docs/monitoring.md
- Uptime alerts to Signal, push monitors for the backups
- Git over SSH (raw TCP 2222 via Pangolin)
- Dozzle and Beszel agent on VM103
- Nightly Proxmox backups of all guests, encrypted off-site copy in B2, restore tested, see docs/backups.md
- Internal HTTPS names (
*.home.<domain>) via AdGuard + Coolify Traefik wildcard cert - VM103 added to Coolify as a remote server
- Renumber the home LAN away from 192.168.1.0/24, see docs/remote-access.md
Cost (per month, incl. 25% VAT)
| Item | Cost |
|---|---|
| netcup VPS nano G11.5s (6-month term) | ~€3.88 |
| Power for the home server | ~€2–3 |
| Backblaze B2 (~170 GB max) | ~€1.10 |
| Total | ~€7–8 |
Documents
- docs/decisions.md: why each component was chosen, and what was considered and rejected
- docs/network.md: UniFi DMZ network and firewall zones
- docs/vm-public.md: creating and hardening VM103
- docs/vps.md: the VPS, Pangolin, sites and resources
- docs/website.md: the website, CI in Coolify, auto-deploy, Sveltia CMS
- docs/opencloud.md: OpenCloud setup and our changes to upstream
- docs/jitsi.md: Jitsi setup, UDP path, auth, branding
- docs/forgejo.md: self-hosted git
- docs/monitoring.md: Uptime Kuma, the public status page and its access rules
- docs/remote-access.md: VPN access, the subnet conflict and the renumbering plan
- docs/proxmox-host.md: the Proxmox host, repositories, guests
- docs/dns.md: domain, DNS, DNSSEC, internal names
- docs/backups.md: Proxmox backups to B2, retention, restore
Security notes
- Secrets live in
.envfiles on the servers (or a password manager), never in this repo..gitignoreexcludes.envand key files. - Documentation uses placeholders such as
<vps-ip>,<domain>and<user>. Replace them locally. - Internal addresses shown here are private (RFC 1918) ranges and not reachable from the internet.