Skip to main content
better-openclaw supports bare-metal deployment with a hybrid architecture: services with native recipes run directly on the host, while others run in Docker.

Deployment types

better-openclaw offers two deployment models:
TypeDescriptionUse Case
DockerAll services in containersDefault, easiest setup
Bare-metalHybrid: native + DockerBetter performance, resource efficiency

Docker deployment (default)

All services run in containers:
npx create-better-openclaw --deployment-type docker
Start the stack:
cd my-openclaw-stack
docker compose up -d

Bare-metal deployment

Services with native recipes run on the host, others in Docker:
npx create-better-openclaw --deployment-type bare-metal --platform linux/amd64
Generated structure:
my-openclaw-stack/
├── install.sh              # Top-level installer
├── docker-compose.yml       # Docker-only services + gateway
├── native/
│   └── install-linux.sh    # Native service installer
├── .env
└── config/
Run the installer:
cd my-openclaw-stack
bash install.sh
The installer:
  1. Installs native services on the host (e.g., Redis via apt/dnf)
  2. Starts native services (systemd)
  3. Runs docker compose up for remaining services

Supported platforms

npx create-better-openclaw \
  --deployment-type bare-metal \
  --platform linux/amd64
Generates: install.sh + native/install-linux.shPackage managers:
  • apt (Ubuntu/Debian)
  • dnf/yum (RHEL/CentOS/Fedora)

Services with native support

Currently, these services have native recipes:
ServiceLinuxmacOSWindowsNative Benefits
Redis✅ apt/dnf + systemd✅ brew + launchdLower latency, better memory usage
PostgreSQL🚧 Coming soon🚧🚧Direct disk I/O, native auth
Caddy🚧🚧🚧System-wide HTTPS, native systemd
Prometheus🚧🚧🚧Direct host metrics access
Services without native recipes remain Docker-only (e.g., Ollama, n8n, Grafana).

Redis native deployment

When you select bare-metal deployment, Redis is installed natively:

Linux installation

native/install-linux.sh
#!/usr/bin/env bash
set -euo pipefail

# ─── 🔴 Redis ─────────────────────────────────────────

# Install Redis
if command -v apt-get &> /dev/null; then
  sudo apt-get update -qq
  sudo apt-get install -y redis-server
elif command -v dnf &> /dev/null; then
  sudo dnf install -y redis
fi

# Write Redis config
sudo tee /etc/redis/redis.conf > /dev/null << 'EOF'
bind 0.0.0.0
port 6379
protected-mode no
maxmemory 2gb
maxmemory-policy allkeys-lru
save 900 1
save 300 10
save 60 10000
EOF

# Start Redis
sudo systemctl enable redis-server
sudo systemctl start redis-server

echo 'Native services started.'

Connecting from Docker

The OpenClaw gateway runs in Docker and connects to native Redis on the host via host.docker.internal:
docker-compose.yml
services:
  openclaw-gateway:
    extra_hosts:
      - "host.docker.internal:host-gateway"
    environment:
      REDIS_HOST: host.docker.internal
      REDIS_PORT: 6379
This is automatically configured when you use --deployment-type bare-metal.

Environment variables

.env
# Redis hostname for OpenClaw (native: host.docker.internal)
# Service: Redis | Required: Yes | Secret: No
REDIS_HOST=host.docker.internal

# Redis port for OpenClaw
# Service: Redis | Required: Yes | Secret: No
REDIS_PORT=6379

Installer scripts

Linux installer

Generated install.sh for Linux:
install.sh
#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"

# Colors
RED='\033[0;31m'; GREEN='\033[0;32m'; CYAN='\033[0;36m'; NC='\033[0m'
info()  { echo -e "${CYAN}ℹ  $*${NC}"; }
ok()    { echo -e "${GREEN}✅ $*${NC}"; }
err()   { echo -e "${RED}❌ $*${NC}" >&2; }

# Native services (install/start on host first)
if [ -f "native/install-linux.sh" ]; then
  info "Installing and starting native services..."
  bash native/install-linux.sh
  ok "Native services ready."
fi

# Install Docker if missing
if ! command -v docker &> /dev/null; then
  info "Installing Docker..."
  curl -fsSL https://get.docker.com | sudo sh
  sudo usermod -aG docker "$USER"
  ok "Docker installed."
fi

# Check Docker Compose
if ! docker compose version &> /dev/null; then
  err "Docker Compose (v2) not found."
  exit 1
fi

# Start stack
if [ -f ".env.example" ] && [ ! -f ".env" ]; then
  cp .env.example .env
fi

info "Starting stack..."
docker compose up -d --remove-orphans

ok "Stack started. Gateway: http://localhost:${OPENCLAW_GATEWAY_PORT:-18789}"

macOS installer

Similar to Linux, but uses Homebrew:
brew install docker
open -a Docker  # Start Docker Desktop

Windows installer

PowerShell script (install.ps1):
# Check Docker Desktop
$docker = Get-Command docker -ErrorAction SilentlyContinue
if (-not $docker) {
  Write-Host "Docker not found. Install from: https://docs.docker.com/desktop/install/windows-install/"
  exit 1
}

# Run native services
if (Test-Path "native/install-windows.ps1") {
  & .\native\install-windows.ps1
}

# Start Docker stack
docker compose up -d --remove-orphans

Advantages of bare-metal

