Configuration Guide
ionscale uses a flexible YAML-based configuration system that supports environment variable substitution and sensible defaults. This guide explains how to configure your ionscale instance.
Configuration File Format
ionscale uses YAML for its configuration files. Here's a basic example:
# Server network configuration
listen_addr: ":8080"
public_addr: "ionscale.example.com:443"
stun_listen_addr: ":3478"
stun_public_addr: "ionscale.example.com:3478"
# TLS configuration
tls:
disable: false
force_https: true
cert_file: /etc/ionscale/cert.pem
key_file: /etc/ionscale/key.pem
# Database configuration
database:
type: postgres
url: postgres://user:password@localhost:5432/ionscale
Loading Configuration
When starting ionscale, you can specify a configuration file using the --config
or -c
flag:
If no configuration file is provided, ionscale will use its default values.
Environment Variable Support
ionscale supports two ways to use environment variables in configuration:
1. Direct Configuration via Environment Variables
You can provide the entire configuration as a base64-encoded string using the IONSCALE_CONFIG_BASE64
environment variable. This is useful for containerized deployments where you want to inject configuration without mounting files.
# Create base64-encoded config
CONFIG_B64=$(cat config.yaml | base64 -w0)
# Run ionscale with environment config
IONSCALE_CONFIG_BASE64=$CONFIG_B64 ionscale server
2. Variable Substitution in YAML Files
You can reference environment variables directly in your YAML configuration files using:
${VAR}
syntax for required variables${VAR:default}
syntax for variables with default values
For example:
In this example:
- DB_TYPE
has a default value of "sqlite" if the environment variable is not set
- DB_URL
is required and must be set in the environment
- DB_MAX_OPEN_CONNS
defaults to 10 if not set
If a required variable is missing, the configuration loading will fail with an error.
Default Configuration
If no configuration file is provided, ionscale uses these default values:
listen_addr: ":8080"
metrics_listen_addr: ":9091"
stun_listen_addr: ":3478"
database:
type: sqlite
url: ./ionscale.db?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)&_pragma=foreign_keys(ON)
max_idle_conns: 2
poll_net:
keep_alive_interval: 1m
dns:
magic_dns_suffix: ionscale.net
derp:
server:
disabled: false
region_id: 1000
region_code: ionscale
region_name: ionscale Embedded DERP
logging:
level: info
Configuration Sections
Server Network Configuration
Controls the network interfaces and addresses:
# The HTTP(S) listen address for the control plane
listen_addr: ":8080"
# The metrics listen address (for Prometheus)
metrics_listen_addr: ":9091"
# The STUN listen address when using the embedded DERP
stun_listen_addr: ":3478"
# The DNS name of the server HTTP(S) endpoint as accessible by clients
public_addr: "ionscale.example.com:443"
# The DNS name of the STUN endpoint as accessible by clients
stun_public_addr: "ionscale.example.com:3478"
TLS Configuration
Controls HTTPS and certificate usage:
tls:
# Disable TLS (not recommended for production)
disable: false
# Force HTTPS redirect
force_https: true
# Path to certificate files (when not using ACME)
cert_file: /etc/ionscale/cert.pem
key_file: /etc/ionscale/key.pem
# Let's Encrypt ACME configuration
acme: true
acme_email: admin@example.com
acme_ca: https://acme-v02.api.letsencrypt.org/directory
Database Configuration
Controls the database storage:
database:
# Database type: sqlite or postgres
type: postgres
# Database connection URL
url: postgres://user:password@localhost:5432/ionscale
# Connection pool settings
max_open_conns: 10
max_idle_conns: 5
conn_max_life_time: 5m
conn_max_idle_time: 5m
OIDC Configuration
Controls OpenID Connect authentication providers and admin access:
auth:
# OIDC provider configuration
provider:
issuer: https://auth.example.com
client_id: client_id
client_secret: client_secret
additional_scopes: ["profile", "email"]
# System administrators configuration
system_admins:
emails: ["admin@example.com"]
subs: ["subject123"]
filters: ["domain == example.com"]
For more details about configuring OIDC authentication, see OIDC Configuration.
DNS Configuration
Controls DNS settings:
dns:
# Suffix for MagicDNS
magic_dns_suffix: ionscale.net
# DNS provider for dynamic updates
provider:
name: cloudflare
zone: example.com
config:
auth_token: ${CLOUDFLARE_TOKEN}
For more details about configuring DNS providers, see DNS Providers.
DERP Configuration
Controls relay server configuration:
derp:
# Embedded DERP server configuration
server:
disabled: false
region_id: 1000
region_code: ionscale
region_name: ionscale Embedded DERP
# External DERP maps to load
sources:
- https://controlplane.tailscale.com/derpmap/default
- file:///etc/ionscale/custom-derp.json
For more details about configuring DERP servers, see DERP Configuration.
Logging Configuration
Controls log output:
logging:
# Log level: debug, info, warn, error
level: info
# Log format: text, json
format: text
# Optional file output (in addition to stdout)
file: /var/log/ionscale.log
Keys and Security
You can configure private keys for the system:
keys:
# System administrator key for CLI authentication
system_admin_key: your-private-key
# Control plane keys (optional, auto-generated when not provided)
control_key: your-control-key
legacy_control_key: your-legacy-control-key
The control_key
and legacy_control_key
are optional and will be automatically generated if not provided. Once generated, they are stored in the database and reused across restarts.
Warning
Never commit sensitive keys in your configuration files to version control. Use environment variables for sensitive values.
Configuration File Locations
Common locations for ionscale configuration files:
/etc/ionscale/config.yaml
- System-wide configuration$HOME/.config/ionscale/config.yaml
- User-specific configuration./config.yaml
- Local directory configuration
Complete Configuration Example
Below is a complete configuration file example with comments:
# Network configuration
listen_addr: ":8080" # HTTP/HTTPS control plane address
stun_listen_addr: ":3478" # STUN server listen address
metrics_listen_addr: ":9091" # Prometheus metrics address
public_addr: "ionscale.example.com:443" # Public HTTPS endpoint for clients
stun_public_addr: "ionscale.example.com:3478" # Public STUN endpoint for clients
# TLS configuration
tls:
disable: false # Set to true if behind a TLS-terminating proxy
force_https: true # Redirect HTTP to HTTPS
# Provide your own certificates
cert_file: "/etc/ionscale/cert.pem"
key_file: "/etc/ionscale/key.pem"
# Or use Let's Encrypt
acme: false # Enable ACME/Let's Encrypt
acme_email: "admin@example.com" # Contact email for Let's Encrypt
acme_ca: "https://acme-v02.api.letsencrypt.org/directory"
acme_path: "./data" # Storage path for ACME certificates
# Database configuration
database:
# SQLite configuration
type: "sqlite"
url: "/var/lib/ionscale/ionscale.db?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)&_pragma=foreign_keys(ON)"
# Or PostgreSQL configuration
# type: "postgres"
# url: "postgres://user:password@localhost:5432/ionscale?sslmode=disable"
# Connection pool settings
max_open_conns: 10
max_idle_conns: 5
conn_max_life_time: "5m"
conn_max_idle_time: "5m"
# DERP (relay) configuration
derp:
# Embedded DERP server
server:
disabled: false # Set to true to disable embedded DERP
region_id: 1000 # Region ID (1000+ reserved for ionscale)
region_code: "ionscale" # Short code for the region
region_name: "ionscale Embedded DERP" # Human-readable name
# External DERP sources (optional)
sources:
- https://controlplane.tailscale.com/derpmap/default # Tailscale's DERP map
# - file:///etc/ionscale/custom-derp.json # Custom DERP map
# - git::https://github.com/example/derp//map.json # DERP map from git
# Security keys
keys:
# System admin key for CLI authentication (required for admin CLI usage)
system_admin_key: "${IONSCALE_SYSTEM_ADMIN_KEY}" # Use environment variable
# Control keys (optional, auto-generated if not provided)
# control_key: "privkey:xxxxxx"
# legacy_control_key: "privkey:xxxxxx"
# Network polling configuration
poll_net:
# How often to send keep-alive messages
keep_alive_interval: "60s"
# OIDC authentication configuration
auth:
# OIDC provider settings
provider:
issuer: "https://auth.example.com" # OIDC issuer URL
client_id: "your-client-id" # OAuth client ID
client_secret: "${OIDC_CLIENT_SECRET}" # OAuth client secret from env var
additional_scopes: ["profile", "email"] # Extra scopes to request
# System administrator policy
system_admins:
# Users identified by email
emails: ["admin@example.com"]
# Users identified by subject ID
subs: ["subject-id-12345"]
# Users matching expression filters
filters: ["domain == example.com"]
# DNS configuration
dns:
# Suffix for MagicDNS hostnames
magic_dns_suffix: "ionscale.net"
# DNS provider for automatic DNS management (optional)
provider:
name: "cloudflare" # Provider name (cloudflare, route53, etc.)
zone: "example.com" # DNS zone to manage
config: # Provider-specific configuration
auth_token: "${DNS_API_TOKEN}"
# Logging configuration
logging:
level: "info" # debug, info, warn, error
format: "text" # text or json
file: "/var/log/ionscale.log" # Optional log file path
Environment variables
In this example, we use environment variables for sensitive values:
${IONSCALE_SYSTEM_ADMIN_KEY} - System admin key for CLI authentication
${OIDC_CLIENT_SECRET} - OIDC client secret
${DNS_API_TOKEN} - DNS provider API token
These must be set in your environment before starting ionscale.