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| Parameter | Type | Description |
|---|---|---|
enable | boolean | Enable or disable all logging |
pretty_backtrace | boolean | Enable formatted stack traces for debugging |
level | string | Minimum log level to output |
format | string | Log output format (compact, pretty, or json) |
override_filter | string | Optional 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| Parameter | Type | Description |
|---|---|---|
binding | string | Network interface to bind (use 0.0.0.0 for all interfaces) |
port | integer | Port number for the HTTP server |
host | string | Public-facing URL used for redirects and callbacks |
middlewares | object | Middleware configuration (see below) |
Middleware Options:
| Middleware | Description |
|---|---|
compression | Enable response compression |
cors | Cross-Origin Resource Sharing settings |
limit_payload | Maximum request body size |
logger | HTTP request logging |
secure_headers | Security headers (CSP, HSTS, etc.) |
static | Static file serving configuration |
timeout_request | Request 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| Parameter | Type | Description |
|---|---|---|
uri | string | PostgreSQL connection string |
enable_logging | boolean | Log all SQL queries (useful for debugging) |
connect_timeout | integer | Timeout for acquiring a connection (ms) |
idle_timeout | integer | Time before idle connections are closed (ms) |
min_connections | integer | Minimum connections to maintain in the pool |
max_connections | integer | Maximum connections allowed in the pool |
auto_migrate | boolean | Run database migrations automatically on startup |
Connection String Format:
postgresql://username:password@hostname:port/databaseWorkers
Background job processing configuration:
workers:
# Worker operation mode
mode: BackgroundAsync| Mode | Description |
|---|---|
BackgroundQueue | Asynchronous processing with job queue |
ForegroundBlocking | Synchronous processing, blocks until complete |
BackgroundAsync | Asynchronous 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:
| Job | Description |
|---|---|
calculate_statistics | Computes security metrics and statistics for dashboards and reporting |
update_status | Refreshes 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:
| Job | Integration |
|---|---|
discover_bamboo_pipelines | Atlassian Bamboo |
discover_github_pipelines | GitHub Actions |
discover_gitlab_pipelines | GitLab CI/CD |
discover_jenkins_pipelines | Jenkins |
discover_team_city_pipelines | JetBrains 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: 604800Sensor JWT
Used for authenticating Security Sensors that communicate with Team Server.
| Parameter | Type | Description |
|---|---|---|
secret | string | Secret key for signing sensor JWTs (minimum 32 characters recommended) |
expiration | integer | Token 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.
| Parameter | Type | Description |
|---|---|---|
secret | string | Secret key for signing user JWTs (minimum 32 characters recommended) |
expiration | integer | Token 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') }}"| Parameter | Type | Description |
|---|---|---|
name | string | Organization name displayed in the UI and notifications |
base_url | string | Public 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"| Parameter | Type | Description |
|---|---|---|
certificate | string | Path to the PEM-encoded TLS certificate file |
private_key | string | Path to the PEM-encoded private key file |
When TLS is configured:
- Update
SERVER_URLto usehttps:// - 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"| Parameter | Type | Description |
|---|---|---|
client_id | string | Slack OAuth application client ID |
client_secret | string | Slack OAuth application client secret |
issuer_url | string | Slack OAuth endpoint (always https://slack.com) |
scopes | array | Required OAuth scopes for Slack integration |
Required Scopes:
| Scope | Purpose |
|---|---|
channels:read | List public channels for notification routing |
chat:write | Send messages to channels the app is a member of |
chat:write.public | Send messages to any public channel |
groups:read | List private channels the app has access to |
All scopes listed above are required for the Slack integration to function properly.
Setup Instructions:
- Go to the Slack API Apps page
- Click Create New App and select From scratch
- Enter an app name (e.g., “Endura Security”) and select your workspace
- Navigate to OAuth & Permissions in the sidebar
- Under Scopes > Bot Token Scopes, add the required scopes:
channels:readchat:writechat:write.publicgroups:read
- Navigate to Basic Information in the sidebar
- Under App Credentials, copy the Client ID and Client Secret
- Navigate to OAuth & Permissions and click Install to Workspace
- 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 Variable | Description |
|---|---|
ENDURA_AUTH_USERNAME | Username for the administrative account |
ENDURA_AUTH_PASSWORD | Password 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| Parameter | Type | Description |
|---|---|---|
client_id | string | OAuth 2.0 client identifier from the identity provider |
client_secret | string | OAuth 2.0 client secret from the identity provider |
issuer_url | string | OIDC issuer URL for the identity provider |
redirect_url | string | Callback URL registered with the identity provider |
scopes | array | OIDC scopes to request (must include openid, email, profile) |
domains | array | Allowed email domains for user authentication |
Required Scopes:
All OIDC providers require these scopes:
openid- Required for OIDC authenticationemail- Access to the user’s email addressprofile- 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.comAuthenticate 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.comSetup Instructions:
- Go to the Google Cloud Console
- Create a new project or select an existing one
- Navigate to APIs & Services > Credentials
- Click Create Credentials > OAuth client ID
- Select Web application as the application type
- Add your redirect URL:
https://your-team-server.com/authentication/google/callback - 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.comSetup Instructions:
- Go to the Azure Portal
- Navigate to Microsoft Entra ID (formerly Azure Active Directory)
- Select App registrations > New registration
- Enter a name and select the supported account types
- Set the redirect URI:
https://your-team-server.com/authentication/microsoft/callback - After registration, go to Certificates & secrets > New client secret
- 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.0You 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.comSetup Instructions:
- Log in to your CyberArk Identity Administration portal
- Navigate to Apps & Widgets > Web Apps
- Click Add Web Apps and select Custom > OIDC
- Configure the application:
- Set the Redirect URL:
https://your-team-server.com/authentication/cyberark/callback - Enable the required scopes:
openid,email,profile
- Set the Redirect URL:
- 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.cloudEnvironment 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.comSetup Instructions:
- Log in to the Oracle Cloud Console
- Navigate to Identity & Security > Domains
- Select your identity domain
- Go to Integrated applications > Add application
- Select Confidential Application
- Configure the OAuth settings:
- Redirect URL:
https://your-team-server.com/authentication/oracle/callback - Allowed Scopes:
openid,email,profile
- Redirect URL:
- 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.comFor Oracle Identity Cloud Service (IDCS), use your tenant-specific URL:
https://idcs-xxxxxxxx.identity.oraclecloud.comEnvironment 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:
| Variable | Description | Example |
|---|---|---|
DATABASE_URL | PostgreSQL connection string | postgresql://user:pass@host:5432/db |
SERVER_URL | Public URL of Team Server | https://team-server.example.com |
JWT_SENSOR_SECRET | Secret for sensor authentication | openssl rand -hex 32 |
JWT_USER_SECRET | Secret for user authentication | openssl rand -hex 32 |
TENANT_NAME | Organization name | Acme Corporation |
Additional variables are required based on your configured authentication providers and integrations.