17 December 2024
Last time on the Homelab Chronicles, I started documenting my ever evolving homelab situation. Things were still early in the journey but I was proud of the progress that had been made: my new network was installed with improved ethernet cabling, added the brand new Mac mini M4 to the mix, hosted Pihole on said Mac mini through Docker, and configured a reverse proxy with Caddy to three of my services. In this chapter, expect to learn more about securing the reverse proxy, reversing course on the Pihole, and getting new application hosted. I learn the magic of Docker Compose and I don’t turn back.
Any time I open portions of my network to the outside world, special care needs to be paid attention. My reverse proxy through Caddy had only three services routed within my network. The domain I chose for the reverse proxy is pretty obscure and hard to guess, but it’s not enough. The services I was using had their own login page, but advertising the existence of a service gives an attacker information on what the surface rea could be. I wanted to add an additional authentication layer to all the endpoints going through the reverse proxy.
Because I wanted to get to other applications, for the first pass I chose to use basic authentication. With basic authentication, the browser will open a username/password dialog that must be successfully gone through to proceed to the service. It worked but left some things to be desired. For example, basic authentication didn’t really integrate well with 1Password. It also was a concern if I wanted to add additional users. Duplicating the authentication line in the Caddyfile was also a pain. It was early going, so I put it on the list of future enhancements.
Doing the setup was surprisingly simple. In the Docker container for Caddy, I went to the Exec area and ran the following command on the container:
caddy hash-password
Once a password is entered twice, it will spit out a hashed password. Then in the Caddyfile, I changed it so that eaach entry looked something like this:
service.mysecretdomain.com {
reverse_proxy 192.168.1.2
basicauth / username $2a$14$0nnEzLEjSf7TAWJqntj2Tec/SWrb.u/6N1y/Eu9LyVgSiKCmhURQi
}
I killed the Docker container and re-ran the command. Viola. I had authentication working on the endpoints.
One downside of running Pihole through Docker is that on the admin console, no information is related to the individual clients that were using the service as its DNS. Everything routed through the Docker network. It wasn’t a major concern, but it was on my list.
Pihole moved to the top of the list when I woke up the Saturday after Thanksgiving to find my network was completely down. I had had a few drinks the night before and since I’m 39, I woke up with a splitting headache. It’s sobering when trying to troubleshoot technical issues. Things resolved after about 90 minutes. I disabled Pihole from my network and removed the Docker container.
The nearest I can figure what happened is that the previous night, I had connected to a Mullvad VPN exit node on the Mac mini. Before I had only used it briefly, but because I left it connected all night problems arose. I configured the DNS for my network on the Unifli console to use the Mac mini’s internal IP address and I put a backup DNS in. My guess is there is a caching mechanism. Once the network needed to re-establish a connection to the Mac mini, the exit node interfered with it, and the backup DNS was not correctly configured. It resulted in all HTTP requests failing even to the Unifli console. I eventually found the internal address to the Unifli network and I disabled the DNS.
After things were back online and my hangover was gone, I reviewed my next steps. Pihole is named after the Raspberry Pi. It is designed to work best on the Raspberry Pi. I ordered one and the plan was to have Pihole installed only on the Raspberry Pi. With it configured, Pihole installed, and more importantly the DNS set up correctly in the Unifli console everything has been amazing. Clients are identified appropriately.
As of writing this, the Pihole Admin dashboard is showing there has been over 100k queries across 33 active clients. 13k of those queries were blocked. Not too shabby.
As I’ve aged, I realized that I’m awful at keeping in touch with people. They can mention things to me and then I completely forget about it. If I write things down, I stand a fighting chance. Last year, I started using a service called Monica. Monica is an open source personal CRM (a personal relationship manager in business speak). I was paying for their managed instance. I loved the feature-set. I added my contacts. I put in information about them ranging from things they’ve told me, their pets, their family, their birthdays, and a log of things we’ve done together. I was running into limitations of file uploads as it was very limited.
Having the Mac mini, Docker, and a reverse proxy meant I could self-host Monica and allocate whatever resources I wanted to it.
The previous applications I installed to Docker were single container application. Monica was something more complicated. Docker has a tool called Docker Compose that allows you to configure multiple containers that can work together as a single application. I found a docker-compose.yml file template and modified it. Monica needed two containers: the application (named monica-app with the monica:latest image) and a database (named monica-db with the mariadb:11 image).
Spinning it up as a simple command. I connected to the database through the Exec function in the Docker application and imported the SQL that I exported from the managed instance. Some things got messed up, but it was easy enough to re-create.
One key feature that I loved from Monica is the email reminders. I love getting notifications to stay in touch or when my contacts have birthdays. So far, my installation did not support emails. The first problem was getting a reliable SMTP service. This is harder than you’d think due to spam. I signed up for mailtrap. They approved my free-tier usage and received an account. Then I had to figure out how to get Monica working. Reading online led me to the need to create a separate instance of the monica:latest image with an additional setting. My docker-compose.yml file was changed to add MAIL entries into the environment and then the creation of a third Docker container I called monica-cron. It was virtually the same as the monica-app but contained the command: cron.sh.
monica-cron:
image:monic:latest
container_name: monica-cron
environment:
…
volumes:
…
depends-on:
- monica-db
command: cron.sh
Once the YML file was updated, it was just a case of spinning everything down and starting them back up:
docker-compose down
docker-compose up -d
Managing the commands through a file that contained all information was so much easier than a collection of docker run comamnds I was using. Immediately, I converted those to their own docker-compose.yml. It was easy to do since it was just Caddy, but I vowed all Docker applications would now go through Docker Compose.
Things were getting fun now! There were more applications that I wanted to self-host. I still wanted to upgrade the basic authentication into something a little easier to use. We’re still about three weeks away from present, so I can tell you that in the next chapter I’ll likely be covering: