Creating terraform to setup cloudflared zero trust and share navidrome to my phone
17 May 2025Hello,
In the previous post I did the setup of Navidrome + Cloudflared to listen my home musics, I decided to take one step further and add the setup of cloudflare (zero trust tunnel) for my home server using terraform. I decided to do it using Gemini and see how it would go, how complex it would be, how many mistakes. I’m not deeply familiar with terraform thus I think it made my life slightly easier but I had to do some manual adjustments as some of the suggested resources were deprecated.
I defined the variables.tf as:
variable "cloudflare_account_id" {
type = string
description = "Your Cloudflare Account ID"
}
variable "cloudflare_api_token" {
type = string
description = "Your Cloudflare API Token"
}
variable "domain_name" {
type = string
description = "Your domain name"
default = "matbra.com"
}
variable "tunnel_name" {
type = string
description = "The name of the Cloudflare Tunnel"
default = "matbra-home-tunnel"
}
variable "ip_range" {
type = string
description = "The IP range of your home network"
default = "192.168.68.0/24"
}
variable "tunnel_secret" {
type = string
description = "The secret for the Cloudflare Tunnel"
sensitive = true # Mark the variable as sensitive
}
variable "emails_allowed" {
type = list(string)
description = "List e-mail allowed"
default = ["<replace>"]
}
We have very basic stuff: cloudflare account id, api token, domain name, tunnel name, ip range, and the tunnel secret.
Besides it, outputs.tf
output "tunnel_token" {
description = "Cloudflare Tunnel Token"
value = cloudflare_zero_trust_tunnel_cloudflared.home_tunnel.tunnel_token
sensitive = true
}
Simply defining the place where we will have the output to be used in my docker-compose cloudflared.
We also have the resources in main.tf
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 4.0"
}
}
}
provider "cloudflare" {
api_token = var.cloudflare_api_token
}
# Create a Cloudflare Tunnel. This sets up the connection point
# between your home network and Cloudflare's network.
resource "cloudflare_zero_trust_tunnel_cloudflared" "home_tunnel" {
account_id = var.cloudflare_account_id
name = var.tunnel_name
secret = var.tunnel_secret
}
# Create a Cloudflare Tunnel route. This tells Cloudflare to route
# traffic for your home network's IP range through the tunnel.
resource "cloudflare_zero_trust_tunnel_route" "home_network_route" {
account_id = var.cloudflare_account_id
tunnel_id = cloudflare_zero_trust_tunnel_cloudflared.home_tunnel.id
network = var.ip_range # Add the network argument here, use the ip_range variable
}
# Create a Cloudflare Access application for the general home network access.
resource "cloudflare_zero_trust_access_application" "home_network_app" {
account_id = var.cloudflare_account_id
name = "Matbra Home Network Access Application"
session_duration = "24h"
}
# Create a Cloudflare Zero Trust policy to control access to the resources
# behind the tunnel.
resource "cloudflare_zero_trust_access_policy" "home_network_policy" {
application_id = cloudflare_zero_trust_access_application.home_network_app.id
account_id = var.cloudflare_account_id
name = "Matbra Home Network Access Policy"
precedence = 1
decision = "allow"
include {
email = var.emails_allowed
}
}
I believe I also had to change some other stuff in their dashboard, to allow my phone to connect to my local network when connected to the vpn. I don’t remember exactly what it was, but well, I’m sure it is possible.