Cover

Install OpenClaw on Synology DiskStation DS1621+ – Step-by-Step Guide

What is OpenClaw – and what will you have at the end?

OpenClaw is an AI agent you run locally on your Synology DiskStation. Instead of running in the cloud, it runs at your home – you keep control of your data, pay only for the API requests you actually use, and access your personal assistant via Telegram or browser.

What OpenClaw actually is, and how gateway, runtime and skills work together, is explained in OpenClaw (ex Moltbot): How a WhatsApp Message Becomes an Acting AI Agent — this guide takes that as read.

At the end of this guide, you will have:

  • A running OpenClaw container on your DiskStation
  • A Telegram bot you can simply write to on your smartphone
  • An optional web interface accessible via SSH tunnel in your browser
  • Optional: Network isolation that denies the container access to your home network
  • Optional: An embedded browser with which OpenClaw can also operate JavaScript-heavy websites

The basic installation – container running, Telegram responding – takes about 30 minutes. The optional steps come after, once the foundation is in place.

Prerequisites

Before you start – make sure you have the following on hand:

  • Synology DS1621+ with current DSM 7.2 or newer
  • Container Manager installed (from the Package Center)
  • SSH access to the DiskStation (will be explained in this guide)
  • An API key from Anthropic (Claude) or OpenAI
  • Telegram on your smartphone

No API key yet? For Claude, go to console.anthropic.com, sign in, add a payment method, and create a key. It begins with sk-ant-...

Architecture at a glance

This is what the finished folder structure on your DiskStation will look like. It is created step by step – you don’t need to prepare anything manually.

/volume1/docker/openclaw/
├── compose.yaml ← Container configuration
├── openclaw-firewall.sh ← Network isolation (optional)
├── config/ ← API keys, settings
└── workspace/ ← Agent work files

OpenClaw consists of two services:

  • openclaw-gateway – the permanently running service. It maintains the connection to Telegram, provides the web UI, and communicates with the AI API.
  • openclaw-cli – a one-time container for administrative tasks (onboarding, configuration, pairing).

Container or VM? The first big decision

Monday morning scene with Bernd, Ulf, and Tanja debating Container vs VM.

Tanja is the IT expert. She has been managing Docker containers in production for years. She values reliability and understands the trade-offs.

Bernd is the self-proclaimed “expert” who always has an opinion but sometimes confuses enthusiasm with expertise.

Ulf is learning and asks the pragmatic questions.

Ulf: “Container or VM – what’s the difference anyway?”

Bernd: “VM, obviously! Total isolation – iron-clad security!”

Tanja: “For a home setup, containers are more practical. Faster to set up, less resource-hungry. Security depends on how you configure it.”

Ulf: “But is a container safe enough for an AI agent?”

Tanja: “Yes, if you’re careful. We’ll use network isolation – iptables rules that restrict what the container can reach. Combined with regular updates and careful image selection, that’s a solid foundation.”

Bernd: “But a VM is safer!”

Tanja: “True. But it also uses more memory and disk space, and it’s slower to manage. For a home setup running Claude – a trustworthy model – containers strike the right balance.”

Ulf: “Got it. So containers it is.”

CriterionContainer (Docker)VM (Synology VMM)
PerformanceBetter – no separate OS kernel neededWorse – needs around 2 GB RAM minimum
InstallationSimple – the docker-compose.yml is ready to useLaborious – install an OS, set up Node ≥22, configure autostart
IsolationProcess isolation at kernel levelFull kernel isolation, no direct host access
In shortFaster, lighter, closer to the official OpenClaw installationStronger isolation, but heavier and more resource-hungry

This guide takes the container route. The iptables rules in the optional security chapter reduce risk. They do not replace VM isolation, patch management, or careful review of container images.

Part 1: Preparation on the DiskStation

Step 1.1: Install Container Manager

Tanja: “First things first – we need Container Manager. It’s in the Package Center.”

Ulf: “Is that the new Docker replacement?”

Tanja: “Exactly. Synology’s official container management tool. It handles Docker Compose, images, and networks.”

  1. Open the Package Center on your DiskStation
  2. Search for Container Manager
  3. Click Install
  4. Wait for the installation to complete (usually 1–2 minutes)
  5. Open Container Manager from your main menu

Step 1.2: Enable SSH

Ulf: “SSH is command-line access to the station?”

