Customize Infrastructure Guide
Complete guide to customizing infrastructure with layers, templates, and extensions.
Overview
The provisioning platform uses a layered configuration system that allows progressive customization without modifying core code.
Configuration Layers
Configuration is loaded in this priority order (low → high):
1. Core Defaults (provisioning/config/config.defaults.toml)
2. Workspace Config (workspace/{name}/config/provisioning.yaml)
3. Infrastructure (workspace/{name}/infra/{infra}/config.toml)
4. Environment (PROVISIONING_* env variables)
5. Runtime Overrides (Command line flags)
Layer System
Layer 1: Core Defaults
Location: provisioning/config/config.defaults.toml
Purpose: System-wide defaults
Modify: ❌ Never modify directly
[paths]
base = "provisioning"
workspace = "workspace"
[settings]
log_level = "info"
parallel_limit = 5
Layer 2: Workspace Configuration
Location: workspace/{name}/config/provisioning.yaml
Purpose: Workspace-specific settings
Modify: ✅ Recommended
workspace:
name: "my-project"
description: "Production deployment"
providers:
- upcloud
- aws
defaults:
provider: "upcloud"
region: "de-fra1"
Layer 3: Infrastructure Configuration
Location: workspace/{name}/infra/{infra}/config.toml
Purpose: Per-infrastructure customization
Modify: ✅ Recommended
[infrastructure]
name = "production"
type = "kubernetes"
[servers]
count = 5
plan = "4xCPU-8GB"
[taskservs]
enabled = ["kubernetes", "cilium", "postgres"]
Layer 4: Environment Variables
Purpose: Runtime configuration Modify: ✅ For dev/CI environments
export PROVISIONING_LOG_LEVEL=debug
export PROVISIONING_PROVIDER=aws
export PROVISIONING_WORKSPACE=dev
Layer 5: Runtime Flags
Purpose: One-time overrides Modify: ✅ Per command
provisioning server create --plan 8xCPU-16GB --zone us-west-2
Using Templates
Templates allow reusing infrastructure patterns:
1. Create Template
# Save current infrastructure as template
provisioning template create kubernetes-ha \
--from my-cluster \
--description "3-node HA Kubernetes cluster"
2. List Templates
provisioning template list
# Output:
# NAME TYPE NODES DESCRIPTION
# kubernetes-ha cluster 3 3-node HA Kubernetes
# small-web server 1 Single web server
# postgres-ha database 2 HA PostgreSQL setup
3. Apply Template
# Create new infrastructure from template
provisioning template apply kubernetes-ha \
--name new-cluster \
--customize
4. Customize Template
# Edit template configuration
provisioning template edit kubernetes-ha
# Validate template
provisioning template validate kubernetes-ha
Creating Custom Extensions
Custom Task Service
Create a custom taskserv for your application:
# Create taskserv from template
provisioning generate taskserv my-app \
--category application \
--version 1.0.0
Directory structure:
workspace/extensions/taskservs/application/my-app/
├── nu/
│ └── my_app.nu # Installation logic
├── kcl/
│ ├── my_app.k # Configuration schema
│ └── version.k # Version info
├── templates/
│ ├── config.yaml.j2 # Config template
│ └── systemd.service.j2 # Service template
└── README.md # Documentation
Custom Provider
Create custom provider for internal cloud:
# Generate provider scaffold
provisioning generate provider internal-cloud \
--type cloud \
--api rest
Custom Cluster
Define complete deployment configuration:
# Create cluster configuration
provisioning generate cluster my-stack \
--servers 5 \
--taskservs "kubernetes,postgres,redis" \
--customize
Configuration Inheritance
Child configurations inherit and override parent settings:
# Base: workspace/config/provisioning.yaml
defaults:
server_plan: "2xCPU-4GB"
region: "de-fra1"
# Override: workspace/infra/prod/config.toml
[servers]
plan = "8xCPU-16GB" # Overrides default
# region inherited: de-fra1
Variable Interpolation
Use variables for dynamic configuration:
workspace:
name: "{{env.PROJECT_NAME}}"
servers:
hostname_prefix: "{{workspace.name}}-server"
zone: "{{defaults.region}}"
paths:
base: "{{env.HOME}}/provisioning"
workspace: "{{paths.base}}/workspace"
Supported variables:
{{env.*}}- Environment variables{{workspace.*}}- Workspace config{{defaults.*}}- Default values{{paths.*}}- Path configuration{{now.date}}- Current date{{git.branch}}- Git branch name
Customization Examples
Example 1: Multi-Environment Setup
# workspace/envs/dev/config.yaml
environment: development
server_count: 1
server_plan: small
# workspace/envs/prod/config.yaml
environment: production
server_count: 5
server_plan: large
high_availability: true
# Deploy to dev
provisioning cluster create app --env dev
# Deploy to prod
provisioning cluster create app --env prod
Example 2: Custom Monitoring Stack
# Create custom monitoring configuration
cat > workspace/infra/monitoring/config.toml <<EOF
[taskservs]
enabled = [
"prometheus",
"grafana",
"alertmanager",
"loki"
]
[prometheus]
retention = "30d"
storage = "100GB"
[grafana]
admin_user = "admin"
plugins = ["cloudflare", "postgres"]
EOF
# Apply monitoring stack
provisioning cluster create monitoring --config monitoring/config.toml
Example 3: Development vs Production
# Development: lightweight, fast
provisioning cluster create app \
--profile dev \
--servers 1 \
--plan small
# Production: robust, HA
provisioning cluster create app \
--profile prod \
--servers 5 \
--plan large \
--ha \
--backup-enabled
Advanced Customization
Custom Workflows
Create custom deployment workflows:
# workspace/workflows/my-deploy.k
import provisioning.workflows as wf
my_deployment: wf.BatchWorkflow = {
name = "custom-deployment"
operations = [
# Your custom steps
]
}
Custom Validation Rules
Add validation for your infrastructure:
# workspace/extensions/validation/my-rules.nu
export def validate-my-infra [config: record] {
# Custom validation logic
if $config.servers < 3 {
error make {msg: "Production requires 3+ servers"}
}
}
Custom Hooks
Execute custom actions at deployment stages:
# workspace/config/hooks.yaml
hooks:
pre_create_servers:
- script: "scripts/validate-quota.sh"
post_create_servers:
- script: "scripts/configure-monitoring.sh"
pre_install_taskserv:
- script: "scripts/check-dependencies.sh"
Best Practices
DO ✅
- Use workspace config for project-specific settings
- Create templates for reusable patterns
- Use variables for dynamic configuration
- Document custom extensions
- Test customizations in dev environment
DON’T ❌
- Modify core defaults directly
- Hardcode environment-specific values
- Skip validation steps
- Create circular dependencies
- Bypass security policies
Testing Customizations
# Validate configuration
provisioning validate config --strict
# Test in isolated environment
provisioning test env cluster my-custom-setup --check
# Dry run deployment
provisioning cluster create test --check --verbose
Related Documentation
- Configuration System - Configuration architecture
- Extension Development - Create extensions
- Template System - Template reference
- KCL Patterns - KCL configuration language
Need Help? Run provisioning help customize or see User Guide.