Add openclaw dropshell template for personal AI assistant
All checks were successful
Test and Publish Templates / test-and-publish (push) Successful in 14s

This commit is contained in:
j
2026-03-11 20:48:14 +13:00
parent 932fe45303
commit 23ec097b39
16 changed files with 555 additions and 0 deletions

126
openclaw/README.txt Normal file
View File

@@ -0,0 +1,126 @@
OpenClaw - Personal AI Assistant
=================================
OpenClaw is an open-source AI assistant that runs on your own server and
communicates via messaging platforms you already use. It connects to LLM
providers (Claude, GPT, etc.) and can interact via Telegram, email, WhatsApp,
Signal, Discord, and many more channels.
Website: https://openclaw.ai/
GitHub: https://github.com/openclaw/openclaw
Prerequisites
-------------
1. An Anthropic API key (https://console.anthropic.com/settings/keys)
and/or an OpenRouter API key (https://openrouter.ai/settings/keys)
2. For Telegram: a bot token from @BotFather on Telegram
3. For Gmail: a Gmail App Password (NOT your real password)
- Enable 2FA on your Google account
- Go to: https://myaccount.google.com/apppasswords
- Create an app password for "Mail"
Configuration
-------------
Required settings in service.env:
ANTHROPIC_API_KEY - Anthropic API key (primary LLM provider)
OPENROUTER_API_KEY - OpenRouter API key (fallback provider)
At least one of these must be set.
Optional channel settings:
TELEGRAM_BOT_TOKEN - Telegram bot token from @BotFather
GMAIL_ADDRESS - Gmail address for email integration
GMAIL_APP_PASSWORD - Gmail App Password (16-character code)
Security settings:
DM_POLICY - "pairing" (default), "allowlist", or "open"
Ports
-----
GATEWAY_PORT (default: 18789) - Web dashboard, WebChat, and API
Setup
-----
1. Configure your service.env with API keys and channel credentials
2. Install the service:
ds install <server> openclaw
3. Note the gateway token printed during installation - you need it
to access the web dashboard
4. Open the web dashboard:
http://<server-ip>:18789
5. Paste the gateway token in Settings to authenticate
Channel Setup
-------------
TELEGRAM (automated):
Set TELEGRAM_BOT_TOKEN in service.env before install.
After install, send a message to your bot on Telegram.
WEBCHAT (always available):
Access via the web dashboard at http://<server-ip>:18789
EMAIL / GMAIL (post-install):
After install, set up the email skill:
1. docker exec <container> openclaw skills install imap-smtp-email
2. Configure in the Control UI with:
IMAP: imap.gmail.com:993 (TLS)
SMTP: smtp.gmail.com:587 (STARTTLS)
Username: your Gmail address
Password: your Gmail App Password
WHATSAPP (interactive, post-install):
Requires scanning a QR code with your phone:
docker exec -it <container> openclaw channels login
SIGNAL (interactive, post-install):
Requires phone number verification:
docker exec -it <container> openclaw channels add --channel signal
Security Notes
--------------
- API keys are stored in openclaw.json inside the data directory
- Gmail App Passwords are scoped credentials, not your real password
- Telegram bot tokens only control the bot, not your Telegram account
- WhatsApp/Signal use session-based auth, no passwords stored
- Set DM_POLICY="pairing" (default) to require a pairing code
before the bot responds to new contacts
- The gateway token controls dashboard access - keep it secret
Data Storage
------------
All data is stored in: ${DATA_PATH}
config/ - OpenClaw configuration (openclaw.json)
workspace/ - Agent workspace and session data
The gateway token is saved in: ${DATA_PATH}/gateway.token
Retrieving Your Gateway Token
------------------------------
If you lose your gateway token:
cat ${DATA_PATH}/gateway.token
Or check the config file:
cat ${DATA_PATH}/config/openclaw.json | grep token
More Information
----------------
Documentation: https://docs.openclaw.ai/
Channel Guide: https://docs.openclaw.ai/gateway/configuration
Docker Guide: https://docs.openclaw.ai/install/docker

7
openclaw/_volumes.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/bash
# Define volume items for openclaw container
# These are used across backup, restore, create, and destroy operations
get_openclaw_volumes() {
echo "path:data:${DATA_PATH}"
}

24
openclaw/backup.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/bash
source "${AGENT_PATH}/common.sh"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/_volumes.sh"
_check_required_env_vars "CONTAINER_NAME" "DATA_PATH"
# Export variables for docker compose
export CONTAINER_NAME DATA_PATH GATEWAY_PORT
export IMAGE_REGISTRY IMAGE_REPO IMAGE_TAG
export ANTHROPIC_API_KEY OPENROUTER_API_KEY
cd "$SCRIPT_DIR" || _die "Failed to change to script directory"
# Stop containers for consistent backup
docker compose -p "${CONTAINER_NAME}" stop
# Backup using dropshell's backup system
# shellcheck disable=SC2046
backup_items $(get_openclaw_volumes) || _die "Failed to create backup"
# Restart containers
docker compose -p "${CONTAINER_NAME}" start
echo "Backup created successfully"

View File

@@ -0,0 +1,66 @@
# OpenClaw - Personal AI Assistant
# https://openclaw.ai/
CONTAINER_NAME=openclaw
SSH_USER="root"
IMAGE_TAG="latest"
# Data path - stores OpenClaw config, workspace, and session data
DATA_PATH="/home/dropshell/openclaw"
# Gateway port (web dashboard + WebChat + API)
GATEWAY_PORT=18789
# ---------------------------------------------------------------------------
# LLM Provider API Keys
# REQUIRED: At least one of these must be set
# ---------------------------------------------------------------------------
# Anthropic API key (PRIMARY) - recommended for best results
# Get from: https://console.anthropic.com/settings/keys
ANTHROPIC_API_KEY=
# OpenRouter API key (FALLBACK) - routes to multiple LLM providers
# Get from: https://openrouter.ai/settings/keys
OPENROUTER_API_KEY=
# Primary model to use (format: provider/model-name)
DEFAULT_MODEL="anthropic/claude-sonnet-4-5"
# Fallback model (used when primary is unavailable)
FALLBACK_MODEL="openrouter/anthropic/claude-sonnet-4-5"
# ---------------------------------------------------------------------------
# Telegram Bot Channel
# ---------------------------------------------------------------------------
# Create a bot via @BotFather on Telegram and paste the token here
# Leave empty to disable Telegram
# Steps: 1. Open Telegram, search @BotFather
# 2. Send /newbot, follow prompts
# 3. Copy the bot token
TELEGRAM_BOT_TOKEN=
# ---------------------------------------------------------------------------
# Gmail Email Integration (IMAP/SMTP)
# ---------------------------------------------------------------------------
# Uses a Gmail App Password - NOT your real Gmail password!
# Steps: 1. Enable 2FA on your Google account
# 2. Go to: https://myaccount.google.com/apppasswords
# 3. Create an app password for "Mail"
# 4. Paste the 16-character app password below
GMAIL_ADDRESS=
GMAIL_APP_PASSWORD=
# ---------------------------------------------------------------------------
# Security Settings
# ---------------------------------------------------------------------------
# DM policy for messaging channels
# "pairing" - require a pairing code before responding (most secure)
# "allowlist" - only respond to approved senders
# "open" - respond to anyone (least secure)
DM_POLICY="pairing"
TEMPLATE=openclaw

21
openclaw/destroy.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
source "${AGENT_PATH}/common.sh"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/_volumes.sh"
_check_required_env_vars "CONTAINER_NAME" "DATA_PATH"
# Export variables for docker compose
export CONTAINER_NAME DATA_PATH GATEWAY_PORT
export IMAGE_REGISTRY IMAGE_REPO IMAGE_TAG
export ANTHROPIC_API_KEY OPENROUTER_API_KEY
cd "$SCRIPT_DIR" || _die "Failed to change to script directory"
# Stop and remove containers
docker compose -p "${CONTAINER_NAME}" down
# Destroy data
# shellcheck disable=SC2046
destroy_items $(get_openclaw_volumes) || _die "Failed to destroy data"
echo "Destroyed ${CONTAINER_NAME} and all data"

View File

@@ -0,0 +1,19 @@
services:
openclaw:
image: ${IMAGE_REGISTRY}/${IMAGE_REPO}:${IMAGE_TAG}
container_name: ${CONTAINER_NAME}
restart: unless-stopped
ports:
- "${GATEWAY_PORT}:18789"
volumes:
- ${DATA_PATH}/config:/home/node/.openclaw
- ${DATA_PATH}/workspace:/home/node/workspace
environment:
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
OPENROUTER_API_KEY: ${OPENROUTER_API_KEY}
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:18789/healthz"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s

13
openclaw/install-pre.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/bash
source "${AGENT_PATH}/common.sh"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
_check_required_env_vars "CONTAINER_NAME"
export CONTAINER_NAME DATA_PATH GATEWAY_PORT
export IMAGE_REGISTRY IMAGE_REPO IMAGE_TAG
export ANTHROPIC_API_KEY OPENROUTER_API_KEY
cd "$SCRIPT_DIR" || _die "Failed to change to script directory"
docker compose -p "${CONTAINER_NAME}" pull || echo "Warning: pre-pull failed, install.sh will retry"
echo "Pre-install complete"

143
openclaw/install.sh Executable file
View File

@@ -0,0 +1,143 @@
#!/bin/bash
source "${AGENT_PATH}/common.sh"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
_check_required_env_vars "CONTAINER_NAME" "IMAGE_REGISTRY" "IMAGE_REPO" "IMAGE_TAG" "DATA_PATH" "GATEWAY_PORT"
# Require at least one LLM provider
if [ -z "$ANTHROPIC_API_KEY" ] && [ -z "$OPENROUTER_API_KEY" ]; then
_die "At least one LLM API key must be set (ANTHROPIC_API_KEY or OPENROUTER_API_KEY) in config/service.env"
fi
_check_docker_installed || _die "Docker test failed, aborting installation..."
# Create data directories
mkdir -p "${DATA_PATH}/config"
mkdir -p "${DATA_PATH}/workspace"
# Set ownership to node user (uid 1000) used by the OpenClaw container
chown -R 1000:1000 "${DATA_PATH}"
# Generate gateway token if one doesn't already exist
TOKEN_FILE="${DATA_PATH}/gateway.token"
if [ -f "$TOKEN_FILE" ]; then
GATEWAY_TOKEN=$(cat "$TOKEN_FILE")
else
GATEWAY_TOKEN=$(openssl rand -hex 32)
echo -n "$GATEWAY_TOKEN" > "$TOKEN_FILE"
chown 1000:1000 "$TOKEN_FILE"
fi
# Generate openclaw.json configuration
CONFIG_FILE="${DATA_PATH}/config/openclaw.json"
# Build model configuration
MODEL_PRIMARY="${DEFAULT_MODEL:-anthropic/claude-sonnet-4-5}"
MODEL_FALLBACK="${FALLBACK_MODEL:-openrouter/anthropic/claude-sonnet-4-5}"
# Build channels section
TELEGRAM_CONFIG=""
if [ -n "$TELEGRAM_BOT_TOKEN" ]; then
TELEGRAM_CONFIG=$(cat <<TGEOF
"telegram": {
"enabled": true,
"token": "${TELEGRAM_BOT_TOKEN}",
"dmPolicy": "${DM_POLICY:-pairing}"
}
TGEOF
)
fi
# Build env section for API keys
ENV_ENTRIES=""
if [ -n "$ANTHROPIC_API_KEY" ]; then
ENV_ENTRIES="\"ANTHROPIC_API_KEY\": \"${ANTHROPIC_API_KEY}\""
fi
if [ -n "$OPENROUTER_API_KEY" ]; then
[ -n "$ENV_ENTRIES" ] && ENV_ENTRIES="${ENV_ENTRIES},"
ENV_ENTRIES="${ENV_ENTRIES}
\"OPENROUTER_API_KEY\": \"${OPENROUTER_API_KEY}\""
fi
# Build fallbacks array
FALLBACKS_JSON=""
if [ -n "$OPENROUTER_API_KEY" ] && [ -n "$ANTHROPIC_API_KEY" ]; then
FALLBACKS_JSON="\"fallbacks\": [\"${MODEL_FALLBACK}\"],"
fi
cat > "$CONFIG_FILE" <<CFGEOF
{
"env": {
${ENV_ENTRIES}
},
"agents": {
"defaults": {
"model": {
"primary": "${MODEL_PRIMARY}",
${FALLBACKS_JSON}
"params": {}
}
}
},
"channels": {
${TELEGRAM_CONFIG}
},
"gateway": {
"token": "${GATEWAY_TOKEN}",
"bind": "lan",
"auth": {
"mode": "password"
}
}
}
CFGEOF
chown 1000:1000 "$CONFIG_FILE"
# Export variables for docker compose
export CONTAINER_NAME DATA_PATH GATEWAY_PORT
export IMAGE_REGISTRY IMAGE_REPO IMAGE_TAG
export ANTHROPIC_API_KEY OPENROUTER_API_KEY
cd "$SCRIPT_DIR" || _die "Failed to change to script directory"
# Pull images
docker compose -p "${CONTAINER_NAME}" pull || _die "Failed to pull images"
# Stop existing containers
docker compose -p "${CONTAINER_NAME}" down 2>/dev/null || true
# Start containers
docker compose -p "${CONTAINER_NAME}" up -d || _die "Failed to start containers"
echo ""
echo "=========================================="
echo "OpenClaw installation complete!"
echo "=========================================="
echo ""
echo "Gateway Token (save this!):"
echo " ${GATEWAY_TOKEN}"
echo ""
echo "Web Dashboard:"
echo " http://localhost:${GATEWAY_PORT}"
echo " Paste the gateway token above into Settings to authenticate."
echo ""
if [ -n "$TELEGRAM_BOT_TOKEN" ]; then
echo "Telegram: Enabled - send a message to your bot to start!"
fi
if [ -n "$GMAIL_ADDRESS" ] && [ -n "$GMAIL_APP_PASSWORD" ]; then
echo ""
echo "Gmail: To enable email, install the IMAP skill after the gateway is running:"
echo " docker exec ${CONTAINER_NAME} openclaw skills install imap-smtp-email"
echo " Then configure it in the Control UI (http://localhost:${GATEWAY_PORT})"
echo " IMAP: imap.gmail.com:993 (TLS) | SMTP: smtp.gmail.com:587 (STARTTLS)"
echo " Username: ${GMAIL_ADDRESS}"
echo " Password: (your app password from service.env)"
fi
echo ""
echo "WebChat: Always available at http://localhost:${GATEWAY_PORT}"
echo ""
echo "To add WhatsApp (interactive, requires QR code):"
echo " docker exec -it ${CONTAINER_NAME} openclaw channels login"
echo ""
echo "Check status: ds status <server> openclaw"
echo "View logs: ds logs <server> openclaw"

12
openclaw/logs.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/bin/bash
source "${AGENT_PATH}/common.sh"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
_check_required_env_vars "CONTAINER_NAME"
# Export variables for docker compose
export CONTAINER_NAME DATA_PATH GATEWAY_PORT
export IMAGE_REGISTRY IMAGE_REPO IMAGE_TAG
export ANTHROPIC_API_KEY OPENROUTER_API_KEY
cd "$SCRIPT_DIR" || _die "Failed to change to script directory"
docker compose -p "${CONTAINER_NAME}" logs "$@"

5
openclaw/ports.sh Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/bash
source "${AGENT_PATH}/common.sh"
_check_required_env_vars "GATEWAY_PORT"
echo "$GATEWAY_PORT"

35
openclaw/restore.sh Executable file
View File

@@ -0,0 +1,35 @@
#!/bin/bash
source "${AGENT_PATH}/common.sh"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/_volumes.sh"
_check_required_env_vars "CONTAINER_NAME" "DATA_PATH"
# Export variables for docker compose
export CONTAINER_NAME DATA_PATH GATEWAY_PORT
export IMAGE_REGISTRY IMAGE_REPO IMAGE_TAG
export ANTHROPIC_API_KEY OPENROUTER_API_KEY
cd "$SCRIPT_DIR" || _die "Failed to change to script directory"
# Stop and remove containers before restore
docker compose -p "${CONTAINER_NAME}" down
# Restore files using dropshell's restore system
# shellcheck disable=SC2046
restore_items $(get_openclaw_volumes) || _die "Failed to restore data from backup file"
# Fix ownership after restore
chown -R 1000:1000 "${DATA_PATH}"
# Start containers
docker compose -p "${CONTAINER_NAME}" up -d
echo "Restore complete! Service is running."
echo ""
echo "Your gateway token:"
if [ -f "${DATA_PATH}/gateway.token" ]; then
cat "${DATA_PATH}/gateway.token"
echo ""
else
echo " (check ${DATA_PATH}/config/openclaw.json)"
fi

14
openclaw/start.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/bash
source "${AGENT_PATH}/common.sh"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
_check_required_env_vars "CONTAINER_NAME" "DATA_PATH"
# Export variables for docker compose
export CONTAINER_NAME DATA_PATH GATEWAY_PORT
export IMAGE_REGISTRY IMAGE_REPO IMAGE_TAG
export ANTHROPIC_API_KEY OPENROUTER_API_KEY
cd "$SCRIPT_DIR" || _die "Failed to change to script directory"
docker compose -p "${CONTAINER_NAME}" up -d || _die "Failed to start containers"
echo "Container ${CONTAINER_NAME} started"

25
openclaw/status.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/bash
source "${AGENT_PATH}/common.sh"
_check_required_env_vars "CONTAINER_NAME"
if ! docker ps -a --format "{{.Names}}" | grep -q "^${CONTAINER_NAME}$"; then
echo "Unknown"
exit 0
fi
STATE=$(docker inspect -f '{{.State.Status}}' "$CONTAINER_NAME" 2>/dev/null)
case "$STATE" in
running)
if docker inspect -f '{{.State.Health.Status}}' "$CONTAINER_NAME" 2>/dev/null | grep -q "unhealthy"; then
echo "Error"
else
echo "Running"
fi
;;
exited|stopped)
echo "Stopped"
;;
*)
echo "Unknown"
;;
esac

