Task needs to bind on privileged ports

Question: What is the best way to give a task the required access it needs for binding to privileged ports?


I am created a Nomad job with a task that needs to bind to the privileged ports 80 and 443.

In the Nomad jobs list, the is reported as “running”.

When I view the task logs I see the following:

 [WARN] Unable to listen: [listen tcp :443: bind: permission denied]
 [WARN] Unable to listen: [listen tcp :80: bind: permission denied]

If I run sudo netstat -tunlp | grep 80 on the Nomad client it does not show any process using either port 80 or 443.

My guess is that because the task is not being run as root (the process owner shows nobody), it does not have the permissions it needs to bind to those privileged ports.

Here is a minimal version of my job definition:

job "web-api" {

  group "primary" {
    count = 1

    network {
      port "http" {
        static       = 80
        host_network = "public"
      }
      port "https" {
        static       = 443
        host_network = "public"
      }

    }

    service {
      name = "web-api"
      port = "http"
    }
    service {
      name = "web-api"
      port = "https"
    }

    task "main" {
      driver = "exec"
      config {
        command = "${NOMAD_ALLOC_DIR}/web-api"
      }

    }

  }
}

Try adding to your config stanza the following line:

config {
  cap_add = ["net_bind_service"]
}

Docs: Drivers: Exec | Nomad by HashiCorp

Related issue (out of date): https://github.com/hashicorp/nomad/issues/5528

@pphysch, good suggestion. I tried adding that capability to the exec config and it did not seem to have any effect. The app still received the bind: permission denied error. I also tried adding the “net_raw” capability, and it quickly informed me that exec is not allowed to use that capability. :thinking:

Is your web app command a binary or an interpreted script?

The application is a binary.

For now I have bypassed this limitation by using the raw_exec driver.