Skip to content

qodex-ai/openclaw-worker

Repository files navigation

🦞 OpenClaw Worker - AWS Terraform

Production-ready Terraform configuration for deploying OpenClaw on AWS EC2 with HTTPS/SSL, automated backups, and enterprise security. One-command deployment with automatic Let's Encrypt SSL certificates.

Terraform AWS License CI


⚑ TL;DR

# Clone repository
git clone https://github.com/qodex-ai/openclaw-worker.git
cd openclaw-worker

# Setup AWS credentials
cp .aws.env.example .aws.env
nano .aws.env  # Add your AWS access key and secret key
source .aws.env

# Configure Terraform
cp terraform.tfvars.example terraform.tfvars
nano terraform.tfvars  # Add your IP, domain, email, and Anthropic API key

# Deploy
terraform init
terraform apply  # Type 'yes' when prompted

# Wait 8-10 minutes for bootstrap + SSL certificate, then get HTTPS dashboard URL
terraform output -raw dashboard_url_with_token

# Pair your browser (first-time only)
$(terraform output -raw ssh_command)
openclaw devices list      # See pending pairing request
openclaw devices approve <request-id>

Open the HTTPS URL in your browser. Done! βœ…

For detailed instructions, see SETUP_GUIDE.md.

πŸ“ After Deployment

After successful deployment, create a LOCAL_README.md file (git-ignored) to store your actual configuration:

  • EC2 instance details, SSH keys, IP addresses
  • Dashboard URLs with tokens
  • S3 bucket names
  • Quick reference commands with your real values

See the template at the end of this README.


🎯 What This Does

This Terraform configuration automatically deploys a production-ready OpenClaw instance on AWS with enterprise-grade security and automation:

Infrastructure Components

  • EC2 Instance (t3.medium) β€” 4GB RAM, Ubuntu 24.04 LTS, auto-updates enabled
  • Security Group β€” Locked down to your IP (SSH), HTTPS/HTTP open for SSL validation
  • S3 Bucket β€” Encrypted backups with automatic cleanup (180 days retention)
  • IAM Role & Instance Profile β€” Secure EC2-to-S3 access without hardcoded credentials
  • Elastic IP β€” Static public IP that persists across restarts
  • Route53 DNS β€” A record pointing your domain to the Elastic IP
  • SSH Key Pair β€” Auto-generated 4096-bit RSA key
  • SSM Integration β€” AWS Systems Manager for secure access

Software Stack

  • Node.js 22 β€” Latest LTS version
  • OpenClaw β€” Installed via npm for easy updates
  • Docker β€” Required for OpenClaw's container management
  • Nginx β€” HTTPS reverse proxy with SSL termination
  • Let's Encrypt SSL β€” Free, auto-renewing SSL certificates via Certbot
  • Systemd Service β€” Auto-start on boot with automatic restarts
  • Management CLI β€” Custom oc command for operations

Automation

  • User Data Script β€” Automated installation and configuration
  • SSL Certificate β€” Automatic acquisition and renewal via Let's Encrypt
  • DNS Management β€” Route53 A record automatically created
  • Automated Daily Backups β€” Cron job runs daily at 2 AM UTC
  • Manual Backups β€” On-demand backup to S3 via oc backup command
  • S3 Lifecycle Policy β€” Automatic deletion after 180 days
  • GitHub Actions β€” CI/CD with Terraform validation and security scanning

Note: Daily backups run automatically. Additional backups can be configured through OpenClaw's interface if needed.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      ARCHITECTURE                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                  β”‚
β”‚   YOUR DOMAIN ──────►  Route53 DNS                              β”‚
β”‚   (HTTPS/SSL)              β”‚                                    β”‚
β”‚                            β–Ό                                    β”‚
β”‚                       EC2 (t3.medium)                            β”‚
β”‚                            β”‚                                    β”‚
β”‚   Let's Encrypt ────► Nginx (HTTPS) ──► OpenClaw (:18789)      β”‚
β”‚   (SSL Cert)               β”‚                 β”‚                  β”‚
β”‚                            β”‚                 β”œβ”€β”€ Node.js 22     β”‚
β”‚   YOUR IP ─────────► SSH (Port 22)          β”œβ”€β”€ Docker         β”‚
β”‚                                              └── Slack API      β”‚
β”‚                                                   β”‚             β”‚
β”‚                                                   β–Ό             β”‚
β”‚                                              S3 Bucket          β”‚
β”‚                                         (encrypted backups)     β”‚
β”‚                                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ’° Cost

