Skip to main content

Task JWT issuance

Semaphore can mint a short-lived JSON Web Token (JWT) for every task execution. The token is signed by Semaphore and exposed to the playbook (or shell/Terraform/PowerShell/Python script) as the SEMAPHORE_JWT environment variable.

Together with the JWKS endpoint that Semaphore publishes, the token lets external systems authenticate a task without any pre-shared secret.

This page describes the server-side configuration. For per-template configuration and consumption inside a task, see the user guide page on task JWTs.


How it works​

Signing uses an ECDSA P-256 key pair. The private key is generated on first use, encrypted with the same access_key_encryption key that protects other secrets, and stored in the Semaphore database. The public key is served via the JWKS endpoint.


Configuration​

JWT issuance is disabled by default. Enable it in your config.json:

{
"jwt": {
"enabled": true,
"issuer": "https://semaphore.example.com",
"default_ttl": "1h",
"max_ttl": "24h"
}
}
OptionDefaultDescription
jwt.enabledfalseWhen false, no tokens are minted and the JWKS endpoint returns 404.
jwt.issuernoneValue emitted in the iss claim. Set this to a stable URL that identifies your Semaphore instance - external systems use it as a trust anchor.
jwt.default_ttl1hToken lifetime used when a template does not override it. Accepts Go-style durations (30m, 1h, 90m, ...).
jwt.max_ttl24hMaximum lifetime a token can have. Templates can't override the TTL with a value higher than this.
tip

The signing key is encrypted at rest with the access_key_encryption key. Make sure this option is configured before you enable JWTs. The key is generated on first start and can not be re-encrypted afterwards.


JWKS endpoint​

When JWT issuance is enabled, Semaphore exposes its public signing key at:

GET /.well-known/jwks.json

The response follows RFC 7517 and can be consumed directly by the JWT verifier:

curl https://semaphore.example.com/.well-known/jwks.json
{
"keys": [
{
"kty": "EC",
"crv": "P-256",
"kid": "...",
"use": "sig",
"alg": "ES256",
"x": "...",
"y": "..."
}
]
}

Key rotation​

The signing key is created automatically when starting Semaphore with the JWT feature enabled. To rotate it, remove the jwt_signing_key row from the option table and restart Semaphore. A fresh key pair will be created automatically.

Because rotation invalidates all previously issued tokens, do this only when no existing token is in use anymore (e.g. no active running tasks)