Volt CLI: source-available under AGPSL v5.0
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
This commit is contained in:
741
docs/compose.md
Normal file
741
docs/compose.md
Normal file
@@ -0,0 +1,741 @@
|
||||
# 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
|
||||
```
|
||||
Reference in New Issue
Block a user