IP addresses and production domain names have been replaced with generic labels for security.
Context
Alongside the network and monitoring infrastructure, I deployed a full application layer on Proxmox VE (PVE-01) in VLAN 20 SERVERS (172.16.20.0/24). The goal: self-hosted services covering documentation, project management, automation, local AI and media — with no dependency on third-party cloud providers.
Services deployed
| Service | CTID | VLAN | Port | Purpose |
|---|---|---|---|---|
| Docmost (wiki) | 200 | VLAN 20 | 3000 | Collaborative documentation |
| Vikunja | 201 | VLAN 20 | 3456 | Task management / Kanban |
| Dashy | 202 | VLAN 20 | 3000 | Centralised homelab dashboard |
| Baikal | 204 | VLAN 20 | 80 | Calendar + contacts (CalDAV/CardDAV) |
| n8n | 205 | VLAN 20 | 5678 | Workflow automation |
| Ollama | 206 | VLAN 20 | 11434 | Local LLM (Llama, Mistral models) |
| Firefly III | 207 | VLAN 20 | 80 | Personal finance management |
| ActualBudget | 208 | VLAN 20 | — | Alternative personal budgeting |
| VM media-01 | 501 | VLAN 20 | 8096 / 2283 | Jellyfin (media) + Immich (photos) |
LXC deployment methodology
Each service follows a standardised 4-step process:
1. Proxmox LXC creation
pct create <CTID> local:vztmpl/debian-12-standard_12.X_amd64.tar.zst \
--hostname lxc-<service>-01 \
--cores 2 --memory 512 --swap 256 \
--rootfs local-lvm:8 \
--net0 name=eth0,bridge=vmbr0,tag=20,ip=172.16.20.X/24,gw=172.16.20.1 \
--nameserver <IP-ADGUARD> \
--searchdomain homelab.lan \
--unprivileged 1 --onboot 1
pct start <CTID>
The
tag=20VLAN tag places the LXC directly in VLAN 20 SERVERS. DNS resolver is AdGuard Home (VLAN 10 MGMT).
2. System update + service installation
Each LXC receives a minimal package set. For services requiring Docker (Ollama, Vaultwarden), an unprivileged LXC with nesting=1 is sufficient without compromising Proxmox isolation.
3. HTTPS exposure via Nginx Proxy Manager NPM (VLAN 10 MGMT) receives inbound HTTPS traffic via a pfSense port-forward (NAT) and routes to the internal service by FQDN:
*.[my-domain.fr]→ automatic wildcard Let's Encrypt cert (Cloudflare DNS-01 challenge)- Internally: AdGuard Home resolves
service.[my-domain.fr] → NPM(split-horizon DNS) - No direct access to application ports from the outside
4. Zabbix inventory + monitoring Each LXC is added to Zabbix via agent2 or auto-registration template for availability monitoring.
Highlight — n8n (automation)
n8n (CTID 205, VLAN 20, exposed at n8n.[my-domain.fr]) is used to:
- Sync data between internal services (Baikal → Firefly III)
- Receive webhooks from GitHub
- Send Telegram alerts on Zabbix triggers
- Automate report generation
Highlight — Ollama (local LLM)
Ollama (CTID 206, VLAN 20) runs on PVE-01 (Dell R720, 386 GB RAM), hosting language models locally without sending data to third-party providers:
ollama pull llama3.2
ollama run llama3.2
Tested models: Llama 3.2, Mistral 7B, CodeGemma for code assistance. Access restricted to the internal network only.
Key points
- VLAN isolation: VLAN 20 services cannot directly reach VLAN 10 MGMT or other VLANs (Cisco 3560-CX ACLs)
- No exposed application ports: all inbound traffic goes through NPM (reverse proxy) with SSL/TLS
- Unprivileged Debian 12 LXC: maximum Proxmox isolation, minimal compromise risk
- Naming conventions:
lxc-<service>-01, CTID 200–299 (VLAN 20) - Automated backups: Proxmox Backup Server (PBS) on both nodes
Skills covered
This project covers making an IT service available in a structured, secured and monitored way (B1.5), installation and testing of application infrastructure on virtualisation (B2.2), infrastructure evolution through automation and reverse proxy (B2.3), and IT asset management via standardised inventorying (B1.1).