Skip to content

Courier Examples and Tutorials

This page provides worked configuration examples for common Courier deployment scenarios. Each example includes a complete YAML configuration and notes on any environment-specific requirements.

For a full description of every configuration option, see the Courier Configuration Reference.


Example 1: Linux Server — Local Key Generation via Bridge

A Courier running on a Linux server with no direct internet access, routing through a Bridge, generating keys locally, and restarting Nginx on successful renewal.

api:
  base_url: https://bridge-prod-01.internal.example.com
  version: v1
  timeout_seconds: 30
  verify_tls: true
  retries: 3
  retry_backoff: 60

auth:
  uuid: cour_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  method: client_secret
  client_id: ${ZAITA_CLIENT_ID}
  client_secret: ${ZAITA_CLIENT_SECRET}

certificate:
  output_dir: /etc/ssl/zaita
  cert_filename: nginx-cert
  key_filename: nginx-key
  generate_keys_locally: true
  key_algorithm: ecdsa
  key_size: 384
  digest: sha-384
  certificate_validity_period: 90
  renewal_threshold_days: 30
  common_name: "web.example.com"
  subject_alternative_names: "www.web.example.com"
  organization: "Example Org"
  country: "AU"
  on_success: "/bin/bash /opt/scripts/restart-nginx.sh"
  on_failure: "/bin/bash /opt/scripts/alert.sh"

logging:
  level: info
  file: /var/log/zaita-courier.log

Cron schedule:

0 */12 * * * /usr/bin/zaita-courier generate -c /etc/zaita/courier/config.yaml

Example 2: Azure Workload Identity — Azure Virtual Machine

A Courier running on an Azure virtual machine with a managed identity assigned. No credentials are stored on the host.

api:
  base_url: https://au.zaita.com
  version: v1
  timeout_seconds: 30
  verify_tls: true
  retries: 3
  retry_backoff: 60

auth:
  uuid: cour_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  method: azure_jwt
  tenant_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  client_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

certificate:
  output_dir: /etc/ssl/zaita
  cert_filename: service-cert
  key_filename: service-key
  generate_keys_locally: true
  key_algorithm: ecdsa
  key_size: 384
  digest: sha-384
  certificate_validity_period: 90
  renewal_threshold_days: 30
  common_name: "api.example.com"
  on_success: "/bin/bash /opt/scripts/reload-service.sh"
  on_failure: "/bin/bash /opt/scripts/alert.sh"

logging:
  level: info
  file: /var/log/zaita-courier.log

Requirements: - The Azure VM must have a system-assigned or user-assigned managed identity. - The Zaita machine account must be configured to accept Azure Workload Identity tokens from the specified tenant_id and client_id. - If using a user-assigned managed identity, ensure the client_id matches the identity assigned to the VM.


Example 3: Azure Arc — On-Premises Server

A Courier running on an on-premises server enrolled in Azure Arc. The Arc agent provides the same managed identity metadata endpoint as Azure-hosted VMs, so the configuration is identical to Example 2. No additional Courier configuration is required.

auth:
  uuid: cour_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  method: azure_jwt
  tenant_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  client_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Requirements: - The server must be enrolled in Azure Arc and the Arc agent must be running. - A managed identity must be assigned to the Arc-enabled server in the Azure portal.


Example 4: AWS IAM OIDC — EC2 Instance

A Courier running on an AWS EC2 instance with an IAM instance profile attached.

api:
  base_url: https://au.zaita.com
  version: v1
  timeout_seconds: 30
  verify_tls: true
  retries: 3
  retry_backoff: 60

auth:
  uuid: cour_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  method: aws_oidc
  role_arn: arn:aws:iam::123456789012:role/ZaitaCourierRole
  region: ap-southeast-2

certificate:
  output_dir: /etc/ssl/zaita
  cert_filename: service-cert
  key_filename: service-key
  generate_keys_locally: true
  key_algorithm: ecdsa
  key_size: 384
  digest: sha-384
  certificate_validity_period: 90
  renewal_threshold_days: 30
  common_name: "service.example.com"
  on_success: "/bin/bash /opt/scripts/reload-service.sh"
  on_failure: "/bin/bash /opt/scripts/alert.sh"

