blog.thms.uk

Self-Hosting Mastodon Behind Cloudflare Tunnel

I recently migrated my Mastodon server to my homelab. As I’m on a domestic UK internet connection, my IP address changes periodically - which rules out relying on a static public IP. I also didn’t want to forward ports 80 and 443, so I opted for Cloudflare Tunnels instead.

Here’s how I got Mastodon running behind a Cloudflare Tunnel.

Set Up Mastodon

I covered the initial setup in my first ever blog post, so I won’t repeat it here. For the migration of my existing server I followed the official migration docs which are really really thorough.

Set Up Cloudflare Tunnel

  1. Install cloudflared. On Ubuntu or another Debian-based distro, I recommend using the Cloudflare package repository:

    # Add the Cloudflare GPG key
    sudo mkdir -p --mode=0755 /usr/share/keyrings
    curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
    
    # Add the repo to your apt sources
    echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main' | sudo tee /etc/apt/sources.list.d/cloudflared.list
    
    # Install cloudflared
    sudo apt-get update && sudo apt-get install cloudflared
    
  2. Log in:

    cloudflared tunnel login
    
  3. Create a tunnel:

    cloudflared tunnel create mastodon
    

    mastodon here is just the internal name for the tunnel - it’s for your reference only. Cloudflare will return a tunnel UUID; keep a note of it for the next step.

  4. Configure the tunnel by creating ~/.cloudflared/config.yml:

    tunnel: {uuid} # replace with your UUID here
    credentials-file: /home/mastodon/.cloudflared/{uuid}.json # replace with your UUID here
    
    ingress:
      - hostname: mastodon.example.com # replace with your Mastodon domain
        service: https://127.0.0.1:443
        originRequest:
          httpHostHeader: mastodon.example.com # replace with your Mastodon domain
          noTLSVerify: true
      - service: http_status:404
    

    Two things to note here:

    • originRequest.httpHostHeader must be set, otherwise the underlying nginx can’t identify your virtual host.
    • originRequest.noTLSVerify: true is required because nginx won’t have a valid certificate for 127.0.0.1. Without this, the tunnel will refuse to connect.
  5. Create the DNS record:

    cloudflared tunnel route dns mastodon mastodon.example.com
    

    Replace mastodon with your tunnel name (if you used a different one in step 3), and mastodon.example.com with your actual domain.

  6. Install cloudflared as a service:

    sudo cloudflared --config /home/mastodon/.cloudflared/config.yml service install
    

That’s it. Visit https://mastodon.example.com in your browser and you should land on your Mastodon instance.