Resource Monthly Cost
EC2 t3.medium ~$30
EBS 20GB ~$2
S3 backups ~$1
Total ~$33/month

πŸ“‹ Prerequisites

  • AWS Account with IAM user access keys
  • Domain Name with Route53 hosting (e.g., openclaw.yourdomain.com)
  • Email Address for SSL certificate notifications
  • Terraform (v1.0+)
  • AWS CLI installed
  • Anthropic API Key (sk-ant-...)

Note: This setup uses environment variables (.aws.env file) for AWS credentials instead of aws configure. This keeps credentials project-local and git-ignored. HTTPS with valid SSL certificate is required for browser security. Slack integration is configured through OpenClaw's interface after deployment.


πŸš€ Quick Start

1. Clone this repo

git clone https://github.com/qodex-ai/openclaw-worker.git
cd openclaw-worker

2. Setup AWS Credentials

cp .aws.env.example .aws.env
nano .aws.env

Add your AWS credentials:

export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_DEFAULT_REGION=us-east-1

Load credentials:

source .aws.env
aws sts get-caller-identity  # Verify they work

3. Get Your Public IP

curl -4 ifconfig.me  # Returns your IPv4 address

4. Configure Terraform Variables

cp terraform.tfvars.example terraform.tfvars
nano terraform.tfvars

Edit with your values:

aws_region    = "us-east-1"
instance_type = "t3.medium"

# Your IP (add /32 at the end)
my_ip_cidrs = ["49.47.128.13/32"]

# Your domain name (must be in Route53)
domain_name = "openclaw.yourdomain.com"

# Your email for SSL certificate notifications
email = "you@example.com"

# Your Anthropic API key
anthropic_api_key = "sk-ant-api03-xxxxx"

# Optional: Route53 hosted zone ID (auto-detected if not provided)
route53_zone_id = "Z1234567890ABC"

5. Deploy Infrastructure

terraform init
terraform apply

Type yes when prompted. Wait ~3 minutes for AWS resources.

6. Wait for Bootstrap & Get Dashboard URL

The EC2 instance will auto-install OpenClaw, nginx, and obtain SSL certificate (8-10 minutes). Then:

terraform output -raw dashboard_url_with_token

Open the HTTPS URL in your browser β€” done! πŸŽ‰

Note: The first time you access the dashboard, you'll need to approve device pairing via SSH (see Device Pairing section). Daily S3 backups run automatically at 2 AM UTC. Configure Slack integration through OpenClaw's dashboard after deployment.


πŸ“ Repository Contents

File/Directory Description
main.tf Core AWS infrastructure (EC2, S3, IAM, Security Groups, Elastic IP)
variables.tf Input variable definitions and validation
outputs.tf Output values (IPs, URLs, SSH commands, tokens)
user_data.sh EC2 bootstrap script - installs Node.js, Docker, and OpenClaw via npm
terraform.tfvars.example Template for Terraform variables (copy to terraform.tfvars)
.aws.env.example Template for AWS credentials (copy to .aws.env)
SETUP_GUIDE.md Complete step-by-step deployment guide (~45 minutes)
CRON_BACKUPS.md Automated backup configuration and management guide
.github/workflows/ci.yml Automated Terraform validation and security scanning
.gitignore Git ignore rules for Terraform and sensitive files
LICENSE MIT License (2025 Qodex AI)

πŸ”’ Security Features

  • HTTPS/SSL β€” Valid Let's Encrypt certificates with auto-renewal
  • IP Restriction β€” Only your IP can access SSH (22)
  • Device Pairing β€” Secure multi-device authentication system
  • IMDSv2 β€” Instance metadata service v2 required
  • Encrypted EBS β€” Root volume encrypted at rest
  • Encrypted S3 β€” AES-256 server-side encryption
  • No Public S3 β€” Bucket blocks all public access
  • IAM Role β€” EC2 uses role-based access (no hardcoded credentials)
  • Token Auth β€” 48-character random gateway token

πŸ› οΈ Management Commands

SSH into your instance:

$(terraform output -raw ssh_command)

Then use the oc command:

Command Description
oc status Check if OpenClaw is running
oc logs View logs (follow mode)
oc restart Restart OpenClaw
oc stop Stop OpenClaw
oc start Start OpenClaw
oc backup Manual backup to S3 (on-demand)
oc restore <file> Restore from S3 backup
oc update Update OpenClaw to latest
oc url Show dashboard URL with token
oc token Show gateway token

