Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/codebase-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ impl ProvisionCommand {
}

// Each method delegates to corresponding Step structs
async fn render_opentofu_templates(&self) -> Result<(), ProvisionTemplateError> {
async fn render_opentofu_templates(&self) -> Result<(), TofuTemplateRendererError> {
RenderOpenTofuTemplatesStep::new(&self.tofu_renderer, &self.config)
.execute().await
}
Expand Down
100 changes: 100 additions & 0 deletions docs/tech-stack/ssh-keys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# SSH Keys

SSH key pairs are used to securely authenticate with provisioned VMs without passwords.

## Overview

The deployer uses SSH keys for:

- Secure access to provisioned instances
- Running Ansible playbooks for configuration
- Executing remote commands via the test command

## Generate SSH Keys

If you don't already have SSH keys:

```bash
# Generate a new SSH key pair (Ed25519 recommended)
ssh-keygen -t ed25519 -C "torrust-deployer" -f ~/.ssh/torrust_deployer

# Set proper permissions
chmod 600 ~/.ssh/torrust_deployer
chmod 644 ~/.ssh/torrust_deployer.pub
```

For RSA keys (if Ed25519 is not supported):

```bash
ssh-keygen -t rsa -b 4096 -C "torrust-deployer" -f ~/.ssh/torrust_deployer
```

## Key Permissions

SSH requires strict file permissions:

```bash
# Private key: owner read/write only
chmod 600 ~/.ssh/your_private_key

# Public key: owner read/write, others read
chmod 644 ~/.ssh/your_private_key.pub

# SSH directory
chmod 700 ~/.ssh
```

## Configuration

Reference your keys in the environment configuration:

```json
{
"ssh_credentials": {
"private_key_path": "/home/youruser/.ssh/torrust_deployer",
"public_key_path": "/home/youruser/.ssh/torrust_deployer.pub",
"username": "torrust",
"port": 22
}
}
```

## Development Keys

For local development and testing, the repository includes test keys in `fixtures/`:

```bash
fixtures/testing_rsa # Private key
fixtures/testing_rsa.pub # Public key
```

> ⚠️ **Warning**: Never use test keys for production deployments.

## Best Practices

1. **Use unique keys per project** - Don't reuse keys across different projects
2. **Never commit private keys** - Keep private keys out of version control
3. **Use passphrases for production** - Add passphrase protection for production keys
4. **Ed25519 over RSA** - Prefer Ed25519 keys for better security and performance

## Troubleshooting

### Permission denied (publickey)

```bash
# Check key permissions
ls -la ~/.ssh/your_private_key

# Should show: -rw------- (600)
chmod 600 ~/.ssh/your_private_key
```

### Agent forwarding

If you need SSH agent forwarding:

```bash
# Add key to SSH agent
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/your_private_key
```
41 changes: 41 additions & 0 deletions docs/user-guide/providers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Provider Guides

This directory contains provider-specific configuration guides.

## Available Providers

| Provider | Status | Description |
| --------------------------- | --------- | ------------------------------------------ |
| [LXD](lxd.md) | ✅ Stable | Local development using LXD containers/VMs |
| [Hetzner Cloud](hetzner.md) | 🆕 New | Cost-effective European cloud provider |

## Choosing a Provider

### LXD (Local Development)

**Best for**: Local development, testing, CI/CD pipelines, zero cloud costs.

**Requirements**: Linux system with LXD installed.

### Hetzner Cloud (Production)

**Best for**: Production deployments, European hosting, cost-sensitive projects.

**Requirements**: Hetzner Cloud account with API token.

## Adding New Providers

To add a new provider:

1. Create OpenTofu templates in `templates/tofu/<provider>/`
2. Add provider configuration types in `src/domain/provider/`
3. Update the template renderer for provider-specific logic
4. Add documentation in `docs/user-guide/providers/<provider>.md`

See the [contributing guide](../../contributing/README.md) for more details.

## Related Documentation

- [Quick Start Guide](../quick-start.md) - Complete deployment workflow
- [Commands Reference](../commands/README.md) - Available commands
- [SSH Keys](../../tech-stack/ssh-keys.md) - SSH key generation and management
151 changes: 151 additions & 0 deletions docs/user-guide/providers/hetzner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# Hetzner Cloud Provider

This guide covers Hetzner-specific configuration for cloud deployments.

## Overview

[Hetzner Cloud](https://www.hetzner.com/cloud) provides affordable virtual servers with excellent performance. Ideal for production deployments.

**Why Hetzner?**

- Cost-effective pricing
- European data centers (Germany, Finland) + US locations
- Simple, predictable billing
- NVMe storage and modern hardware

## Prerequisites

- Hetzner Cloud account ([sign up](https://www.hetzner.com/cloud))
- API token with read/write permissions
- SSH key pair (see [SSH keys guide](../../tech-stack/ssh-keys.md))

## Create API Token

1. Log in to [Hetzner Cloud Console](https://console.hetzner.cloud/)
2. Select your project (or create a new one)
3. Navigate to **Security** → **API Tokens**
4. Click **Generate API Token**
5. Select **Read & Write** permissions
6. **Copy the token immediately** - it won't be shown again!

> ⚠️ **Security**: Never commit API tokens to version control.

## Hetzner-Specific Configuration

```json
{
"provider": {
"provider": "hetzner",
"api_token": "YOUR_HETZNER_API_TOKEN",
"server_type": "cx22",
"location": "nbg1",
"image": "ubuntu-24.04"
}
}
```

| Field | Description | Example |
| ------------- | ---------------------- | -------------- |
| `provider` | Must be `"hetzner"` | `hetzner` |
| `api_token` | Your Hetzner API token | `hcloud_xxx…` |
| `server_type` | Server size/type | `cx22` |
| `location` | Datacenter location | `nbg1` |
| `image` | Operating system image | `ubuntu-24.04` |

### Available Server Types

| Type | vCPUs | RAM | Storage | Use Case |
| ------- | ----- | ----- | ------- | --------------------------- |
| `cx22` | 2 | 4 GB | 40 GB | Development, small trackers |
| `cx32` | 4 | 8 GB | 80 GB | Production, medium traffic |
| `cx42` | 8 | 16 GB | 160 GB | High-traffic trackers |
| `cpx11` | 2 | 2 GB | 40 GB | Testing (AMD) |
| `cpx21` | 3 | 4 GB | 80 GB | Development (AMD) |

### Available Locations

| Location | City | Country |
| -------- | ----------- | ---------- |
| `fsn1` | Falkenstein | Germany |
| `nbg1` | Nuremberg | Germany |
| `hel1` | Helsinki | Finland |
| `ash` | Ashburn | USA (East) |
| `hil` | Hillsboro | USA (West) |

### Available Images

| Image | Description |
| -------------- | ------------------------------ |
| `ubuntu-24.04` | Ubuntu 24.04 LTS (recommended) |
| `ubuntu-22.04` | Ubuntu 22.04 LTS |
| `debian-12` | Debian 12 (Bookworm) |
| `debian-11` | Debian 11 (Bullseye) |

## Cost Estimation

Approximate monthly costs (check [Hetzner pricing](https://www.hetzner.com/cloud) for current rates):

| Server Type | Monthly Cost (EUR) |
| ----------- | ------------------ |
| `cx22` | ~€4.35 |
| `cx32` | ~€8.70 |
| `cx42` | ~€17.40 |

> ⚠️ **Important**: Remember to destroy resources when not in use to avoid charges.

## Troubleshooting

### API Token Invalid

**Error**: `Failed to authenticate with Hetzner API`

- Verify your API token is correct
- Ensure the token has **Read & Write** permissions
- Check the token hasn't been revoked

### Server Creation Failed

**Possible causes**:

- **Quota exceeded**: Check your Hetzner project limits
- **Invalid server type**: Verify the server type exists in your location
- **Image not available**: Some images may not be available in all locations

### SSH Connection Timeout

```bash
# Check if server is running in Hetzner Console
# Verify firewall rules (if using Hetzner Firewall) - port 22 must be open

# Check SSH key permissions
chmod 600 ~/.ssh/your_private_key

# Test manual SSH connection
ssh -i ~/.ssh/your_private_key -v torrust@<server-ip>
```

### Cloud-init Timeout

```bash
# SSH into the server manually
ssh -i ~/.ssh/your_key root@<server-ip>

# Check cloud-init status
cloud-init status --wait

# View cloud-init logs
cat /var/log/cloud-init-output.log
```

## Security Best Practices

1. **Never commit API tokens** - Use environment variables or secure vaults
2. **Restrict SSH access** - Consider using Hetzner Firewall
3. **Use strong SSH keys** - Ed25519 or RSA 4096-bit minimum
4. **Regular updates** - Keep server packages updated

## Related Documentation

- [Quick Start Guide](../quick-start.md) - Complete deployment workflow
- [SSH Keys Guide](../../tech-stack/ssh-keys.md) - SSH key generation
- [LXD Provider](lxd.md) - Local development alternative
Loading
Loading