logging:
  level: info
  file: /var/log/zaita-courier.log

Requirements: - The EC2 instance must have an IAM instance profile attached with permission to assume ZaitaCourierRole. - The IAM role's trust policy must allow the EC2 service or the specific instance profile to assume it. - The Zaita machine account must be configured to accept AWS IAM OIDC tokens from the specified role ARN.


Example 5: SPIFFE / SPIRE

A Courier running in an environment with a SPIRE agent deployed. The Courier obtains its identity from the local SPIRE workload API at runtime.

api:
  base_url: https://au.zaita.com
  version: v1
  timeout_seconds: 30
  verify_tls: true
  retries: 3
  retry_backoff: 60

auth:
  uuid: cour_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  method: spiffe
  workload_api_socket: unix:///tmp/spire-agent/public/api.sock

certificate:
  output_dir: /etc/ssl/zaita
  cert_filename: service-cert
  key_filename: service-key
  generate_keys_locally: true
  key_algorithm: ecdsa
  key_size: 384
  digest: sha-384
  certificate_validity_period: 90
  renewal_threshold_days: 30
  common_name: "service.example.com"
  on_success: "/bin/bash /opt/scripts/reload-service.sh"
  on_failure: "/bin/bash /opt/scripts/alert.sh"

logging:
  level: info
  file: /var/log/zaita-courier.log

Requirements: - A SPIRE agent must be running on the host and accessible at the configured workload_api_socket path. - The SPIRE server must be configured with a registration entry that matches the workload running the Courier. - The Courier process user must have read access to the workload API socket. - The Zaita machine account must be configured to accept SPIFFE/SPIRE identity.


Example 6: Windows — Microsoft IIS

A Courier running as a Windows Scheduled Task under a Group Managed Service Account (gMSA), renewing a certificate bound to an IIS site.

api:
  base_url: https://au.zaita.com
  version: v1
  timeout_seconds: 30
  verify_tls: true
  retries: 3
  retry_backoff: 60

auth:
  uuid: cour_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  method: client_secret
  client_id: ${ZAITA_CLIENT_ID}
  client_secret: ${ZAITA_CLIENT_SECRET}

certificate:
  output_dir: C:\ProgramData\Zaita\Certs
  cert_filename: iis-cert
  key_filename: iis-key
  generate_keys_locally: true
  key_algorithm: rsa
  key_size: 4096
  digest: sha-256
  certificate_validity_period: 365
  renewal_threshold_days: 60
  common_name: "www.example.com"
  subject_alternative_names: "example.com"
  organization: "Example Org"
  country: "AU"
  key_usage: "Digital Signature, Key Encipherment"
  extended_key_usage: "Server Authentication"
  on_success: "powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\Update-IISBinding.ps1"
  on_failure: "powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\Alert-CertFailure.ps1"

logging:
  level: info
  file: C:\ProgramData\Zaita\Logs\courier.log

Requirements: - The gMSA must have write access to the output_dir. - The gMSA must have permissions to write to the Windows certificate store, update IIS bindings, and restart IIS. - RSA is used here for broad IIS compatibility. ECDSA P-384 can be used on Windows Server 2019 and later with IIS 10+.


Example 7: CI/CD Pipeline — GitHub Actions

A Courier invoked within a GitHub Actions workflow using OIDC token federation. No secrets are stored in the repository or pipeline configuration.

Note: This example requires the Zaita machine account to be configured for OIDC federation with your GitHub organisation and repository.

# .github/workflows/renew-cert.yml
name: Renew Certificate

on:
  schedule:
    - cron: '0 */12 * * *'
  workflow_dispatch:

permissions:
  id-token: write
  contents: read

jobs:
  renew:
    runs-on: self-hosted
    steps:
      - name: Run Zaita Courier
        env:
          ZAITA_CLIENT_ID: ${{ vars.ZAITA_CLIENT_ID }}
          ZAITA_CLIENT_SECRET: ${{ secrets.ZAITA_CLIENT_SECRET }}
        run: |
          zaita-courier generate -c /etc/zaita/courier/config.yaml

For pipeline environments that support OIDC token issuance, replace the Client ID/Secret auth with the appropriate federated identity method (Azure, AWS, or SPIFFE) to eliminate stored secrets entirely.