Setting up Cloudflare Tunnel

Setting up Cloudflare Tunnel

Cloudflare Tunnel provides a secure way to expose your homelab services to the internet without opening ports or managing complex firewall rules. In this section, we'll walk through the process of setting up Cloudflare Tunnel on your remote nodes using Ansible.

Installing Cloudflared

Step 1: Add Cloudflared to the package list

In the setup_nuc.yml playbook, add cloudflared to the list of packages to be installed:

vars:
  packages:
    - ...
    - cloudflared
    - ...

Step 2: Install Cloudflared using the package manager

The setup_nuc.yml playbook will automatically install Cloudflared along with the other required packages on the remote nodes.

Creating and Managing Tunnels

Step 1: Configure tunnel credentials

Create a new file named cloudflared_config.yml.j2 in the templates directory to store the tunnel configuration:

tunnel: "{{ cloudflared_tunnel_uuid }}"
credentials-file: "{{ cloudflared_credentials_file }}"
 
logfile: /var/log/cloudflared.log
loglevel: info
 
ingress:
{% for domain in cloudflared_domains.values() %}
  - hostname: "{{ domain.domain }}"
    service: http://localhost:{{ domain.port }}
{% endfor %}
  - service: http_status:404

Step 2: Create and delete tunnels

In the setup_nuc.yml playbook, add tasks to create and delete Cloudflare tunnels using the Cloudflare API:

- name: Create Cloudflare tunnel
  uri:
    url: "https://api.cloudflare.com/client/v4/accounts/{{ cloudflare_account_id }}/tunnels"
    method: POST
    body_format: json
    body: "{{ {'name': tunnel_name} | to_json }}"
    headers:
      Authorization: "Bearer {{ cloudflare_api_token }}"
      Content-Type: "application/json"
    status_code: [200, 201]
  register: cloudflared_tunnel_creation
 
- name: Delete existing tunnel if it exists
  uri:
    url: "https://api.cloudflare.com/client/v4/accounts/{{ cloudflare_account_id }}/tunnels/{{ item.id }}"
    method: DELETE
    headers:
      Authorization: "Bearer {{ cloudflare_api_token }}"
      Content-Type: "application/json"
    status_code: [200, 204]
  loop: "{{ existing_tunnels.json.result }}"
  when: item.name == tunnel_name
  register: tunnel_delete_result
  ignore_errors: yes

Saving Tunnel UUIDs for Terraform

To allow Terraform to manage the DNS records for your tunnels, you need to save the tunnel UUIDs generated by Ansible.

Step 1: Extract the tunnel UUID

Add a task to the setup_nuc.yml playbook to extract the tunnel UUID from the API response:

- name: Extract Cloudflared tunnel UUID
  set_fact:
    cloudflared_tunnel_uuid: "{{ cloudflared_tunnel_creation.json.result.id }}"
  when: cloudflared_tunnel_creation.json.result.id is defined

Step 2: Save the tunnel UUID to a file

Create a task to save the tunnel UUID to a file that Terraform can read:

- name: Save tunnel UUID to a file
  copy:
    content: "{{ cloudflared_tunnel_uuid }}"
    dest: "./cloudflare/{{ tunnel_name }}-tunnel-uuid.txt"
  delegate_to: localhost
  when: cloudflared_tunnel_uuid is defined

The tunnel UUIDs saved by Ansible will be used in the Managing DNS with Terraform section to configure DNS records for your homelab services.

By following these steps, you'll have Cloudflare Tunnel set up on your remote nodes, allowing secure access to your homelab services without exposing them directly to the internet.