Tanja: “Right. We need it to create folders, upload files, and manage the container from the terminal.”

  1. Go to Control PanelTerminal & SNMP
  2. Check the box Enable SSH service
  3. Note the port (usually 22, but can be different)
  4. Click Apply

Step 1.3: Connect via SSH

Open a terminal on your PC or Mac and connect to your DiskStation.

For Mac / Linux:

ssh your-username@DISKSTATION_IP

For Windows (PowerShell):

ssh your-username@DISKSTATION_IP

(Replace DISKSTATION_IP with your DiskStation’s IP address and 22 with the SSH port if different.)

Enter your root password when prompted.

Once you’re logged in, you’re ready to create the folder structure and configuration files. All subsequent commands are typed into this terminal window.

Step 1.4: Create folders

Ulf: “Now I create the folder where OpenClaw will live?”

Tanja: “Yes. We’ll put everything in /volume1/docker/openclaw. This keeps it organized and makes backups easy.”

mkdir -p /volume1/docker/openclaw/config
mkdir -p /volume1/docker/openclaw/workspace
chown -R root:root /volume1/docker/openclaw
chmod -R 755 /volume1/docker/openclaw

Expected result

ls -la /volume1/docker/openclaw/
total 8
drwxr-xr-x 4 root root 4096 Mar 29 12:00 .
drwxr-xr-x 3 root root 4096 Mar 29 12:00 ..
drwxr-xr-x 2 root root 4096 Mar 29 12:00 config
drwxr-xr-x 2 root root 4096 Mar 29 12:00 workspace

Step 1.5: Create compose.yaml

Bernd: “YAML – yet another markup language?”

Tanja: “Close – but it’s a configuration format. Docker uses it to describe services, volumes, networks. Think of it as a blueprint for your container.”

Create a file named compose.yaml in /volume1/docker/openclaw/ with the following content:

cat > /volume1/docker/openclaw/compose.yaml << 'DATEIENDE'
services:
  openclaw-gateway:
    image: ghcr.io/openclaw/openclaw:latest
    container_name: openclaw-gateway
    restart: unless-stopped
    user: "1000:1000"
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    read_only: true
    tmpfs:
      - /tmp
      - /run
    pids_limit: 256
    dns:
      - 1.1.1.1
      - 8.8.8.8
    networks:
      - openclaw-isolated
    ports:
      - "18789:18789"
    volumes:
      - /volume1/docker/openclaw/config:/home/node/.openclaw
      - /volume1/docker/openclaw/workspace:/home/node/.openclaw/workspace
    environment:
      - HOME=/home/node
      - TERM=xterm-256color
      - NODE_ENV=production
    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:18789/ >/dev/null 2>&1 || exit 1"]
      interval: 60s
      timeout: 10s
      retries: 3
      start_period: 30s
    init: true
    command:
      [
        "node",
        "dist/index.js",
        "gateway",
        "--bind",
        "lan",
        "--port",
        "18789",
      ]

  openclaw-cli:
    image: ghcr.io/openclaw/openclaw:latest
    container_name: openclaw-cli
    user: "1000:1000"
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    network_mode: "service:openclaw-gateway"
    volumes:
      - /volume1/docker/openclaw/config:/home/node/.openclaw
      - /volume1/docker/openclaw/workspace:/home/node/.openclaw/workspace
    environment:
      - HOME=/home/node
      - TERM=xterm-256color
      - NODE_ENV=production
    stdin_open: true
    tty: true
    init: true
    entrypoint: ["node", "dist/index.js"]
    profiles:
      - cli

networks:
  openclaw-isolated:
    driver: bridge
    ipam:
      config:
        - subnet: 172.30.0.0/24
          gateway: 172.30.0.1
DATEIENDE

Configuration explained

SettingWhat it means
user: "1000:1000"The container does not run as root – no administrator access.
cap_drop: ALLAll Linux special privileges (capabilities) are removed.
read_only: trueThe root filesystem is write-protected – malware cannot establish itself permanently.
tmpfs: /tmp, /runTemporary storage in RAM for programs that need to write somewhere.
pids_limit: 256A maximum of 256 processes – protection against fork bombs.
dns: 1.1.1.1 / 8.8.8.8DNS queries go straight out to the internet. Without this setting they would go to the router – which the optional firewall blocks, leaving the container with no internet.
"18789:18789"Web UI reachable on port 18789.
No docker.sock volumeThe container cannot control Docker or the host.
subnet: 172.30.0.0/24A fixed subnet that the optional firewall chapter can block specifically.

