Nomad Series - Nomad+Traefik+Tailscale Integration for Zero Trust Security

This article was last updated on: May 17, 2026 am

Series Articles

Overview

Finally, we’ve arrived at the exciting part: Nomad+Traefik+Tailscale integration for zero trust security.

Here:

  • Nomad handles container scheduling (container orchestration tool)
  • Traefik manages ingress traffic (Ingress tool)
  • Tailscale enables cross-region connectivity, Layer 4 encryption, and HTTPS certificate provisioning.

Introduction to Traefik

Traefik is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy.

Traefik integrates with many existing infrastructure components (Docker, Swarm mode, Kubernetes, Marathon, Consul, Etcd, Rancher, Amazon ECS, Nomad…) and configures itself automatically and dynamically.

Traefik Integration with Nomad Native Service

In early May 2023, HashiCorp released Nomad 1.3. Prior to this release, when using service discovery with Nomad, Traefik Proxy users had to use both HashiCorp Consul and Nomad to benefit from Traefik Proxy’s well-known automatic configuration. Now, Nomad has a simple and straightforward way to use built-in service discovery. This greatly improves out-of-the-box usability — not only in simple test environments, but also in edge environments.

Traefik Integration with Tailscale

Starting with the Traefik Proxy 3.0 Beta 1 release, Traefik Proxy supports Tailscale. When Traefik receives an HTTPS request for a *.ts.net site, it obtains the HTTPS certificate from the machine’s local Tailscale daemon (specifically, the Tailscale socket). No certificate configuration is required.

Traefik Summary

In this integration, we use Traefik as the HTTP reverse proxy and load balancer for workloads in the Nomad cluster, integrating with Nomad via Nomad Native Service, and integrating with Tailscale via Traefik Resolver.

Introduction to Tailscale

Tailscale is a V(irtual)P(rivate)N(etwork) service that lets you securely and easily access your devices and applications from anywhere in the world. It uses the open-source WireGuard protocol for encrypted point-to-point connections, meaning only devices on your private network can communicate with each other.

Tailscale is fast and reliable. Unlike traditional V(irtual)P(rivate)N(etwork)s that tunnel all network traffic through a central gateway server, Tailscale creates a peer-to-peer full-mesh network (called a tailnet).

Tailscale provides a range of additional useful features, such as:

By default, (Layer 4) connections between Tailscale nodes are protected by end-to-end encryption. However, browsers, Web APIs, and products like Visual Studio Code are unaware of this and may warn users or disable features based on the fact that HTTP URLs to your tailnet services appear unencrypted because they are not using TLS certificates.

After enabling the following in Tailscale:

  1. tailnet name
  2. MagicDNS
  3. HTTPS Certificates

You can automatically or manually generate certificates for each Tailscale machine. The certificate domain names are as follows:

Tailscale HTTPS Cert

In this integration, we use Tailscale for cross-region connectivity, Layer 4 encryption, and HTTPS certificate provisioning. Cross-region connectivity requires configuration on Nomad; Layer 4 encryption is provided by default; HTTPS certificates require configuration on both Nomad and Traefik.

Nomad+Traefik+Tailscale Integration Architecture

  • Tailscale is installed via package repositories on multiple Linux nodes in the same or different regions, and started via systemd.
  • Nomad is installed on these Linux nodes, with the network interface set to the Tailscale interface — tailscale0.
  • Traefik runs on Nomad as a system type job via Docker, integrating with both Tailscale and Nomad.

Nomad+Traefik+Tailscale Integration Steps

Prerequisites

  • Multiple Linux nodes (preferably in different regions; Ubuntu nodes in this example)
  • These Linux nodes should preferably have distinct hostnames
  • Nomad prerequisites:
    • Docker is installed
    • Nomad is installed (version ≥ 1.3, newer is better)
    • A Nomad cluster is created and running (at least 1 Server and 1 Client)
  • Tailscale prerequisites:
    • A Tailscale account has been created
    • Tailscale version ≥ 1.14 (newer is better)
    • MagicDNS feature is enabled
    • HTTPS certificate feature is enabled
  • Traefik prerequisites:
    • Traefik Proxy version ≥ 3.0 Beta 1

Install and Run Tailscale

On each machine, run the following command to install:

1
curl -fsSL https://tailscale.com/install.sh | sh

For more installation methods, see: Traefik Nomad Service Discovery Routing - Traefik

We won’t go into detail here.

1
sudo tailscale up

Then log in to Tailscale.

Nomad Client Configuration Adjustments

The Nomad Client requires the following configuration adjustments to facilitate subsequent integration with Tailscale and Traefik:

  1. Configure the Tailscale Socket as a Nomad Host Volume (for communication between Traefik running in Docker and Tailscale)
  2. Set the network interface to tailscale0 to use the Tailscale network for east-west traffic.

Modify the client block in /etc/nomad.d/nomoad.hcl as follows:

1
2
3
4
5
6
7
8
9
10
11
12
data_dir  = "/opt/nomad/data"
bind_addr = "0.0.0.0"

