auberge 0.1.0

CLI tool for managing self-hosted infrastructure with Ansible
# Auberge

CLI tool for managing self-hosted infrastructure with Ansible.

## Prerequisites

- Ansible installed locally
- SSH access to target servers
- Rust toolchain (for building the CLI)

> [!IMPORTANT]
> **Before running bootstrap**, you MUST configure your VPS provider's firewall to allow your custom SSH port.
>
> Most VPS providers (IONOS, DigitalOcean, Hetzner, AWS, etc.) have their own firewall layer **separate from UFW**.
>
> **Steps:**
>
> 1. Decrypt your `SSH_PORT` value: `mise env | grep SSH_PORT`
> 2. Log into your VPS provider's control panel (e.g., IONOS Dashboard)
> 3. Navigate to firewall/security settings for your VPS
> 4. Add a rule to **allow TCP traffic on your SSH_PORT**
> 5. Save the firewall rule
> 6. Then run the auberge deployment
>
> **Why this is needed:**
>
> - Auberge changes SSH from port 22 → your custom SSH_PORT during bootstrap
> - UFW (on the VPS) will allow the port, but provider firewalls block it by default
> - Without this step, you'll be locked out after SSH port change
>
> **Common provider firewall locations:**
>
> - **IONOS**: Cloud Panel → Server → Firewall
> - **DigitalOcean**: Networking → Firewalls
> - **Hetzner**: Cloud Console → Firewalls
> - **AWS**: Security Groups
> - **Vultr**: Settings → Firewall

> [!IMPORTANT]
> **Before running the apps playbook**, you MUST generate a Cloudflare API token for DNS management.
>
> The certificate automation (Lego) runs from your VPS and uses Cloudflare's API for DNS-01 challenges.
>
> **Required steps:**
>
> 1. Log into Cloudflare: https://dash.cloudflare.com
> 2. Navigate to: **My Profile → API Tokens → Create Token**
> 3. Use the **"Edit zone DNS"** template
> 4. Configure permissions:
>    - Zone → DNS → Edit
>    - Zone → Zone → Read
> 5. Set zone resources to your domain (e.g., sripwoud.xyz)
> 6. No IP filtering needed (unlike Namecheap)
> 7. Copy the token (shown only once)
> 8. Add to `mise.toml` as `CLOUDFLARE_DNS_API_TOKEN`
>
> **Why this is needed:**
>
> - Lego (certificate tool) runs from your VPS, not your local machine
> - It makes Cloudflare API calls for DNS-01 challenge validation
> - Token-based auth (simpler than Namecheap's IP whitelisting)

## Initial Setup

### 1. Configuration

Copy the example configuration files and customize them:

```bash
# Copy CLI config
cp config.example.toml config.toml

# Copy Ansible vault
cp ansible/group_vars/all/hosts.vault.example ansible/group_vars/all/hosts.vault
```

Edit `config.toml` with your details:

- `domain`: Your primary domain (e.g., example.com)
- `default_ttl`: DNS record TTL in seconds (default: 300)
- `cloudflare.zone_id`: (Optional) Your Cloudflare zone ID for performance

Edit `ansible/group_vars/all/hosts.vault` with:

- Server IPs
- User configuration (username, email, domain)
- Sudo password

### 2. Encrypt Sensitive Data

```bash
# Create Ansible vault password file
echo "your-vault-password" > ~/.ansible-vault-pass

# Encrypt the vault file
ansible-vault encrypt ansible/group_vars/all/hosts.vault

# Optionally encrypt secrets.vault if you have one
ansible-vault encrypt ansible/group_vars/all/secrets.vault
```

### 3. Environment Variables

Set your Cloudflare API token using mise:

```bash
# Set encrypted secret (will prompt for value)
mise set --age-encrypt --prompt CLOUDFLARE_DNS_API_TOKEN
```

### 4. Build the CLI

```bash
cargo build --release
# Binary will be at target/release/auberge
```

## Project Structure

```
auberge/
├── src/              # Rust CLI source code
├── ansible/          # Ansible infrastructure
│   ├── playbooks/    # Ansible playbooks
│   ├── roles/        # Ansible roles
│   ├── inventory/    # Dynamic inventory
│   ├── inventory.yml # Static inventory
│   └── ansible.cfg   # Ansible configuration
├── Cargo.toml        # Rust package manifest
└── README.md
```

The CLI wraps Ansible operations, providing an interactive interface for managing infrastructure.

## Usage

### Bootstrap New VPS

Use `mise run ansible-bootstrap` for initial VPS setup (first run only):

```bash
mise run ansible-bootstrap
# 1) Select host to bootstrap
# 2) Connects as root with password authentication
# 3) Creates user account and secures SSH
```

**Bootstrap process:**

- Creates non-root user with sudo privileges
- Disables root login and password authentication
- Sets up SSH key-based authentication

### Interactive Playbook Execution

Use `mise run ansible-run` to interactively select both the host and playbook to execute:

```bash
mise run ansible-run
# 1) Select host: lechuck-cloud:194.164.53.11
# 2) Select playbook: bootstrap, hardening, infrastructure, apps, auberge, vibecoder
# 3) Runs ansible-playbook with your selections
```

## Available Playbooks

Playbooks are organized in layers for modular deployment:

| Layer | Playbook                                                   | Description                                                                          |
| ----- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| 0     | [bootstrap.yml]ansible/playbooks/bootstrap.yml           | Initial VPS setup - creates users and secures SSH. Run once per new server.          |
| 1     | [hardening.yml]ansible/playbooks/hardening.yml           | Security hardening - firewall (UFW), intrusion prevention (fail2ban), kernel.        |
| 2     | [infrastructure.yml]ansible/playbooks/infrastructure.yml | Core infrastructure - package management (apt), shell (bash), reverse proxy (Caddy). |
| 3     | [apps.yml]ansible/playbooks/apps.yml                     | Self-hosted applications layer.                                                      |
| -     | [auberge.yml]ansible/playbooks/auberge.yml               | **Master playbook** - runs all layers (bootstrap → hardening → infra → apps).        |
| -     | [vibecoder.yml]ansible/playbooks/vibecoder.yml           | Development environment with Vibecoder and Claude Code integration.                  |

### Layer Tags

Each playbook supports hierarchical tagging for granular control:

```bash
# Run entire layer
ansible-playbook auberge.yml --tags hardening

# Run specific function across layers
ansible-playbook auberge.yml --tags security

# Run specific component
ansible-playbook auberge.yml --tags caddy

# Skip bootstrap (already done)
ansible-playbook auberge.yml --skip-tags bootstrap
```