Skip to content
This repository was archived by the owner on Oct 10, 2025. It is now read-only.

Commit 0e85e50

Browse files
committed
fix: [#28] improve infrastructure provisioning UX and documentation
- Infrastructure waiting logic: Added proper VM IP and cloud-init waiting - SSH key auto-detection: Documented automatic detection of ~/.ssh/torrust_rsa.pub - Environment file naming: Clarified flexible naming conventions (not mandatory format) - Output display fix: Fixed cosmetic issue showing actual VM IP instead of 'No IP assigned yet' - Documentation updates: Enhanced cloud deployment guide with SSH and environment details Key improvements: ✅ Infrastructure provisioning now waits for full readiness by default ✅ Clear SSH key auto-detection documentation and comments ✅ Flexible environment file naming (my-dev.env, local-test.env, etc.) ✅ Fixed final output to display correct VM IP address (192.168.122.21) ✅ Enhanced user experience with automatic waiting and progress indicators Files changed: - infrastructure/scripts/provision-infrastructure.sh: Added waiting logic and fixed IP display - infrastructure/config/templates/environments/: Updated SSH key documentation - docs/guides/cloud-deployment-guide.md: Comprehensive SSH and environment documentation - infrastructure/config/environments/README.md: Environment file naming clarification
1 parent f19d2cc commit 0e85e50

File tree

5 files changed

+149
-49
lines changed

5 files changed

+149
-49
lines changed

docs/guides/cloud-deployment-guide.md

Lines changed: 89 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ This project implements a **four-step deployment workflow** aligned with twelve-
2020

2121
Create environment-specific configuration from templates:
2222

23-
- **Local Development**: `infrastructure/config/environments/local.env.tpl``local.env`
24-
- **Production**: `infrastructure/config/environments/production.env.tpl``production.env`
23+
- **Development Environment**: `development-libvirt.env` (default) or custom name like `my-dev.env`
24+
- **End-to-end Testing**: `e2e-libvirt.env` (default) or custom name like `ci-test.env`
25+
- **Production Environment**: `production-hetzner.env` (default) or custom name like `prod.env`
2526

2627
The environment file contains **all deployment configuration**, including:
2728

@@ -66,8 +67,37 @@ Verify deployment health and functionality:
6667
- **OpenTofu** (or Terraform) installed
6768
- **Git** for repository access
6869
- **SSH client** for server access
70+
- **SSH key pair** for VM access (see SSH Key Configuration below)
6971
- **Domain name** (required for HTTPS certificates in production)
7072

73+
#### SSH Key Configuration
74+
75+
The deployment system requires an SSH public key for secure VM access. The system
76+
automatically detects SSH keys from these locations (in order):
77+
78+
1. `~/.ssh/torrust_rsa.pub` (recommended - dedicated key for Torrust deployments)
79+
2. `~/.ssh/id_rsa.pub` (common default SSH key)
80+
3. `~/.ssh/id_ed25519.pub` (Ed25519 SSH key)
81+
4. `~/.ssh/id_ecdsa.pub` (ECDSA SSH key)
82+
83+
**Recommended Setup**:
84+
85+
```bash
86+
# Generate dedicated SSH key for Torrust deployments
87+
ssh-keygen -t rsa -b 4096 -f ~/.ssh/torrust_rsa -C "[email protected]"
88+
89+
# The public key (~/.ssh/torrust_rsa.pub) will be auto-detected
90+
# The private key (~/.ssh/torrust_rsa) will be used for SSH connections
91+
```
92+
93+
**Alternative Options**:
94+
95+
- **Use existing key**: Copy your existing public key to `~/.ssh/torrust_rsa.pub`
96+
- **Manual configuration**: Set `SSH_PUBLIC_KEY` in your environment file
97+
- **Environment variable**: Export the key content as an environment variable
98+
99+
If no SSH key is found, the deployment will provide detailed error messages with setup instructions.
100+
71101
### Cloud Provider Requirements (For Future Implementation)
72102

73103
When cloud providers are implemented, they will need:
@@ -90,10 +120,18 @@ cloud-agnostic to facilitate adding cloud providers that support cloud-init in t
90120

91121
## Quick Start
92122

93-
### Current Implementation: Local Development
123+
### Current Implementation: Development Environment (KVM/libvirt)
94124

95-
The current implementation supports local KVM/libvirt deployment, which is perfect
96-
for development, testing, and understanding the system before cloud deployment.
125+
The current implementation supports local KVM/libvirt deployment using the **development**
126+
environment type, which is perfect for development, testing, and understanding the system
127+
before cloud deployment.
128+
129+
**Environment Types vs Environment Files**:
130+
131+
- **Environment Types**: `development`, `testing`, `e2e`, `staging`, `production`
132+
- **Environment Files**: Any name you choose (e.g., `my-dev.env`, `local-test.env`)
133+
- **Default Format**: `{environment-type}-{provider}.env` (when using generation scripts)
134+
- **Examples**: `development-libvirt.env`, `production-hetzner.env`, `my-custom-setup.env`
97135

98136
### 1. Clone and Setup
99137

@@ -105,22 +143,29 @@ cd torrust-tracker-demo
105143
# Install dependencies (Ubuntu/Debian)
106144
make install-deps
107145

108-
# Configure SSH access for VMs
109-
make infra-config-local
146+
# Setup SSH key for VM access (if you don't have ~/.ssh/torrust_rsa.pub)
147+
ssh-keygen -t rsa -b 4096 -f ~/.ssh/torrust_rsa -C "[email protected]"
148+
149+
# The system will auto-detect ~/.ssh/torrust_rsa.pub during deployment
110150
```
111151

112152
### 2. Local Testing with KVM/libvirt
113153

114154
```bash
115-
# Test deployment locally with KVM
155+
# Test deployment locally with KVM using development environment (default naming)
116156
# Commands wait for full readiness by default
117-
make infra-apply ENVIRONMENT=local
118-
make app-deploy ENVIRONMENT=local
157+
make infra-apply ENVIRONMENT_TYPE=development ENVIRONMENT_FILE=development-libvirt
158+
make app-deploy ENVIRONMENT_TYPE=development ENVIRONMENT_FILE=development-libvirt
159+
make app-health-check
160+
161+
# Alternative: Use custom file names
162+
make infra-apply ENVIRONMENT_TYPE=development ENVIRONMENT_FILE=my-custom-dev
163+
make app-deploy ENVIRONMENT_TYPE=development ENVIRONMENT_FILE=my-custom-dev
119164
make app-health-check
120165

121166
# Advanced users: Skip waiting for faster execution
122-
make infra-apply ENVIRONMENT=local SKIP_WAIT=true
123-
make app-deploy ENVIRONMENT=local SKIP_WAIT=true
167+
make infra-apply ENVIRONMENT_TYPE=development ENVIRONMENT_FILE=development-libvirt SKIP_WAIT=true
168+
make app-deploy ENVIRONMENT_TYPE=development ENVIRONMENT_FILE=development-libvirt SKIP_WAIT=true
124169
make app-health-check
125170

126171
# Access the local instance via SSH
@@ -134,17 +179,20 @@ make vm-ssh
134179
make infra-destroy
135180
```
136181

182+
**Note**: `ENVIRONMENT_FILE` can be any filename (without `.env` extension).
183+
The system looks for the file in `infrastructure/config/environments/{filename}.env`.
184+
137185
### 3. Cloud Deployment (Planned - Hetzner)
138186

139187
**Note**: Cloud deployment is not yet implemented. The following commands show the
140188
planned interface for future Hetzner Cloud deployment:
141189

142190
```bash
143-
# Planned: Deploy infrastructure to Hetzner Cloud
144-
make infra-apply ENVIRONMENT=production PROVIDER=hetzner
191+
# Planned: Deploy infrastructure to Hetzner Cloud using production environment
192+
make infra-apply ENVIRONMENT_TYPE=production ENVIRONMENT_FILE=production-hetzner
145193

146194
# Planned: Deploy application services
147-
make app-deploy ENVIRONMENT=production
195+
make app-deploy ENVIRONMENT_TYPE=production ENVIRONMENT_FILE=production-hetzner
148196

149197
# Validate deployment
150198
make app-health-check
@@ -315,9 +363,14 @@ default, providing a much better user experience:
315363

316364
```bash
317365
# Each command waits for full readiness by default
318-
make infra-apply ENVIRONMENT=local # Waits for VM IP + cloud-init completion
319-
make app-deploy ENVIRONMENT=local # Waits for all services to be healthy
320-
make app-health-check # Validates everything is working
366+
make infra-apply ENVIRONMENT_TYPE=development ENVIRONMENT_FILE=development-libvirt
367+
make app-deploy ENVIRONMENT_TYPE=development ENVIRONMENT_FILE=development-libvirt
368+
make app-health-check
369+
370+
# What each command does:
371+
# infra-apply: Waits for VM IP + cloud-init completion
372+
# app-deploy: Waits for all services to be healthy
373+
# health-check: Validates everything is working
321374
```
322375

323376
**Key improvements**:
@@ -331,17 +384,17 @@ make app-health-check # Validates everything is working
331384

332385
```bash
333386
# Skip waiting for faster execution (original behavior)
334-
make infra-apply ENVIRONMENT=local SKIP_WAIT=true
335-
make app-deploy ENVIRONMENT=local SKIP_WAIT=true
387+
make infra-apply ENVIRONMENT_TYPE=development ENVIRONMENT_FILE=development-libvirt SKIP_WAIT=true
388+
make app-deploy ENVIRONMENT_TYPE=development ENVIRONMENT_FILE=development-libvirt SKIP_WAIT=true
336389
```
337390

338391
### Infrastructure Deployment
339392

340393
The infrastructure deployment creates and configures the VM:
341394

342395
```bash
343-
# Deploy infrastructure
344-
make infra-apply ENVIRONMENT=production
396+
# Deploy infrastructure using development environment
397+
make infra-apply ENVIRONMENT_TYPE=development ENVIRONMENT_FILE=development-libvirt
345398

346399
# What this does:
347400
# 1. Creates VM with Ubuntu 24.04
@@ -359,8 +412,8 @@ make infra-apply ENVIRONMENT=production
359412
The application deployment sets up all services:
360413

361414
```bash
362-
# Deploy application
363-
make app-deploy ENVIRONMENT=production
415+
# Deploy application using development environment
416+
make app-deploy ENVIRONMENT_TYPE=development ENVIRONMENT_FILE=development-libvirt
364417

365418
# What this does:
366419
# 1. Clones torrust-tracker-demo repository
@@ -478,18 +531,18 @@ docker compose exec -T mysql mysql -u root -p torrust_tracker
478531

479532
## Environment Configuration
480533

481-
### Local Development
534+
### Development Environment (Local Testing)
482535

483-
For local testing and development:
536+
For local testing and development using KVM/libvirt:
484537

485538
```bash
486-
# Use local environment
487-
make infra-apply ENVIRONMENT=local
488-
make app-deploy ENVIRONMENT=local
539+
# Use development environment type with libvirt provider
540+
make infra-apply ENVIRONMENT_TYPE=development ENVIRONMENT_FILE=development-libvirt
541+
make app-deploy ENVIRONMENT_TYPE=development ENVIRONMENT_FILE=development-libvirt
489542

490543
# Features enabled:
491544
# - HTTPS with self-signed certificates (automatic)
492-
# - Local domain names (tracker.test.local, grafana.test.local)
545+
# - Local domain names (test.local)
493546
# - Full monitoring with Grafana and Prometheus
494547
# - MySQL database (same as production)
495548
# - All production features except trusted SSL certificates
@@ -535,10 +588,10 @@ Generate the production configuration template:
535588

536589
```bash
537590
# Generate production configuration template with placeholders
538-
make infra-config-production
591+
make infra-config-production PROVIDER=hetzner
539592
```
540593

541-
This will create `infrastructure/config/environments/production.env` with secure placeholder
594+
This will create `infrastructure/config/environments/production-hetzner.env` with secure placeholder
542595
values that need to be replaced with your actual configuration.
543596

544597
#### Step 3: Replace Placeholder Values
@@ -547,7 +600,7 @@ Edit the generated production environment file with your secure secrets and doma
547600

548601
```bash
549602
# Edit the production configuration
550-
vim infrastructure/config/environments/production.env
603+
vim infrastructure/config/environments/production-hetzner.env
551604
```
552605

553606
**Replace these placeholder values with your actual configuration**:
@@ -594,9 +647,9 @@ make infra-config-production
594647
planned interface for future production deployments:
595648

596649
```bash
597-
# Planned: Use production environment
598-
make infra-apply ENVIRONMENT=production DOMAIN=your-domain.com
599-
make app-deploy ENVIRONMENT=production
650+
# Planned: Use production environment type with Hetzner provider
651+
make infra-apply ENVIRONMENT_TYPE=production ENVIRONMENT_FILE=production-hetzner
652+
make app-deploy ENVIRONMENT_TYPE=production ENVIRONMENT_FILE=production-hetzner
600653

601654
# Planned features:
602655
# - HTTPS support (with automated certificate setup)

infrastructure/config/environments/README.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,27 @@ These files are generated from templates in `../templates/environments/` and con
2121

2222
## File Naming Convention
2323

24-
Environment files follow the pattern: `{environment}-{provider}.env`
24+
Environment files can use any naming convention you prefer. The generation scripts use the
25+
**default pattern**: `{environment-type}-{provider}.env`
2526

26-
Examples:
27+
**Default Examples** (when using generation scripts):
2728

2829
- `development-libvirt.env` - Development environment using libvirt provider
2930
- `staging-hetzner.env` - Staging environment using Hetzner Cloud provider
3031
- `production-hetzner.env` - Production environment using Hetzner Cloud provider
3132

33+
**Custom Examples** (user-defined names):
34+
35+
- `my-dev-setup.env` - Custom development configuration
36+
- `local-testing.env` - Local testing environment
37+
- `client-prod.env` - Client-specific production setup
38+
3239
## Creating Environment Files
3340

34-
1. **Use templates**: Copy from `../templates/environments/{environment}.env.tpl`
35-
2. **Use generation scripts**: Run `infrastructure/scripts/configure-env.sh {environment}`
36-
3. **Follow naming convention**: Always include the provider suffix
41+
1. **Use generation scripts**: Run `infrastructure/scripts/configure-env.sh {environment} {provider}`
42+
(creates files with default naming: `{environment}-{provider}.env`)
43+
2. **Use templates manually**: Copy from `../templates/environments/{environment}.env.tpl`
44+
3. **Custom naming**: Name your files however you prefer, just ensure they have `.env` extension
3745

3846
## Security Best Practices
3947

infrastructure/config/templates/environments/base.env.tpl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ VM_MEMORY=${VM_MEMORY}
1818
VM_VCPUS=${VM_VCPUS}
1919
VM_DISK_SIZE=${VM_DISK_SIZE}
2020
PERSISTENT_DATA_SIZE=${PERSISTENT_DATA_SIZE}
21+
22+
# SSH Public Key for VM access
23+
# Leave empty for auto-detection from ~/.ssh/torrust_rsa.pub (recommended)
24+
# Or set manually: SSH_PUBLIC_KEY="ssh-rsa AAAAB3NzaC1yc2EAAAA... [email protected]"
2125
SSH_PUBLIC_KEY=${SSH_PUBLIC_KEY}
26+
2227
USE_MINIMAL_CONFIG=${USE_MINIMAL_CONFIG}
2328

2429
# === SECRETS (DOCKER SERVICES) ===

infrastructure/config/templates/environments/development.defaults

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ VM_MEMORY="2048"
1212
VM_VCPUS="2"
1313
VM_DISK_SIZE="20"
1414
PERSISTENT_DATA_SIZE="20"
15-
SSH_PUBLIC_KEY="" # Will be auto-detected or user must configure
15+
SSH_PUBLIC_KEY="" # Leave empty - auto-detected from ~/.ssh/torrust_rsa.pub during deployment
1616
USE_MINIMAL_CONFIG="false"
1717

1818
TEMPLATE_PROCESSING_VARS="

infrastructure/scripts/provision-infrastructure.sh

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -181,17 +181,51 @@ provision_infrastructure() {
181181
if [[ "${ACTION}" == "apply" ]]; then
182182
log_success "Infrastructure provisioning completed"
183183

184-
# Try to get VM IP from Terraform output
184+
# Wait for VM readiness if not skipped
185+
if [[ "${SKIP_WAIT}" != "true" ]]; then
186+
# Wait for VM IP assignment
187+
if ! wait_for_vm_ip "${ENVIRONMENT_TYPE}" "${ENVIRONMENT_FILE}" "${PROJECT_ROOT}"; then
188+
log_error "Failed to get VM IP - infrastructure may not be fully ready"
189+
return 1
190+
fi
191+
192+
# Wait for cloud-init completion
193+
if ! wait_for_cloud_init_completion "${ENVIRONMENT_TYPE}" "${ENVIRONMENT_FILE}" "${PROJECT_ROOT}"; then
194+
log_error "Failed to wait for cloud-init completion - VM may not be fully ready"
195+
return 1
196+
fi
197+
198+
log_success "✅ Infrastructure is fully ready"
199+
fi
200+
201+
# Get VM IP for final display - use the reliable traditional output approach
185202
local vm_ip
186-
vm_ip=$(tofu output -raw vm_ip 2>/dev/null || echo "")
187203

188-
if [[ -n "${vm_ip}" ]]; then
204+
# Change to terraform directory and get IP from tofu output
205+
cd "${PROJECT_ROOT}/infrastructure/terraform" || return 1
206+
vm_ip=$(tofu output vm_ip 2>/dev/null | tr -d '"' || echo "")
207+
208+
# If Terraform doesn't have it, get directly from libvirt
209+
if [[ -z "${vm_ip}" || "${vm_ip}" == "No IP assigned yet" ]]; then
210+
vm_ip=$(get_vm_ip_from_libvirt "${ENVIRONMENT_TYPE}" "${ENVIRONMENT_FILE}" "${PROJECT_ROOT}")
211+
fi
212+
213+
if [[ -n "${vm_ip}" && "${vm_ip}" != "No IP assigned yet" ]]; then
189214
log_success "VM IP Address: ${vm_ip}"
190215
log_info ""
191-
log_info "Next steps:"
192-
log_info "1. Wait for cloud-init to complete (may take 2-3 minutes)"
193-
log_info "2. Connect via SSH: ssh torrust@${vm_ip}"
194-
log_info "3. Deploy application: make app-deploy ENVIRONMENT_TYPE=${ENVIRONMENT_TYPE} ENVIRONMENT_FILE=${ENVIRONMENT_FILE}"
216+
if [[ "${SKIP_WAIT}" == "true" ]]; then
217+
log_info "Next steps (SKIP_WAIT enabled):"
218+
log_info "1. Wait for cloud-init to complete (may take 2-3 minutes)"
219+
log_info "2. Connect via SSH: ssh torrust@${vm_ip}"
220+
log_info "3. Deploy application: make app-deploy ENVIRONMENT_TYPE=${ENVIRONMENT_TYPE} ENVIRONMENT_FILE=${ENVIRONMENT_FILE}"
221+
else
222+
log_info "Next steps:"
223+
log_info "1. Deploy application: make app-deploy ENVIRONMENT_TYPE=${ENVIRONMENT_TYPE} ENVIRONMENT_FILE=${ENVIRONMENT_FILE}"
224+
log_info "2. Access VM: ssh torrust@${vm_ip}"
225+
fi
226+
else
227+
log_warning "Could not determine VM IP address for display"
228+
log_info "Check VM status with: make infra-status ENVIRONMENT_TYPE=${ENVIRONMENT_TYPE} ENVIRONMENT_FILE=${ENVIRONMENT_FILE}"
195229
fi
196230
fi
197231
}

0 commit comments

Comments
 (0)