Jump to content

Cloudflared

From Official NixOS Wiki
Revision as of 04:41, 31 May 2026 by Phobos (talk | contribs) (clarified steps)

Cloudflared is a command line client that can be used to establish a network tunnel from the Cloudflare network to a server.

Cloudflare Tunnel

Prerequisites

If you do not wish to install cloudflared you may use a nix-shell to use it for the following steps without adding it to your configuration.

$ nix-shell -p cloudflared

You will need to log in to your Cloudflare account through the command line, the following command will open a web browser to allow you to log in:

$ cloudflared -- tunnel login

You can use the link it provides on any machine that has a browser in order to get the needed cert.pem file. Afterwards you will need to create the tunnel from the machine.

$ cloudflared tunnel create <tunnel-name-of-choice>

The command will output the tunnel ID in the format 00000000-0000-0000-0000-000000000000, which will be needed for setting up the tunnel service. The following example uses flakes and sops-nix to hide the credentials file secret.

❄︎ cloudflare_tunnel.nix
{
  inputs,
  config,
  ...
}: {

  imports = [
    inputs.sops-nix.nixosModules.sops
  ];

  sops = {
    age.keyFile = "/home/username/.config/sops/age/keys.txt";
    defaultSopsFile = secrets/secrets.yaml;

    secrets."cloudflared-creds" = {
      owner = "username";
      group = "users";
      mode = "0400";
    };
  };

  services.cloudflared = {
    enable = true;
    tunnels = {
      "00000000-0000-0000-0000-000000000000" = {
        credentialsFile = "${config.sops.secrets.cloudflared-creds.path}";
        default = "http_status:404";
      };
    };
  };
}

Then you can use the dashboard to add your public hosts (will need to convert the new tunnel to dashboard-managed).

Alternatively, save the cert.pem to cloudflared user's %home%/.cloudflared/cert.pem, and instead of using dashboard specify ingress rules in your configuration.nix like this:

{
  services.cloudflared = {
    enable = true;
    tunnels = {
      "00000000-0000-0000-0000-000000000000" = {
        credentialsFile = "${config.sops.secrets.cloudflared-creds.path}";
        ingress = {
          "*.domain1.com" = {
            service = "http://localhost:80";
            path = "/*.(jpg|png|css|js)";
          };
          "*.domain2.com" = "http://localhost:80";
        };
        default = "http_status:404";
      };
    };
  };
}

Troubleshooting

At the moment (2025), for support of browser rendering of the tunnels, this line is required:

services.openssh.settings.Macs = [
  # Current defaults:
  "hmac-sha2-512-etm@openssh.com"
  "hmac-sha2-256-etm@openssh.com"
  "umac-128-etm@openssh.com"
  # Added:
  "hmac-sha2-256"
];

The issue has been reported on Github