Verify the YAML syntax before starting the container:

cd /volume1/docker/openclaw
docker compose config

If there are no errors, you’ll see the validated configuration printed to the terminal.

Step 1.6: Run the OpenClaw Onboarding

Before you start the gateway service, you must complete the onboarding. This configures your API key, Telegram bot, and basic settings.

cd /volume1/docker/openclaw
docker compose run --rm openclaw-cli onboard

This launches an interactive setup wizard. Follow along:

Step 1 – Confirm security notice

The onboarding shows a disclaimer about running AI agents locally. Read it and type Yes to proceed.

Step 2 – Choose onboarding mode

Select QuickStart (the default option). This sets up essentials without extra configuration.

Step 3 – Choose AI provider and model

Ulf: “Which provider – Claude, OpenAI, or something else?”

Tanja: “It depends on cost and capability. Claude’s Haiku is very fast and cheap. Sonnet is more capable. OpenAI’s models work too, but Claude is generally more reliable for this use case.”

Select Anthropic (Claude).

Recommendation: take Anthropic, because Claude is often qualitatively stronger in longer conversations and with complex instructions. Choose Haiku if you want to save money, Sonnet if you want quality. You can switch at any time. If the lowest price matters most to you: OpenAI with GPT-4.1 mini or nano.

If you do not have an API key yet: for Claude, go to console.anthropic.com. If you do not want to set that up right now, choose Back, then Skip for now. You can add the provider later:

cd /volume1/docker/openclaw
docker compose run --rm openclaw-cli configure

Step 4 – Authentication method

Choose Anthropic API key.

Step 5 – Enter your API key

Paste your API key (starts with sk-ant-). Keep it secret – never share it or commit it to version control.

Step 6 – Confirm default model

ModelInput (per million tokens)Output (per million tokens)
OpenAI GPT-4.1 nano~$0.10~$0.40
OpenAI GPT-4.1 mini~$0.40~$1.60
Anthropic Haiku 3.5~$0.80~$4.00
OpenAI GPT-4o~$2.50~$10
Anthropic Sonnet 4~$3.00~$15

Select Sonnet as your default (good balance of cost and capability).

Step 7 – Choose communication channel

Select Telegram. This lets you chat with OpenClaw from your phone.

Step 8 – Set up Telegram Bot

OpenClaw will guide you through creating a Telegram bot. You’ll need the BotFather app in Telegram:

  1. Open Telegram and search for @BotFather
  2. Start a chat and send /newbot
  3. Give your bot a name (e.g., “MyOpenClaw”)
  4. Give it a username (e.g., “my_openclaw_bot”)
  5. BotFather will give you a token – copy it
  6. Paste the token into the OpenClaw onboarding

Step 9 – Configure skills

Bernd: “What are skills?”

Tanja: “Extensions that give OpenClaw special abilities – web search, file access, etc. For now, skip them. We’ll add what we need later.”

Select No when asked about installing skills.

Steps 10–15

You’ll be asked about additional features (webhooks, integrations, etc.). For a first setup, answer No to all of these. You can add them later.

Step 16 – Hooks

Select Skip for now.

Onboarding complete!

The onboarding finishes and shows a Gateway Token. Save this token – you’ll need it if you add browser-based access.

If you plan to use the web UI, configure allowed origins:

cd /volume1/docker/openclaw
docker compose run --rm openclaw-cli config set gateway.controlUi.allowedOrigins '["http://localhost:18789"]'

Step 1.7: Start the container

Option A: Via Container Manager (GUI)

  1. Open Container Manager on your DiskStation
  2. Go to Projects
  3. Click Create
  4. Choose Create from compose file
  5. Navigate to /volume1/docker/openclaw/compose.yaml and upload it
  6. Name the project openclaw
  7. Click Next, then Create
  8. Wait for the project to start

Important: Do not start the container before completing the onboarding. The gateway needs the config files from onboarding to run.

Option B: Via SSH

cd /volume1/docker/openclaw
docker compose up -d

Expected result

[+] Running 2/2
 ⠿ Network openclaw_openclaw-net  Created
 ⠿ Container openclaw-gateway     Started

Check the logs to see if the container is running:

docker compose logs -f

You should see output like:

openclaw-gateway  | [INFO] Gateway started on http://0.0.0.0:8080
openclaw-gateway  | [INFO] Connected to Telegram bot
openclaw-gateway  | [INFO] Ready for requests

