Simplify cloudflared tunnel configuration
This commit is contained in:
parent
8c5b711681
commit
bddfe0b656
1 changed files with 45 additions and 79 deletions
|
|
@ -3,110 +3,76 @@
|
||||||
let
|
let
|
||||||
# Cloudflare tunnel definitions
|
# Cloudflare tunnel definitions
|
||||||
tunnels = {
|
tunnels = {
|
||||||
# Define each tunnel with its configuration
|
|
||||||
warp = {
|
warp = {
|
||||||
name = "ftlhost-ssh"; # Tunnel name (used for service name and config)
|
remoteHost = "warp.ftl.host"; # Cloudflare hostname
|
||||||
id = ""; # Leave empty initially, you'll need to create and fill this
|
remoteTarget = "localhost:22"; # Where traffic routes to
|
||||||
hostname = "warp.ftl.host"; # Cloudflare DNS hostname
|
localBindPort = 4401; # Local port exposed by cloudflared
|
||||||
service = "ssh://localhost:22"; # Local service to route traffic to
|
logPath = "/var/log/cloudflared/warp.log";
|
||||||
};
|
};
|
||||||
# Add more tunnels here as needed
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# Function to generate config file content for each tunnel
|
|
||||||
tunnelConfigFor = name: tunnel: ''{
|
|
||||||
"tunnel": "${tunnel.id}",
|
|
||||||
"credentials-file": "/var/lib/cloudflared/${name}.json",
|
|
||||||
"logfile": "/var/lib/cloudflared/${name}.log",
|
|
||||||
"loglevel": "info",
|
|
||||||
"ingress": [
|
|
||||||
{
|
|
||||||
"hostname": "${tunnel.hostname}",
|
|
||||||
"service": "${tunnel.service}"
|
|
||||||
},
|
|
||||||
{"service": "http_status:404"}
|
|
||||||
]
|
|
||||||
}'';
|
|
||||||
|
|
||||||
in {
|
in {
|
||||||
# Install cloudflared
|
# Install cloudflared
|
||||||
environment.systemPackages = with pkgs; [ cloudflared ];
|
environment.systemPackages = with pkgs; [ cloudflared ];
|
||||||
|
|
||||||
# Define cloudflared user and group
|
# Ensure /var/log/cloudflared exists
|
||||||
users.users.cloudflared = {
|
|
||||||
isSystemUser = true;
|
|
||||||
group = "cloudflared";
|
|
||||||
description = "Cloudflared service user";
|
|
||||||
home = "/var/lib/cloudflared";
|
|
||||||
createHome = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
users.groups.cloudflared = {};
|
|
||||||
|
|
||||||
# Ensure /var/lib/cloudflared exists with proper permissions
|
|
||||||
systemd.tmpfiles.rules = [
|
systemd.tmpfiles.rules = [
|
||||||
"d /var/lib/cloudflared 0755 cloudflared cloudflared -"
|
"d /var/log/cloudflared 0755 root root -"
|
||||||
];
|
];
|
||||||
|
|
||||||
# Create a systemd service for each tunnel
|
# Systemd services per tunnel
|
||||||
systemd.services = lib.mapAttrs (name: tunnel: {
|
systemd.services = lib.mapAttrs (name: tunnel: {
|
||||||
description = "Cloudflare Tunnel for ${tunnel.hostname}";
|
description = "Cloudflared Access TCP Tunnel for ${tunnel.remoteHost}";
|
||||||
after = [ "network-online.target" ];
|
after = [ "network-online.target" ];
|
||||||
wants = [ "network-online.target" ];
|
wants = [ "network-online.target" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
||||||
# Create config file before starting the service
|
# Use StateDirectory for persistent storage of logs
|
||||||
preStart = ''
|
|
||||||
# Create config file if it doesn't exist
|
|
||||||
if [ ! -f "/var/lib/cloudflared/${name}.yml" ]; then
|
|
||||||
echo '${tunnelConfigFor name tunnel}' > /var/lib/cloudflared/${name}.yml
|
|
||||||
chown cloudflared:cloudflared /var/lib/cloudflared/${name}.yml
|
|
||||||
chmod 600 /var/lib/cloudflared/${name}.yml
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
|
|
||||||
# Service configuration
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
|
StateDirectory = "cloudflared";
|
||||||
|
StateDirectoryMode = "0755";
|
||||||
|
RuntimeDirectory = "cloudflared";
|
||||||
|
RuntimeDirectoryMode = "0700";
|
||||||
|
|
||||||
|
# The key setting to ensure the service stays running
|
||||||
Type = "simple";
|
Type = "simple";
|
||||||
ExecStart = "${pkgs.cloudflared}/bin/cloudflared tunnel --config /var/lib/cloudflared/${name}.yml run";
|
ExecStart = "${pkgs.cloudflared}/bin/cloudflared access tcp --hostname ${tunnel.remoteHost} --url ${tunnel.remoteTarget} --port ${toString tunnel.localBindPort} --logfile /var/lib/cloudflared/warp.log";
|
||||||
Restart = "always";
|
Restart = "always";
|
||||||
RestartSec = "5s";
|
RestartSec = "5s";
|
||||||
|
|
||||||
|
# Use systemd's built-in user
|
||||||
User = "cloudflared";
|
User = "cloudflared";
|
||||||
Group = "cloudflared";
|
Group = "cloudflared";
|
||||||
|
|
||||||
|
# Standard outputs
|
||||||
StandardOutput = "journal";
|
StandardOutput = "journal";
|
||||||
StandardError = "journal";
|
StandardError = "journal";
|
||||||
|
|
||||||
# Security hardening
|
|
||||||
ProtectSystem = "strict";
|
|
||||||
ProtectHome = "read-only";
|
|
||||||
PrivateTmp = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Ensure the user exists
|
||||||
|
users.users.cloudflared = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = "cloudflared";
|
||||||
|
description = "Cloudflared service user";
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.cloudflared = {};
|
||||||
}) tunnels;
|
}) tunnels;
|
||||||
|
|
||||||
# Documentation metadata
|
# Activation step to ensure log directory exists
|
||||||
|
system.activationScripts.cloudflaredLogs = lib.stringAfter [ "users" ] ''
|
||||||
|
mkdir -p /var/log/cloudflared
|
||||||
|
chmod 755 /var/log/cloudflared
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Optional documentation metadata
|
||||||
meta.doc = ''
|
meta.doc = ''
|
||||||
This module defines persistent Cloudflare Tunnels using the tunnel command.
|
This module defines persistent cloudflared TCP tunnels using access tcp.
|
||||||
|
Add tunnels by appending to the `tunnels` attribute set.
|
||||||
|
|
||||||
Before using this module:
|
Required keys:
|
||||||
|
- remoteHost: The public hostname exposed via Cloudflare Tunnel.
|
||||||
1. Create a tunnel for each service with:
|
- remoteTarget: The internal service to forward traffic to (e.g. localhost:22).
|
||||||
$ sudo -u cloudflared cloudflared tunnel create <name>
|
- localBindPort: The port to expose locally (e.g. 4401).
|
||||||
|
- logPath: File path to capture logs.
|
||||||
2. Get the tunnel ID with:
|
|
||||||
$ sudo -u cloudflared cloudflared tunnel list
|
|
||||||
|
|
||||||
3. Add the tunnel ID to the corresponding tunnel definition in this file
|
|
||||||
|
|
||||||
4. Create a credentials file for each tunnel at /var/lib/cloudflared/<name>.json
|
|
||||||
This will be created automatically when you create the tunnel
|
|
||||||
|
|
||||||
5. Configure DNS for your hostname to point to the tunnel with:
|
|
||||||
$ sudo -u cloudflared cloudflared tunnel route dns <tunnel-id> <hostname>
|
|
||||||
|
|
||||||
Add more tunnels by adding entries to the tunnels attribute set with:
|
|
||||||
- name: Descriptive name for the tunnel
|
|
||||||
- id: The tunnel ID (from cloudflared tunnel create)
|
|
||||||
- hostname: The hostname to expose via Cloudflare
|
|
||||||
- service: The local service to route to (e.g., ssh://localhost:22)
|
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue