Provision virtual machine infrastructure for a deployment environment.
Creates and configures VM infrastructure using OpenTofu (Terraform). This command takes an environment from the "Created" state to the "Provisioned" state with running VM instances.
The provision command works with all supported providers:
- LXD - Creates local VMs for development and testing
- Hetzner Cloud - Creates cloud servers for production deployments
torrust-tracker-deployer provision <ENVIRONMENT><ENVIRONMENT>(required) - Name of the environment to provision
- Environment created - Must run
create environmentfirst - Provider-specific requirements:
- LXD: Local LXD installation configured
- Hetzner: Valid API token in environment configuration
- OpenTofu installed - OpenTofu CLI available in PATH
- SSH keys - SSH key pair referenced in environment configuration
📖 See Provider Guides for provider-specific setup.
[Created] --provision--> [Provisioned]
When you provision an environment:
- Renders OpenTofu templates - Generates provider-specific infrastructure-as-code files
- Initializes OpenTofu - Sets up backend and providers (
tofu init) - Creates execution plan - Validates configuration (
tofu plan) - Applies infrastructure - Creates VM resources (
tofu apply) - Retrieves instance info - Gets IP address and instance details
- Renders Ansible templates - Generates configuration management files
- Waits for SSH - Verifies network connectivity
- Waits for cloud-init - Ensures VM initialization is complete
- Updates environment state - Transitions to "Provisioned"
# Provision the environment
torrust-tracker-deployer provision my-environment
# Output:
# ✓ Rendering OpenTofu templates...
# ✓ Initializing infrastructure...
# ✓ Planning infrastructure changes...
# ✓ Applying infrastructure...
# ✓ Retrieving instance information...
# ✓ Instance IP: 10.140.190.42
# ✓ Rendering Ansible templates...
# ✓ Waiting for SSH connectivity...
# ✓ Waiting for cloud-init completion...
# ✓ Environment provisioned successfully# Development
torrust-tracker-deployer provision dev-local
# Staging
torrust-tracker-deployer provision staging
# Production (Hetzner)
torrust-tracker-deployer provision productionThe provision command creates provider-specific resources:
- VM instance - LXD virtual machine (
torrust-tracker-vm-<env-name>) - LXD profile - Custom profile with cloud-init configuration
- Network configuration - Bridged network with IP assignment
- OpenTofu state - Infrastructure state in
build/<env>/tofu/lxd/
- Cloud server - Hetzner Cloud server instance
- Firewall - Hetzner firewall with SSH access
- SSH key - Uploaded SSH public key
- OpenTofu state - Infrastructure state in
build/<env>/tofu/hetzner/
- Ansible inventory - Generated inventory in
build/<env>/ansible/ - Environment state update - State file updated to "Provisioned"
After provisioning:
# 1. Configure the infrastructure (install Docker, Docker Compose)
torrust-tracker-deployer configure my-environment
# 2. Verify infrastructure readiness
torrust-tracker-deployer test my-environmentProblem: Cannot find environment with the specified name
Solution: Verify the environment was created
# Check environment data directory exists
ls -la data/my-environment/
# If not, create the environment first
torrust-tracker-deployer create environment -f config.jsonProblem: LXD is not properly initialized
Solution: Initialize LXD
# Initialize LXD with default settings
sudo lxd init --auto
# Add your user to lxd group
sudo usermod -a -G lxd $USER
newgrp lxdProblem: OpenTofu CLI is not installed or not in PATH
Solution: Install OpenTofu
# Install OpenTofu
curl -fsSL https://get.opentofu.org/install-opentofu.sh | sudo bash
# Verify installation
tofu versionProblem: Cannot establish SSH connection to provisioned VM
Solution: Check network connectivity and cloud-init status
# Get VM IP address
lxc list
# Try to connect manually
ssh -i <path-to-private-key> torrust@<vm-ip>
# Check cloud-init status
lxc exec <instance-name> -- cloud-init statusProblem: LXD profile or instance name already exists
Solution: Clean up existing resources
# List existing instances
lxc list
# Delete old instance if needed
lxc delete <instance-name> --force
# List profiles
lxc profile list
# Delete old profile if needed
lxc profile delete <profile-name># Create, provision, and configure in sequence
torrust-tracker-deployer create environment -f dev.json
torrust-tracker-deployer provision dev-local
torrust-tracker-deployer configure dev-local#!/bin/bash
set -e
ENV_NAME="ci-${CI_JOB_ID}"
# Create environment
torrust-tracker-deployer create environment -f ci-config.json
# Provision infrastructure
torrust-tracker-deployer provision ${ENV_NAME}
# Run tests...
# Cleanup is handled by destroy commandIf you need to reprovision (destroy and create again):
# Destroy existing environment
torrust-tracker-deployer destroy my-environment
# Create fresh environment
torrust-tracker-deployer create environment -f config.json
# Provision again
torrust-tracker-deployer provision my-environmentLXD Resources:
- Instance:
torrust-tracker-vm-<environment-name> - Profile:
torrust-profile-<environment-name> - Network: Bridged network with DHCP
File Artifacts:
- OpenTofu files:
build/<env>/tofu/lxd/ - Ansible inventory:
build/<env>/ansible/inventory.yml - Instance info: Stored in environment state
The provisioned VM includes cloud-init configuration for:
- User account creation (SSH username from config)
- SSH key deployment (public key from config)
- Network configuration
- Initial system setup