๐Ÿ›ก๏ธSecurity & Hardening

How to Run OpenClaw as Non-Root in Docker

Intermediate30-60 minutesUpdated 2025-01-12

Running Docker containers as root is a major security risk. If an attacker escapes the container, they gain root access to your host system. OpenClaw's default Docker image runs as root for simplicity, but production deployments need proper privilege separation. This guide shows you how to create a non-root user, fix file permissions, handle volume mounts, and troubleshoot common issues when running OpenClaw securely.

Why This Is Hard to Do Yourself

These are the common pitfalls that trip people up.

๐Ÿ”“

Root by default

OpenClaw Docker images run as root (UID 0), giving container processes full privileges.

๐Ÿ“

Permission errors

Non-root users can't write to volumes owned by root, breaking logs, data, and cache directories.

๐Ÿ”ง

Build-time vs runtime

Creating users in Dockerfile is different from switching users in docker-compose. Both are needed.

๐Ÿ›

Skill compatibility

Some ClawHub skills expect root access for package installation or system commands.

Step-by-Step Guide

Step 1

Create a custom Dockerfile with non-root user

Extend the official OpenClaw image.

# Dockerfile.nonroot
FROM openclaw/openclaw:2.4.1

# Create openclaw user and group
RUN groupadd --system --gid 1000 openclaw && \
    useradd --system --uid 1000 --gid openclaw --shell /bin/bash openclaw

# Create directories and set ownership
RUN mkdir -p /app/data /app/logs /app/.cache && \
    chown -R openclaw:openclaw /app

# Switch to non-root user
USER openclaw

CMD ["npm", "start"]
Step 2

Build the custom image

docker build -f Dockerfile.nonroot -t openclaw-nonroot:latest .
Step 3

Update docker-compose.yml with proper user and volumes

Configure user ID and fix volume permissions.

# docker-compose.yml
services:
  openclaw:
    image: openclaw-nonroot:latest
    user: "1000:1000"
    volumes:
      - ./data:/app/data
      - ./logs:/app/logs
    environment:
      - NODE_ENV=production
Step 4

Fix volume mount ownership on host

Ensure host directories are owned by UID 1000.

# On the Docker host:
sudo chown -R 1000:1000 ./data ./logs

# Or let Docker create them with correct ownership:
mkdir -p data logs
sudo chown 1000:1000 data logs

Warning: If you skip this step, the container will fail with "Permission denied" errors when trying to write to mounted volumes.

Step 5

Test non-root operation

Verify OpenClaw starts and runs as non-root.

docker-compose up -d

# Check that process runs as UID 1000:
docker-compose exec openclaw id
# Output: uid=1000(openclaw) gid=1000(openclaw)

# Verify logs are written:
ls -la logs/
# Should show files owned by 1000:1000
Step 6

Handle skills that require elevated privileges

Identify and restrict skills needing root.

# In soul.md or gateway config:
skill_restrictions:
  disabled_skills:
    - system-package-installer  # Requires apt/yum
    - docker-in-docker          # Requires socket access
  allowed_skills:
    - web-search
    - file-analyzer
    - code-review

Non-Root Docker Is Tricky

Permission errors, broken skills, and subtle bugs are common when switching to non-root. We handle the migration, test your skills, and ensure everything works securely.

Get matched with a specialist who can help.

Sign Up for Expert Help โ†’

Frequently Asked Questions