Adding a New Application

Some notes when adding a new application jobspec to Nomad in terraform/nomad/apps.

Traefik

To place the application behind the Traefik reverse proxy, its jobspec should include the service.tags:

tags = [
    "traefik.enable=true",
    "traefik.http.routers.app-proxy.entrypoints=https",
    "traefik.http.routers.app-proxy.tls=true",
    "traefik.http.routers.app-proxy.rule=Host(`app.example.tld`)",
]

Secrets

This section is relevant if the application requires KV secrets from Vault. It uses the Vault Terraform module.

  1. Firstly, add the relevant KV secrets to Vault.

  2. Next, create and add a Vault policy for read-only access to the relevant KV secrets:

# terraform/vault/policies/nomad_app.hcl
path "kvv2/data/prod/nomad/app" {
    capabilities = ["read"]
}

# terraform/vault/policies.tf
resource "vault_policy" "nomad_app" {
    name   = "nomad_app"
    policy = file("policies/nomad_app.hcl")
}
  1. Include the vault and template blocks in the Nomad jobspec:
vault {
    policies = ["nomad_app"]
}

template {
    data        = <<EOF
{{ with secret "kvv2/data/prod/nomad/app" }}
AUTH="{{ .Data.data.username }}":"{{ .Data.data.password }}"
{{ end }}
EOF
    destination = "secrets/auth.env"
    env         = true
}

This will access the Vault secrets and include them as the AUTH environment variable in the job.

Database

This section is relevant if the application requires access to the Postgres database. It uses the Postgres Terraform module.

  1. Add the application name into the postgres_roles variable in terraform/postgres/:
postgres_roles = [
    {
        name = "app"
        rotation_period = 86400
    }
]

This will create a Postgres role and database in the running Postgres instance, a static role in Vault for rotation of the role's credentials, and a Vault policy to read the role's credentials.

  1. Add a template and vault block to access the database credentials:
vault {
    policies = ["app"]
}

template {
    data        = <<EOF
{{ with secret "postgres/static-creds/app" }}
DATABASE_URL = "postgres://foo:{{ .Data.password }}@localhost:5432/foo?sslmode=disable"
{{ end }}
EOF
    destination = "secrets/.env"
    env         = true
}

Diun

Diun allows monitoring a Docker image for new updates. To opt in to watching a task's Docker image, include the diun.enable label:

config {
  labels = {
    "diun.enable" = "true"
  }
}

By default, this will only watch the current tag of the image. If the tag is latest, Diun will send a notification when that tag's checksum changes.

To allow Diun to watch other tags, include additional labels:

config {
  labels = {
    "diun.enable"     = "true"
    "diun.watch_repo" = "true"
    "diun.max_tags"   = 3
  }
}

This will let Diun watch all tags in the Docker repo. It is highly recommended to set a maximum number of tags that Diun should watch, otherwise Diun will watch ALL tags, including older ones.

See Diun for more information on configuring Diun.