Profiles Overview
Profiles enable you to manage different configurations for various environments (development, staging, production) or scenarios. They provide a clean way to override base configuration values without duplicating entire configuration files.
What Are Profiles?
Profiles are named configuration sets that can:
- Override global variables
- Modify target configurations
- Set environment-specific values
- Inherit from other profiles
- Be activated via command-line or environment variables
Basic Profile Structure
profiles:
development:
vars:
environment: dev
debug: true
logLevel: debug
production:
vars:
environment: prod
debug: false
logLevel: error
Profile Activation
Environment Variable
# Set profile via environment
export XEC_PROFILE=production
xec run deploy
Per-Command Flag
Some commands (on, in, copy, logs, watch, forward, inspect) accept a profile flag directly:
xec on -p production hosts.web "systemctl restart app"
There is no global --profile flag and no defaultProfile configuration key — use XEC_PROFILE to select a profile for a whole session.
Variable Overrides
Profiles can override any variables defined in the main configuration:
# Base configuration
vars:
appName: myapp
version: "1.0.0"
replicas: 1
profiles:
production:
vars:
replicas: 3 # Override replicas
version: stable # Override version
# appName inherited as "myapp"
Target Overrides
Modify target configurations per environment:
# Base targets
targets:
hosts:
app-server:
host: localhost
port: 2222
profiles:
production:
targets:
hosts:
app-server:
host: prod.example.com
port: 22
username: deploy
Profile Inheritance
Profiles can extend other profiles:
profiles:
base:
vars:
region: us-east-1
monitoring: enabled
staging:
extends: base
vars:
environment: staging
replicas: 2
production:
extends: base
vars:
environment: production
replicas: 5
highAvailability: true
Inheritance Chains
extends accepts a single parent profile (multi-parent inheritance is not supported). Build layered configurations as a chain instead:
profiles:
base:
vars:
encryption: true
auditLog: enabled
hardened:
extends: base
vars:
caching: true
compression: true
production:
extends: hardened
vars:
environment: production
Environment Variables in Profiles
Set environment variables for command execution:
profiles:
development:
env:
NODE_ENV: development
DEBUG: "*"
API_URL: http://localhost:3000
production:
env:
NODE_ENV: production
DEBUG: ""
API_URL: https://api.example.com
Conditional Configuration
Profile-Specific Tasks
tasks:
deploy:
command: |
if [ "${profile}" = "production" ]; then
./deploy-prod.sh
else
./deploy-dev.sh
fi
Profile Detection in Scripts
The active profile is available to scripts through the environment:
tasks:
smart-deploy:
script: |
const profile = process.env.XEC_PROFILE;
if (profile === 'production') {
await $`./production-checks.sh`;
}
await $`./deploy.sh`;
Profile Files
Profiles that are not defined inline in config.yaml are looked up automatically in .xec/profiles/<name>.yaml:
# .xec/profiles/prod.yaml
extends: base
vars:
environment: production
replicas: 5
targets:
hosts:
web:
host: prod-web.example.com
# Activates .xec/profiles/prod.yaml
XEC_PROFILE=prod xec run deploy
Dynamic Profile Selection
Select the profile in the shell before invoking Xec:
# Based on git branch
branch=$(git branch --show-current)
XEC_PROFILE=$([ "$branch" = "main" ] && echo production || echo staging) xec run deploy
# Based on CI environment
XEC_PROFILE=${CI:+ci} xec run test
Profile Validation
Ensure profile configurations are valid:
# Validate configuration (including the active profile)
XEC_PROFILE=production xec config validate
# Show a profile definition
xec config get profiles.staging
Common Patterns
Development Profile
profiles:
development:
vars:
environment: dev
debug: true
logLevel: debug
replicas: 1
cache: false
targets:
hosts:
app:
host: localhost
port: 2222
containers:
db:
image: postgres:15
ports: ["5432:5432"]
env:
NODE_ENV: development
DEBUG: "*"
Staging Profile
profiles:
staging:
extends: development
vars:
environment: staging
debug: false
logLevel: info
replicas: 2
cache: true
targets:
hosts:
app:
host: staging.example.com
port: 22
Production Profile
profiles:
production:
vars:
environment: prod
debug: false
logLevel: error
replicas: 5
cache: true
monitoring: enabled
alerting: enabled
targets:
hosts:
app:
host: prod.example.com
username: deploy
privateKey: ~/.ssh/prod_key
kubernetes:
context: production-cluster
namespace: production
env:
NODE_ENV: production
LOG_LEVEL: error
Region-Specific Profiles
profiles:
us-east:
vars:
region: us-east-1
availability_zones:
- us-east-1a
- us-east-1b
targets:
hosts:
api:
host: api-us-east.example.com
eu-west:
vars:
region: eu-west-1
availability_zones:
- eu-west-1a
- eu-west-1b
targets:
hosts:
api:
host: api-eu-west.example.com
Feature Flags
profiles:
feature-x-enabled:
vars:
features:
x: true
y: false
feature-y-enabled:
vars:
features:
x: false
y: true
all-features:
vars:
features:
x: true
y: true
Profile Composition
extends takes a single parent, so compose baselines as a chain — each layer extends the previous one:
profiles:
# Security baseline
secure:
vars:
tls: true
authentication: required
encryption: aes256
# Performance layer on top of the security baseline
secure-fast:
extends: secure
vars:
caching: true
compression: gzip
connectionPool: 10
# Final profile
production:
extends: secure-fast
vars:
environment: production
Profile Priority
Configuration sources are merged in this order (later overrides earlier):
- Built-in defaults
- Global configuration (
~/.xec/config.yaml) - Project configuration (
.xec/config.yaml) XEC_CONFIGfile andXEC_*environment variables- Active profile (inheritance chain resolved parent-first)
The active profile is the highest-priority source — its values win over everything else.
# Base
vars:
value: "base"
profiles:
parent:
vars:
value: "parent"
child:
extends: parent
vars:
value: "child" # This wins when child profile is active
Testing with Profiles
profiles:
test:
vars:
environment: test
database: test_db
mockServices: true
targets:
containers:
test-db:
image: postgres:15
env:
POSTGRES_DB: test_db
env:
NODE_ENV: test
MOCK_EXTERNAL_APIS: true
CI/CD Profiles
profiles:
ci:
vars:
environment: ci
parallel: true
failFast: true
env:
CI: true
TERM: dumb
NO_COLOR: true
Best Practices
1. Use Descriptive Names
# Good
profiles:
production-us-east:
staging-eu-west:
development-local:
# Bad
profiles:
p1:
s2:
d3:
2. Inherit Common Settings
profiles:
base:
vars:
company: acme
team: platform
production:
extends: base
vars:
environment: production
3. Keep Secrets Separate
profiles:
production:
vars:
apiKey: ${secrets.prod_api_key} # Good
# apiKey: "sk-12345" # Bad
4. Document Profiles
profiles:
# Production environment profile.
# Requires: VPN connection, prod credentials
# Region: us-east-1
production:
vars:
environment: production
5. Validate Profile Changes
# Before switching profiles
XEC_PROFILE=new-profile xec config validate
XEC_PROFILE=new-profile xec run smoke-test
Troubleshooting
Profile Not Found
# List profile definitions
xec config list --path profiles
# Check the profile definition
xec config get profiles.correct-name
Variable Not Overridden
# Check inheritance chain
profiles:
child:
extends: parent # Check parent profile
vars:
myVar: value # Ensure correct path
Circular Inheritance
# Avoid circular references
profiles:
a:
extends: b # Error if b extends a
b:
extends: a
See Also
- Configuration Command - Profile management
- Variables - Variable system
- Environment Variables - Environment configuration