Automated Backups: Daily backups run automatically at 2 AM UTC via cron. View logs: tail -f ~/.openclaw/backup.log


πŸ”— Device Pairing

OpenClaw uses device pairing for secure access. When you first access the dashboard, you'll need to pair your browser.

Pairing a New Device/Browser

  1. Access the dashboard - Open the dashboard URL in your browser
  2. SSH to server:
    $(terraform output -raw ssh_command)
  3. List pending pairing requests:
    openclaw devices list
  4. Approve the request:
    openclaw devices approve <request-id>
  5. Refresh the dashboard - Your browser is now paired!

Device Management Commands

openclaw devices list      # List pending and paired devices
openclaw devices approve   # Approve a pending device
openclaw devices reject    # Reject a pending device
openclaw devices revoke    # Revoke a paired device

Alternative: Token-Only Mode

If you prefer to skip device pairing and use only the gateway token:

openclaw config set gateway.auth.mode token
sudo systemctl restart openclaw

To revert to pairing mode:

openclaw config unset gateway.auth.mode
sudo systemctl restart openclaw

πŸ”„ Common Operations

Update your IP address

If your IP changes:

# Edit terraform.tfvars with new IP
nano terraform.tfvars

# Apply changes (instant, no restart)
terraform apply

Update OpenClaw

# SSH into server
$(terraform output -raw ssh_command)

# Update
oc update

View backups

# List all backups in S3
aws s3 ls s3://$(terraform output -raw s3_bucket)/backups/

# View automated backup logs
ssh -i openclaw-key.pem ubuntu@<your-ip>
tail -f ~/.openclaw/backup.log

Check backup schedule

# SSH into server
$(terraform output -raw ssh_command)

# View cron schedule
crontab -l

# Check recent automated backups
tail -20 ~/.openclaw/backup.log

Restore from backup

# SSH into server
$(terraform output -raw ssh_command)

# List backups
oc restore

# Restore specific backup
oc restore openclaw-backup-20240115.tar.gz

πŸ“Š Outputs

After deployment, these outputs are available:

terraform output                              # All outputs
terraform output instance_public_ip           # Server IP
terraform output ssh_command                  # SSH command
terraform output -raw dashboard_url_with_token # Dashboard URL
terraform output -raw gateway_token           # Just the token
terraform output s3_bucket                    # Backup bucket name

πŸ—‘οΈ Cleanup

To destroy all resources:

# Download backups first (optional)
aws s3 sync s3://$(terraform output -raw s3_bucket) ./my-backups/

# Destroy everything
terraform destroy

βš™οΈ Configuration Options

Variable Default Description
aws_region us-east-1 AWS region
instance_type t3.medium EC2 instance type
my_ip_cidrs β€” Your IP(s) for SSH access (required)
domain_name β€” Domain name for HTTPS (required)
email β€” Email for SSL notifications (required)
anthropic_api_key β€” Anthropic API key (required)
route53_zone_id (auto) Route53 zone ID (optional)

πŸ”§ Customization

Use a different instance type

instance_type = "t3.small"   # $15/month, 2GB RAM
instance_type = "t3.medium"  # $30/month, 4GB RAM (default)
instance_type = "t3.large"   # $60/month, 8GB RAM

Allow multiple IPs

my_ip_cidrs = [
  "203.0.113.50/32",   # Home
  "198.51.100.25/32",  # Office
]

Use a different region

aws_region = "eu-west-1"  # Ireland
aws_region = "ap-south-1" # Mumbai

πŸ› Troubleshooting

Terraform: "Failed to load plugin schemas" (macOS)

If you get a timeout error with AWS provider on macOS:

# Remove Gatekeeper quarantine from Terraform providers
xattr -r -d com.apple.quarantine .terraform/providers/

# Then retry
terraform plan

This happens because macOS Gatekeeper blocks unsigned provider binaries.

AWS Credentials Not Working

# Test credentials
source .aws.env
aws sts get-caller-identity

# If it fails, verify the .env file has 'export' statements:
cat .aws.env  # Should show: export AWS_ACCESS_KEY_ID=...

Can't Connect to Dashboard

  1. Check your IP hasn't changed: curl -4 ifconfig.me
  2. Update terraform.tfvars with new IP
  3. Run terraform apply

OpenClaw Not Starting

# SSH into server
$(terraform output -raw ssh_command)

