Running a Personal Website from a Mac Mini Homelab
Setting up a personal homelab can be more rewarding and educational than using a traditional VPS. In this guide, I’ll continue to share my experience NixOS setup and Cloudflare for domain management. This approach gives you complete control over your hosting environment while learning valuable skills in system administration.
Background and Prerequisites
It’s worth understanding why I chose a homelab over a VPS. While a VPS offers simplicity with a pre-assigned IPv4 address, running your own hardware provides flexibility, learning opportunities, and potentially lower long-term costs. I documented the initial NixOS Darwin setup in my article Setting up Nix Darwin on Mac Mini M1.
The process of hosting a website from home involves three key challenges:
- Serving the website on port 80 (using Docker)
- Managing domain configuration (e.g., zloutek1.com)
- Implementing Dynamic DNS to handle changing IP addresses
A crucial consideration when hosting from home is that most ISPs provide only IPv6 addresses (like 2001:db8:3333:4444:5555:6666:7777:8888) and regularly change these addresses for security reasons – sometimes as frequently as daily. This is where Dynamic DNS becomes essential.
Domain Management with Cloudflare
Cloudflare stands out for web hosting due to its robust security features, reliability, and user-friendly interface. Here’s how to set up your domain:
Domain Registration Options
You have two approaches for domain registration:
- Purchase through a third-party registrar (I got epicartificials.com through https://forpsi.sk)
- Buy directly from Cloudflare (as I did with zloutek1.com)
If you choose a third-party registrar, you’ll need to update your domain’s nameservers to point to Cloudflare:
- veronica.ns.cloudflare.com
- nolan.ns.cloudflare.com
To complete the setup, visit https://dash.cloudflare.com, sign in, and select “Add a domain” from the Account Home.
DNS Configuration
Navigate to DNS > Records in your domain’s dashboard to configure routing rules. You’ll need two primary records:
- Main domain record (points directly to your IP)
- Wildcard subdomain record (routes all subdomains to your main domain)
Here’s an example configuration:
| Type | Name | Content | Proxy Status | TTL |
|---|---|---|---|---|
| AAAA | zloutek1.com | 2a02:8308:b08e:2100:8076:a… | 🌩️ Proxied | Auto |
| CNAME | * | zloutek1.com | 🌩️ Proxied | Auto |
Note: Use type A for IPv4 addresses and AAAA for IPv6 addresses.
Implementing Dynamic DNS
To handle changing IP addresses, we’ll set up an automated system that updates Cloudflare whenever your IP changes.
Cloudflare API Configuration
- Visit https://dash.cloudflare.com and navigate to Profile > Account Home > Manage Account > Account API Tokens
- Create a new token with these permissions:
| Token name | Permissions | Resources | Status |
|---|---|---|---|
| Edit zone DNS | Zone.Zone Settings, Zone.Zone, Zone.DNS | All zones | Active |
Consider restricting the token to specific domains for enhanced security.
Setting Up the DDNS Client
Since we’re using Darwin Nix, we’ll implement the Dynamic DNS client through the home manager system. First, install the required package:
home.packages = with pkgs; [
yabai
cloudflare-dynamic-dns
];Then create a dedicated Cloudflare module (cloudflare-ddns.nix):
{ pkgs, config, ... }:
let
# Custom script to handle token file reading
epicartificials-clouflare-ddns = pkgs.writeShellScriptBin "epicartificials-clouflare-ddns" ''
token_file="${config.sops.secrets."cloudflare/token".path}"
${pkgs.cloudflare-dynamic-dns}/bin/cloudflare-dynamic-dns \
--domains "zloutek1.com,epicartificials.com" \
--token "$(cat $token_file)" \
--ipcmd "curl -fsSL https://api6.ipify.org" \
--run-every "10m"
'';
in {
launchd.agents = {
cloudflare-ddns = {
enable = true;
config = {
ProgramArguments = [
"${epicartificials-clouflare-ddns}/bin/epicartificials-clouflare-ddns"
];
KeepAlive = true;
RunAtLoad = true;
StandardErrorPath = "/tmp/cloudflare-ddns.log";
};
};
};
}This configuration creates a launchd service (macOS’s equivalent to systemd) that:
- Runs automatically at system startup
- Checks your IP address every 10 minutes using https://api6.ipify.org
- Updates the DNS records for your specified domains
- Logs any errors to /tmp/cloudflare-ddns.log
We use a separate shell script to handle token reading because it provides better reliability when accessing secrets at runtime.
Conclusion
With this setup, you’ll have a robust, self-hosted website running from your Mac Mini, complete with automatic IP address updates and professional domain management through Cloudflare. This solution provides the flexibility of home hosting while maintaining reliable accessibility through dynamic DNS updates.