Personal project · not production · one physical host
A single-host lab for the things I don't run at work yet
I use a Proxmox homelab to practise infrastructure as code, DNS, networking, remote access and service operations. It's separate from my professional work. Each item is labelled running, partial or planned.
Monitoring · homelab map
- Running
- Partial
- Planned
Workstation · WSL
- Partial: TerraformP01
- Running: Ansible—
Remote access
- Partial: Tailscale subnet routerP03
- Planned: WireGuard fallbackP03B
- Planned: Cloudflare Tunnel + AccessP18
Network edge
- Partial: AdGuard Home DNSP02
- Planned: Pi-hole (2nd resolver)P02B
- Partial: Caddy reverse proxyP04
- Planned: OPNsense + VLANsP16
Partial: Proxmox VE 9.x · one physical host · Ubuntu VM template · Terraform-provisioned VMs
Home services
- Running: This portfolio (rafifdzaky.com)site
- Running: Pit Wall On-Call (pitwall.rafifdzaky.com)game
- Partial: JellyfinP05
- Planned: Seerr + Arr stackP05B
- Planned: NextcloudP07
- Planned: VaultwardenP07B
- Planned: ImmichP08
- Planned: Home AssistantP09
- Planned: Homepage dashboardP09B
Platform lab
- Planned: Harbor + golden workloadP06
- Planned: Gitea + CI runnerP11
- Planned: Prometheus · Grafana · LokiP10
- Planned: k3s × 3 VMsP12
- Planned: Argo CD (GitOps)P13
- Planned: Trivy · gitleaks · VaultP15
Security labruns at different times from k3s
- Planned: Active Directory + KaliP17
Off the box
- Planned: 3-2-1 backups + restore testP14
- Planned: AWS bridge (one stack)P19
- Planned: Incident Day drillP20
Deploys · running now
Runningsite
This portfolio
The site you are reading: a static Astro build. GitHub Actions deploys it over Tailscale into a new release folder and switches a symlink.
Runningpitwall
Pit Wall On-Call
My on-call game. GitHub Actions pushes SHA-tagged images to GHCR and deploys over Tailscale; deploy.sh runs a smoke test and rolls back if it fails.
PartialP01
Proxmox VE + Terraform VM provisioning
Proxmox VE 9.x host with an Ubuntu VM template; VMs are provisioned through the Terraform Proxmox provider instead of the web UI.
Running—
Ansible configuration from WSL
Ansible runs from WSL on my workstation, using SSH keys and roles to configure the VMs Terraform creates.
PartialP02
AdGuard Home — local DNS
AdGuard Home on a dedicated DNS VM provides local DNS resolution and filtering for the lab.
PartialP03
Tailscale remote access
A Tailscale subnet router advertises the home LAN, so I can reach lab services remotely without opening inbound ports.
PartialP04
Caddy reverse proxy & DNS
Caddy and DNS work in progress to put lab services behind friendly names. Internal TLS is not done yet.
PartialP05
Jellyfin media servers
Jellyfin instances running as Docker workloads. The playbook’s full isolation model is not verified yet.
Terminal · things that broke, and why
AdGuard vs. systemd-resolved on port 53resolved
- Symptom
- AdGuard Home could not bind its DNS listener on port 53 on the Ubuntu VM.
- Cause
- systemd-resolved already held port 53 with its local stub resolver.
- Takeaway
- Check what owns a port before blaming the new service. On Ubuntu the DNS port is taken by default.
Terraform → Proxmox returns HTTP 403resolved
- Symptom
- Terraform plans against the Proxmox API failed with HTTP 403.
- Cause
- The Proxmox role assigned to the Terraform user lacked the privileges the provider needs to create and configure VMs.
- Takeaway
- A 403 is an authorization problem, not a network one. Give the automation user its own role with exactly the privileges it uses.
Docker permission denied after joining the groupresolved
- Symptom
- Docker commands still failed with permission denied after adding my user to the docker group.
- Cause
- Group membership is evaluated at login; the existing session did not have the new group.
- Takeaway
- Start a new login session (or use newgrp) after changing group membership.
Clients bypassing local DNSinvestigating
- Symptom
- Some devices appeared to resolve names without going through AdGuard.
- Cause
- Investigating IPv6 DNS paths and encrypted DNS (DoH) as bypass routes.
- Takeaway
- Open. DNS filtering is only as strong as the paths a client is allowed to use.
Docs · learning roadmap
My own 31-module curriculum. The order is the plan, not completion dates. First up: running the v2 pipeline template end to end here, on a golden workload with a private registry (P06) and a self-hosted CI runner (P11).
Show the full roadmap
0 · Engineering fundamentals
- L00ALinux under the hoodPlannedProcesses, signals, systemd, journals, filesystem diagnosis.
- L00BBash and text processingPlannedPipelines, parsing and basic scripting.
- L00CGit for infrastructurePlannedVersioned config, readable commits, rollback.
- L00DNetworking fundamentalsPlannedDNS, ports, routing, connectivity investigation.
- L00EAnatomy of one HTTP requestPlannedBrowser → DNS → proxy → app → response, traced end to end.
1 · Foundations
- P01Proxmox + Terraform VM provisioningPartialRepeatable VMs from code.
- P02AdGuard Home DNS filteringPartialLocal DNS and filtering.
- P02BPi-hole as a second resolverPlannedWhat DNS redundancy actually requires.
- P03Tailscale remote accessPartialReach the lab without inbound ports.
- P03BManual WireGuard fallbackPlannedAn access path that does not depend on one vendor.
- P04Caddy reverse proxy, DNS, internal TLSPartialNamed services behind one proxy.
2 · Applications & CI/CD
- P05Jellyfin private and shared serversPartialSeparate instances for separate audiences.
- P05BRequest and media automation stackPlannedControlled mounts and service-to-service auth.
- P06Golden workload + Harbor registryPlannedA reference app built into an image, scanned, and pushed to a private registry — the lab target for my containerized pipeline template.
- P07Nextcloud file servicePlannedStorage and backup trade-offs.
- P07BVaultwarden password managerPlannedSecrets handling for a personal service.
- P08Immich photo platformPlannedResource and storage planning.
- P09Home Assistant + power monitoringPlannedFailure domains at home.
- P09BHomepage dashboard as config-as-codePlannedA service directory kept in Git.
3 · Platform engineering
- P10Prometheus, Grafana, LokiPlannedMetrics, logs and alerting for the lab itself (separate from my work monitoring).
- P11Gitea + self-hosted CI runnerPlannedRun the pipeline template end to end on infrastructure I control.
- P12Three-node k3s clusterPlannedOrchestration and failure tests. All nodes share one host, so no physical HA.
- P13GitOps with Argo CDPlannedDeclarative deploys and drift reconciliation.
- P143-2-1 backupsPlannedBackups only count once a restore has been tested.
4 · Security
- P15DevSecOps pass: Trivy, gitleaks, VaultPlannedScanning and secrets, and the difference between a scan and a gate.
- P16OPNsense + VLAN segmentationPlannedNetwork zones and firewall policy.
- P17Isolated AD + Kali lab (elective)PlannedAuthorized security learning in an isolated environment.
- P18Public app via Cloudflare Tunnel + AccessPlannedPublishing one service safely.
5 · Real-world DevOps
- P19Cloud bridge: one stack to AWSPlannedA bounded AWS experiment.
- P20Incident DayPlannedDetection → diagnosis → recovery → postmortem, with real timestamps.
Optional
- P05CCustom media portalPlannedA product experiment outside the core path.