14
openclaw/stop.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/bash
source "${AGENT_PATH}/common.sh"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
_check_required_env_vars "CONTAINER_NAME"
# Export variables for docker compose
export CONTAINER_NAME DATA_PATH GATEWAY_PORT
export IMAGE_REGISTRY IMAGE_REPO IMAGE_TAG
export ANTHROPIC_API_KEY OPENROUTER_API_KEY
cd "$SCRIPT_DIR" || _die "Failed to change to script directory"
docker compose -p "${CONTAINER_NAME}" stop || _die "Failed to stop containers"
echo "Container ${CONTAINER_NAME} stopped"

View File

@@ -0,0 +1,14 @@
# DO NOT EDIT THIS FILE FOR YOUR SERVICE!
# This file is replaced from the template whenever there is an update.
# Edit the service.env file to make changes.
# Template to use - always required!
TEMPLATE=openclaw
REQUIRES_HOST_ROOT=false
REQUIRES_DOCKER=true
REQUIRES_DOCKER_ROOT=false
# Docker image settings
IMAGE_REGISTRY="ghcr.io"
IMAGE_REPO="openclaw/openclaw"
IMAGE_TAG="latest"

17
openclaw/uninstall.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/bin/bash
source "${AGENT_PATH}/common.sh"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
_check_required_env_vars "CONTAINER_NAME"
# Export variables for docker compose
export CONTAINER_NAME DATA_PATH GATEWAY_PORT
export IMAGE_REGISTRY IMAGE_REPO IMAGE_TAG
export ANTHROPIC_API_KEY OPENROUTER_API_KEY
cd "$SCRIPT_DIR" || _die "Failed to change to script directory"
# Stop and remove containers (but preserve data)
docker compose -p "${CONTAINER_NAME}" down || _die "Failed to stop containers"
echo "Uninstalled ${CONTAINER_NAME} (data preserved in ${DATA_PATH})"
echo "Note: Your gateway token and configuration are still in ${DATA_PATH}"