If you see errors, check the troubleshooting section.

ModelStrengthRelative cost
HaikuFast, cheap – for simple tasks~1/4 of Sonnet
SonnetBest price-performance ratioMedium
OpusMost capable – for complex tasks~5× Sonnet

Step 1.8: Test with Telegram

Once the gateway is running, you can test it via Telegram.

Tanja: “Your bot won’t respond until you pair your Telegram account with it. That happens with a special command.”

  1. In Telegram, search for your bot (the one you created with BotFather, e.g., @my_openclaw_bot)
  2. Send the command /pair
  3. The bot will respond with a pairing request. Get the pairing code from the OpenClaw logs:

You’ll see something like:

Send this code back to the bot in Telegram. Once accepted, you can start chatting:

@my_openclaw_bot: "What is 2+2?"

The bot should respond with an answer. Congratulations – OpenClaw is alive!

The very first time, your bot answers with a pairing code. Pairing means you confirm once that this device – your smartphone – is allowed to chat with the bot. Without that confirmation the bot does not answer. Write anything to the bot in Telegram. It replies with a code. Then, in the SSH session:

cd /volume1/docker/openclaw
docker compose run --rm openclaw-cli pairing approve telegram <CODE>

Insert the code from the Telegram message. After that the chat works normally. Expected result: the bot answers your next message.

Part 2: Optional Enhancements

Optional A: Web interface via SSH tunnel

Alongside Telegram there is a browser-based interface. It is deliberately not reachable directly on the network – access runs through an SSH tunnel. That is not a detour but the point: the web UI should not sit open on your home network.

Open the SSH tunnel (on the Mac, in a new terminal window):

ssh -L 18789:127.0.0.1:18789 your-username@DISKSTATION_IP

The command forwards your local port 18789 encrypted through SSH to port 18789 on the DiskStation. The tunnel works for as long as this terminal window stays open.

Then open this in the browser (inserting your own token from step 1.6):

http://localhost:18789#token=2bbea678f.........................67003d38

Use localhost, not 127.0.0.1. That is not a typo – it makes a technical difference to how the token is recognised. The token has to come directly after the #, with no space.

If you get “channel: open failed: administratively prohibited”:

SSH port forwarding is disabled on the DiskStation. Enable it once (in another terminal session, as root):

sudo -i
echo "AllowTcpForwarding yes" >> /etc/ssh/sshd_config
sed -i '85s/AllowTcpForwarding no/AllowTcpForwarding yes/' /etc/ssh/sshd_config
systemctl restart sshd

If systemctl is not available:

synosystemctl restart sshd

Then restart the SSH tunnel and open the browser again. If it shows “pairing required”, the browser has to be paired once – exactly like Telegram in step 1.8. Show open pairing codes:

sudo docker exec -it openclaw-gateway node /app/openclaw.mjs devices list

Note the code from the “Pending → Request → Code” column and confirm it:

sudo docker exec -it openclaw-gateway node /app/openclaw.mjs devices approve YOUR_CODE

Optional B: Harden network isolation

Bernd: “The container is running – isn’t that secure enough?”

Tanja: “Not quite. By default, a container can access your home network. An iptables firewall blocks that. It’s like adding a second lock on the door.”

Ulf: “How does that work?”

Tanja: “We write a shell script that sets firewall rules. It runs at boot and again whenever we need it. The rules say: ‘This container can only reach the outside world – not your home network, not your other devices.'”

Step B.1: Create the firewall script

The script works in three phases:

  • Phase 1: deletes its own rules, in case the script has run before.
  • Phase 2: rebuilds the IPv4 rules.
  • Phase 3: adds the IPv6 rules. The script is idempotent – you can run it as often as you like, it always rebuilds cleanly.
cat > /volume1/docker/openclaw/openclaw-firewall.sh << 'DATEIENDE'
#!/bin/bash
# =============================================================================
# openclaw-firewall.sh
# Network isolation script for OpenClaw on a Synology DS1621+
# =============================================================================
# Compatible with Synology DSM iptables 1.8.x (no comment module available).
#
# Blocks outbound traffic from the OpenClaw container to all private
# and reserved IPv4 networks. Internet access stays allowed.
# DNS goes through public servers (1.1.1.1 / 8.8.8.8, set in
# docker-compose.yml), because the router DNS is blocked by these rules.
#
# Idempotent: first deletes all of its own rules (by exact specification),
# then rebuilds the rules in a defined order.
# Can be run as often as you like.
#
# IPv6: blocks ULA (fc00::/7) and link-local (fe80::/10) globally for all
# Docker forward traffic, because the container has no fixed IPv6 prefix
# assigned. If you later want to run other containers with IPv6,
# adjust these rules.
#
# Usage:
#   Set it up as a boot task in the Synology Task Scheduler:
#   bash /volume1/docker/openclaw/openclaw-firewall.sh
# =============================================================================

