Nomad

Install Nomad with hashi-up (Single Node)

hashi-up nomad install \
  --ssh-target-addr 192.168.1.10 \
  --ssh-target-user ubuntu \
  --ssh-target-key ~/.ssh/id_ed25519 \
  --server

Replace the IP address, username, and SSH key path with your environment details.

Enable Podman Task Driver & Raw exec plugin in Nomad

Make sure you have Podman installed. Edit the nomad configuration file (/etc/nomad.d/nomad.hcl) and add the following:

# generated with hashi-up

datacenter = "dc1"
data_dir   = "/opt/nomad"
plugin_dir = "/opt/nomad/data/plugins"

server {
  enabled          = true
  bootstrap_expect = 1
}

plugin "nomad-driver-podman" {
  enabled = true
}

plugin "raw_exec" {
  config {
    enabled = true
  }
}

client {
  enabled = true
}

Restart Nomad to apply the changes.

sudo systemctl restart nomad

Check that the Podman and Raw exec driver is enabled:

nomad node status -self -short | grep Drivers
CSI Drivers     = <none>
Drivers         = exec,java,podman,qemu,raw_exec

Deploy Traefik with Nomad and Enable Nomad Service Discovery

Create a Nomad job file (e.g., traefik.nomad) with the following content:

job "traefik" {
  datacenters = ["dc1"]
  type        = "service"

  group "traefik" {
    count = 1

    network {
      port "http" {
        static = 8080
      }
      port "admin" {
        static = 8081
      }
    }

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

    task "server" {
      driver = "podman"

      config {
        image = "docker.io/traefik:v2.11.2"
        ports = ["admin", "http"]
        args = [
          "--api.dashboard=true",
          "--api.insecure=true", # Do not expose to the internet!
          "--entrypoints.web.address=:${NOMAD_PORT_http}",
          "--entrypoints.traefik.address=:${NOMAD_PORT_admin}",
          "--providers.nomad=true",
          "--providers.nomad.endpoint.address=http://${NOMAD_IP_http}:4646",
          "--providers.nomad.exposedByDefault=false"
        ]
      }
    }
  }
}

Deploy the job:

nomad job run traefik.nomad

Deploy a Demo Web Application (with Nomad Service Discovery and Traefik Routing):

Create a Nomad job file (e.g., demo-webapp.nomad) with the following content:

job "demo-webapp" {
  datacenters = ["dc1"]

  group "demo" {
    count = 3

    network {
      port "http" {
        to = -1 # Dynamic port allocation
      }
    }

    service {
      name     = "demo-webapp"
      port     = "http"
      provider = "nomad"
      tags = [
        "traefik.enable=true",
        "traefik.http.routers.demo-webapp-http.rule=Host(`demo-webapp-192-168-1-10.sslip.io`)",
        "traefik.http.routers.demo-webapp-http.tls=false"
      ]

      check {
        type     = "http"
        path     = "/"
        interval = "2s"
        timeout  = "2s"
      }
    }

    task "server" {
      env {
        PORT   = "${NOMAD_PORT_http}"
        NODEIP = "${NOMAD_IP_http}"
      }

      driver = "podman"

      config {
        image = "docker.io/hashicorp/demo-webapp-lb-guide"
        ports = ["http"]
      }
    }
  }
}

Deploy the job:

nomad job run demo-webapp.nomad

Once deployed, Traefik will automatically discover the demo-webapp service via the Nomad provider and route traffic to all running instances. You can test load balancing by sending HTTP requests to the configured hostname and port.

curl http://demo-webapp-192-168-1-10.sslip.io:8080
# Output example:
# Welcome! You are on node 192.168.1.10:20190

Repeat the request several times to see responses from different containers, indicating load balancing is working.