Courier Configuration Reference¶
The Courier is configured entirely via a single YAML file. By default it is named config.yaml in the current directory; override with the --config / -c flag.
courier --config /etc/courier/production.yaml generate
The file has four top-level sections: api, auth, certificate, and logging.
Table of Contents¶
- CLI Reference
- api — API Connection
- auth — Authentication
- client_secret
- certificate
- azure_jwt
- azure_arc
- aws_oidc
- spiffe
- oidc_jwt
- none
- certificate — Certificate Options
- logging — Logging
- Complete Example
- Auth Method Quick Reference
1. CLI Reference¶
courier [OPTIONS] [COMMAND]
Options:
| Flag | Short | Default | Description |
|---|---|---|---|
--config <PATH> |
-c |
config.yaml |
Path to the YAML configuration file |
--verbose |
-v |
off | Promotes log level from info to debug. Has no effect if the config level is already debug or higher. |
--help |
-h |
— | Print help |
--version |
-V |
— | Print version |
Commands:
| Command | Description | Requires auth | Requires certificate section |
|---|---|---|---|
check-api-health |
Check connectivity to the API | No | No |
check-health |
Alias for check-api-health |
No | No |
check-api-auth |
Validate credentials against the API | Yes | No |
status |
Check certificate lifecycle status | Yes | Yes |
generate |
Generate a new certificate | Yes | Yes |
generate-keys |
Generate a local key pair only, no API calls | No | Yes |
validate-config |
Validate the config file and print a summary | No | No |
renew |
Force certificate renewal | — | — |
When no command is given, the default command is determined by the api.action field in the configuration file (see api — API Connection).
Note: The
renewcommand is not yet implemented. Running it will return an error. To renew a certificate, use thegeneratecommand, which issues a new certificate using the subject configuration.
Exit codes: 0 = success, 1 = any error (config load failure, auth failure, API error, etc.).
2. api — API Connection¶
Controls how the Courier reaches the Zaita control plane.
api:
base_url: https://au.zaita.com
version: v1
timeout_seconds: 30
verify_tls: true
uuid: "your-courier-uuid"
action: check_health
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
base_url |
string | Yes | — | Base URL of the Zaita control plane or Bridge. Must not be empty. |
version |
string | No | v1 |
API version prefix used in all request paths. |
timeout_seconds |
integer | No | 30 |
Per-request HTTP timeout in seconds. |
verify_tls |
bool | No | true |
Whether to verify the server's TLS certificate. Set false only for self-signed or internal CAs in isolated development environments. |
uuid |
string | No | — | Courier UUID. Used as the UUID source for auth methods that do not include their own uuid field (azure_jwt, aws_oidc, spiffe). Not required when the UUID is carried in the auth block. See Auth Method Quick Reference. |
action |
enum | No | check_health |
Default command to run when no subcommand is specified on the CLI. |
Valid action values:
| Value | Equivalent command |
|---|---|
check_health |
check-api-health |
check_auth |
check-api-auth |
provision_certificate |
generate |
renew_certificate |
renew (not yet implemented) |
3. auth — Authentication¶
Exactly one auth block is required. The method field selects which variant is used.
In addition to the method-specific fields, every auth block accepts one optional shared field:
| Field | Type | Required | Description |
|---|---|---|---|
on_failure |
string | No | Shell command to run when authentication fails before the process exits. Useful for alerting or triggering remediation. Executed via sh -c on Unix or cmd /C on Windows. A non-zero exit code from the hook is logged as a warning and does not change the Courier's own exit code. |
3.1 client_secret¶
Authenticates with a pre-issued client ID and secret pair.
auth:
method: client_secret
uuid: "your-courier-uuid"
client_id: "cour_EZaon9BpoifhjkNEaxinZQNh6UNzaGrU"
client_secret: "pV8nPaQ3SrjJPp0Ven1oE2oblPudYXSLcmQ8OXb9j7IxYyVqPFK1c6jyfkZSkgc6"
| Field | Required | Description |
|---|---|---|
uuid |
Yes | The Courier's UUID as registered in the control plane. |
client_id |
Yes | The cour_-prefixed client ID issued when the Courier was created. |
client_secret |
Yes | The client secret. Shown only once at creation time. |
3.2 certificate (X.509)¶
Authenticates using a pre-registered X.509 client certificate. The certificate fingerprint must match the one registered in the control plane. The certificate is presented via TLS proxy headers — it is not sent in the request body.
auth:
method: certificate
uuid: "your-courier-uuid"
cert_path: /etc/ssl/courier/client.crt
key_path: /etc/ssl/courier/client.key
| Field | Required | Description |
|---|---|---|
uuid |
Yes | The Courier's UUID. |
cert_path |
Yes | Path to the PEM-encoded client certificate file. |
key_path |
Yes | Path to the PEM-encoded private key file for the client certificate. |
3.3 azure_jwt¶
Authenticates using an Azure Workload Identity JWT. Designed for workloads running inside Azure Kubernetes Service (AKS) or Azure virtual machines with workload identity or managed identity configured.
api:
uuid: "your-courier-uuid" # UUID comes from api.uuid for this method
auth:
method: azure_jwt
tenant_id: "your-azure-tenant-id"
client_id: "your-azure-client-id"
token_file: /var/run/secrets/azure/tokens/azure-identity-token # optional
| Field | Required | Description |
|---|---|---|
api.uuid |
Yes | The Courier's UUID — set in the api section, not here. |
tenant_id |
Yes | Azure AD tenant ID. |
client_id |
Yes | Azure application (client) ID or managed identity client ID. |
token_file |
No | Path to the projected token file. Defaults to the AZURE_FEDERATED_TOKEN_FILE environment variable, then /var/run/secrets/azure/tokens/azure-identity-token. |
3.4 azure_arc¶
Authenticates using the Azure Arc Hybrid Instance Metadata Service (HIMDS). For Windows and Linux servers enrolled in Azure Arc.
auth:
method: azure_arc
uuid: "your-courier-uuid"
resource: "https://management.azure.com/" # optional
himds_port: 40342 # optional
| Field | Required | Description |
|---|---|---|
uuid |
Yes | The Courier's UUID. |
resource |
No | Azure resource URI (audience) for the token request. Defaults to https://management.azure.com/. |
himds_port |
No | Override the HIMDS local port. Defaults to 40342. |
Token flow: The Courier contacts http://localhost:{himds_port}/metadata/identity/oauth2/token, reads the challenge file path from the WWW-Authenticate response header, reads the challenge file from the local filesystem (proving machine access), then re-submits to receive an Azure access token.
Challenge file locations:
- Linux: /var/opt/azcmagent/tokens/
- Windows: %ProgramData%\AzureConnectedMachineAgent\Tokens\
3.5 aws_oidc¶
Authenticates using an AWS IAM OIDC identity token. Designed for workloads running in EKS with IAM Roles for Service Accounts (IRSA) configured, or on-premises servers using IAM Roles Anywhere.
api:
uuid: "your-courier-uuid" # UUID comes from api.uuid for this method
auth:
method: aws_oidc
role_arn: "arn:aws:iam::123456789:role/your-role"
region: "us-east-1"
| Field | Required | Description |
|---|---|---|
api.uuid |
Yes | The Courier's UUID — set in the api section, not here. |
role_arn |
Yes | The IAM role ARN. Sent in the auth payload for the control plane to validate. |
region |
Yes | AWS region. |
The token is read from the AWS_WEB_IDENTITY_TOKEN_FILE environment variable path, defaulting to /var/run/secrets/eks.amazonaws.com/serviceaccount/token.
3.6 spiffe¶
Authenticates using a SPIFFE JWT-SVID obtained from a local SPIRE agent.
api:
uuid: "your-courier-uuid" # UUID comes from api.uuid for this method
auth:
method: spiffe
workload_api_socket: "unix:///tmp/spire-agent/public/api.sock"
| Field | Required | Description |
|---|---|---|
api.uuid |
Yes | The Courier's UUID — set in the api section, not here. |
workload_api_socket |
Yes | Path to the SPIRE agent workload API Unix socket. |
The SVID file path can be overridden via the SPIFFE_SVID_PATH environment variable.
3.7 oidc_jwt¶
Authenticates using a generic OIDC JWT obtained from a configurable token endpoint. Useful for custom identity providers or testing with custom JWT issuers.
auth:
method: oidc_jwt
uuid: "your-courier-uuid"
token_endpoint: "https://your-idp.example.com/token"
resource: "api://zaita-courier" # optional
client_id: "courier-client" # optional
| Field | Required | Description |
|---|---|---|
uuid |
Yes | The Courier's UUID. |
token_endpoint |
Yes | URL to fetch a JWT from. The Courier makes a GET request with resource and client_id as query parameters if provided. Response must be {"access_token": "...", ...}. |
resource |
No | Audience or resource value to include in the token request. |
client_id |
No | Client ID to include in the token request. |
3.8 none¶
Disables authentication. Only valid for check-api-health operations or local development.
auth:
method: none
No additional fields. Attempting to use any authenticated command with this method will return an error.
4. certificate — Certificate Options¶
Required for generate and status operations. Not required for check-api-health, check-api-auth, or validate-config.
certificate:
uuid: "aa0ec92b-ee25-4def-b512-13944a2782ad"
output_dir: /etc/ssl/zaita
cert_filename: certificate
key_filename: private_key
full_chain_filename: full_chain
my_private_key_filename: my_private_key.prv # optional override
my_public_key_filename: my_public_key.pub # optional override
generate_keys_locally: true
key_algorithm: rsa
key_size: 4096
digest: sha-512
certificate_validity_period: 90
renewal_threshold_days: 30
common_name: "api.example.com"
subject_alternative_names: "www.example.com, api.example.com"
organization: "Example Org"
organizational_unit: "IT Department"
country: "AU"
state: "New South Wales"
locality: "Sydney"
key_usage: "Digital Signature, Key Encipherment"
extended_key_usage: "Server Authentication"
on_success: "/bin/bash -c /usr/local/bin/restart_nginx.sh"
on_failure: "/bin/bash -c 'logger courier certificate failure'"
4.1 Identification¶
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
uuid |
string | No | — | UUID of an existing certificate. When provided, status lookups target this specific certificate directly rather than searching by subject fields. |
4.2 Output Files¶
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
output_dir |
string | Yes | — | Directory where certificate and key files are written. Created automatically with 700 permissions if it does not exist. |
cert_filename |
string | No | certificate |
Base name for the certificate file. Extension .pem is appended automatically. Produces {output_dir}/{cert_filename}.pem. |
key_filename |
string | No | private_key |
Base name for the private key file. Extension .pem is appended automatically. Produces {output_dir}/{key_filename}.pem. Also used to derive the public key filename as {key_filename}_pub.pem unless my_public_key_filename is set. |
full_chain_filename |
string | No | full_chain |
Base name for the full certificate chain file. Extension .pem is appended automatically. Produces {output_dir}/{full_chain_filename}.pem. Used when generate_keys_locally: false — contains the end-entity certificate concatenated with all intermediate certificates from the PFX bundle returned by the control plane. |
my_private_key_filename |
string | No | — | Full filename including extension for the private key (e.g. my_key.prv). When set, overrides the {key_filename}.pem default. |
my_public_key_filename |
string | No | — | Full filename including extension for the public key (e.g. my_key.pub). When set, overrides the {key_filename}_pub.pem default. |
Private key files are written with 600 permissions. Public key files are written with 644 permissions. The output directory is created with 700 permissions.
4.3 Key Generation¶
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
generate_keys_locally |
bool | No | true |
When true, the Courier generates the key pair locally, creates a CSR, and submits only the CSR for signing. The private key never leaves the host. When false, the control plane generates the key pair server-side; the private key and certificate are returned as an encrypted PFX bundle. |
key_algorithm |
enum | No | rsa |
Key algorithm. Valid values: rsa, ecdsa. |
key_size |
integer | No | 0 (defaults to RSA 2048) |
Key size or curve. For RSA: 2048, 3072, 4096. For ECDSA: 256 (P-256), 384 (P-384), 521 (P-521). When 0 or unset, defaults to RSA 2048. |
4.4 Certificate Parameters¶
These fields populate the certificate subject and are sent to the control plane as part of the generation request. All are optional — the control plane applies its own defaults for any unspecified fields, subject to tenant policy.
| Field | Type | Default | Description |
|---|---|---|---|
digest |
string | server default | Digest algorithm. Values: sha-256, sha-384, sha-512. |
certificate_validity_period |
integer | server default (90) | Requested certificate validity in days. Range: 1–825. May be overridden by tenant policy. |
renewal_threshold_days |
integer | 30 |
Number of days before expiry at which the status command reports needs_renewal: true. |
common_name |
string | — | Certificate CN (Common Name). Required for generate. |
subject_alternative_names |
string | — | Comma-separated SANs. Example: "www.example.com, api.example.com, 192.168.1.10". |
organization |
string | — | Certificate subject Organization (O). |
organizational_unit |
string | — | Certificate subject Organizational Unit (OU). |
country |
string | — | Two-letter ISO 3166-1 country code (e.g. AU, NZ, US). |
state |
string | — | State or province. |
locality |
string | — | City or locality. |
4.5 Key and Extended Key Usage¶
Both fields accept comma-separated values in either human-readable or OpenSSL format. The Courier normalises them to OpenSSL format before sending to the control plane.
key_usage — Default: "digitalSignature, keyEncipherment"
| Human-readable | OpenSSL format |
|---|---|
Digital Signature |
digitalSignature |
Key Encipherment |
keyEncipherment |
Content Commitment / Non Repudiation |
nonRepudiation |
Data Encipherment |
dataEncipherment |
Key Agreement |
keyAgreement |
Key Cert Sign |
keyCertSign |
CRL Sign |
cRLSign |
Encipher Only |
encipherOnly |
Decipher Only |
decipherOnly |
extended_key_usage — Default: "serverAuth"
| Human-readable | OpenSSL format |
|---|---|
Server Authentication |
serverAuth |
Client Authentication |
clientAuth |
Code Signing |
codeSigning |
Email Protection |
emailProtection |
Time Stamping |
timeStamping |
OCSP Signing |
OCSPSigning |
Any Extended Key Usage |
anyExtendedKeyUsage |
IPSEC End System |
ipsecEndSystem |
IPSEC Tunnel |
ipsecTunnel |
IPSEC User |
ipsecUser |
4.6 Hooks¶
Hook commands are executed via the system shell (sh -c on Linux/macOS, cmd /C on Windows) after a certificate operation completes. Hook failures are logged as warnings and never affect the exit code of the Courier.
| Field | Type | Default | Description |
|---|---|---|---|
on_success |
string | — | Shell command to run after a successful certificate generation. Typically used to install the certificate and reload or restart the dependent service. |
on_failure |
string | — | Shell command to run after a failed certificate generation. Typically used to send an alert. |
Examples:
on_success: "/bin/bash -c /usr/local/bin/restart_nginx.sh"
on_failure: "logger -t courier 'certificate renewal failed'"
on_success: "/bin/bash -c 'systemctl reload nginx && echo ok > /tmp/courier_last_run'"
5. logging — Logging¶
logging:
level: info
file: /var/log/courier.log # optional
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
level |
string | No | info |
Log verbosity. Valid values: trace, debug, info, warn, error. The --verbose / -v CLI flag promotes info to debug at runtime without changing this value. |
file |
string | No | — | Path to write logs to. When not set, logs are written to stdout. |
The log level can also be overridden at runtime via the RUST_LOG environment variable, which takes precedence over both the config file and --verbose.
6. Complete Example¶
# Zaita Courier — production configuration example
api:
base_url: https://au.zaita.com
version: v1
timeout_seconds: 30
verify_tls: true
auth:
method: client_secret
uuid: "86675abd-7b03-4eea-a5bd-15ef9076b9bb"
client_id: "cour_EZaon9BpoifhjkNEaxinZQNh6UNzaGrU"
client_secret: "pV8nPaQ3SrjJPp0Ven1oE2oblPudYXSLcmQ8OXb9j7IxYyVqPFK1c6jyfkZSkgc6"
certificate:
output_dir: /etc/ssl/zaita
cert_filename: certificate
key_filename: private_key
full_chain_filename: full_chain
generate_keys_locally: true
key_algorithm: rsa
key_size: 4096
digest: sha-512
certificate_validity_period: 90
renewal_threshold_days: 30
common_name: "api.example.com"
subject_alternative_names: "www.example.com, api.example.com"
organization: "Example Org"
organizational_unit: "IT Department"
country: "AU"
state: "New South Wales"
locality: "Sydney"
key_usage: "Digital Signature, Key Encipherment"
extended_key_usage: "Server Authentication"
on_success: "/bin/bash -c /usr/local/bin/restart_nginx.sh"
on_failure: "logger -t courier 'certificate operation failed'"
logging:
level: info
# file: /var/log/courier.log
7. Auth Method Quick Reference¶
| Method | UUID source | Token source | Auth payload |
|---|---|---|---|
client_secret |
auth.uuid |
Config fields | uuid + client_id + client_secret |
certificate |
auth.uuid |
TLS handshake (proxy header) | uuid only |
azure_jwt |
api.uuid |
Projected token file / AZURE_FEDERATED_TOKEN_FILE |
uuid + token |
azure_arc |
auth.uuid |
HIMDS challenge flow | uuid + token |
aws_oidc |
api.uuid |
AWS_WEB_IDENTITY_TOKEN_FILE |
uuid + token + provider + role_arn |
spiffe |
api.uuid |
SPIFFE_SVID_PATH / socket path |
uuid + svid |
oidc_jwt |
auth.uuid |
token_endpoint GET |
uuid + token |
none |
— | — | (not valid for authenticated commands) |