sleep 30

DOCKER_SUBNET="172.30.0.0/24"   # Must match compose.yaml

# ─────────────────────────────────────────────────────────────────────────────
# Phase 1: remove all of our own rules (exact specification)
# ─────────────────────────────────────────────────────────────────────────────

# IPv4
iptables -D DOCKER-USER -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 2>/dev/null
iptables -D DOCKER-USER -s "$DOCKER_SUBNET" -d 192.168.0.0/16 -j DROP 2>/dev/null
iptables -D DOCKER-USER -s "$DOCKER_SUBNET" -d 10.0.0.0/8 -j DROP 2>/dev/null
iptables -D DOCKER-USER -s "$DOCKER_SUBNET" -d 172.16.0.0/12 -j DROP 2>/dev/null
iptables -D DOCKER-USER -s "$DOCKER_SUBNET" -d 169.254.0.0/16 -j DROP 2>/dev/null
iptables -D DOCKER-USER -s "$DOCKER_SUBNET" -d 100.64.0.0/10 -j DROP 2>/dev/null

# IPv6
ip6tables -D DOCKER-USER -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 2>/dev/null
ip6tables -D DOCKER-USER -d fc00::/7 -j DROP 2>/dev/null
ip6tables -D DOCKER-USER -d fe80::/10 -j DROP 2>/dev/null

# ─────────────────────────────────────────────────────────────────────────────
# Phase 2: build the IPv4 rules in DOCKER-USER
# ─────────────────────────────────────────────────────────────────────────────

# Position 1: let reply packets of allowed connections through
iptables -I DOCKER-USER 1 \
  -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Positions 2-6: block private and reserved networks
iptables -I DOCKER-USER 2 \
  -s "$DOCKER_SUBNET" -d 192.168.0.0/16 -j DROP

iptables -I DOCKER-USER 3 \
  -s "$DOCKER_SUBNET" -d 10.0.0.0/8 -j DROP

iptables -I DOCKER-USER 4 \
  -s "$DOCKER_SUBNET" -d 172.16.0.0/12 -j DROP

iptables -I DOCKER-USER 5 \
  -s "$DOCKER_SUBNET" -d 169.254.0.0/16 -j DROP

iptables -I DOCKER-USER 6 \
  -s "$DOCKER_SUBNET" -d 100.64.0.0/10 -j DROP

# RETURN: only add it if none exists
if ! iptables -L DOCKER-USER -n 2>/dev/null | grep -q "RETURN"; then
  iptables -A DOCKER-USER -j RETURN
fi

# ─────────────────────────────────────────────────────────────────────────────
# Phase 3: IPv6 rules (if DOCKER-USER exists in ip6tables)
# ─────────────────────────────────────────────────────────────────────────────

if ip6tables -L DOCKER-USER -n >/dev/null 2>&1; then
  ip6tables -I DOCKER-USER 1 \
    -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

  ip6tables -I DOCKER-USER 2 \
    -d fc00::/7 -j DROP

  ip6tables -I DOCKER-USER 3 \
    -d fe80::/10 -j DROP

  if ! ip6tables -L DOCKER-USER -n 2>/dev/null | grep -q "RETURN"; then
    ip6tables -A DOCKER-USER -j RETURN
  fi
fi

# ─────────────────────────────────────────────────────────────────────────────
# Ausgabe
# ─────────────────────────────────────────────────────────────────────────────
logger "openclaw-firewall: DOCKER-USER Regeln aktiv fuer $DOCKER_SUBNET"

echo ""
echo "========================================"
echo " OpenClaw Netzwerk-Isolation aktiviert"
echo "========================================"
echo ""
echo "IPv4 DOCKER-USER:"
iptables -L DOCKER-USER -n -v --line-numbers
echo ""

if ip6tables -L DOCKER-USER -n >/dev/null 2>&1; then
  echo "IPv6 DOCKER-USER:"
  ip6tables -L DOCKER-USER -n -v --line-numbers
  echo ""