client {
enabled = true
servers = ["100.99.99.99"]
network_interface = "tailscale0"
host_volume "tailscale-socket" {
path = "/run/tailscale/tailscaled.sock"
read_only = true
}
}

Detailed explanation:

  • servers = [“100.99.99.99”]: Specifies the server IP list as the corresponding Servers’ Tailscale IP addresses. Replace this address with the actual address(es) of your Nomad Server(s).
  • network_interface = “tailscale0”: Specifies the interface name to force network fingerprinting on. When running in dev mode, this defaults to the loopback interface. When not in dev mode, the interface connected to the default route is used. The scheduler selects from these fingerprinted IP addresses when assigning ports to tasks. Here we specify Nomad to use the Tailscale tunnel interface tailscale0 for network fingerprinting.
  • host_volume “tailscale-socket” {: As described in the previous article, configure a Nomad Host Volume.
    • path = “/run/tailscale/tailscaled.sock”: Tailscale Socket host path.
    • read_only = true: Read-only.

Run the Traefik Job

The Traefik Job HCL — traefik.hcl is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
job "traefik" {
datacenters = ["dc1"]
type = "system"

group "traefik" {

network {
port "http"{
static = 80
}
port "https" {
static = 443
}
port "admin"{
static = 8080
}
}

service {
name = "traefik-http"
provider = "nomad"
port = "http"
}

service {
name = "traefik-https"
provider = "nomad"
port = "https"
}

volume "tailscale-socket" {
type = "host"
read_only = true
source = "tailscale-socket"
}

task "server" {
driver = "docker"
volume_mount {
volume = "tailscale-socket"
destination = "/var/run/tailscale/tailscaled.sock"
read_only = true
}
config {
image = "traefik:v3.0"
ports = ["admin", "http", "https"]
args = [
"--api.dashboard=true",
"--api.insecure=true", ### For Test only, please do not use that in production
"--entrypoints.web.address=:${NOMAD_PORT_http}",
"--entryPoints.websecure.address=:${NOMAD_PORT_https}",
"--entrypoints.traefik.address=:${NOMAD_PORT_admin}",
"--providers.nomad=true",
"--providers.nomad.endpoint.address=http://100.99.99.99:4646", ### Tailscale IP to your nomad server
"--certificatesresolvers.tailscaleresolver.tailscale=true"
]
}
}
}
}

Detailed explanation:

  • type = “system”: Every client in the datacenter and node pool receives an allocation. Similar to a Kubernetes DaemonSet.
  • network {} Network block — here we specify 3 static ports (similar to HostSubnet in Kubernetes), meaning both the container and the host listen on:
    • http port 80
    • https port 443
    • admin Traefik admin port 8080 (since the underlying network is Tailscale, HTTP traffic is actually transparently encrypted at Layer 4)
  • service {} Two Service blocks, both using Nomad Native Service:
    • traefik-http service: points to the http port — 80
    • traefik-https service: points to the https port — 443
  • volume “tailscale-socket” { Declares the Tailscale Socket via Nomad Host Volume
    • type = “host”: Volume type is Nomad Host Volume
    • read_only = true: Volume-level read-only configuration
    • source: Points to the Nomad Client’s tailscale-socket, i.e., the /run/tailscale/tailscaled.sock path
  • driver = “docker”: Traefik actually runs inside Docker
  • volume_mount {: Volume mount configuration:
    • destination = “/var/run/tailscale/tailscaled.sock”: Mounts the Tailscale Socket to the /var/run/tailscale/tailscaled.sock path inside the container.
  • config { Docker configuration block.
    • image = “traefik:v3.0”: Specifies the Traefik image as traefik:v3.0
    • ports = [“admin”, “http”, “https”]: Exposed ports are 80, 443, and 8080
    • args [: Traefik startup arguments
      • “–api.dashboard=true”: Enable the Traefik Dashboard
      • “–api.insecure=true”: For testing only — do not use in production
      • “–entrypoints.web.address=:${NOMAD_PORT_http}”: Sets the Traefik web port to the NOMAD_PORT_http environment variable, i.e., 80. The address is :80 (listening on all interfaces)
      • “–entryPoints.websecure.address=:${NOMAD_PORT_https}”: Sets the Traefik websecure address to :443
      • “–entrypoints.traefik.address=:${NOMAD_PORT_admin}”: Sets the Traefik admin address to :8080
      • “–providers.nomad=true”: Enables Traefik integration with Nomad
      • “–providers.nomad.endpoint.address=http://100.99.99.99:4646”: Specifies the Nomad Server address
      • “–certificatesresolvers.tailscaleresolver.tailscale=true”: Enables Traefik integration with Tailscale. Creates a Traefik Resolver named tailscaleresolver that integrates with Tailscale.

Run the job:

1
nomad run traefik.hcl

Traefik will then be deployed to all Nomad Clients.

At this point, we have completed the Nomad+Traefik+Tailscale integration. 🎉🎉🎉

Verifying the Nomad+Traefik+Tailscale Integration

Verification via Traefik Dashboard

First, open the Traefik Dashboard at http://100.99.99.99. The result is as follows:

Traefik Integrated with Nomad

From the screenshot above, we can see:

  • The Traefik version is above 3.0 Beta 1 — specifically 3.0.0-beta3
  • Traefik is listening on ports 80, 443, and 8080
  • Traefik is integrated with Nomad — the Providers section shows Nomad.

Verification by Creating a Nomad Service

We use another demo application provided by HashiCorp Nomad: HashiCups, with configuration adjustments:

1
2
3
git clone https://github.com/hashicorp/learn-nomad-sd.git
cd learn-nomad-sd
git checkout tags/v0.1 -b nomad-hashicups-sd

Modify the following content in hashicups.hcl (some content omitted):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
job "hashicups" {
type = "service"

...
group "nginx" {
network {
port "nginx" {
to = var.nginx_port
}
}
task "nginx" {
driver = "docker"
service {
name = "nginx"
provider = "nomad"
port = "nginx"
tags = [
"traefik.http.routers.hashicups.rule=Host(`firefly-sub03.west-beta.ts.net`)",
"traefik.http.routers.hashicups.tls.certResolver=tailscaleresolver"
]
}
...
}
}
}

Detailed explanation:

  • to = var.nginx_port: 🐾 Note that this is changed from static to to to avoid host port conflicts. The host port will be randomly assigned.
  • service {: The service block — here provider = “nomad”. Traefik retrieves Nomad Native Services via the Nomad Server API and obtains specific routing configuration through tags.
1
2
3
4
tags = [
"traefik.http.routers.hashicups.rule=Host(`firefly-sub03.west-beta.ts.net`)",
"traefik.http.routers.hashicups.tls.certResolver=tailscaleresolver"
]

This follows Traefik’s configuration style. When Traefik integrates with Nomad, the Nomad tags configuration style is exactly the same as Traefik’s Docker integration configuration style.

  • traefik.http.routers.hashicups.rule=Host(…) Creates a hashicups router and specifies the domain. Here I specified the full Tailscale domain of one of my Nomad Client nodes: firefly-sub03.west-beta.ts.net. The .west-beta.ts.net part is my dedicated domain — if you’re configuring this, adjust it according to the domain obtained from your Tailscale Admin Console. firefly-sub03 is the hostname of one of my Linux nodes, which has nomad client, tailscale, and traefik installed.
  • “traefik.http.routers.hashicups.tls.certResolver=tailscaleresolver” Specifies the TLS certificate resolver for this router as tailscaleresolver, i.e., Tailscale.

The results are as follows:

The Traefik Dashboard shows:

Traefik Dashboard - hashicups router
△ As shown, the Nomad nginx service is accessible via both http://firefly-sub03.west-beta.ts.net/ and https://firefly-sub03.west-beta.ts.net/. TLS is enabled with the tailscaleresolver Resolver.

Traefik Dashboard - hashicups nginx service
△ As shown, the address automatically assigned by Nomad for the nginx service is http://100.74.143.10:25061 — a random port (in my setup, Nomad networking uses host mode rather than bridge mode).

Accessing https://firefly-sub03.west-beta.ts.net/ directly via the Tailscale internal network:

HashiCups Demo with https cert

△ As shown, HashiCups is accessible via the domain name, and the HTTPS certificate for this domain is trusted.

🎉🎉🎉

Summary

In this article, we achieved zero trust security through Nomad+Traefik+Tailscale integration.

Here:

  • Nomad handles container scheduling (container orchestration tool)
  • Traefik manages ingress traffic (Ingress tool)
  • Tailscale enables cross-region connectivity, Layer 4 encryption, and HTTPS certificate provisioning.

Specifically, in this integration:

  • Traefik serves as the HTTP reverse proxy and load balancer for workloads in the Nomad cluster, integrating with Nomad via Nomad Native Service, and integrating with Tailscale via Traefik Resolver.
  • Tailscale provides cross-region connectivity, Layer 4 encryption, and HTTPS certificate provisioning.
    • Cross-region connectivity requires configuration on Nomad.
    • Layer 4 encryption is provided by default.
    • HTTPS certificates require configuration on both Nomad and Traefik.

Moreover, this solution is particularly well-suited for edge environments:

  • Nomad provides simple and lightweight (container) orchestration for edge clusters.
  • Traefik provides Layer 4 and Layer 7 load balancing as well as Layer 7 HTTP proxy services for edge clusters.
  • Tailscale provides tunnel connectivity across “cloud”, “edge”, and “endpoint” for edge clusters, enabling network connectivity and edge network encryption. It also automatically provisions trusted certificates for HTTPS.

📚️ References


Nomad Series - Nomad+Traefik+Tailscale Integration for Zero Trust Security
https://e-whisper.com/posts/12244/
Author
east4ming
Posted on
September 4, 2023
Licensed under