Complete infrastructure platform CLI: - Container runtime (systemd-nspawn) - VoltVisor VMs (Neutron Stardust / QEMU) - Stellarium CAS (content-addressed storage) - ORAS Registry - GitOps integration - Landlock LSM security - Compose orchestration - Mesh networking Copyright (c) Armored Gates LLC. All rights reserved. Licensed under AGPSL v5.0
742 lines
15 KiB
Markdown
742 lines
15 KiB
Markdown
# Voltfile / Constellation Format
|
|
|
|
A **Constellation** is the definition of how containers, VMs, services, and resources form a coherent system. `volt compose` manages Constellations as declarative multi-service stacks — define containers, VMs, services, tasks, networks, and volumes in a single YAML file and deploy them together.
|
|
|
|
## File Discovery
|
|
|
|
`volt compose` looks for Constellation definitions in this order:
|
|
|
|
1. `-f <path>` flag (explicit)
|
|
2. `volt-compose.yaml` in current directory
|
|
3. `volt-compose.yml` in current directory
|
|
4. `Voltfile` in current directory (YAML format)
|
|
|
|
## Quick Example
|
|
|
|
```yaml
|
|
version: "1"
|
|
name: web-stack
|
|
|
|
containers:
|
|
web:
|
|
image: armoredgate/nginx:1.25
|
|
ports:
|
|
- "80:80"
|
|
networks:
|
|
- frontend
|
|
depends_on:
|
|
api:
|
|
condition: service_started
|
|
|
|
api:
|
|
image: armoredgate/node:20
|
|
ports:
|
|
- "8080:8080"
|
|
environment:
|
|
DATABASE_URL: "postgresql://app:secret@db:5432/myapp"
|
|
networks:
|
|
- frontend
|
|
- backend
|
|
|
|
vms:
|
|
db:
|
|
image: armoredgate/ubuntu-24.04
|
|
cpu: 2
|
|
memory: 4G
|
|
networks:
|
|
- backend
|
|
|
|
networks:
|
|
frontend:
|
|
subnet: 10.20.0.0/24
|
|
backend:
|
|
subnet: 10.30.0.0/24
|
|
internal: true
|
|
```
|
|
|
|
Deploy:
|
|
|
|
```bash
|
|
volt compose up -d # Create and start in background
|
|
volt compose ps # Check status
|
|
volt compose logs -f # Follow all logs
|
|
volt compose down # Tear down
|
|
```
|
|
|
|
## Top-Level Keys
|
|
|
|
| Key | Type | Required | Description |
|
|
|-----|------|----------|-------------|
|
|
| `version` | string | Yes | File format version. Currently `"1"`. |
|
|
| `name` | string | No | Stack name. Used as prefix for workload names. |
|
|
| `description` | string | No | Human-readable description. |
|
|
| `containers` | map | No | Container definitions (Voltainer). |
|
|
| `vms` | map | No | VM definitions (Voltvisor). |
|
|
| `services` | map | No | systemd service definitions. |
|
|
| `tasks` | map | No | Scheduled task definitions. |
|
|
| `networks` | map | No | Network definitions. |
|
|
| `volumes` | map | No | Volume definitions. |
|
|
| `configs` | map | No | Configuration file references. |
|
|
| `secrets` | map | No | Secret file references. |
|
|
|
|
## Container Definition
|
|
|
|
```yaml
|
|
containers:
|
|
<name>:
|
|
image: <string> # Image name (required)
|
|
build: # Build configuration (optional)
|
|
context: <path> # Build context directory
|
|
file: <path> # Build spec file
|
|
ports: # Port mappings
|
|
- "host:container"
|
|
volumes: # Volume mounts
|
|
- host_path:container_path[:ro]
|
|
- volume_name:container_path
|
|
networks: # Networks to join
|
|
- network_name
|
|
environment: # Environment variables
|
|
KEY: value
|
|
env_file: # Load env vars from files
|
|
- .env
|
|
depends_on: # Dependencies
|
|
other_service:
|
|
condition: service_started|service_healthy|service_completed_successfully
|
|
restart: no|always|on-failure|unless-stopped
|
|
restart_max_retries: <int> # Max restart attempts (for on-failure)
|
|
resources:
|
|
cpu: "<number>" # CPU shares/quota
|
|
memory: <size> # e.g., 256M, 1G
|
|
memory_swap: <size> # Swap limit
|
|
healthcheck:
|
|
command: ["cmd", "args"] # Health check command
|
|
interval: <duration> # Check interval (e.g., 30s)
|
|
timeout: <duration> # Check timeout
|
|
retries: <int> # Retries before unhealthy
|
|
start_period: <duration> # Grace period on start
|
|
labels:
|
|
key: value
|
|
```
|
|
|
|
### Container Example
|
|
|
|
```yaml
|
|
containers:
|
|
app-server:
|
|
image: armoredgate/node:20
|
|
build:
|
|
context: ./app
|
|
file: build-spec.yaml
|
|
ports:
|
|
- "8080:8080"
|
|
volumes:
|
|
- app-data:/app/data
|
|
- ./config:/app/config:ro
|
|
networks:
|
|
- backend
|
|
environment:
|
|
NODE_ENV: production
|
|
DATABASE_URL: "postgresql://app:${DB_PASSWORD}@db:5432/myapp"
|
|
env_file:
|
|
- .env
|
|
- .env.production
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
cache:
|
|
condition: service_started
|
|
restart: on-failure
|
|
restart_max_retries: 5
|
|
resources:
|
|
cpu: "2"
|
|
memory: 1G
|
|
memory_swap: 2G
|
|
healthcheck:
|
|
command: ["curl", "-sf", "http://localhost:8080/health"]
|
|
interval: 15s
|
|
timeout: 3s
|
|
retries: 5
|
|
```
|
|
|
|
## VM Definition
|
|
|
|
```yaml
|
|
vms:
|
|
<name>:
|
|
image: <string> # Base image (required)
|
|
cpu: <int> # vCPU count
|
|
memory: <size> # Memory allocation (e.g., 4G)
|
|
disks: # Additional disks
|
|
- name: <string>
|
|
size: <size>
|
|
mount: <path> # Mount point inside VM
|
|
networks:
|
|
- network_name
|
|
ports:
|
|
- "host:vm"
|
|
provision: # First-boot scripts
|
|
- name: <string>
|
|
shell: |
|
|
commands to run
|
|
healthcheck:
|
|
command: ["cmd", "args"]
|
|
interval: <duration>
|
|
timeout: <duration>
|
|
retries: <int>
|
|
restart: no|always|on-failure
|
|
tune: # Performance tuning
|
|
cpu_pin: [<int>, ...] # Pin to physical CPUs
|
|
hugepages: <bool> # Use hugepages
|
|
io_scheduler: <string> # I/O scheduler
|
|
```
|
|
|
|
### VM Example
|
|
|
|
```yaml
|
|
vms:
|
|
db-primary:
|
|
image: armoredgate/ubuntu-24.04
|
|
cpu: 4
|
|
memory: 8G
|
|
disks:
|
|
- name: system
|
|
size: 40G
|
|
- name: pgdata
|
|
size: 200G
|
|
mount: /var/lib/postgresql/data
|
|
networks:
|
|
- backend
|
|
ports:
|
|
- "5432:5432"
|
|
provision:
|
|
- name: install-postgres
|
|
shell: |
|
|
apt-get update && apt-get install -y postgresql-16
|
|
systemctl enable postgresql
|
|
healthcheck:
|
|
command: ["pg_isready", "-U", "postgres"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
restart: always
|
|
tune:
|
|
cpu_pin: [4, 5, 6, 7]
|
|
hugepages: true
|
|
io_scheduler: none
|
|
```
|
|
|
|
## Service Definition
|
|
|
|
Define systemd services managed by the Constellation:
|
|
|
|
```yaml
|
|
services:
|
|
<name>:
|
|
unit:
|
|
type: simple|oneshot|forking|notify
|
|
exec: <string> # Command to run (required)
|
|
user: <string>
|
|
group: <string>
|
|
restart: no|always|on-failure
|
|
networks:
|
|
- network_name
|
|
healthcheck:
|
|
command: ["cmd", "args"]
|
|
interval: <duration>
|
|
resources:
|
|
memory: <size>
|
|
depends_on:
|
|
other_service:
|
|
condition: service_started
|
|
```
|
|
|
|
### Service Example
|
|
|
|
```yaml
|
|
services:
|
|
cache-redis:
|
|
unit:
|
|
type: simple
|
|
exec: "/usr/bin/redis-server /etc/redis/redis.conf"
|
|
user: redis
|
|
group: redis
|
|
restart: always
|
|
networks:
|
|
- backend
|
|
healthcheck:
|
|
command: ["redis-cli", "ping"]
|
|
interval: 10s
|
|
resources:
|
|
memory: 512M
|
|
```
|
|
|
|
## Task Definition
|
|
|
|
Define scheduled tasks (systemd timers):
|
|
|
|
```yaml
|
|
tasks:
|
|
<name>:
|
|
exec: <string> # Command to run (required)
|
|
schedule:
|
|
on_calendar: <string> # systemd calendar syntax
|
|
every: <duration> # Alternative: interval
|
|
environment:
|
|
KEY: value
|
|
user: <string>
|
|
persistent: <bool> # Run missed tasks on boot
|
|
```
|
|
|
|
### Task Example
|
|
|
|
```yaml
|
|
tasks:
|
|
db-backup:
|
|
exec: "/usr/local/bin/backup.sh --target db-primary"
|
|
schedule:
|
|
on_calendar: "*-*-* 02:00:00"
|
|
environment:
|
|
BACKUP_DEST: /mnt/backups
|
|
|
|
cleanup:
|
|
exec: "/usr/local/bin/cleanup-old-logs.sh"
|
|
schedule:
|
|
every: 6h
|
|
```
|
|
|
|
## Network Definition
|
|
|
|
```yaml
|
|
networks:
|
|
<name>:
|
|
driver: bridge # Network driver (default: bridge)
|
|
subnet: <cidr> # e.g., 10.20.0.0/24
|
|
internal: <bool> # If true, no external access
|
|
options:
|
|
mtu: <int> # MTU (default: 1500)
|
|
```
|
|
|
|
### Network Examples
|
|
|
|
```yaml
|
|
networks:
|
|
# Public-facing network
|
|
frontend:
|
|
driver: bridge
|
|
subnet: 10.20.0.0/24
|
|
options:
|
|
mtu: 9000
|
|
|
|
# Internal only — no external access
|
|
backend:
|
|
driver: bridge
|
|
subnet: 10.30.0.0/24
|
|
internal: true
|
|
```
|
|
|
|
## Volume Definition
|
|
|
|
```yaml
|
|
volumes:
|
|
<name>:
|
|
driver: local # Storage driver
|
|
size: <size> # Optional size for file-backed volumes
|
|
```
|
|
|
|
### Volume Examples
|
|
|
|
```yaml
|
|
volumes:
|
|
web-static:
|
|
driver: local
|
|
|
|
app-data:
|
|
driver: local
|
|
size: 10G
|
|
|
|
pgdata:
|
|
driver: local
|
|
size: 200G
|
|
```
|
|
|
|
## Configs and Secrets
|
|
|
|
```yaml
|
|
configs:
|
|
<name>:
|
|
file: <path> # Path to config file
|
|
|
|
secrets:
|
|
<name>:
|
|
file: <path> # Path to secret file
|
|
```
|
|
|
|
### Example
|
|
|
|
```yaml
|
|
configs:
|
|
nginx-conf:
|
|
file: ./config/nginx.conf
|
|
app-env:
|
|
file: ./.env.production
|
|
|
|
secrets:
|
|
db-password:
|
|
file: ./secrets/db-password.txt
|
|
tls-cert:
|
|
file: ./secrets/server.crt
|
|
tls-key:
|
|
file: ./secrets/server.key
|
|
```
|
|
|
|
## Dependency Conditions
|
|
|
|
When specifying `depends_on`, the `condition` field controls when the dependent service starts:
|
|
|
|
| Condition | Description |
|
|
|-----------|-------------|
|
|
| `service_started` | Dependency has started (default) |
|
|
| `service_healthy` | Dependency passes its health check |
|
|
| `service_completed_successfully` | Dependency ran and exited with code 0 |
|
|
|
|
```yaml
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
migrations:
|
|
condition: service_completed_successfully
|
|
cache:
|
|
condition: service_started
|
|
```
|
|
|
|
## Environment Variable Interpolation
|
|
|
|
The Constellation definition supports shell-style variable interpolation:
|
|
|
|
```yaml
|
|
environment:
|
|
DATABASE_URL: "postgresql://app:${DB_PASSWORD}@db:5432/myapp"
|
|
APP_VERSION: "${APP_VERSION:-latest}"
|
|
```
|
|
|
|
Variables are resolved from:
|
|
|
|
1. Host environment variables
|
|
2. `.env` file in the same directory as the Constellation definition
|
|
3. Files specified in `env_file`
|
|
|
|
Unset variables with no default cause an error.
|
|
|
|
## Compose Commands
|
|
|
|
### Lifecycle
|
|
|
|
```bash
|
|
# Deploy the Constellation — create and start everything
|
|
volt compose up
|
|
|
|
# Detached mode (background)
|
|
volt compose up -d
|
|
|
|
# Specific Constellation file
|
|
volt compose -f production.yaml up -d
|
|
|
|
# Build images first
|
|
volt compose up --build
|
|
|
|
# Force recreate
|
|
volt compose up --force-recreate
|
|
|
|
# Tear down the Constellation
|
|
volt compose down
|
|
|
|
# Also remove volumes
|
|
volt compose down --volumes
|
|
```
|
|
|
|
### Status and Logs
|
|
|
|
```bash
|
|
# Stack status
|
|
volt compose ps
|
|
|
|
# All logs
|
|
volt compose logs
|
|
|
|
# Follow logs
|
|
volt compose logs --follow
|
|
|
|
# Logs for one service
|
|
volt compose logs api
|
|
|
|
# Last 50 lines
|
|
volt compose logs --tail 50 api
|
|
|
|
# Resource usage
|
|
volt compose top
|
|
|
|
# Events
|
|
volt compose events
|
|
```
|
|
|
|
### Operations
|
|
|
|
```bash
|
|
# Start existing (without recreating)
|
|
volt compose start
|
|
|
|
# Stop (without removing)
|
|
volt compose stop
|
|
|
|
# Restart
|
|
volt compose restart
|
|
|
|
# Execute command in a service
|
|
volt compose exec api -- node --version
|
|
|
|
# Pull images
|
|
volt compose pull
|
|
|
|
# Build images
|
|
volt compose build
|
|
|
|
# Validate Constellation
|
|
volt compose config
|
|
```
|
|
|
|
### Project Naming
|
|
|
|
```bash
|
|
# Override project name
|
|
volt compose --project my-project up
|
|
|
|
# This prefixes all workload names: my-project-web, my-project-api, etc.
|
|
```
|
|
|
|
## Full Example: Production Constellation
|
|
|
|
```yaml
|
|
# volt-compose.yaml — Production Constellation
|
|
version: "1"
|
|
name: production
|
|
description: "Production web application"
|
|
|
|
containers:
|
|
web-proxy:
|
|
image: armoredgate/nginx:1.25
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
volumes:
|
|
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
|
- web-static:/usr/share/nginx/html:ro
|
|
networks:
|
|
- frontend
|
|
- backend
|
|
depends_on:
|
|
app-server:
|
|
condition: service_healthy
|
|
restart: always
|
|
resources:
|
|
cpu: "0.5"
|
|
memory: 256M
|
|
healthcheck:
|
|
command: ["curl", "-sf", "http://localhost/health"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 10s
|
|
|
|
app-server:
|
|
image: armoredgate/node:20
|
|
build:
|
|
context: ./app
|
|
file: build-spec.yaml
|
|
environment:
|
|
NODE_ENV: production
|
|
DATABASE_URL: "postgresql://app:${DB_PASSWORD}@db-primary:5432/myapp"
|
|
REDIS_URL: "redis://cache-redis:6379"
|
|
env_file:
|
|
- .env.production
|
|
ports:
|
|
- "8080:8080"
|
|
volumes:
|
|
- app-data:/app/data
|
|
networks:
|
|
- backend
|
|
depends_on:
|
|
db-primary:
|
|
condition: service_healthy
|
|
cache-redis:
|
|
condition: service_started
|
|
restart: on-failure
|
|
restart_max_retries: 5
|
|
resources:
|
|
cpu: "2"
|
|
memory: 1G
|
|
healthcheck:
|
|
command: ["curl", "-sf", "http://localhost:8080/health"]
|
|
interval: 15s
|
|
timeout: 3s
|
|
retries: 5
|
|
|
|
vms:
|
|
db-primary:
|
|
image: armoredgate/ubuntu-24.04
|
|
cpu: 4
|
|
memory: 8G
|
|
disks:
|
|
- name: system
|
|
size: 40G
|
|
- name: pgdata
|
|
size: 200G
|
|
mount: /var/lib/postgresql/data
|
|
networks:
|
|
- backend
|
|
ports:
|
|
- "5432:5432"
|
|
provision:
|
|
- name: install-postgres
|
|
shell: |
|
|
apt-get update && apt-get install -y postgresql-16
|
|
systemctl enable postgresql
|
|
healthcheck:
|
|
command: ["pg_isready", "-U", "postgres"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
restart: always
|
|
tune:
|
|
cpu_pin: [4, 5, 6, 7]
|
|
hugepages: true
|
|
io_scheduler: none
|
|
|
|
services:
|
|
cache-redis:
|
|
unit:
|
|
type: simple
|
|
exec: "/usr/bin/redis-server /etc/redis/redis.conf"
|
|
user: redis
|
|
group: redis
|
|
restart: always
|
|
networks:
|
|
- backend
|
|
healthcheck:
|
|
command: ["redis-cli", "ping"]
|
|
interval: 10s
|
|
resources:
|
|
memory: 512M
|
|
|
|
log-shipper:
|
|
unit:
|
|
type: simple
|
|
exec: "/usr/local/bin/vector --config /etc/vector/vector.toml"
|
|
restart: on-failure
|
|
depends_on:
|
|
app-server:
|
|
condition: service_started
|
|
|
|
tasks:
|
|
db-backup:
|
|
exec: "/usr/local/bin/backup.sh --target db-primary"
|
|
schedule:
|
|
on_calendar: "*-*-* 02:00:00"
|
|
environment:
|
|
BACKUP_DEST: /mnt/backups
|
|
|
|
cleanup:
|
|
exec: "/usr/local/bin/cleanup-old-logs.sh"
|
|
schedule:
|
|
every: 6h
|
|
|
|
networks:
|
|
frontend:
|
|
driver: bridge
|
|
subnet: 10.20.0.0/24
|
|
options:
|
|
mtu: 9000
|
|
|
|
backend:
|
|
driver: bridge
|
|
subnet: 10.30.0.0/24
|
|
internal: true
|
|
|
|
volumes:
|
|
web-static:
|
|
driver: local
|
|
app-data:
|
|
driver: local
|
|
size: 10G
|
|
|
|
configs:
|
|
nginx-conf:
|
|
file: ./config/nginx.conf
|
|
|
|
secrets:
|
|
db-password:
|
|
file: ./secrets/db-password.txt
|
|
tls-cert:
|
|
file: ./secrets/server.crt
|
|
tls-key:
|
|
file: ./secrets/server.key
|
|
```
|
|
|
|
## Full Example: Developer Constellation
|
|
|
|
```yaml
|
|
# volt-compose.yaml — Developer Constellation
|
|
version: "1"
|
|
name: dev-environment
|
|
|
|
vms:
|
|
dev-box:
|
|
image: armoredgate/fedora-workstation
|
|
cpu: 4
|
|
memory: 8G
|
|
disks:
|
|
- name: system
|
|
size: 80G
|
|
volumes:
|
|
- ~/projects:/home/dev/projects
|
|
networks:
|
|
- devnet
|
|
ports:
|
|
- "2222:22"
|
|
- "3000:3000"
|
|
- "5173:5173"
|
|
provision:
|
|
- name: dev-tools
|
|
shell: |
|
|
dnf install -y git nodejs rust golang
|
|
npm install -g pnpm
|
|
|
|
containers:
|
|
test-db:
|
|
image: armoredgate/postgres:16
|
|
environment:
|
|
POSTGRES_PASSWORD: devpass
|
|
POSTGRES_DB: myapp_dev
|
|
volumes:
|
|
- test-pgdata:/var/lib/postgresql/data
|
|
networks:
|
|
- devnet
|
|
ports:
|
|
- "5432:5432"
|
|
|
|
mailhog:
|
|
image: armoredgate/mailhog:latest
|
|
networks:
|
|
- devnet
|
|
ports:
|
|
- "1025:1025"
|
|
- "8025:8025"
|
|
|
|
networks:
|
|
devnet:
|
|
subnet: 10.99.0.0/24
|
|
|
|
volumes:
|
|
test-pgdata:
|
|
driver: local
|
|
```
|