fi

echo "Erwartete Reihenfolge:"
echo "  1  ACCEPT     ctstate RELATED,ESTABLISHED"
echo "  2  DROP       172.30.0.0/24 -> 192.168.0.0/16"
echo "  3  DROP       172.30.0.0/24 -> 10.0.0.0/8"
echo "  4  DROP       172.30.0.0/24 -> 172.16.0.0/12"
echo "  5  DROP       172.30.0.0/24 -> 169.254.0.0/16"
echo "  6  DROP       172.30.0.0/24 -> 100.64.0.0/10"
echo "  7  RETURN"
DATEIENDE

Then make the script executable:

# Switch to root
sudo -i

chmod +x /volume1/docker/openclaw/openclaw-firewall.sh

What these rules do

RangeProtocolWhat is it?
192.168.0.0/16IPv4Home networks (routers such as the Fritzbox, etc.)
10.0.0.0/8IPv4Corporate networks, VPNs
172.16.0.0/12IPv4Further private networks
169.254.0.0/16IPv4Link-local (mDNS devices, APIPA)
100.64.0.0/10IPv4CGNAT (some providers/VPNs)
fc00::/7IPv6 (global)ULA (the IPv6 equivalent of private networks)
fe80::/10IPv6 (global)IPv6 link-local

A note on IPv6: the IPv6 rules apply to all Docker forward traffic on the DiskStation, not only to OpenClaw. If you later want to run other containers with IPv6, these rules have to be adjusted.

Step B.2: Set up firewall as a boot task

The script must run every time the DiskStation boots (to restore rules after reboot) and whenever the container restarts. Set it up as a scheduled task:

  1. Open the DiskStation control panel
  2. Go to SystemTask Scheduler
  3. Click CreateTriggered TaskUser-defined script
  4. Configure:
  • Task name: OpenClaw Firewall Init
  • Event: Boot-up
  • User: root
  • Enabled: Check the box
  • Go to the Task Settings tab
  • In the Run command field, paste:
/bin/bash /volume1/docker/openclaw/openclaw-firewall.sh
  • Add a small delay (wait for Docker to be fully ready):
sleep 30 && /bin/bash /volume1/docker/openclaw/openclaw-firewall.sh
  • Click OK to save

Step B.3: Activate firewall immediately

Expected result – check the rules:

iptables -L DOCKER-USER -n -v --line-numbers

Expected output:

num   target     prot  source           destination
1     ACCEPT     all   0.0.0.0/0        0.0.0.0/0        ctstate RELATED,ESTABLISHED
2     DROP       all   172.30.0.0/24    192.168.0.0/16
3     DROP       all   172.30.0.0/24    10.0.0.0/8
4     DROP       all   172.30.0.0/24    172.16.0.0/12
5     DROP       all   172.30.0.0/24    169.254.0.0/16
6     DROP       all   172.30.0.0/24    100.64.0.0/10
7     RETURN     all   0.0.0.0/0        0.0.0.0/0

If the order is not right, run the script again – it cleans up first and then rebuilds.

Step B.4: Test isolation

Verify that the container can’t reach your home network but can reach the outside:

docker exec openclaw-gateway ping -c 1 192.168.1.1
# Expected: UNREACHABLE (blocked by firewall)

docker exec openclaw-gateway ping -c 1 8.8.8.8
# Expected: REACHABLE (Google DNS – public internet)

What you’ll see:

PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
--- 192.168.1.1 statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=119 time=15.3 ms
--- 8.8.8.8 statistics ---
1 packets transmitted, 1 received,   0% packet loss, time 0ms

Perfect – your home network is blocked, but the internet is accessible. OpenClaw can call the Claude API but can’t snoop on your local devices.

Optional C: Retrofit a Playwright browser

Up to now OpenClaw communicates over APIs and text. With an embedded Playwright browser it can also load real web pages, scroll, fill in forms and make use of JavaScript rendering.

Ulf: “OpenClaw should be able to browse by itself? Like a sweeper who suddenly goes on the attack?”
Tanja: “Exactly! The LLM plans, Playwright executes. That lets OpenClaw read content from dynamic pages that plain HTTP requests cannot reach.”
Bernd: “I just used the system Chromium. It didn’t run. Tried three times. Never worked.”
Tanja: “That is exactly why you ship the browser binaries with the container. Then it works reproducibly – every time.”