# Check service status
oc status

# View logs
oc logs

# Check bootstrap log
sudo cat /var/log/openclaw-bootstrap.log

Manual Backup Not Working

Verify IAM role:

# SSH to server
$(terraform output -raw ssh_command)

# Test S3 access
aws s3 ls s3://$(terraform output -raw s3_bucket)/

# If it fails, check IAM role attachment
aws sts get-caller-identity

The EC2 instance has an IAM role automatically configured by Terraform. If backups fail:

  1. Verify the role is attached to the instance
  2. Check CloudWatch logs for permissions errors
  3. Ensure the S3 bucket exists: terraform output s3_bucket

Test backup:

ssh -i openclaw-key.pem ubuntu@<your-ip>
oc backup

Expected output: Backup uploaded: s3://your-bucket/backups/openclaw-backup-YYYYMMDD-HHMMSS.tar.gz

Bootstrap Fails: "Package 'awscli' has no installation candidate"

Fixed in latest version. If you encounter this with an older version:

Problem: Ubuntu 24.04 doesn't have awscli in default apt repositories.

Solution: The user_data.sh script now installs AWS CLI v2 directly from Amazon. Update to the latest version:

git pull origin main
terraform init -upgrade
terraform apply

If you need to fix a running instance manually:

ssh -i openclaw-key.pem ubuntu@<your-ip>
cd /tmp
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
sudo apt-get install -y unzip
unzip -q awscliv2.zip
sudo ./aws/install
rm -rf aws awscliv2.zip
aws --version

Terraform Hangs on Apple Silicon (M3/M2/M1)

Problem: Terraform stuck for hours during apply on Apple Silicon Macs.

Root Cause: Intel x86_64 Terraform running under Rosetta causes AWS provider crashes.

Solution: Use ARM64 native Terraform:

# Uninstall Intel version
brew uninstall terraform

# Download ARM64 version
cd ~/Downloads
wget https://releases.hashicorp.com/terraform/1.14.4/terraform_1.14.4_darwin_arm64.zip
unzip terraform_1.14.4_darwin_arm64.zip

# Install to ~/bin
mkdir -p ~/bin
mv terraform ~/bin/
chmod +x ~/bin/terraform

# Add to PATH (add this to ~/.zshrc for persistence)
export PATH="$HOME/bin:$PATH"

# Verify
terraform --version
file ~/bin/terraform  # Should show: Mach-O 64-bit executable arm64

# Reinitialize to get ARM64 providers
cd ~/Projects/flinket/jarvis/openclaw-worker
rm -rf .terraform
terraform init
terraform apply

πŸ“š Resources


πŸ“ LOCAL_README.md Template

After deployment, create a LOCAL_README.md file (automatically git-ignored) to store your actual configuration values:

# Create your local documentation
nano LOCAL_README.md

What to include:

  • EC2 instance ID, public IP, SSH key path
  • Dashboard URL with token
  • S3 bucket name
  • Actual Terraform commands with your values
  • AWS credentials reference
  • Quick reference commands for daily use

Example structure:

# My OpenClaw Deployment

## Instance Info
- Instance ID: i-xxxxx
- Public IP: x.x.x.x
- Domain: openclaw.yourdomain.com
- Dashboard (HTTPS): https://openclaw.yourdomain.com/?token=xxxxx
- Dashboard (Direct): http://x.x.x.x:18789/?token=xxxxx

## SSL Certificate
- Provider: Let's Encrypt
- Expires: [Date]
- Auto-renewal: Enabled

## Quick Commands
ssh -i openclaw-key.pem ubuntu@x.x.x.x
terraform output -raw dashboard_url_with_token
aws s3 ls s3://my-bucket/backups/
openclaw devices list

## Credentials
- AWS Account: 123456789012
- S3 Bucket: my-openclaw-backups-xxx
- Anthropic Key: sk-ant-xxx...

This keeps your actual values separate from version control while maintaining easy access to deployment details.


🀝 Contributing

Contributions welcome! Please:

  1. Fork the repo
  2. Create a feature branch
  3. Make your changes
  4. Submit a pull request

πŸ“„ License

MIT License β€” feel free to use, modify, and distribute.


⭐ Star History

If this helped you, please star the repo!


Made with ❀️ for the OpenClaw community

About

🦞 One-command deployment of OpenClaw on AWS with automatic HTTPS, SSL certificates, Route53 DNS, encrypted S3 backups, and security hardening. Ready for production use.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors