Configuration

Configuration

Team Server uses a YAML configuration file that controls all aspects of the application’s behavior. The application is built on the loco-rs framework, which provides the foundation for many configuration options. This guide covers both the standard loco-rs configuration sections and Endura-specific settings.

Configuration File Location

The configuration file is typically located at config/production.yaml within the application directory. When running in a container, mount this file to /app/config/production.yaml.

Environment Variable Templating

Configuration values can reference environment variables using the Tera templating syntax:

# Basic environment variable reference
secret: "{{ get_env(name='MY_SECRET') }}"

# With a default value
host: "{{ get_env(name='SERVER_URL', default='http://localhost') }}"

This allows sensitive values like secrets and credentials to be injected at runtime rather than stored in configuration files.

Standard Configuration Sections

The following sections are provided by the loco-rs framework and control core application behavior.

Logger

Controls application logging output:

logger:
  # Enable or disable logging
  enable: true
  # Enable pretty backtraces (sets RUST_BACKTRACE=1)
  pretty_backtrace: false
  # Log level: trace, debug, info, warn, error
  level: info
  # Output format: compact, pretty, json
  format: compact
  # Override default log filters to include third-party libraries
  # override_filter: trace
ParameterTypeDescription
enablebooleanEnable or disable all logging
pretty_backtracebooleanEnable formatted stack traces for debugging
levelstringMinimum log level to output
formatstringLog output format (compact, pretty, or json)
override_filterstringOptional filter to include third-party library logs

Server

Configures the HTTP server and middleware:

server:
  # Network interface to bind to
  binding: 0.0.0.0
  # Port number
  port: 5150
  # Public URL for the server (used in redirects and emails)
  host: "{{ get_env(name='SERVER_URL', default='http://localhost') }}"
  middlewares:
    compression:
      enable: true
    cors:
      enable: true
      allow_origins:
        - "{{ get_env(name='SERVER_URL') }}"
      allow_headers:
        - "*"
      allow_methods:
        - "*"
    fallback:
      enable: false
    limit_payload:
      body_limit: 5mb
    logger:
      enable: true
    secure_headers:
      preset: github
    static:
      enable: true
      must_exist: false
      folder:
        uri: "/"
        path: "public"
      fallback: "public/index.html"
    timeout_request:
      enable: true
      timeout: 30000
ParameterTypeDescription
bindingstringNetwork interface to bind (use 0.0.0.0 for all interfaces)
portintegerPort number for the HTTP server
hoststringPublic-facing URL used for redirects and callbacks
middlewaresobjectMiddleware configuration (see below)

Middleware Options:

MiddlewareDescription
compressionEnable response compression
corsCross-Origin Resource Sharing settings
limit_payloadMaximum request body size
loggerHTTP request logging
secure_headersSecurity headers (CSP, HSTS, etc.)
staticStatic file serving configuration
timeout_requestRequest timeout in milliseconds

Database

PostgreSQL database connection settings:

database:
  # PostgreSQL connection URI
  uri: "{{ get_env(name='DATABASE_URL') }}"
  # Log SQL queries
  enable_logging: false
  # Connection timeout in milliseconds
  connect_timeout: 1500
  # Idle connection timeout in milliseconds
  idle_timeout: 500
  # Minimum connection pool size
  min_connections: 2
  # Maximum connection pool size
  max_connections: 16
  # Automatically run migrations on startup
  auto_migrate: true
ParameterTypeDescription
uristringPostgreSQL connection string
enable_loggingbooleanLog all SQL queries (useful for debugging)
connect_timeoutintegerTimeout for acquiring a connection (ms)
idle_timeoutintegerTime before idle connections are closed (ms)
min_connectionsintegerMinimum connections to maintain in the pool
max_connectionsintegerMaximum connections allowed in the pool
auto_migratebooleanRun database migrations automatically on startup

Connection String Format:

