Deploy OpenClaw, your self-hosted personal AI assistant, with a single command using Juju.
Website • CharmHub • OpenClaw Docs • Report Bug
OpenClaw is an open-source, self-hosted personal AI assistant that runs on your own hardware and integrates with multiple messaging platforms. It acts as your persistent, 24/7 assistant accessible through WhatsApp, Telegram, Slack, Discord, and 10+ other channels.
- 🤖 AI-Powered: Works with Claude, GPT-4, or local models via Ollama
- 💬 Multi-Platform: Supports 13+ messaging platforms simultaneously
- 🔒 Self-Hosted: Your data stays on your infrastructure
- 🌐 Browser Automation: Integrated Playwright for web tasks
- ⚡ Production-Ready: Systemd service with automatic restarts
- 🛡️ Security-First: Built-in sandboxing and pairing mode for DMs
- A Juju controller (version 3.1+)
- An Ubuntu machine or LXD container (Noble 24.04)
- API keys for your chosen AI provider (Anthropic, OpenAI, etc.)
# Deploy OpenClaw
juju deploy openclaw --channel edge
# Configure with your AI provider
juju config openclaw \
ai-provider="anthropic" \
ai-api-key="sk-ant-xxx" \
ai-model="claude-opus-4-5"
# Wait for deployment
juju status --watch 1s
# Get the gateway URL
juju status openclaw
# Get the gateway token and dashboard URL
juju run openclaw/0 get-gateway-token format=urlAccess the OpenClaw Gateway at http://<unit-ip>:18789
For remote access, see the FAQ - SSH Tunnel Setup
The OpenClaw charm provides several actions for managing your deployment.
Retrieve the authentication token for accessing the OpenClaw Gateway:
# Get token only
juju run openclaw/0 get-gateway-token
# Get structured JSON with URLs
juju run openclaw/0 get-gateway-token format=json
# Get tokenized dashboard URL
juju run openclaw/0 get-gateway-token format=urlWhen deploying multiple units, Node devices are automatically approved via the peer relation within ~15 seconds of connecting to the Gateway. This action is provided for manual intervention if needed (e.g., troubleshooting or forcing re-approval):
# Manually approve all pending Node devices (usually not needed)
juju run openclaw/leader approve-nodes
# Check which devices are pending
juju ssh openclaw/0 'openclaw devices list'Note: In normal operation, nodes automatically pair with the Gateway through the openclaw-cluster peer relation. This action is only needed if automatic approval fails or for administrative purposes.
Create a timestamped compressed backup of all OpenClaw data including conversations, memory, and configurations. The service will be gracefully stopped during backup and automatically restarted.
# Create backup with default settings (output to /tmp)
juju run openclaw/0 backup
# Specify custom output path
juju run openclaw/0 backup output-path=/home/ubuntu/backups
# Set custom wait timeout (default 30 seconds)
juju run openclaw/0 backup wait-timeout=60
# Force backup even if processes are active (not recommended)
juju run openclaw/0 backup force=trueWhat gets backed up:
- Conversation sessions (
.openclaw/agents/main/sessions/) - Memory and workspace files (
.openclaw/workspace/) - AI model configurations (
.openclaw/agents/main/agent/) - Device pairings (
.openclaw/devices/) - OpenClaw configuration (
.openclaw/openclaw.json)
Backup process:
- Waits for active processes to complete (up to
wait-timeoutseconds) - Gracefully stops the OpenClaw service
- Creates compressed tar.gz archive with timestamp
- Restarts the service
- Sets proper permissions (600, owner: ubuntu)
Example output:
backup-file: /tmp/openclaw-backup-20260202-082607.tar.gz
backup-size: 400K
status: success
Restore from backup:
# Stop OpenClaw service
juju ssh openclaw/0 'sudo systemctl stop openclaw.service'
# Extract backup (this will overwrite existing data)
juju ssh openclaw/0 'tar -xzf /tmp/openclaw-backup-TIMESTAMP.tar.gz -C /home/ubuntu'
# Start service
juju ssh openclaw/0 'sudo systemctl start openclaw.service'Configure your preferred AI provider using the following examples:
Anthropic Claude (Recommended)
juju config openclaw \
ai-provider="anthropic" \
ai-api-key="sk-ant-xxx" \
ai-model="claude-opus-4-5"OpenAI
juju config openclaw \
ai-provider="openai" \
ai-api-key="sk-xxx" \
ai-model="gpt-4"Google Gemini
juju config openclaw \
ai-provider="google" \
ai-api-key="YOUR-GEMINI-API-KEY" \
ai-model="gemini-2.5-flash-lite"Local Models (Ollama)
juju config openclaw \
ai-provider="ollama" \
ai-model="llama3"Local Models (LM Studio)
juju config openclaw \
ai-provider="openai" \
ai-api-key="lm-studio" \
ai-model="local-model" \
ai-base-url="http://localhost:1234/v1"Other OpenAI-compatible Services
# vLLM
juju config openclaw \
ai-provider="openai" \
ai-api-key="dummy-key" \
ai-model="meta-llama/Llama-3.3-70B-Instruct" \
ai-base-url="http://localhost:8000/v1"
# Text Generation WebUI
juju config openclaw \
ai-provider="openai" \
ai-api-key="dummy-key" \
ai-model="local-model" \
ai-base-url="http://localhost:5000/v1"Both ai-model and ai[0-9]-model configurations support comma-separated model lists. The first model becomes the primary, and remaining models are added as fallbacks.
Multiple Models from Same Provider:
juju config openclaw \
ai-provider="openai" \
ai-api-key="sk-xxx" \
ai-model="gpt-4,gpt-3.5-turbo"This sets gpt-4 as primary with gpt-3.5-turbo as fallback.
Cross-Provider Fallbacks (using provider/ prefix):
juju config openclaw \
ai-provider="openai" \
ai-api-key="sk-xxx" \
ai-model="gpt-4,anthropic/claude-sonnet-4,google/gemini-2.5-pro"This enables intelligent fallback across providers:
- Primary:
openai/gpt-4 - Fallback 1:
anthropic/claude-sonnet-4 - Fallback 2:
google/gemini-2.5-pro
Note: Models without provider/ prefix will use the configured ai-provider. When using provider/ prefixes in comma-separated lists, ensure corresponding auth profiles are configured via additional AI slots (each provider needs its own slot with API key).
GitHub Copilot as Model Aggregator:
GitHub Copilot Models API acts as an aggregator, routing requests to multiple backend providers (Anthropic, Google, OpenAI, etc.) through a single GitHub API key:
juju config openclaw \
ai-provider="github-copilot" \
ai-api-key="ghp_your_github_token" \
ai-model="gemini-3-flash-preview,gemini-3-pro-preview,gemini-2.5-pro,claude-haiku-4.5,claude-sonnet-4.5,claude-sonnet-4"This configures:
- Primary:
github-copilot/gemini-3-flash-preview - Fallbacks: All other models via
github-copilot/*provider
GitHub Copilot handles routing to the appropriate backend provider (Google for Gemini models, Anthropic for Claude models).
OpenClaw Charm supports configuring up to 11 AI models simultaneously (1 primary + 10 additional slots). This enables model switching, fallback, and specialized model usage for different tasks.
Using Multiple Providers - Requires Multiple Slots:
To use models from different AI providers (e.g., both Google Gemini and Anthropic Claude), configure each provider in a separate slot with its own API key:
# Slot 0: Google models
juju config openclaw \
ai-provider="google" \
ai-api-key="GOOGLE_API_KEY" \
ai-model="gemini-3-flash-preview,gemini-3-pro-preview,gemini-2.5-pro"
# Slot 1: Anthropic models
juju config openclaw \
ai0-provider="anthropic" \
ai0-api-key="ANTHROPIC_API_KEY" \
ai0-model="claude-haiku-4.5,claude-sonnet-4.5,claude-sonnet-4"Result:
- Primary:
google/gemini-3-flash-preview - Fallbacks:
google/gemini-3-pro-preview,google/gemini-2.5-pro,anthropic/claude-haiku-4.5,anthropic/claude-sonnet-4.5,anthropic/claude-sonnet-4
Configure Additional AI Models:
# Configure primary AI model
juju config openclaw \
ai-provider="anthropic" \
ai-api-key="sk-ant-xxx" \
ai-model="claude-opus-4-5"
# Add additional models in slots 0-9
juju config openclaw \
ai0-provider="openai" \
ai0-model="gpt-4" \
ai0-api-key="sk-xxx"
juju config openclaw \
ai1-provider="google" \
ai1-model="gemini-2.5-flash-lite" \
ai1-api-key="YOUR-GEMINI-API-KEY"
juju config openclaw \
ai2-provider="anthropic" \
ai2-model="claude-sonnet-4" \
ai2-api-key="sk-ant-yyy"
# Slots also support comma-separated models
juju config openclaw \
ai3-provider="openai" \
ai3-model="gpt-4,gpt-3.5-turbo,gpt-4o-mini" \
ai3-api-key="sk-xxx"All AI Slots:
- Primary:
ai-provider,ai-model,ai-api-key,ai-base-url(optional) - Slot 0:
ai0-provider,ai0-model,ai0-api-key,ai0-base-url(optional) - Slot 1:
ai1-provider,ai1-model,ai1-api-key,ai1-base-url(optional) - Slot 2:
ai2-provider,ai2-model,ai2-api-key,ai2-base-url(optional) - Slot 3:
ai3-provider,ai3-model,ai3-api-key,ai3-base-url(optional) - Slot 4:
ai4-provider,ai4-model,ai4-api-key,ai4-base-url(optional) - Slot 5:
ai5-provider,ai5-model,ai5-api-key,ai5-base-url(optional) - Slot 6:
ai6-provider,ai6-model,ai6-api-key,ai6-base-url(optional) - Slot 7:
ai7-provider,ai7-model,ai7-api-key,ai7-base-url(optional) - Slot 8:
ai8-provider,ai8-model,ai8-api-key,ai8-base-url(optional) - Slot 9:
ai9-provider,ai9-model,ai9-api-key,ai9-base-url(optional)
Note: Each slot requires at minimum the three core parameters (provider, model, api-key). The base-url parameter is optional and only needed for custom API endpoints. Partially configured slots will trigger validation errors.
Using Custom Base URLs with Multiple Models:
# Mix cloud and local AI models
juju config openclaw \
ai-provider="anthropic" \
ai-api-key="sk-ant-xxx" \
ai-model="claude-opus-4-5"
# Add LM Studio instance in slot 0
juju config openclaw \
ai0-provider="openai" \
ai0-api-key="lm-studio" \
ai0-model="local-llama3" \
ai0-base-url="http://localhost:1234/v1"
# Add vLLM instance in slot 1
juju config openclaw \
ai1-provider="openai" \
ai1-api-key="vllm-key" \
ai1-model="meta-llama/Llama-3.3-70B-Instruct" \
ai1-base-url="http://192.168.1.100:8000/v1"This configuration creates:
- Primary model using Anthropic's cloud API
- Slot 0 using LM Studio running locally
- Slot 1 using a vLLM server on your network
OpenClaw will generate the appropriate models.providers configuration in openclaw.json with custom baseUrls for each provider that has one specified.
Configure messaging platform integrations:
Enable Telegram:
juju config openclaw telegram-bot-token="123456:ABC-DEF"Enable Discord:
juju config openclaw discord-bot-token="YOUR.DISCORD.TOKEN"Enable Slack:
juju config openclaw \
slack-bot-token="xoxb-xxx" \
slack-app-token="xapp-xxx"Enable LINE:
juju config openclaw \
line-channel-access-token="YOUR-CHANNEL-ACCESS-TOKEN" \
line-channel-secret="YOUR-CHANNEL-SECRET"Enable Multiple Platforms Simultaneously:
juju config openclaw \
telegram-bot-token="123456:ABC-DEF" \
discord-bot-token="YOUR.DISCORD.TOKEN" \
slack-bot-token="xoxb-xxx" \
slack-app-token="xapp-xxx" \
line-channel-access-token="YOUR-CHANNEL-ACCESS-TOKEN" \
line-channel-secret="YOUR-CHANNEL-SECRET"# Set DM access policy (pairing mode recommended)
juju config openclaw dm-policy="pairing"
# Set DM session scope (isolate conversations per user)
juju config openclaw dm-scope="per-channel-peer"
# Configure sandbox mode
juju config openclaw sandbox-mode="non-main"
# Disable browser automation if not needed
juju config openclaw use-browser=""DM Session Scope Options:
The dm-scope setting controls how direct message conversations are isolated:
-
main(default): All DMs share the main session for continuity across devices/channels- ✅ Best for: Single-user personal assistants
⚠️ Security Risk: Multiple users will share conversation context
-
per-peer: Isolate sessions by sender ID across channels- ✅ Best for: Multi-user setups where the same person contacts via different channels
- Each unique sender gets their own isolated session
-
per-channel-peer: Isolate by channel + sender (recommended for multi-user inboxes)- ✅ Best for: Agents receiving DMs from multiple people on one channel
- ✅ Recommended for shared inboxes
- Prevents conversation leakage between users
-
per-account-channel-peer: Isolate by account + channel + sender- ✅ Best for: Multi-account inboxes on the same channel
- Maximum isolation for complex multi-user scenarios
Security Warning: If your agent can receive DMs from multiple people (pairing approvals for multiple senders, DM allowlist with multiple entries, or dm-policy: "open"), you should use per-channel-peer or per-account-channel-peer to prevent private information leakage between users.
# Change gateway port
juju config openclaw gateway-port=8080
# Bind to all interfaces (for remote access)
juju config openclaw gateway-bind="lan"
# Set log level
juju config openclaw log-level="debug"
# Enable browser automation (can be set anytime)
juju config openclaw use-browser=chrome # or chromium, firefox| Option | Type | Default | Description |
|---|---|---|---|
gateway-port |
int | 18789 | Gateway WebSocket/HTTP port |
gateway-bind |
string | loopback | Bind mode: loopback, lan, or IP |
node-version |
string | 24 | Node.js major version (min 22) |
ai-provider |
string | - | AI provider: anthropic, openai, google, bedrock, ollama |
ai-model |
string | - | AI model name |
ai-api-key |
string | - | API key for selected provider |
ai-base-url |
string | - | Custom API base URL (for LM Studio, vLLM, etc.) |
ai0-provider ... ai9-provider |
string | - | Additional AI provider slots (0-9) |
ai0-model ... ai9-model |
string | - | Additional AI model name slots (0-9) |
ai0-api-key ... ai9-api-key |
string | - | Additional AI API key slots (0-9) |
ai0-base-url ... ai9-base-url |
string | - | Custom API base URL for additional slots (0-9) |
telegram-bot-token |
string | - | Telegram bot token from @BotFather |
discord-bot-token |
string | - | Discord bot token |
slack-bot-token |
string | - | Slack bot token (xoxb-...) |
slack-app-token |
string | - | Slack app token (xapp-...) |
line-channel-access-token |
string | - | LINE channel access token |
line-channel-secret |
string | - | LINE channel secret |
dm-policy |
string | pairing | DM policy: pairing, open, closed |
dm-scope |
string | main | DM session scope: main, per-peer, per-channel-peer, per-account-channel-peer |
sandbox-mode |
string | non-main | Sandbox: all, non-main, none |
install-method |
string | npm | Install method: npm, pnpm, bun, source |
version |
string | latest | Version to install |
auto-update |
boolean | false | Auto-update on charm upgrade |
use-browser |
string | "" | Browser for automation: chrome, chromium, firefox, or empty |
log-level |
string | info | Log level: debug, info, warn, error |
OpenClaw charm supports horizontal scaling with automatic Gateway-Node architecture:
# Deploy with 3 units (IMPORTANT: set gateway-bind=lan for multi-unit)
juju deploy openclaw --channel edge -n 3 \
--config gateway-bind=lan \
--config ai-provider="anthropic" \
--config ai-api-key="sk-ant-xxx" \
--config ai-model="claude-opus-4-5"
# Wait for deployment
juju status --watch 1s
# Nodes will automatically pair with Gateway via peer relation
# (Auto-approval happens within ~15 seconds of node connection)
# Scale up to 5 units
juju add-unit openclaw -n 2
# Scale down to 2 units
juju remove-unit openclaw/2For multi-unit deployments to work properly, you MUST set gateway-bind=lan:
juju config openclaw gateway-bind=lanWhy this is required:
- Default
gateway-bind=loopbackbinds Gateway to127.0.0.1(localhost only) - Node units on different machines cannot connect to
127.0.0.1 - Setting
gateway-bind=lanbinds Gateway to all network interfaces - This allows Nodes to connect via the Gateway's private IP address
The charm will automatically block deployment if you attempt multi-unit with gateway-bind=loopback.
Status example:
Unit Workload Message
openclaw/0* active Gateway: http://10.47.232.168:18789
openclaw/1 active Node - connected to openclaw/0
openclaw/2 active Node - connected to openclaw/0
How it works:
- Leader unit (elected by Juju) runs the OpenClaw Gateway service
- Non-leader units run OpenClaw Node services that connect to the Gateway
- All units automatically coordinate through peer relations
- Nodes authenticate using gateway tokens and device pairing
- Gateway handles all messaging channels and AI processing
- Nodes provide additional compute capacity and system access
Authentication Flow:
- Gateway generates auth token during onboarding
- Token shared via Juju peer relation (
openclaw-cluster) - Nodes receive token and inject into systemd service via drop-in file
- Nodes connect with gateway token → Gateway validates
- Device pairing created → Auto-approved by Gateway
- Node receives device token → Subsequent connections use device token
Benefits:
- Horizontal scaling: Add more nodes for increased capacity
- Load distribution: Nodes can handle system.run commands across multiple machines
- Distributed access: Nodes provide system access across different machines
- Automatic coordination: Units discover and connect through peer relations
- High availability: Add redundancy across multiple machines
Deploy multiple independent OpenClaw instances (separate applications):
# Production instance
juju deploy openclaw openclaw-prod \
--config gateway-port=18789 --channel edge
# Development instance
juju deploy openclaw openclaw-dev \
--config gateway-port=18790 --channel edgeChoose your preferred installation method:
Install using Bun:
juju config openclaw install-method="bun"Install using pnpm:
juju config openclaw install-method="pnpm"Install from source:
juju config openclaw \
install-method="source" \
version="main"Pin to specific version:
juju config openclaw \
version="2026.1.29"Enable auto-updates:
juju config openclaw auto-update=trueOpenClaw Gateway is designed to run as a single instance managing multiple channels. For high availability:
- Deploy multiple instances with different channels
- Use load balancer in front of multiple gateways
- Share workspace storage via NFS or similar
For detailed troubleshooting and common issues, see the FAQ.
# View charm status
juju status openclaw --relations
# SSH into unit
juju ssh openclaw/0
# Check systemd service (Gateway)
juju ssh openclaw/0 'systemctl --user status openclaw-gateway.service'
# Check systemd service (Node)
juju ssh openclaw/1 'systemctl --user status openclaw-node.service'
# View service logs
juju ssh openclaw/0 'journalctl --user -u openclaw-gateway.service -f'
juju ssh openclaw/1 'journalctl --user -u openclaw-node.service -f'Service won't start:
- Verify API keys are configured correctly
- Check logs:
juju debug-log --replay --include openclaw - Ensure Node.js 22+ is installed:
juju ssh openclaw/0 'node --version'
Cannot access gateway:
- Check port is open:
juju ssh openclaw/0 'ss -tulpn | grep 18789' - Verify gateway-bind setting:
juju config openclaw gateway-bind - Check firewall rules on the host
Messaging channels not working:
- Verify channel tokens are correct
- Check channel configuration:
juju ssh openclaw/0 'cat /home/ubuntu/.openclaw/openclaw.json' - Review OpenClaw logs for connection errors
Issue: Node shows "unauthorized: gateway token missing"
Symptoms:
juju ssh openclaw/1 'journalctl --user -u openclaw-node.service --no-pager | tail -20'
# Shows: "unauthorized: gateway token missing (provide gateway auth token)"
Causes:
- Systemd drop-in file not created or token not in peer relation
- Node started before Gateway published token to relation
Solutions:
# Check if token drop-in exists
juju ssh openclaw/1 'cat /home/ubuntu/.config/systemd/user/openclaw-node.service.d/gateway-token.conf'
# Check peer relation data
juju ssh openclaw/0 'relation-get -r $(relation-ids openclaw-cluster | head -1) - openclaw/0'
# Trigger config-changed to recreate drop-in
juju config openclaw log-level=info
# Manual restart if needed
juju ssh openclaw/1 'systemctl --user restart openclaw-node.service'Issue: Node shows "Waiting for device pairing approval"
Symptoms:
juju status openclaw/1
# Shows: waiting - "Waiting for device pairing approval"
Causes:
- Auto-approve hasn't completed yet (normal delay: ~15 seconds after node connects)
- Auto-approve script failed to run
- Device is in pending list but approval failed
Solutions:
# Check pending devices on Gateway
juju ssh openclaw/0 'sudo su - ubuntu -c ". ~/.nvm/nvm.sh && openclaw devices list"'
# Manually approve all pending nodes
juju run openclaw/leader approve-nodes
# Check auto-approve script logs
juju ssh openclaw/0 'sudo journalctl --user -u openclaw-gateway.service --no-pager | grep auto-approve'Issue: Node shows "Cannot reach Gateway"
Symptoms:
juju status openclaw/1
# Shows: blocked - "Cannot reach Gateway at 10.x.x.x:18789"
Causes:
- Gateway bound to loopback instead of LAN
- Network connectivity issue between units
- Firewall blocking Gateway port
Solutions:
# Check Gateway binding
juju config openclaw gateway-bind
# Should be "lan" for multi-unit, not "loopback"
# Fix binding
juju config openclaw gateway-bind=lan
# Verify Gateway is listening on network interface
juju ssh openclaw/0 'ss -tulpn | grep 18789'
# Should show: 0.0.0.0:18789 (not 127.0.0.1:18789)
# Test connectivity from Node
juju ssh openclaw/1 'timeout 3 bash -c "echo > /dev/tcp/$(relation-get -r $(relation-ids openclaw-cluster | head -1) gateway-host openclaw/0)/18789" && echo "Gateway reachable" || echo "Gateway unreachable"'Issue: Multi-unit deployment blocked at start
Symptoms:
juju status openclaw/0
# Shows: blocked - "Multi-unit deployment requires gateway-bind=lan (currently: loopback)"
Cause:
- Attempting multi-unit deployment with
gateway-bind=loopback
Solution:
# Set gateway-bind to lan
juju config openclaw gateway-bind=lan
# Deployment will proceed automaticallyIssue: Node configuration shows wrong display name
Symptoms:
- Device list shows "ip-10-x-x-x" instead of "openclaw/1"
Cause:
- Using old charm version without Juju unit name support
Solution:
# Check node.json
juju ssh openclaw/1 'cat /home/ubuntu/.openclaw/node.json'
# Should show: "displayName": "openclaw/1"
# If not, upgrade charm
juju refresh openclaw --channel edge
# Or regenerate config
juju config openclaw log-level=debug # Triggers config-changed# Enable debug logging
juju config openclaw log-level="debug"
# View detailed logs (Gateway)
juju ssh openclaw/0 'journalctl --user -u openclaw-gateway.service -n 500'
# View detailed logs (Node)
juju ssh openclaw/1 'journalctl --user -u openclaw-node.service -n 500'
# Check all relation data
juju run openclaw/0 relation-get -r $(relation-ids openclaw-cluster | head -1)# 1. Check deployment status
juju status openclaw
# 2. Verify Node config (no token in file - by design)
juju ssh openclaw/1 'cat /home/ubuntu/.openclaw/node.json | jq .'
# 3. Verify systemd drop-in (token should be present)
juju ssh openclaw/1 'cat /home/ubuntu/.config/systemd/user/openclaw-node.service.d/gateway-token.conf'
# 4. Check Gateway devices list
juju ssh openclaw/0 'sudo su - ubuntu -c ". ~/.nvm/nvm.sh && openclaw devices list"'
# 5. Check Node connection logs
juju ssh openclaw/1 'journalctl --user -u openclaw-node.service --since "5 minutes ago" --no-pager | tail -30'
# 6. Verify Gateway listening on network interface
juju ssh openclaw/0 'ss -tulpn | grep 18789'
# Expected: 0.0.0.0:18789 (not 127.0.0.1:18789)
# 7. Test Gateway connectivity from Node
juju ssh openclaw/1 'nc -zv $(relation-get -r $(relation-ids openclaw-cluster | head -1) gateway-host openclaw/0) 18789'# Install charmcraft
sudo snap install charmcraft --classic
# Pack the charm
charmcraft pack
# Deploy locally
juju deploy ./openclaw_ubuntu-24.04-amd64.charm \
--config anthropic-api-key="test-key"# Lint shell scripts
shellcheck hooks/*
# Run full test suite (requires LXD and Juju)
./.github/workflows/test.yaml # See workflow for test commandsopenclaw-charm/
├── metadata.yaml # Charm metadata
├── config.yaml # Configuration options
├── hooks/ # Charm hooks
│ ├── common.sh # Shared functions
│ ├── install # Installation hook
│ ├── start # Start hook
│ ├── stop # Stop hook
│ ├── config-changed # Config change handler
│ └── upgrade-charm # Upgrade handler
├── docs/ # GitHub Pages
│ └── index.html # Documentation site
├── .github/workflows/ # CI/CD
│ ├── test.yaml # Automated tests
│ ├── publish.yaml # CharmHub publishing
│ └── pages.yaml # GitHub Pages deploy
└── README.md # This file
This charm includes comprehensive CI/CD workflows:
Runs on every push and PR:
- Lint: Validates shell scripts and metadata
- Install Test: Deploys charm with both npm and pnpm methods on Noble 24.04
- Channel Test: Verifies messaging channel configuration
- Upgrade Test: Tests charm upgrade process
Triggered on version tags:
- Builds and packs the charm
- Uploads to CharmHub
- Releases to appropriate channel:
vX.Y.Ztags → candidate channelvX.Y.Z-rc*tags → beta channel- Other tags → edge channel
- Manual approval required for stable channel
- Creates GitHub release with charm artifact
Automatically deploys documentation site on changes to docs/
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests and linting
- Submit a pull request
Found a bug? Open an issue with:
- Juju version (
juju version) - Charm version (
juju status openclaw) - Steps to reproduce
- Relevant logs
Please report security vulnerabilities privately to fourdollars+security@gmail.com.
Follow these security best practices:
- Use pairing mode for DM access (
dm-policy="pairing") - Enable sandboxing for non-main sessions
- Bind to loopback unless remote access is required
- Rotate API keys regularly
- Keep charm updated to latest stable version
This charm is licensed under the MIT License. See LICENSE for details.
OpenClaw itself is MIT licensed. See openclaw/openclaw for the upstream project.
- FAQ - Frequently Asked Questions: Common issues and solutions
- OpenClaw Website: https://openclaw.ai
- OpenClaw Documentation: https://docs.openclaw.ai
- OpenClaw GitHub: https://github.com/openclaw/openclaw
- Charm Documentation: https://fourdollars.github.io/openclaw-charm/
- CharmHub Page: https://charmhub.io/openclaw
- Juju Documentation: https://juju.is/docs
- Discord Community: https://discord.gg/clawd
- OpenClaw team for creating an amazing open-source AI assistant
- Canonical for the Juju ecosystem and tooling
- The charm development community for best practices and examples
Happy Deploying! 🎉
If you find this charm useful, please ⭐ star the repository and share it with others!