Performance

  • Lower latency: No Docker network overhead for native services
  • Direct I/O: Native services access disk/network directly
  • Memory efficiency: No container memory overhead (~50-100 MB per container)

Resource management

  • System integration: Native services use systemd/launchd for lifecycle management
  • Better observability: System tools (systemctl, journalctl) work natively
  • Easier debugging: Logs in standard locations (/var/log, journalctl)

Flexibility

  • Mix and match: Run performance-critical services natively, others in Docker
  • Gradual migration: Start with Docker, move to native as needed
  • Existing infrastructure: Integrate with existing native services

Disadvantages of bare-metal

Complexity

  • Platform-specific: Different install steps for each OS
  • Manual cleanup: Uninstalling requires OS-specific commands
  • Dependency management: Native package managers handle dependencies

Portability

  • Less portable: Can’t just copy the directory to another machine
  • Version pinning: Harder to guarantee exact versions across systems
  • State management: Native services have state in system directories

Security

  • System-wide access: Native services run with more privileges
  • No isolation: Services can access entire filesystem
  • Shared resources: Can conflict with other system services

Managing native services

Linux (systemd)

# Check status
sudo systemctl status redis-server

# View logs
sudo journalctl -u redis-server -f

# Restart
sudo systemctl restart redis-server

# Stop
sudo systemctl stop redis-server

# Disable auto-start
sudo systemctl disable redis-server

macOS (launchd)

# Check status
brew services list

# Restart
brew services restart redis

# Stop
brew services stop redis

# View logs
tail -f /usr/local/var/log/redis.log

Windows (Services)

# Check status
Get-Service redis

# Restart
Restart-Service redis

# Stop
Stop-Service redis

# View logs
Get-EventLog -LogName Application -Source Redis

Uninstalling

Linux

# Stop Docker services
docker compose down -v

# Stop and remove native services
sudo systemctl stop redis-server
sudo systemctl disable redis-server
sudo apt-get remove --purge redis-server  # or sudo dnf remove redis

# Remove data
sudo rm -rf /var/lib/redis
sudo rm -f /etc/redis/redis.conf

macOS

# Stop Docker services
docker compose down -v

# Stop and remove native services
brew services stop redis
brew uninstall redis

# Remove data
rm -rf /usr/local/var/db/redis

Windows

# Stop Docker services
docker compose down -v

# Uninstall via package manager
choco uninstall redis  # or scoop uninstall redis

# Remove data
Remove-Item -Recurse -Force C:\ProgramData\Redis

Hybrid configurations

Example: Native Redis + Docker PostgreSQL

npx create-better-openclaw \
  --services postgresql,redis,n8n \
  --deployment-type bare-metal \
  --platform linux/amd64
Result:
  • Redis: Native (systemd)
  • PostgreSQL: Docker (no native recipe yet)
  • n8n: Docker (Node.js app, Docker-only)
  • OpenClaw gateway: Docker (connects to both)

Example: All-Docker

For consistency across environments:
npx create-better-openclaw \
  --services postgresql,redis,n8n \
  --deployment-type docker
All services in Docker, even if native recipes exist.

Troubleshooting

Native service won’t start

Check service status:
# Linux
sudo systemctl status redis-server
sudo journalctl -u redis-server -n 50

# macOS
brew services list
tail -n 50 /usr/local/var/log/redis.log
Common issues:
  • Port conflict: Another service using the port
  • Permission denied: Config file not readable
  • Missing dependencies: Package installation incomplete

Docker can’t connect to native service

Verify host.docker.internal:
docker compose exec openclaw-gateway ping host.docker.internal
If ping fails:
docker-compose.yml
services:
  openclaw-gateway:
    extra_hosts:
      - "host.docker.internal:172.17.0.1"  # Docker bridge IP
Test connection:
docker compose exec openclaw-gateway redis-cli -h host.docker.internal ping
# Expected: PONG

Firewall blocking connections

Linux (UFW):
sudo ufw allow 6379/tcp comment 'Redis for OpenClaw'
sudo ufw reload
Linux (firewalld):
sudo firewall-cmd --permanent --add-port=6379/tcp
sudo firewall-cmd --reload
macOS: System Preferences → Security & Privacy → Firewall → Firewall Options → Allow Redis

Port conflicts

Error: Address already in use
Find conflicting process:
# Linux/macOS
sudo lsof -i :6379

# Windows
netstat -ano | findstr :6379
Solutions:
  1. Stop the conflicting service
  2. Change the port in native service config:
    # /etc/redis/redis.conf
    port 6380
    
  3. Update .env to match:
    REDIS_PORT=6380
    

Performance benchmarks

Redis: Native vs Docker

Native (systemd):
redis-benchmark -q -n 100000
PING_INLINE: 98234.56 requests per second
SET: 96712.23 requests per second
GET: 99800.40 requests per second
Docker:
docker compose exec redis redis-benchmark -q -n 100000
PING_INLINE: 92421.47 requests per second
SET: 90009.00 requests per second
GET: 94607.38 requests per second
Native Redis is ~5-8% faster for this workload.

Future native recipes

Planned for upcoming releases:
  • PostgreSQL (systemd + native authentication)
  • Caddy (system-wide reverse proxy)
  • Prometheus (direct host metrics)
  • Node.js apps (pm2 process manager)
Contributions welcome! See CONTRIBUTING.md.

Build docs developers (and LLMs) love