postgresql://username:password@hostname:port/database

Workers

Background job processing configuration:

workers:
  # Worker operation mode
  mode: BackgroundAsync
ModeDescription
BackgroundQueueAsynchronous processing with job queue
ForegroundBlockingSynchronous processing, blocks until complete
BackgroundAsyncAsynchronous processing with async capabilities (recommended)

For most deployments, BackgroundAsync is the recommended mode as it provides efficient async task processing without blocking the main application.

Scheduler

Scheduled job configuration for periodic tasks:

scheduler:
  output: stdout
  jobs:
    # Required jobs
    calculate_statistics:
      run: "calculate_statistics"
      schedule: "0 0 5 * * * *"
    update_status:
      run: "update_status"
      schedule: "0 */5 * * * * *"
    # Optional pipeline discovery jobs
    discover_bamboo_pipelines:
      run: "discover_bamboo_pipelines"
      schedule: "0 0 0 * * * *"
    discover_github_pipelines:
      run: "discover_github_pipelines"
      schedule: "0 0 1 * * * *"
    discover_gitlab_pipelines:
      run: "discover_gitlab_pipelines"
      schedule: "0 0 2 * * * *"
    discover_jenkins_pipelines:
      run: "discover_jenkins_pipelines"
      schedule: "0 0 3 * * * *"
    discover_team_city_pipelines:
      run: "discover_team_city_pipelines"
      schedule: "0 0 4 * * * *"

Schedule expressions use cron syntax with seconds precision: second minute hour day month day-of-week year

Required Jobs

These jobs are essential for Team Server operation and must always be enabled:

JobDescription
calculate_statisticsComputes security metrics and statistics for dashboards and reporting
update_statusRefreshes status for monitored resources and sensors

Optional Pipeline Discovery Jobs

These jobs discover CI/CD pipelines from external integrations. Each job corresponds to a specific CI/CD platform integration configured within Team Server:

JobIntegration
discover_bamboo_pipelinesAtlassian Bamboo
discover_github_pipelinesGitHub Actions
discover_gitlab_pipelinesGitLab CI/CD
discover_jenkins_pipelinesJenkins
discover_team_city_pipelinesJetBrains TeamCity

These jobs only perform work when the corresponding integration has been configured in Team Server. If no integration is configured for a particular platform, the job will complete immediately without taking any action. There is no harm in leaving all pipeline discovery jobs enabled in your configuration—they will simply do nothing if the corresponding integration is not set up.


Application Settings

The settings section contains Endura-specific configuration that extends beyond the standard loco-rs options.

JWT Configuration

JSON Web Tokens are used for authenticating both users and security sensors with Team Server.

settings:
  jwt:
    sensor:
      secret: "{{ get_env(name='JWT_SENSOR_SECRET') }}"
      expiration: 31557600
    user:
      secret: "{{ get_env(name='JWT_USER_SECRET') }}"
      expiration: 604800

Sensor JWT

Used for authenticating Security Sensors that communicate with Team Server.

ParameterTypeDescription
secretstringSecret key for signing sensor JWTs (minimum 32 characters recommended)
expirationintegerToken validity duration in seconds

Recommended expiration: 31557600 (1 year) - Sensors maintain long-lived connections and should not require frequent re-authentication.

User JWT

Used for authenticating users accessing the Team Server web interface and API.

ParameterTypeDescription
secretstringSecret key for signing user JWTs (minimum 32 characters recommended)
expirationintegerToken validity duration in seconds

Recommended expiration: 604800 (7 days) - Balances security with user convenience.

Security Best Practices:

  • Generate secrets using cryptographically secure random generators: openssl rand -hex 32
  • Use different secrets for sensors and users
  • Store secrets in environment variables, never in configuration files
  • Rotate secrets periodically and when personnel changes occur

Tenant Configuration

Basic properties identifying the Team Server installation:

