For any homelab enthusiast, the setup is never truly "finished." It's a constantly evolving ecosystem. Recently, my own lab underwent a significant migration and optimization phase, driven by a classic problem: port conflicts. This is the first in a three-part series detailing the journey.
The Problem: A Port 443 Standoff
The catalyst for this entire overhaul was a conflict on my primary media server (192.168.50.20). It was running both Traefik (my reverse proxy) and AdGuard Home, both of which wanted exclusive control of port 443 for HTTPS traffic. In networking, you can't have two services listening on the same port—something had to give.
The Solution: Dedicated Infrastructure
Rather than trying to work around the conflict with port remapping tricks, I decided to take a more robust approach: migrate Traefik to its own dedicated Docker host (192.168.50.21). This separation of concerns would provide several benefits:
- Clean Separation: The media server could focus on media services and AdGuard Home, while the dedicated host would handle all reverse proxy duties.
- Improved Stability: If the media server needed maintenance or rebooting, my reverse proxy infrastructure would remain unaffected.
- Better Security Posture: Isolating the reverse proxy reduces the attack surface and makes security policies easier to manage.
- Scalability: Future expansion becomes easier with dedicated infrastructure.
Implementation Challenges
This migration wasn't without its complications. Moving Traefik meant several immediate changes were necessary:
1. Pi-hole Port Reconfiguration
The new host (.21) was already running Pi-hole with its web interface on port 80. Since Traefik needed both ports 80 and 443, I had to relocate Pi-hole's interface to port 8082. This required updating the Pi-hole container configuration and ensuring all my bookmarks and scripts pointed to the new port.
2. Rethinking the Proxy Architecture
Previously, I was using Traefik's Docker provider, which automatically discovers and configures routes for containers using labels. While convenient, this approach has security implications—it requires exposing the Docker socket to the proxy container.
For the new setup, I opted for a more explicit, file-based configuration using dynamic.yml. This approach:
- Eliminates the need to expose the Docker socket
- Provides a clear, documented configuration
- Makes changes more deliberate and reviewable
- Offers better version control and auditability
/home/geoff/traefik/dynamic.yml on the Docker host and is mounted into the container as /etc/traefik/dynamic.yml. This makes it easy to edit without entering the container.
The Migration Process
The actual migration followed these steps:
- Backup Everything: Before making any changes, I documented my current Traefik configuration and backed up all relevant files.
- Prepare the New Host: Set up Docker on
.21, configure the firewall, and ensure networking was properly configured. - Build the Configuration: Created the
dynamic.ymlfile with all my service routes, middleware, and certificates. - Test Locally: Verified Traefik could start and routes were being recognized before switching DNS.
- Update DNS: This was the big moment—updating 31 DNS records to point to the new host (covered in Part 2).
- Cleanup: Remove the old Traefik container from the media server and reclaim resources.
Unexpected Benefits
Beyond solving the port conflict, this migration revealed some additional advantages:
- Resource Distribution: The media server's CPU and memory utilization dropped noticeably without Traefik competing for resources.
- Cleaner Logs: Separating Traefik logs from media server logs made troubleshooting much easier.
- Faster Deployments: Testing new services on the media server no longer required worrying about reverse proxy impacts.
Lessons Learned
This migration reinforced several important homelab principles:
- Plan for Growth: While it's tempting to run everything on one box, having room to separate services pays dividends.
- Document As You Go: The file-based configuration approach naturally creates documentation of your infrastructure.
- Security First: Taking the time to avoid exposing the Docker socket was worth the extra configuration effort.
- Test Before Switching: Validating the new setup before updating DNS prevented extended downtime.
What's Next
With Traefik successfully migrated, the next challenge was updating all 31 DNS records and cleaning up legacy configuration. That massive DNS operation and system cleanup is covered in Part 2.
Tools & Workflow
This migration project demonstrates a modern AI-assisted infrastructure workflow:
- Gemini CLI & CodeX (ChatGPT CLI): Used for all infrastructure automation—Docker container management, Traefik configuration, SSH operations, and system diagnostics. These CLI tools execute commands directly on the homelab hosts.
- GEMINI.md Context File: Maintains project context, infrastructure details (IPs, credentials, API keys), and an operations log. This file is provided to AI tools at the start of each session, ensuring continuity even when closing and reopening CLIs. It serves as both living documentation and an audit trail.
- Claude: Used exclusively for creating this website, blog design, and documentation writing. Not involved in the actual infrastructure work.
The .md file approach is particularly powerful: instead of repeating context every session, the AI tools read the file and immediately understand the infrastructure layout, recent changes, and ongoing issues. Each session's work gets logged back into the file, creating a comprehensive record of what was done, why, and how to verify it.