Skip to content
Open
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
31 changes: 24 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![Ansible](https://img.shields.io/badge/Ansible-2.14+-blue.svg)](https://www.ansible.com/)
[![Multi-OS](https://img.shields.io/badge/OS-Debian%20%7C%20Ubuntu-orange.svg)](https://www.debian.org/)

Automated, hardened installation of [OpenClaw](https://github.com/openclaw/openclaw) with Docker and Tailscale VPN support for Debian/Ubuntu Linux.
Automated, hardened installation of [OpenClaw](https://github.com/openclaw/openclaw) with Docker and VPN support (Tailscale or Netbird) for Debian/Ubuntu Linux.

## ⚠️ macOS Support: Deprecated & Disabled

Expand All @@ -24,7 +24,7 @@ The underlying project currently requires system-level permissions and configura
- 🔒 **Firewall-first**: UFW firewall + Docker isolation
- 🛡️ **Fail2ban**: SSH brute-force protection out of the box
- 🔄 **Auto-updates**: Automatic security patches via unattended-upgrades
- 🔐 **Tailscale VPN**: Secure remote access without exposing services
- 🔐 **VPN Support**: Tailscale or Netbird for secure remote access
- 🐳 **Docker**: Docker CE with security hardening
- 🚀 **One-command install**: Complete setup in minutes
- 🔧 **Auto-configuration**: DBus, systemd, environment setup
Expand Down Expand Up @@ -55,8 +55,8 @@ cd openclaw-ansible

## What Gets Installed

- Tailscale (mesh VPN)
- UFW firewall (SSH + Tailscale ports only)
- VPN: Tailscale or Netbird (optional, choose one)
- UFW firewall (SSH + VPN ports only)
- Docker CE + Compose V2 (for sandboxes)
- Node.js 22.x + pnpm
- OpenClaw on host (not containerized)
Expand Down Expand Up @@ -241,7 +241,7 @@ Enable with: `-e openclaw_install_mode=development`

## Security

- **Public ports**: SSH (22), Tailscale (41641/udp) only
- **Public ports**: SSH (22) + VPN port only (Tailscale 41641/udp or Netbird 51820/udp)
- **Fail2ban**: SSH brute-force protection (5 attempts → 1 hour ban)
- **Automatic updates**: Security patches via unattended-upgrades
- **Docker isolation**: Containers can't expose ports externally (DOCKER-USER chain)
Expand Down Expand Up @@ -303,7 +303,8 @@ openclaw_ssh_keys:
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB... user@host"
openclaw_repo_url: "https://github.com/YOUR_USERNAME/openclaw.git"
openclaw_repo_branch: "feature-branch"
tailscale_authkey: "tskey-auth-xxxxxxxxxxxxx"
vpn_provider: "netbird"
netbird_setup_key: "your-setup-key"
EOF

# Use it
Expand All @@ -324,7 +325,10 @@ Edit `roles/openclaw/defaults/main.yml` before running the playbook.
| `openclaw_ssh_keys` | `[]` | List of SSH public keys |
| `openclaw_repo_url` | `https://github.com/openclaw/openclaw.git` | Git repository (dev mode) |
| `openclaw_repo_branch` | `main` | Git branch (dev mode) |
| `vpn_provider` | `""` | VPN provider: `"tailscale"`, `"netbird"`, or `""` (none) |
| `tailscale_authkey` | `""` | Tailscale auth key for auto-connect |
| `netbird_setup_key` | `""` | Netbird setup key for auto-connect |
| `netbird_management_url` | `""` | Netbird self-hosted management URL (optional) |
| `nodejs_version` | `22.x` | Node.js version to install |

See [`roles/openclaw/defaults/main.yml`](roles/openclaw/defaults/main.yml) for the complete list.
Expand All @@ -347,11 +351,24 @@ ansible-playbook playbook.yml --ask-become-pass \
-e openclaw_repo_branch=feature-branch
```

#### Tailscale Auto-Connect
#### VPN Auto-Connect

```bash
# Tailscale
ansible-playbook playbook.yml --ask-become-pass \
-e vpn_provider=tailscale \
-e tailscale_authkey=tskey-auth-xxxxxxxxxxxxx

# Netbird
ansible-playbook playbook.yml --ask-become-pass \
-e vpn_provider=netbird \
-e netbird_setup_key=your-setup-key

# Netbird (self-hosted)
ansible-playbook playbook.yml --ask-become-pass \
-e vpn_provider=netbird \
-e netbird_setup_key=your-setup-key \
-e netbird_management_url=https://netbird.example.com
```

## License
Expand Down
13 changes: 7 additions & 6 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,11 @@ systemd → docker compose → openclaw container

## Installation Flow

1. **Tailscale Setup** (`tailscale.yml`)
- Add Tailscale repository
- Install Tailscale package
- Display connection instructions
1. **VPN Setup** (`tailscale-linux.yml` or `netbird-linux.yml`)
- Add VPN provider repository
- Install VPN package
- Auto-connect if auth/setup key provided
- Display connection instructions otherwise

2. **User Creation** (`user.yml`)
- Create `openclaw` system user
Expand All @@ -80,7 +81,7 @@ systemd → docker compose → openclaw container
- Install UFW
- Configure DOCKER-USER chain
- Configure Docker daemon (`/etc/docker/daemon.json`)
- Allow SSH (22/tcp) and Tailscale (41641/udp)
- Allow SSH (22/tcp) and VPN port (Tailscale 41641/udp or Netbird 51820/udp)

5. **Node.js Installation** (`nodejs.yml`)
- Add NodeSource repository
Expand Down Expand Up @@ -119,7 +120,7 @@ Principle of least privilege. If container is compromised, attacker has limited

```
main.yml
├── tailscale.yml (VPN setup)
├── tailscale-linux.yml / netbird-linux.yml (VPN setup, conditional on vpn_provider)
├── user.yml (create openclaw user)
├── docker.yml (install Docker, create /etc/docker)
├── firewall.yml (configure UFW + Docker daemon)
Expand Down
87 changes: 74 additions & 13 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ openclaw_ssh_keys:
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB... admin@laptop"
openclaw_repo_url: "https://github.com/YOUR_USERNAME/openclaw.git"
openclaw_repo_branch: "main"
tailscale_authkey: "tskey-auth-xxxxxxxxxxxxx"
vpn_provider: "netbird"
netbird_setup_key: "your-setup-key"
nodejs_version: "22.x"
```

Expand Down Expand Up @@ -167,18 +168,46 @@ These variables only apply when `openclaw_install_mode: development`
-e nodejs_version=20.x
```

### Tailscale Configuration
### VPN Configuration

#### `vpn_provider`
- **Type**: String (`"tailscale"`, `"netbird"`, or `""`)
- **Default**: `""` (disabled)
- **Description**: VPN provider to install and configure
- **Example**:
```bash
-e vpn_provider=netbird
```

#### `tailscale_authkey`
- **Type**: String
- **Default**: `""` (empty - manual setup required)
- **Description**: Tailscale authentication key for automatic connection
- **Description**: Tailscale authentication key for automatic connection (when `vpn_provider: "tailscale"`)
- **Example**:
```bash
-e tailscale_authkey=tskey-auth-k1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6
```
- **Get Key**: https://login.tailscale.com/admin/settings/keys

#### `netbird_setup_key`
- **Type**: String
- **Default**: `""` (empty - manual setup required)
- **Description**: Netbird setup key for automatic connection (when `vpn_provider: "netbird"`)
- **Example**:
```bash
-e netbird_setup_key=your-setup-key
```
- **Get Key**: https://app.netbird.io/setup-keys

#### `netbird_management_url`
- **Type**: String
- **Default**: `""` (empty - uses Netbird Cloud)
- **Description**: Self-hosted Netbird management server URL (when `vpn_provider: "netbird"`)
- **Example**:
```bash
-e netbird_management_url=https://netbird.example.com
```

### OS-Specific Settings

These are automatically set based on the detected OS:
Expand Down Expand Up @@ -225,11 +254,23 @@ openclaw_ssh_keys:
ansible-playbook playbook.yml --ask-become-pass -e @vars-dev.yml
```

### Production Setup with Tailscale
### Production Setup with VPN

```yaml
# vars-prod.yml
# vars-prod.yml (Netbird example)
openclaw_install_mode: release
vpn_provider: "netbird"
netbird_setup_key: "your-setup-key"
netbird_management_url: "https://netbird.example.com" # optional, for self-hosted
openclaw_ssh_keys:
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGxxxxxxxx admin@mgmt-server"
nodejs_version: "22.x"
```

```yaml
# vars-prod.yml (Tailscale example)
openclaw_install_mode: release
vpn_provider: "tailscale"
tailscale_authkey: "tskey-auth-k1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6"
openclaw_ssh_keys:
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGxxxxxxxx admin@mgmt-server"
Expand Down Expand Up @@ -286,7 +327,8 @@ openclaw_ssh_keys:
```yaml
# environments/staging.yml
openclaw_install_mode: release
tailscale_authkey: "{{ lookup('env', 'TAILSCALE_AUTHKEY_STAGING') }}"
vpn_provider: "netbird"
netbird_setup_key: "{{ lookup('env', 'NETBIRD_SETUP_KEY_STAGING') }}"
openclaw_ssh_keys:
- "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"
```
Expand All @@ -296,7 +338,9 @@ openclaw_ssh_keys:
```yaml
# environments/prod.yml
openclaw_install_mode: release
tailscale_authkey: "{{ lookup('env', 'TAILSCALE_AUTHKEY_PROD') }}"
vpn_provider: "netbird"
netbird_setup_key: "{{ lookup('env', 'NETBIRD_SETUP_KEY_PROD') }}"
netbird_management_url: "{{ lookup('env', 'NETBIRD_MGMT_URL') }}"
openclaw_ssh_keys:
- "ssh-ed25519 AAAAC3... ops@prod-mgmt"
- "ssh-ed25519 AAAAC3... admin@backup-server"
Expand All @@ -323,16 +367,23 @@ nodejs_version: "22.x"
-e "openclaw_ssh_keys=['$(cat ~/.ssh/new_key.pub)']"
```

### Tailscale Auth Keys
### VPN Auth/Setup Keys

1. **Use ephemeral keys** for temporary access
2. **Set expiration times** for auth keys
2. **Set expiration times** for auth/setup keys
3. **Use reusable keys** only for automation
4. **Store in secrets manager**: Don't commit to git
```bash
# Use environment variable
# Netbird example
export NETBIRD_SETUP_KEY=$(vault read -field=key secret/netbird)
ansible-playbook playbook.yml --ask-become-pass \
-e vpn_provider=netbird \
-e netbird_setup_key="$NETBIRD_SETUP_KEY"

# Tailscale example
export TAILSCALE_AUTHKEY=$(vault read -field=key secret/tailscale)
ansible-playbook playbook.yml --ask-become-pass \
-e vpn_provider=tailscale \
-e tailscale_authkey="$TAILSCALE_AUTHKEY"
```

Expand All @@ -342,19 +393,23 @@ Never commit sensitive data to git:

```yaml
# ❌ BAD - Don't do this
netbird_setup_key: "actual-key-here"
tailscale_authkey: "tskey-auth-actual-key-here"

# ✅ GOOD - Use environment variables or vault
netbird_setup_key: "{{ lookup('env', 'NETBIRD_SETUP_KEY') }}"
tailscale_authkey: "{{ lookup('env', 'TAILSCALE_AUTHKEY') }}"

# ✅ GOOD - Use Ansible Vault
netbird_setup_key: "{{ vault_netbird_setup_key }}"
tailscale_authkey: "{{ vault_tailscale_authkey }}"
```

Create encrypted vault:
```bash
ansible-vault create secrets.yml
# Add: vault_tailscale_authkey: tskey-auth-xxxxx
# Add: vault_netbird_setup_key: your-setup-key
# Or: vault_tailscale_authkey: tskey-auth-xxxxx

ansible-playbook playbook.yml --ask-become-pass \
-e @secrets.yml --ask-vault-pass
Expand Down Expand Up @@ -385,13 +440,19 @@ sudo ls -la /home/openclaw/.ssh/
sudo cat /home/openclaw/.ssh/authorized_keys
```

### Tailscale Not Connecting
### VPN Not Connecting

Verify auth key is valid:
Tailscale - verify auth key is valid:
```bash
sudo tailscale up --authkey=YOUR_KEY --verbose
```

Netbird - verify setup key and connectivity:
```bash
sudo netbird up --setup-key YOUR_KEY
sudo netbird status
```

### Installation Mode Issues

Check which mode is active:
Expand Down
Loading