settings:
  tenant:
    name: "Acme Corporation"
    base_url: "{{ get_env(name='SERVER_URL') }}"
ParameterTypeDescription
namestringOrganization name displayed in the UI and notifications
base_urlstringPublic URL of the Team Server instance

The base_url is used for generating links in notifications, emails, and API responses. Ensure this matches the URL users and sensors will use to access Team Server.

TLS Configuration

Team Server supports native TLS termination for encrypted communications:

settings:
  tls:
    certificate: "config/certs/server.pem"
    private_key: "config/certs/server-key.pem"
ParameterTypeDescription
certificatestringPath to the PEM-encoded TLS certificate file
private_keystringPath to the PEM-encoded private key file

When TLS is configured:

  • Update SERVER_URL to use https://
  • Update all callback URLs in authentication providers
  • Ensure certificate files are readable by the application

Reverse Proxy Deployments

If you are using a reverse proxy (such as nginx, Traefik, or a cloud load balancer) to handle TLS termination, omit the tls section entirely. The reverse proxy will manage HTTPS connections, and Team Server will receive unencrypted traffic on its internal port. Ensure SERVER_URL still uses https:// to reflect the public-facing URL.

For detailed TLS setup instructions, see the deployment guides for Docker, Podman, or Kubernetes.

Slack Integration

Configure Slack for security notifications and alerts:

settings:
  slack:
    client_id: "{{ get_env(name='SLACK_CLIENT_ID') }}"
    client_secret: "{{ get_env(name='SLACK_CLIENT_SECRET') }}"
    issuer_url: "https://slack.com"
    scopes:
      - "channels:read"
      - "chat:write"
      - "chat:write.public"
      - "groups:read"