A Playwright browser inside the Docker container brings its own browser binaries and dependencies with it. That avoids conflicts with system libraries and version incompatibilities.

Step C.1: Create a Dockerfile

Create /volume1/docker/openclaw/Dockerfile:

FROM ghcr.io/openclaw/openclaw:latest

USER root

# System libraries for Chromium / Playwright
RUN apt-get update && apt-get install -y \
    libnspr4 \
    libnss3 \
    libatk1.0-0 \
    libatk-bridge2.0-0 \
    libcups2 \
    libdrm2 \
    libxkbcommon0 \
    libxcomposite1 \
    libxdamage1 \
    libxfixes3 \
    libxrandr2 \
    libgbm1 \
    libasound2 \
    ca-certificates \
    wget \
    && rm -rf /var/lib/apt/lists/*

USER node

Then, in compose.yaml, replace the image line for both services (openclaw-gateway and openclaw-cli):

# Before:
image: ghcr.io/openclaw/openclaw:latest

# After:
build:
  context: /volume1/docker/openclaw
  dockerfile: Dockerfile

Step C.2: Install Chromium

cd /volume1/docker/openclaw

sudo docker compose -p openclaw run --rm --entrypoint sh \
  -e PLAYWRIGHT_BROWSERS_PATH=/home/node/.openclaw/workspace/.browser \
  openclaw-cli -c 'mkdir -p /home/node/.openclaw/workspace/.browser && \
  node /app/node_modules/playwright-core/cli.js install chromium'

Expected result – check the installation:

sudo docker exec -it openclaw-gateway sh -c 'ls -la /home/node/.openclaw/workspace/.browser'

You should see a folder such as chromium-1208. Then test the browser itself:

sudo docker exec -it openclaw-gateway sh -c '/home/node/.openclaw/workspace/.browser/chromium-1208/chrome-linux64/chrome --version'

If a Chrome version number is printed, Chromium is installed and runnable.

Step C.3: Set the browser path in openclaw.json

Open /volume1/docker/openclaw/config/openclaw.json and add the browser block:

"browser": {
  "enabled": true,
  "defaultProfile": "openclaw",
  "headless": true,
  "noSandbox": true,
  "executablePath": "/home/node/.openclaw/workspace/.browser/chromium-1208/chrome-linux64/chrome",
  "profiles": {
    "openclaw": {
      "cdpPort": 18800,
      "color": "#FF4500"
    }
  }
}

Step C.4: Test it

sudo docker exec -it openclaw-gateway sh -c '/home/node/.openclaw/workspace/.browser/chromium-1208/chrome-linux64/chrome --version'

Then, in OpenClaw (via Telegram or the web UI):

Use the browser profile "openclaw" and open https://example.com.

If OpenClaw answers and describes the page content, everything is set up correctly.

Useful commands – the cheat sheet

WhatCommand
StopContainer Manager → Project → openclaw → Stop
StartContainer Manager → Project → openclaw → Start
LogsContainer Manager → Project → openclaw → Logs
Stop (SSH)cd /volume1/docker/openclaw && docker compose down
Start (SSH)cd /volume1/docker/openclaw && docker compose up -d openclaw-gateway
Logs (SSH)docker logs openclaw-gateway --tail 20
Updatecd /volume1/docker/openclaw && docker compose pull && docker compose down && docker compose up -d openclaw-gateway
SSH tunnel (from the Mac)ssh -L 18789:127.0.0.1:18789 Teddy@192.168.2.10
Check the firewallsudo iptables -L DOCKER-USER -n -v --line-numbers
Reload the firewallsudo bash /volume1/docker/openclaw/openclaw-firewall.sh

Troubleshooting

Container won’t start

Error messageCauseFix
Missing configOnboarding not completedWork through step 1.6
non-loopback Control UI requires allowedOriginsThe config set command is missingRun the command at the end of step 1.6
EACCES: permission deniedFolder permissions are wrongsudo chown -R 1000:1000 /volume1/docker/openclaw
pids_limit discardedThe Synology kernel does not support itHarmless, ignore it

Web interface not reachable

Possible causeCheck command / fix
The container is not runningdocker compose up -d openclaw-gateway
The SSH tunnel is not activeOpen ssh -L 18789:127.0.0.1:18789 user@NAS_IP in a terminal
Port forwarding is disabledError “administratively prohibited” → enable SSH forwarding (see Optional A)
allowedOrigins is not setdocker compose run --rm openclaw-cli config set gateway.controlUi.allowedOrigins '["http://localhost:18789"]'
The browser is not paired yetdevices list and devices approve (see Optional A)
Wrong URLhttp://localhost:18789 – not 127.0.0.1, and not the NAS IP

Telegram bot doesn’t respond

Possible causeFix
Pairing not completedWork through step 1.8
No internetRun the test below
Wrong bot tokenEnter the token again in the onboarding (configure)

To test internet connectivity from the container:

docker exec openclaw-gateway curl -I https://api.anthropic.com
# Should return HTTP 200 or similar (not connection refused)

Firewall rules missing after DSM update

Synology sometimes resets iptables during system updates. Reapply the rules:

/volume1/docker/openclaw/openclaw-firewall.sh

# Verify:
iptables -L FORWARD -n | grep DROP

If the scheduled task stopped working, check:

grep openclaw /var/log/cron
# Look for successful runs

“Read-only file system” error

The disk might be full or corrupted. Check available space:

df -h /volume1
# If usage is >95%, you need to free space

Clean up old Docker layers:

docker system prune -a --volumes

“non-loopback Control UI” error

The web UI is trying to listen on a public IP instead of localhost. This is rare but fixable:

cat /volume1/docker/openclaw/config/webclient.json
# Should contain "localhost" or "127.0.0.1"
# If not, edit to add: {"allowedOrigins": ["http://localhost:18789"]}

“Permission denied” errors

You’re probably not running as root. Check:

whoami
# Should print your user name

# If not, connect again:
ssh your-username@DISKSTATION_IP

For files, fix ownership:

chown -R root:root /volume1/docker/openclaw
chmod -R 755 /volume1/docker/openclaw

DNS / no internet in container

The container can’t reach the outside world. Check:

docker exec openclaw-gateway cat /etc/resolv.conf
# Should list nameservers (8.8.8.8, etc.)

docker exec openclaw-gateway ping -c 1 1.1.1.1
# Should succeed (Cloudflare DNS)

If DNS is broken, your DiskStation network is misconfigured. Check:

cat /etc/resolv.conf
# Your host should also have working DNS

“PIDs limit discarded” warning

This is harmless. It means the container’s process limit is not enforced. You can ignore it, or add this to compose.yaml if it bothers you:

pids_limit: 256

Maintenance and updates

Update OpenClaw to the latest version

cd /volume1/docker/openclaw
docker compose pull
docker compose up -d
# The new image will be pulled and the container restarted

Change your API key or Telegram token

Edit the config files directly:

nano /volume1/docker/openclaw/config/api_key.txt
# Update the key, save (Ctrl+O, Enter, Ctrl+X)

docker compose restart

Backup your configuration

tar -czf /volume1/backups/openclaw-config-$(date +%Y%m%d).tar.gz /volume1/docker/openclaw/config
# Creates a dated backup of your config and API keys

Keep backups safe – they contain your API keys.

Done!

One week later. Ulf is chatting with OpenClaw through Telegram. Bernd is impressed. Tanja is sipping coffee.

Ulf: “This is amazing. I asked it to summarize a long article – done in seconds. And everything stays on my network!”

Bernd: “I told you containers were the way to go. Well, Tanja told us. But I agreed.”

Tanja: “You’ve got a solid foundation. Now you can extend it – add more skills, connect other services, maybe integrate with your NAS backups. The possibilities are endless.”

Ulf: “What about security updates?”

Tanja: “Run docker compose pull once a month. Keep your DSM updated. Monitor the logs. And don’t expose the gateway to the internet – always use SSH tunnels for remote access.”

Bernd: “So we’re done?”

Tanja: “You’re done with setup. But this is just the beginning. Your personal AI assistant is now running 24/7 on your DiskStation. Treat it well, and it’ll serve you well.”

What you’ve built

  • An OpenClaw container running permanently on your DiskStation
  • A Telegram bot integrated and ready to chat
  • SSH tunnel access to a web interface (optional)
  • Network isolation that protects your home devices (optional)
  • Browser automation via Playwright + Chromium (optional)
  • Proper logging, monitoring, and update procedures
  • A foundation for future expansion

Your data stays with you. Your costs are predictable. Your AI assistant is always available. Welcome to OpenClaw on Synology.

FOUNDIC.org is ad-free and has no paywall. If this guide helped you: Ko-fi donationsTreat us to a coffee

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top