How to setup Cloudflare DDNS

tags

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:

  1. Serving the website on port 80 (using Docker)
  2. Managing domain configuration (e.g., zloutek1.com)
  3. 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:

  1. Main domain record (points directly to your IP)
  2. Wildcard subdomain record (routes all subdomains to your main domain)

Here’s an example configuration:

TypeNameContentProxy StatusTTL
AAAAzloutek1.com2a02:8308:b08e:2100:8076:a…🌩️ ProxiedAuto
CNAME*zloutek1.com🌩️ ProxiedAuto

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

  1. Visit https://dash.cloudflare.com and navigate to Profile > Account Home > Manage Account > Account API Tokens
  2. Create a new token with these permissions:
Token namePermissionsResourcesStatus
Edit zone DNSZone.Zone Settings, Zone.Zone, Zone.DNSAll zonesActive

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.