ParameterTypeDescription
client_idstringSlack OAuth application client ID
client_secretstringSlack OAuth application client secret
issuer_urlstringSlack OAuth endpoint (always https://slack.com)
scopesarrayRequired OAuth scopes for Slack integration

Required Scopes:

ScopePurpose
channels:readList public channels for notification routing
chat:writeSend messages to channels the app is a member of
chat:write.publicSend messages to any public channel
groups:readList private channels the app has access to

All scopes listed above are required for the Slack integration to function properly.

Setup Instructions:

  1. Go to the Slack API Apps page
  2. Click Create New App and select From scratch
  3. Enter an app name (e.g., “Endura Security”) and select your workspace
  4. Navigate to OAuth & Permissions in the sidebar
  5. Under Scopes > Bot Token Scopes, add the required scopes:
    • channels:read
    • chat:write
    • chat:write.public
    • groups:read
  6. Navigate to Basic Information in the sidebar
  7. Under App Credentials, copy the Client ID and Client Secret
  8. Navigate to OAuth & Permissions and click Install to Workspace
  9. Authorize the app for your workspace

Environment Variables:

export SLACK_CLIENT_ID="your-slack-client-id"
export SLACK_CLIENT_SECRET="your-slack-client-secret"

Once configured, you can connect Team Server to your Slack workspace through the Integrations page in the Team Server UI.


Authentication

Team Server supports multiple authentication methods. You must configure at least one authentication provider for users to access the system.

Built-in Username/Password Provider

Non-Production Use Only

The built-in username/password authentication is intended solely for testing and development environments. It is not recommended for production deployments due to the inherent security limitations of passing credentials via environment variables.

For testing scenarios, Team Server supports a single administrative user authenticated via environment variables:

Environment VariableDescription
ENDURA_AUTH_USERNAMEUsername for the administrative account
ENDURA_AUTH_PASSWORDPassword for the administrative account

Example:

podman run -d \
  --name endura-team-server \
  -e ENDURA_AUTH_USERNAME="admin" \
  -e ENDURA_AUTH_PASSWORD="your-secure-password" \
  # ... other options ...
  ghcr.io/endurasecurity/container/endura-team-server:testing
# podman-compose.yaml
services:
  endura-team-server:
    image: ghcr.io/endurasecurity/container/endura-team-server:testing
    environment:
      - ENDURA_AUTH_USERNAME=admin
      - ENDURA_AUTH_PASSWORD=your-secure-password
      # ... other environment variables ...
docker run -d \
  --name endura-team-server \
  -e ENDURA_AUTH_USERNAME="admin" \
  -e ENDURA_AUTH_PASSWORD="your-secure-password" \
  # ... other options ...
  ghcr.io/endurasecurity/container/endura-team-server:testing
# docker-compose.yaml
services:
  endura-team-server:
    image: ghcr.io/endurasecurity/container/endura-team-server:testing
    environment:
      - ENDURA_AUTH_USERNAME=admin
      - ENDURA_AUTH_PASSWORD=your-secure-password
      # ... other environment variables ...
kubectl create secret generic endura-team-server-secrets \
  -n endura-team-server \
  --from-literal=ENDURA_AUTH_USERNAME="admin" \
  --from-literal=ENDURA_AUTH_PASSWORD="your-secure-password"
  # ... other secrets ...

This provider is automatically enabled when both environment variables are set. No additional configuration is required in production.yaml.

Limitations:

  • Only supports a single user account
  • Credentials are visible in process listings and container inspection
  • No support for password rotation without restart
  • Not suitable for audit compliance requirements

For production deployments, use one of the OpenID Connect providers described below.

OpenID Connect (OIDC) Providers

Team Server supports enterprise single sign-on through OpenID Connect. Configure one or more providers in the settings.oidc section.

Common OIDC Configuration

All OIDC providers share the same configuration structure:

settings:
  oidc:
    provider_name:
      client_id: "your-client-id"
      client_secret: "your-client-secret"
      issuer_url: "https://identity-provider.com"
      redirect_url: "https://your-team-server.com/authentication/provider_name/callback"
      scopes:
        - openid
        - email
        - profile
      domains:
        - yourdomain.com
ParameterTypeDescription
client_idstringOAuth 2.0 client identifier from the identity provider
client_secretstringOAuth 2.0 client secret from the identity provider
issuer_urlstringOIDC issuer URL for the identity provider
redirect_urlstringCallback URL registered with the identity provider
scopesarrayOIDC scopes to request (must include openid, email, profile)
domainsarrayAllowed email domains for user authentication

Required Scopes:

All OIDC providers require these scopes:

  • openid - Required for OIDC authentication
  • email - Access to the user’s email address
  • profile - Access to the user’s name and profile information

Domain Restrictions:

The domains parameter restricts which email domains can authenticate. Only users with email addresses matching one of the listed domains will be permitted access. This parameter is required—you must specify at least one allowed domain. To allow multiple domains, list each one separately:

domains:
  - example.com
  - subsidiary.example.com

Google

Authenticate users with Google Workspace or personal Google accounts.

settings:
  oidc:
    google:
      client_id: "{{ get_env(name='GOOGLE_OIDC_CLIENT_ID') }}"
      client_secret: "{{ get_env(name='GOOGLE_OIDC_CLIENT_SECRET') }}"
      issuer_url: "https://accounts.google.com"
      redirect_url: "https://your-team-server.com/authentication/google/callback"
      scopes:
        - openid
        - email
        - profile
      domains:
        - yourdomain.com

Setup Instructions:

  1. Go to the Google Cloud Console
  2. Create a new project or select an existing one
  3. Navigate to APIs & Services > Credentials
  4. Click Create Credentials > OAuth client ID
  5. Select Web application as the application type
  6. Add your redirect URL: https://your-team-server.com/authentication/google/callback
  7. Copy the Client ID and Client Secret to your environment variables

Environment Variables:

export GOOGLE_OIDC_CLIENT_ID="your-client-id.apps.googleusercontent.com"
export GOOGLE_OIDC_CLIENT_SECRET="your-client-secret"

Microsoft (Entra ID / Azure AD)

Authenticate users with Microsoft 365 or Azure Active Directory accounts.

settings:
  oidc:
    microsoft:
      client_id: "{{ get_env(name='MICROSOFT_OIDC_CLIENT_ID') }}"
      client_secret: "{{ get_env(name='MICROSOFT_OIDC_CLIENT_SECRET') }}"
      issuer_url: "https://login.microsoftonline.com/YOUR_TENANT_ID/v2.0"
      redirect_url: "https://your-team-server.com/authentication/microsoft/callback"
      scopes:
        - openid
        - email
        - profile
      domains:
        - yourdomain.com

Setup Instructions:

  1. Go to the Azure Portal
  2. Navigate to Microsoft Entra ID (formerly Azure Active Directory)
  3. Select App registrations > New registration
  4. Enter a name and select the supported account types
  5. Set the redirect URI: https://your-team-server.com/authentication/microsoft/callback
  6. After registration, go to Certificates & secrets > New client secret
  7. Copy the Application (client) ID and client secret value

Issuer URL Format:

Replace YOUR_TENANT_ID with your Microsoft Entra tenant ID (GUID format):

https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/v2.0

You can find your tenant ID in the Azure Portal under Microsoft Entra ID > Overview.

Environment Variables:

export MICROSOFT_OIDC_CLIENT_ID="your-application-client-id"
export MICROSOFT_OIDC_CLIENT_SECRET="your-client-secret-value"

CyberArk

Authenticate users with CyberArk Identity.

settings:
  oidc:
    cyberark:
      client_id: "{{ get_env(name='CYBERARK_OIDC_CLIENT_ID') }}"
      client_secret: "{{ get_env(name='CYBERARK_OIDC_CLIENT_SECRET') }}"
      issuer_url: "https://your-tenant.id.cyberark.cloud"
      redirect_url: "https://your-team-server.com/authentication/cyberark/callback"
      scopes:
        - openid
        - email
        - profile
      domains:
        - yourdomain.com

Setup Instructions:

  1. Log in to your CyberArk Identity Administration portal
  2. Navigate to Apps & Widgets > Web Apps
  3. Click Add Web Apps and select Custom > OIDC
  4. Configure the application:
    • Set the Redirect URL: https://your-team-server.com/authentication/cyberark/callback
    • Enable the required scopes: openid, email, profile
  5. Save and copy the Client ID and Client Secret

Issuer URL Format:

Replace your-tenant with your CyberArk tenant subdomain:

https://your-tenant.id.cyberark.cloud

Environment Variables:

export CYBERARK_OIDC_CLIENT_ID="your-cyberark-client-id"
export CYBERARK_OIDC_CLIENT_SECRET="your-cyberark-client-secret"

Oracle (OCI IAM)

Authenticate users with Oracle Cloud Infrastructure Identity and Access Management.

settings:
  oidc:
    oracle:
      client_id: "{{ get_env(name='ORACLE_OIDC_CLIENT_ID') }}"
      client_secret: "{{ get_env(name='ORACLE_OIDC_CLIENT_SECRET') }}"
      issuer_url: "https://identity.oraclecloud.com"
      redirect_url: "https://your-team-server.com/authentication/oracle/callback"
      scopes:
        - openid
        - email
        - profile
      domains:
        - yourdomain.com

Setup Instructions:

  1. Log in to the Oracle Cloud Console
  2. Navigate to Identity & Security > Domains
  3. Select your identity domain
  4. Go to Integrated applications > Add application
  5. Select Confidential Application
  6. Configure the OAuth settings:
    • Redirect URL: https://your-team-server.com/authentication/oracle/callback
    • Allowed Scopes: openid, email, profile
  7. Activate the application and copy the Client ID and Client Secret

Issuer URL:

For Oracle Cloud Infrastructure, the issuer URL is typically:

https://identity.oraclecloud.com

For Oracle Identity Cloud Service (IDCS), use your tenant-specific URL:

https://idcs-xxxxxxxx.identity.oraclecloud.com

Environment Variables:

export ORACLE_OIDC_CLIENT_ID="your-oracle-client-id"
export ORACLE_OIDC_CLIENT_SECRET="your-oracle-client-secret"

Complete Configuration Example

Below is a complete production configuration example with all sections:

# Application logging configuration
logger:
  enable: true
  pretty_backtrace: false
  level: info
  format: compact

# Scheduled jobs
scheduler:
  output: stdout
  jobs:
    discover_github_pipelines:
      run: "discover_github_pipelines"
      schedule: "0 0 1 * * * *"
    calculate_statistics:
      run: "calculate_statistics"
      schedule: "0 0 5 * * * *"
    update_status:
      run: "update_status"
      schedule: "0 */5 * * * * *"

# Web server configuration
server:
  binding: 0.0.0.0
  port: 5150
  host: "{{ get_env(name='SERVER_URL') }}"
  middlewares:
    compression:
      enable: true
    cors:
      enable: true
      allow_origins:
        - "{{ get_env(name='SERVER_URL') }}"
      allow_headers:
        - "*"
      allow_methods:
        - "*"
    fallback:
      enable: false
    limit_payload:
      body_limit: 5mb
    logger:
      enable: true
    secure_headers:
      preset: github
    static:
      enable: true
      must_exist: false
      folder:
        uri: "/"
        path: "public"
      fallback: "public/index.html"
    timeout_request:
      enable: true
      timeout: 30000

# Background worker configuration
workers:
  mode: BackgroundAsync

# Database configuration
database:
  uri: "{{ get_env(name='DATABASE_URL') }}"
  enable_logging: false
  connect_timeout: 1500
  idle_timeout: 500
  min_connections: 2
  max_connections: 16
  auto_migrate: true

# Application-specific settings
settings:
  jwt:
    sensor:
      secret: "{{ get_env(name='JWT_SENSOR_SECRET') }}"
      expiration: 31557600
    user:
      secret: "{{ get_env(name='JWT_USER_SECRET') }}"
      expiration: 604800
  tenant:
    name: "{{ get_env(name='TENANT_NAME') }}"
    base_url: "{{ get_env(name='SERVER_URL') }}"
  # TLS configuration (optional - omit if using a reverse proxy for TLS termination)
  tls:
    certificate: "config/certs/server.pem"
    private_key: "config/certs/server-key.pem"
  oidc:
    google:
      client_id: "{{ get_env(name='GOOGLE_OIDC_CLIENT_ID') }}"
      client_secret: "{{ get_env(name='GOOGLE_OIDC_CLIENT_SECRET') }}"
      issuer_url: "https://accounts.google.com"
      redirect_url: "{{ get_env(name='SERVER_URL') }}/authentication/google/callback"
      scopes:
        - openid
        - email
        - profile
      domains:
        - yourdomain.com
  slack:
    client_id: "{{ get_env(name='SLACK_CLIENT_ID') }}"
    client_secret: "{{ get_env(name='SLACK_CLIENT_SECRET') }}"
    issuer_url: "https://slack.com"
    scopes:
      - "channels:read"
      - "chat:write"
      - "chat:write.public"
      - "groups:read"

Required Environment Variables

The following environment variables must be set for a production deployment:

VariableDescriptionExample
DATABASE_URLPostgreSQL connection stringpostgresql://user:pass@host:5432/db
SERVER_URLPublic URL of Team Serverhttps://team-server.example.com
JWT_SENSOR_SECRETSecret for sensor authenticationopenssl rand -hex 32
JWT_USER_SECRETSecret for user authenticationopenssl rand -hex 32
TENANT_NAMEOrganization nameAcme Corporation

Additional variables are required based on your configured authentication providers and integrations.