Repository: phioranex/openclaw-docker Branch: main Commit: a45e13e6232a Files: 12 Total size: 59.7 KB Directory structure: gitextract_uobwqc7k/ ├── .github/ │ └── workflows/ │ ├── build-image.yml │ └── openclaw-release-tracker.yml ├── .gitignore ├── .last-openclaw-version ├── Dockerfile ├── LICENSE ├── README.md ├── docker-compose.yml ├── install.ps1 ├── install.sh ├── uninstall.ps1 └── uninstall.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/build-image.yml ================================================ name: Build and Push Docker Image on: workflow_dispatch: inputs: openclaw_version: description: 'OpenClaw version to build (branch/tag)' required: false default: 'main' type: string push_image: description: 'Push image to registry' required: false default: true type: boolean push: branches: - main paths: - 'Dockerfile' - '.github/workflows/build-image.yml' schedule: # Build daily at 00:00 UTC to get latest OpenClaw updates - cron: '0 0 * * *' env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository_owner }}/openclaw-docker jobs: build: runs-on: ubuntu-latest permissions: contents: read packages: write steps: - name: Checkout repository uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=raw,value=latest,enable={{is_default_branch}} type=sha,prefix={{branch}}- type=ref,event=branch type=schedule,pattern={{date 'YYYYMMDD'}} - name: Determine OpenClaw version id: version run: | if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then VERSION="${{ inputs.openclaw_version }}" else VERSION=$(cat .last-openclaw-version) fi echo "openclaw_version=${VERSION}" >> $GITHUB_OUTPUT echo "Building with OpenClaw version: ${VERSION}" - name: Build and push Docker image uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile push: ${{ (github.event_name != 'workflow_dispatch') || inputs.push_image }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} build-args: | OPENCLAW_VERSION=${{ steps.version.outputs.openclaw_version }} cache-from: type=gha cache-to: type=gha,mode=max platforms: linux/amd64,linux/arm64 - name: Generate build summary run: | echo "### 🦞 OpenClaw Docker Build Summary" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**OpenClaw Version:** \`${{ steps.version.outputs.openclaw_version }}\`" >> $GITHUB_STEP_SUMMARY echo "**Image Tags:**" >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Registry:** \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then if [ "${{ inputs.push_image }}" = "true" ]; then echo "✅ Image pushed to registry" >> $GITHUB_STEP_SUMMARY else echo "ℹ️ Image built but not pushed (manual trigger with push disabled)" >> $GITHUB_STEP_SUMMARY fi else echo "✅ Image pushed to registry" >> $GITHUB_STEP_SUMMARY fi ================================================ FILE: .github/workflows/openclaw-release-tracker.yml ================================================ name: OpenClaw Release Tracker on: schedule: # Check for new OpenClaw releases every 6 hours - cron: '0 */6 * * *' workflow_dispatch: jobs: check-release: runs-on: ubuntu-latest permissions: contents: write packages: write actions: write steps: - name: Checkout repository uses: actions/checkout@v4 - name: Check for new OpenClaw release id: check_release run: | # Get the latest release from OpenClaw repository LATEST_RELEASE=$(curl -s https://api.github.com/repos/openclaw/openclaw/releases/latest | jq -r '.tag_name // empty') # Get the latest commit from main branch if no releases if [ -z "$LATEST_RELEASE" ]; then LATEST_COMMIT=$(curl -s https://api.github.com/repos/openclaw/openclaw/commits/main | jq -r '.sha[:7]') LATEST_RELEASE="main-${LATEST_COMMIT}" fi echo "Latest OpenClaw version: ${LATEST_RELEASE}" echo "latest_version=${LATEST_RELEASE}" >> $GITHUB_OUTPUT # Check if we've already built this version if [ -f ".last-openclaw-version" ]; then LAST_VERSION=$(cat .last-openclaw-version) echo "Last built version: ${LAST_VERSION}" if [ "$LATEST_RELEASE" = "$LAST_VERSION" ]; then echo "new_release=false" >> $GITHUB_OUTPUT echo "No new release found" else echo "new_release=true" >> $GITHUB_OUTPUT echo "New release detected!" fi else echo "new_release=true" >> $GITHUB_OUTPUT echo "First run - will build" fi - name: Update version tracker if: steps.check_release.outputs.new_release == 'true' run: | echo "${{ steps.check_release.outputs.latest_version }}" > .last-openclaw-version git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" git add .last-openclaw-version git diff --quiet && git diff --staged --quiet || git commit -m "Update OpenClaw version tracker to ${{ steps.check_release.outputs.latest_version }}" git push - name: Trigger build workflow if: steps.check_release.outputs.new_release == 'true' uses: actions/github-script@v7 with: script: | await github.rest.actions.createWorkflowDispatch({ owner: context.repo.owner, repo: context.repo.repo, workflow_id: 'build-image.yml', ref: 'main', inputs: { openclaw_version: '${{ steps.check_release.outputs.latest_version }}', push_image: 'true' } }); console.log('✅ Triggered build workflow for new OpenClaw release: ${{ steps.check_release.outputs.latest_version }}'); - name: Create summary if: always() run: | echo "### 🦞 OpenClaw Release Check" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Latest OpenClaw Version:** \`${{ steps.check_release.outputs.latest_version }}\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY if [ "${{ steps.check_release.outputs.new_release }}" = "true" ]; then echo "✅ **New release detected!** Build workflow triggered." >> $GITHUB_STEP_SUMMARY else echo "ℹ️ No new release. Docker image is up to date." >> $GITHUB_STEP_SUMMARY fi ================================================ FILE: .gitignore ================================================ # Moltbot Docker Build artifacts and temporary files ================================================ FILE: .last-openclaw-version ================================================ v2026.5.7 ================================================ FILE: Dockerfile ================================================ FROM node:22-bookworm LABEL org.opencontainers.image.source="https://github.com/phioranex/openclaw-docker" LABEL org.opencontainers.image.description="Pre-built OpenClaw (Clawbot) Docker image" LABEL org.opencontainers.image.licenses="MIT" # Install system dependencies (including Homebrew prerequisites) RUN apt-get update && apt-get install -y \ git \ curl \ ca-certificates \ unzip \ build-essential \ procps \ file \ sudo \ jq \ && rm -rf /var/lib/apt/lists/* # Install Bun (required for build) RUN curl -fsSL https://bun.sh/install | bash ENV PATH="/root/.bun/bin:${PATH}" # Install Homebrew (required for first-party skills) # Create linuxbrew user+group and grant sudo access (required for Homebrew package installations) RUN groupadd -f linuxbrew && \ useradd -m -s /bin/bash -g linuxbrew linuxbrew && \ echo 'linuxbrew ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers && \ mkdir -p /home/linuxbrew/.linuxbrew && \ chown -R linuxbrew:linuxbrew /home/linuxbrew/.linuxbrew # Download and install Homebrew manually (shallow clone to reduce image size) # Note: HOMEBREW_NO_AUTO_UPDATE is set below to disable updates RUN mkdir -p /home/linuxbrew/.linuxbrew/Homebrew && \ git clone --depth 1 https://github.com/Homebrew/brew /home/linuxbrew/.linuxbrew/Homebrew && \ mkdir -p /home/linuxbrew/.linuxbrew/bin && \ ln -s /home/linuxbrew/.linuxbrew/Homebrew/bin/brew /home/linuxbrew/.linuxbrew/bin/brew && \ chown -R linuxbrew:linuxbrew /home/linuxbrew/.linuxbrew && \ chmod -R g+rwX /home/linuxbrew/.linuxbrew ENV PATH="/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:${PATH}" ENV HOMEBREW_NO_AUTO_UPDATE=1 ENV HOMEBREW_NO_INSTALL_CLEANUP=1 # Enable corepack for pnpm RUN corepack enable WORKDIR /app # Clone and build OpenClaw - always fetch latest from main branch ARG OPENCLAW_VERSION=main RUN git clone --depth 1 --branch ${OPENCLAW_VERSION} https://github.com/openclaw/openclaw.git . && \ echo "Building OpenClaw from branch: ${OPENCLAW_VERSION}" && \ git rev-parse HEAD > /app/openclaw-commit.txt # Install dependencies RUN pnpm install --frozen-lockfile # Build RUN OPENCLAW_A2UI_SKIP_MISSING=1 pnpm build # Force pnpm for UI build (Bun may fail on ARM/Synology architectures) RUN npm_config_script_shell=bash pnpm ui:install RUN npm_config_script_shell=bash pnpm ui:build # Clean up build artifacts to reduce image size RUN rm -rf .git node_modules/.cache # Create app user (node already exists in base image) # Add node user to linuxbrew group for Homebrew access # Fix permissions for global npm installs RUN mkdir -p /home/node/.openclaw /home/node/.openclaw/workspace \ && chown -R node:node /home/node /app \ && chmod -R 755 /home/node/.openclaw \ && usermod -aG linuxbrew node \ && chmod -R g+w /home/linuxbrew/.linuxbrew \ && chown -R node:node /usr/local/lib/node_modules \ && chown -R node:node /usr/local/bin # Install Playwright system dependencies (as root before switching to node user) RUN npx -y playwright@latest install-deps chromium # Copy SSL certificates to a location accessible by all users RUN mkdir -p /usr/local/share/ca-certificates && \ cp /etc/ssl/certs/ca-certificates.crt /usr/local/share/ca-certificates/ca-certificates.crt && \ chmod 755 /usr/local/share/ca-certificates && \ chmod 644 /usr/local/share/ca-certificates/ca-certificates.crt USER node # Install Playwright browsers for the node user # Use NODE_EXTRA_CA_CERTS to point to accessible certificate bundle RUN NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/ca-certificates.crt npx -y playwright@latest install chromium WORKDIR /home/node ENV NODE_ENV=production ENV PATH="/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/app/node_modules/.bin:${PATH}" ENV HOMEBREW_NO_AUTO_UPDATE=1 ENV HOMEBREW_NO_INSTALL_CLEANUP=1 # Default command ENTRYPOINT ["node", "/app/dist/index.js"] CMD ["--help"] ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2026 Phioranex Pvt Ltd Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --- Note: This repository provides Docker packaging for Moltbot. Moltbot itself is a separate project with its own license. See: https://github.com/moltbot/moltbot ================================================ FILE: README.md ================================================ # OpenClaw (Clawbot) Docker Image Pre-built Docker image for [OpenClaw](https://github.com/openclaw/openclaw) — run your AI assistant in seconds without building from source. > 🔄 **Always Up-to-Date:** This image automatically builds daily and checks for new OpenClaw releases every 6 hours, ensuring you always have the latest version. ## One-Line Install (Recommended) ### Linux / macOS ```bash bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh) ``` ### Windows (PowerShell) ```powershell irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.ps1 | iex ``` > **Note for Windows users:** Make sure Docker Desktop is installed and running. You can also use WSL2 with the Linux installation command. This will: - ✅ Check prerequisites (Docker, Docker Compose) - ✅ Download necessary files - ✅ Pull the pre-built image - ✅ Run the onboarding wizard - ✅ Start the gateway ### Install Options **Linux / macOS:** ### Install Options **Linux / macOS:** ```bash # Just pull the image (no setup) bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh) --pull-only # Skip onboarding (if already configured) bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh) --skip-onboard # Don't start gateway after setup bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh) --no-start # Custom install directory bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh) --install-dir /opt/openclaw ``` **Windows (PowerShell):** ```powershell # Just pull the image (no setup) irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.ps1 | iex -PullOnly # Skip onboarding (if already configured) irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.ps1 | iex -SkipOnboard # Don't start gateway after setup irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.ps1 | iex -NoStart # Custom install directory $env:TEMP_INSTALL_SCRIPT = irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.ps1; Invoke-Expression $env:TEMP_INSTALL_SCRIPT -InstallDir "C:\openclaw" ``` ## Manual Install ### Quick Start ```bash # Pull the image docker pull ghcr.io/phioranex/openclaw-docker:latest # Run onboarding (first time setup) docker run -it --rm \ -v ~/.openclaw:/home/node/.openclaw \ -v ~/.openclaw/workspace:/home/node/.openclaw/workspace \ ghcr.io/phioranex/openclaw-docker:latest onboard # Start the gateway docker run -d \ --name openclaw \ --restart unless-stopped \ -v ~/.openclaw:/home/node/.openclaw \ -v ~/.openclaw/workspace:/home/node/.openclaw/workspace \ -p 18789:18789 \ ghcr.io/phioranex/openclaw-docker:latest gateway start --foreground ``` ### Using Docker Compose ```bash # Clone this repo git clone https://github.com/phioranex/openclaw-docker.git cd openclaw-docker # Run onboarding docker compose run --rm openclaw-cli onboard # Start the gateway docker compose up -d openclaw-gateway ``` ## Configuration During onboarding, you'll configure: - **AI Provider** (Anthropic Claude, OpenAI, etc.) - **Channels** (Telegram, WhatsApp, Discord, etc.) - **Gateway settings** Config is stored in `~/.openclaw/` and persists across container restarts. ## Available Tags | Tag | Description | |-----|-------------| | `latest` | Latest OpenClaw build (updated daily and on new releases) | | `vX.Y.Z` | Specific version (if available) | | `main` | Latest from main branch (cutting edge) | > **Note:** The `latest` tag is automatically rebuilt daily at 00:00 UTC and whenever OpenClaw releases a new version. ## Volumes | Path | Purpose | |------|---------| | `/home/node/.openclaw` | Config and session data | | `/home/node/.openclaw/workspace` | Agent workspace | ## Ports | Port | Purpose | |------|---------| | `18789` | Gateway API + Dashboard | ## Links - [OpenClaw Website](https://openclaw.ai/) - [OpenClaw Docs](https://docs.openclaw.ai) - [OpenClaw GitHub](https://github.com/openclaw/openclaw) - [Discord Community](https://discord.gg/clawd) ## Uninstallation ### One-Line Uninstall **Linux / macOS:** ```bash bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.sh) ``` **Windows (PowerShell):** ```powershell irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.ps1 | iex ``` This will: - ✅ Stop and remove all containers - ✅ Ask before removing configuration and workspace data - ✅ Ask before removing Docker image - ✅ Ask before removing installation directory ### Uninstall Options **Linux / macOS:** ```bash # Keep configuration and workspace data bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.sh) --keep-data # Keep Docker image (useful if reinstalling later) bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.sh) --keep-image # Skip all confirmation prompts bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.sh) --force # Custom install directory bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.sh) --install-dir /opt/openclaw ``` **Windows (PowerShell):** ```powershell # Keep configuration and workspace data & ([scriptblock]::Create((irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.ps1))) -KeepData # Keep Docker image (useful if reinstalling later) & ([scriptblock]::Create((irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.ps1))) -KeepImage # Skip all confirmation prompts & ([scriptblock]::Create((irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.ps1))) -Force # Custom install directory & ([scriptblock]::Create((irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.ps1))) -InstallDir "C:\openclaw" ``` ### Manual Uninstall If you prefer to uninstall manually: ```bash # Stop and remove containers docker stop openclaw-gateway openclaw-socat docker rm openclaw-gateway openclaw-socat openclaw-cli # Remove data (optional) rm -rf ~/.openclaw # Remove Docker image (optional) docker rmi ghcr.io/phioranex/openclaw-docker:latest # Remove installation directory (optional) rm -rf ~/openclaw ``` ## Troubleshooting ### Permission Issues on Synology NAS If you encounter `EACCES: permission denied` errors when running on Synology NAS: 1. **Option 1: Run install script with sudo (Recommended)** ```bash sudo bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh) ``` The script will automatically: - Set proper ownership (UID 1000) for the container user - Configure your user account to access the files - Update docker-compose.yml to use the correct home directory 2. **Option 2: Fix permissions manually** ```bash # RECOMMENDED: Set ownership to UID 1000 with group access (most secure) sudo chown -R 1000:$(id -g) ~/.openclaw sudo chmod -R u+rwX,g+rwX,o-rwx ~/.openclaw # Alternative: Make directory writable by owner and group (less secure) chmod -R 775 ~/.openclaw # LAST RESORT ONLY: World-writable (least secure, use only if above options fail) # chmod -R 777 ~/.openclaw ``` 3. **Option 3: Use host user mapping** Edit `docker-compose.yml` and uncomment the `user: "1000:1000"` line in both services: ```yaml user: "1000:1000" # Uncomment this line ``` ### Telegram Bot Connection Issues If the Telegram bot cannot find your username or numeric ID: 1. Ensure your container has internet access: ```bash docker exec openclaw-gateway ping -c 3 api.telegram.org ``` 2. Check if firewall or network restrictions are blocking Telegram API access 3. Verify your Telegram bot token is correct in `~/.openclaw/openclaw.json` ### Docker Permission Issues (Image Pull) If you need root/sudo to pull Docker images: 1. Add your user to the docker group: ```bash sudo usermod -aG docker $USER ``` 2. Log out and log back in for the changes to take effect 3. Alternatively, use `sudo` when running the install script ### Installing Skills (npm global packages) The container is configured to allow the `node` user to install global npm packages without permission issues. You can install skills using: ```bash # If using docker compose docker compose exec openclaw-gateway npm install -g @package/name # If using standalone container docker exec -it npm install -g @package/name # Find your container name with: docker ps ``` If you're using `user: "1000:1000"` in docker-compose.yml, global npm installs will work without any additional configuration. ## YouTube Tutorial 📺 Watch the installation tutorial: [Coming Soon] ## License This Docker packaging is provided by [Phioranex](https://phioranex.com). OpenClaw itself is licensed under MIT — see the [original repo](https://github.com/openclaw/openclaw). ================================================ FILE: docker-compose.yml ================================================ services: openclaw-gateway: image: ghcr.io/phioranex/openclaw-docker:latest container_name: openclaw-gateway restart: unless-stopped stdin_open: true tty: true # Uncomment the following line if running on Synology NAS or other systems with UID/GID issues # user: "1000:1000" volumes: - ~/.openclaw:/home/node/.openclaw - ~/.openclaw/workspace:/home/node/.openclaw/workspace ports: - "18789:18789" - "18790:18790" environment: - NODE_ENV=production - OPENCLAW_SKIP_SERVICE_CHECK=true command: ["gateway"] socat-proxy: image: alpine/socat container_name: openclaw-socat restart: unless-stopped network_mode: "service:openclaw-gateway" command: "TCP-LISTEN:18790,fork,bind=0.0.0.0,reuseaddr TCP:127.0.0.1:18789" openclaw-cli: image: ghcr.io/phioranex/openclaw-docker:latest container_name: openclaw-cli stdin_open: true tty: true # Uncomment the following line if running on Synology NAS or other systems with UID/GID issues # user: "1000:1000" volumes: - ~/.openclaw:/home/node/.openclaw - ~/.openclaw/workspace:/home/node/.openclaw/workspace environment: - NODE_ENV=production entrypoint: ["node", "/app/dist/index.js"] profiles: - cli ================================================ FILE: install.ps1 ================================================ # # OpenClaw (Clawbot) Docker Installer - Windows PowerShell Version # One-command setup for OpenClaw on Docker for Windows # # Usage: # irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.ps1 | iex # # Or with options: # & ([scriptblock]::Create((irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.ps1))) -NoStart # param( [string]$InstallDir = "$env:USERPROFILE\openclaw", [switch]$NoStart, [switch]$SkipOnboard, [switch]$PullOnly, [switch]$Help ) # Config $Image = "ghcr.io/phioranex/openclaw-docker:latest" $RepoUrl = "https://github.com/phioranex/openclaw-docker" $ComposeUrl = "https://raw.githubusercontent.com/phioranex/openclaw-docker/main/docker-compose.yml" # Error handling $ErrorActionPreference = "Stop" # Functions function Write-Banner { Write-Host "" Write-Host "╔══════════════════════════════════════════════════════════════╗" -ForegroundColor Red Write-Host "║ ║" -ForegroundColor Red Write-Host "║ ____ _____ _ ║" -ForegroundColor Red Write-Host "║ / __ \ / ____| | ║" -ForegroundColor Red Write-Host "║ | | | |_ __ ___ _ __ | | | | __ ___ __ ║" -ForegroundColor Red Write-Host "║ | | | | '_ \ / _ \ '_ \| | | |/ _`` \ \ /\ / / ║" -ForegroundColor Red Write-Host "║ | |__| | |_) | __/ | | | |____| | (_| |\ V V / ║" -ForegroundColor Red Write-Host "║ \____/| .__/ \___|_| |_|\_____|_|\__,_| \_/\_/ ║" -ForegroundColor Red Write-Host "║ | | ║" -ForegroundColor Red Write-Host "║ |_| ║" -ForegroundColor Red Write-Host "║ ║" -ForegroundColor Red Write-Host "║ Docker Installer by Phioranex ║" -ForegroundColor Red Write-Host "║ ║" -ForegroundColor Red Write-Host "╚══════════════════════════════════════════════════════════════╝" -ForegroundColor Red Write-Host "" } function Write-Step { param([string]$Message) Write-Host "" Write-Host "▶ $Message" -ForegroundColor Blue } function Write-Success { param([string]$Message) Write-Host "✓ $Message" -ForegroundColor Green } function Write-Warning { param([string]$Message) Write-Host "⚠ $Message" -ForegroundColor Yellow } function Write-Error { param([string]$Message) Write-Host "✗ $Message" -ForegroundColor Red } function Test-Command { param([string]$Command) try { Get-Command $Command -ErrorAction Stop | Out-Null return $true } catch { return $false } } # Show help if ($Help) { Write-Host "OpenClaw (Clawbot) Docker Installer - Windows" Write-Host "" Write-Host "Usage: install.ps1 [OPTIONS]" Write-Host "" Write-Host "Options:" Write-Host " -InstallDir DIR Installation directory (default: ~\openclaw)" Write-Host " -NoStart Don't start the gateway after setup" Write-Host " -SkipOnboard Skip onboarding wizard" Write-Host " -PullOnly Only pull the image, don't set up" Write-Host " -Help Show this help message" return } # Main script Write-Banner Write-Step "Checking prerequisites..." # Check Docker if (Test-Command docker) { Write-Success "docker found" } else { Write-Error "docker not found" Write-Host "" Write-Host "Docker is required but not installed." -ForegroundColor Red Write-Host "Install Docker Desktop: https://docs.docker.com/desktop/install/windows-install/" -ForegroundColor Yellow return } # Check Docker Compose $ComposeCmd = "" if (docker compose version 2>$null) { Write-Success "Docker Compose found (plugin)" $ComposeCmd = "docker compose" } elseif (Test-Command docker-compose) { Write-Success "Docker Compose found (standalone)" $ComposeCmd = "docker-compose" } else { Write-Error "Docker Compose not found" Write-Host "" Write-Host "Docker Compose is required but not installed." -ForegroundColor Red Write-Host "It usually comes with Docker Desktop." -ForegroundColor Yellow exit 1 } # Check Docker is running try { docker info 2>$null | Out-Null Write-Success "Docker is running" } catch { Write-Error "Docker is not running" Write-Host "" Write-Host "Please start Docker Desktop and try again." -ForegroundColor Red exit 1 } # Pull only mode if ($PullOnly) { Write-Step "Pulling OpenClaw image..." docker pull $Image Write-Success "Image pulled successfully!" Write-Host "" Write-Host "Done! Run the installer again without -PullOnly to complete setup." -ForegroundColor Green exit 0 } Write-Step "Setting up installation directory..." New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null Set-Location $InstallDir Write-Success "Created $InstallDir" Write-Step "Downloading docker-compose.yml..." Invoke-WebRequest -Uri $ComposeUrl -OutFile "docker-compose.yml" Write-Success "Downloaded docker-compose.yml" Write-Step "Creating data directories..." $ConfigDir = "$env:USERPROFILE\.openclaw" $WorkspaceDir = "$env:USERPROFILE\.openclaw\workspace" New-Item -ItemType Directory -Force -Path $ConfigDir | Out-Null New-Item -ItemType Directory -Force -Path $WorkspaceDir | Out-Null Write-Success "Created $ConfigDir (config)" Write-Success "Created $WorkspaceDir (workspace)" Write-Step "Pulling OpenClaw image..." docker pull $Image Write-Success "Image pulled successfully!" # Onboarding if (-not $SkipOnboard) { Write-Step "Initializing OpenClaw configuration..." Write-Host "Setting up configuration and workspace..." -ForegroundColor Yellow Write-Host "" Write-Step "Running onboarding wizard..." Write-Host "This will configure your AI provider and channels." -ForegroundColor Yellow Write-Host "Follow the prompts to complete setup." -ForegroundColor Yellow Write-Host "" # Run onboarding $composeParts = $ComposeCmd -split " ", 2 if ($composeParts.Count -eq 2) { & $composeParts[0] $composeParts[1] run -T --rm openclaw-cli onboard } else { & $composeParts[0] run -T --rm openclaw-cli onboard } if ($LASTEXITCODE -ne 0) { Write-Warning "Onboarding wizard was skipped or failed" Write-Host "You can run it later with: cd $InstallDir && $ComposeCmd run --rm openclaw-cli onboard" -ForegroundColor Yellow } else { Write-Success "Onboarding complete!" } } # Start gateway if (-not $NoStart) { Write-Step "Starting OpenClaw gateway..." $composeParts = $ComposeCmd -split " ", 2 if ($composeParts.Count -eq 2) { & $composeParts[0] $composeParts[1] up -d openclaw-gateway } else { & $composeParts[0] up -d openclaw-gateway } # Wait for gateway to be ready Write-Host "Waiting for gateway to start" -NoNewline for ($i = 0; $i -lt 30; $i++) { try { $response = Invoke-WebRequest -Uri "http://localhost:18789/health" -TimeoutSec 1 -ErrorAction SilentlyContinue if ($response.StatusCode -eq 200) { Write-Host "" Write-Success "Gateway is running!" break } } catch { # Continue waiting } Write-Host "." -NoNewline Start-Sleep -Seconds 1 } try { $response = Invoke-WebRequest -Uri "http://localhost:18789/health" -TimeoutSec 1 -ErrorAction SilentlyContinue if ($response.StatusCode -ne 200) { throw } } catch { Write-Host "" Write-Warning "Gateway may still be starting. Check logs with: docker logs openclaw-gateway" } } # Success message Write-Host "" Write-Host "╔══════════════════════════════════════════════════════════════╗" -ForegroundColor Green Write-Host "║ ║" -ForegroundColor Green Write-Host "║ 🎉 OpenClaw installed successfully! 🎉 ║" -ForegroundColor Green Write-Host "║ ║" -ForegroundColor Green Write-Host "╚══════════════════════════════════════════════════════════════╝" -ForegroundColor Green Write-Host "" Write-Host "Quick reference:" -ForegroundColor White Write-Host " Dashboard: http://localhost:18789" -ForegroundColor Cyan Write-Host " Config: $ConfigDir" -ForegroundColor Cyan Write-Host " Workspace: $WorkspaceDir" -ForegroundColor Cyan Write-Host " Install dir: $InstallDir" -ForegroundColor Cyan Write-Host "" Write-Host "Useful commands:" -ForegroundColor White Write-Host " View logs: docker logs -f openclaw-gateway" -ForegroundColor Cyan Write-Host " Stop: cd $InstallDir && $ComposeCmd down" -ForegroundColor Cyan Write-Host " Start: cd $InstallDir && $ComposeCmd up -d openclaw-gateway" -ForegroundColor Cyan Write-Host " Restart: cd $InstallDir && $ComposeCmd restart openclaw-gateway" -ForegroundColor Cyan Write-Host " CLI: cd $InstallDir && $ComposeCmd run --rm openclaw-cli " -ForegroundColor Cyan Write-Host " Update: docker pull $Image && cd $InstallDir && $ComposeCmd up -d" -ForegroundColor Cyan Write-Host "" Write-Host "Documentation: https://docs.openclaw.ai" -ForegroundColor White Write-Host "Support: https://discord.gg/clawd" -ForegroundColor White Write-Host "Docker image: $RepoUrl" -ForegroundColor White Write-Host "" Write-Host "Happy automating! 🤖🦞" -ForegroundColor Yellow Write-Host "" ================================================ FILE: install.sh ================================================ #!/bin/bash # # OpenClaw (Clawbot) Docker Installer # One-command setup for OpenClaw on Docker # # Usage: # bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh) # # Or with options: # bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh) --no-start # set -e # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' BOLD='\033[1m' NC='\033[0m' # No Color # Config INSTALL_DIR="${OPENCLAW_INSTALL_DIR:-$HOME/openclaw}" IMAGE="ghcr.io/phioranex/openclaw-docker:latest" REPO_URL="https://github.com/phioranex/openclaw-docker" COMPOSE_URL="https://raw.githubusercontent.com/phioranex/openclaw-docker/main/docker-compose.yml" # Detect if we have a TTY (for Docker interactive mode) if [ -t 0 ]; then DOCKER_TTY_FLAG="" else DOCKER_TTY_FLAG="-T" fi # Flags NO_START=false SKIP_ONBOARD=false PULL_ONLY=false # Parse arguments while [[ $# -gt 0 ]]; do case $1 in --no-start) NO_START=true shift ;; --skip-onboard) SKIP_ONBOARD=true shift ;; --pull-only) PULL_ONLY=true shift ;; --install-dir) INSTALL_DIR="$2" shift 2 ;; --help|-h) echo "OpenClaw (Clawbot) Docker Installer" echo "" echo "Usage: install.sh [OPTIONS]" echo "" echo "Options:" echo " --install-dir DIR Installation directory (default: ~/openclaw)" echo " --no-start Don't start the gateway after setup" echo " --skip-onboard Skip onboarding wizard" echo " --pull-only Only pull the image, don't set up" echo " --help, -h Show this help message" exit 0 ;; *) echo -e "${RED}Unknown option: $1${NC}" exit 1 ;; esac done # Functions print_banner() { echo -e "${RED}" echo "╔══════════════════════════════════════════════════════════════╗" echo "║ ║" echo "║ ____ _____ _ ║" echo "║ / __ \\\\ / ____| | ║" echo "║ | | | |_ __ ___ _ __ | | | | __ ___ __ ║" echo "║ | | | | '_ \\\\ / _ \\\\ '_ \\\\| | | |/ _\\\` \\\\ \\\\ /\\\\ / / ║" echo "║ | |__| | |_) | __/ | | | |____| | (_| |\\\\ V V / ║" echo "║ \\\\____/| .__/ \\\\___|_| |_|\\\\_____|_|\\\\__,_| \\\\_/\\\\_/ ║" echo "║ | | ║" echo "║ |_| ║" echo "║ ║" echo "║ Docker Installer by Phioranex ║" echo "║ ║" echo "╚══════════════════════════════════════════════════════════════╝" echo -e "${NC}" } # Get user's home directory, handling sudo correctly get_user_home() { if [ -n "$SUDO_USER" ]; then # Running with sudo - use the actual user's home local user_home user_home=$(getent passwd "$SUDO_USER" | cut -d: -f6) if [ -z "$user_home" ]; then # Fallback to eval if getent fails user_home=$(eval echo ~"$SUDO_USER") fi echo "$user_home" else # Running normally echo "$HOME" fi } log_step() { echo -e "\n${BLUE}▶${NC} ${BOLD}$1${NC}" } log_success() { echo -e "${GREEN}✓${NC} $1" } log_warning() { echo -e "${YELLOW}⚠${NC} $1" } log_error() { echo -e "${RED}✗${NC} $1" } check_command() { if command -v "$1" &> /dev/null; then log_success "$1 found" return 0 else log_error "$1 not found" return 1 fi } # Main script print_banner log_step "Checking prerequisites..." # Check Docker if ! check_command docker; then echo -e "\n${RED}Docker is required but not installed.${NC}" echo "Install Docker: https://docs.docker.com/get-docker/" exit 1 fi # Check Docker Compose if docker compose version &> /dev/null; then log_success "Docker Compose found (plugin)" COMPOSE_CMD="docker compose" elif command -v docker-compose &> /dev/null; then log_success "Docker Compose found (standalone)" COMPOSE_CMD="docker-compose" else log_error "Docker Compose not found" echo -e "\n${RED}Docker Compose is required but not installed.${NC}" echo "Install Docker Compose: https://docs.docker.com/compose/install/" exit 1 fi # Check Docker is running and capture output for better error reporting DOCKER_INFO_OUTPUT=$(docker info 2>&1) DOCKER_INFO_EXIT=$? if [ $DOCKER_INFO_EXIT -ne 0 ]; then log_error "Docker is not running or you don't have permission to access it" # Check if it's a permission issue if [ "$(id -u)" -ne 0 ] && echo "$DOCKER_INFO_OUTPUT" | grep -qi "permission denied"; then echo -e "\n${YELLOW}Tip: You may need to run this script with sudo or add your user to the docker group:${NC}" echo -e " ${CYAN}sudo usermod -aG docker \$USER${NC}" echo -e " ${CYAN}(then log out and log back in)${NC}" echo -e "\n${YELLOW}Or run the installer with sudo:${NC}" echo -e " ${CYAN}sudo bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh)${NC}" else echo -e "\n${RED}Please start Docker and try again.${NC}" fi exit 1 fi log_success "Docker is running" # Pull only mode if [ "$PULL_ONLY" = true ]; then log_step "Pulling OpenClaw image..." docker pull "$IMAGE" log_success "Image pulled successfully!" echo -e "\n${GREEN}Done!${NC} Run the installer again without --pull-only to complete setup." exit 0 fi log_step "Setting up installation directory..." mkdir -p "$INSTALL_DIR" cd "$INSTALL_DIR" log_success "Created $INSTALL_DIR" log_step "Downloading docker-compose.yml..." curl -fsSL "$COMPOSE_URL" -o docker-compose.yml # Update docker-compose.yml to use correct home directory when running with sudo if [ -n "$SUDO_USER" ]; then USER_HOME=$(get_user_home) # Replace ~/.openclaw with the actual user's home directory if grep -q "~/.openclaw" docker-compose.yml; then if sed -i.bak "s|~/.openclaw|$USER_HOME/.openclaw|g" docker-compose.yml; then rm -f docker-compose.yml.bak # Verify the replacement actually occurred if ! grep -q "~/.openclaw" docker-compose.yml; then log_success "Updated docker-compose.yml for sudo user ($SUDO_USER)" else log_warning "sed replacement may have failed, check docker-compose.yml manually" fi else log_warning "Failed to update docker-compose.yml paths" fi else log_warning "docker-compose.yml doesn't contain '~/.openclaw', skipping path update" fi fi log_success "Downloaded docker-compose.yml" log_step "Creating data directories..." # Determine the correct home directory USER_HOME=$(get_user_home) OPENCLAW_DIR="$USER_HOME/.openclaw" mkdir -p "$OPENCLAW_DIR" mkdir -p "$OPENCLAW_DIR/workspace" # Fix permissions for container access # Docker container runs as node user (UID 1000, GID 1000) # Ensure the directory is writable by the container user if [ "$(id -u)" -eq 0 ]; then # Running as root/sudo - set ownership to UID 1000 (node user in container) # and grant group access to the actual user (if using sudo) if [ -n "$SUDO_USER" ]; then # Get the sudo user's primary group SUDO_GID=$(id -g "$SUDO_USER") # Set ownership: UID 1000 (container), GID to sudo user's group chown -R 1000:"$SUDO_GID" "$OPENCLAW_DIR" # Allow group read/write access chmod -R u+rwX,g+rwX,o-rwx "$OPENCLAW_DIR" log_success "Set ownership to UID 1000 with group access for $SUDO_USER" else # Running as actual root user, not via sudo chown -R 1000:1000 "$OPENCLAW_DIR" chmod -R 755 "$OPENCLAW_DIR" log_success "Set ownership to UID 1000 (container user)" fi else # Running as non-root user # Try 775 first (safer than 777) if chmod -R 775 "$OPENCLAW_DIR" 2>/dev/null; then ACTUAL_PERMS="775" log_warning "Running as non-root user, set permissions to 775" else # Fallback to 777 if 775 fails (e.g., not the owner) chmod -R 777 "$OPENCLAW_DIR" ACTUAL_PERMS="777" log_warning "Could not set 775 permissions (not owner?), using 777 instead" fi log_warning "For better security on Synology/NAS, consider running with sudo" fi log_success "Created $OPENCLAW_DIR (config)" log_success "Created $OPENCLAW_DIR/workspace (workspace)" log_step "Pulling OpenClaw image..." docker pull "$IMAGE" log_success "Image pulled successfully!" # Onboarding if [ "$SKIP_ONBOARD" = false ]; then log_step "Initializing OpenClaw configuration..." echo -e "${YELLOW}Setting up configuration and workspace...${NC}\n" log_step "Running onboarding wizard..." echo -e "${YELLOW}This will configure your AI provider and channels.${NC}" echo -e "${YELLOW}Follow the prompts to complete setup.${NC}\n" # Run onboarding interactively (works with bash process substitution) if ! $COMPOSE_CMD run --rm openclaw-cli onboard; then log_warning "Onboarding was cancelled or failed" echo -e "${YELLOW}You can run it later with:${NC} cd $INSTALL_DIR && $COMPOSE_CMD run --rm openclaw-cli onboard" else log_success "Onboarding complete!" fi fi # Start gateway if [ "$NO_START" = false ]; then log_step "Starting OpenClaw gateway..." $COMPOSE_CMD up -d openclaw-gateway # Wait for gateway to be ready echo -n "Waiting for gateway to start" for i in {1..30}; do if curl -s http://localhost:18789/health &> /dev/null; then echo "" log_success "Gateway is running!" break fi echo -n "." sleep 1 done if ! curl -s http://localhost:18789/health &> /dev/null; then echo "" log_warning "Gateway may still be starting. Check logs with: docker logs openclaw-gateway" fi fi # Success message echo -e "\n${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}" echo -e "${GREEN}║ ║${NC}" echo -e "${GREEN}║ 🎉 OpenClaw installed successfully! 🎉 ║${NC}" echo -e "${GREEN}║ ║${NC}" echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}" echo -e "\n${BOLD}Quick reference:${NC}" echo -e " ${CYAN}Dashboard:${NC} http://localhost:18790/?token=YOUR_TOKEN" echo -e " ${CYAN}GET TOKEN:${NC} http://localhost:18790/?token=YOUR_TOKEN" echo -e " ${CYAN}Config:${NC} ~/.openclaw/" echo -e " ${CYAN}Workspace:${NC} cat ~/.openclaw/openclaw.json| grep '"token":' | grep -v '"mode"' | cut -d '\"' -f4" echo -e " ${CYAN}Install dir:${NC} $INSTALL_DIR" echo -e "\n${BOLD}Useful commands:${NC}" echo -e " ${CYAN}View logs:${NC} docker logs -f openclaw-gateway" echo -e " ${CYAN}Stop:${NC} cd $INSTALL_DIR && $COMPOSE_CMD down" echo -e " ${CYAN}Start:${NC} cd $INSTALL_DIR && $COMPOSE_CMD up -d openclaw-gateway" echo -e " ${CYAN}Restart:${NC} cd $INSTALL_DIR && $COMPOSE_CMD restart openclaw-gateway" echo -e " ${CYAN}CLI:${NC} cd $INSTALL_DIR && $COMPOSE_CMD run --rm openclaw-cli " echo -e " ${CYAN}Update:${NC} docker pull $IMAGE && cd $INSTALL_DIR && $COMPOSE_CMD up -d" echo -e "\n${BOLD}Documentation:${NC} https://docs.openclaw.ai" echo -e "${BOLD}Support:${NC} https://discord.gg/clawd" echo -e "${BOLD}Docker image:${NC} $REPO_URL" echo -e "\n${YELLOW}Happy automating! 🤖🦞${NC}\n" ================================================ FILE: uninstall.ps1 ================================================ # # OpenClaw (Clawbot) Docker Uninstaller - Windows PowerShell Version # Removes OpenClaw installation from your system # # Usage: # irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.ps1 | iex # # Or with options: # & ([scriptblock]::Create((irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.ps1))) -KeepData # param( [string]$InstallDir = "$env:USERPROFILE\openclaw", [switch]$KeepData, [switch]$KeepImage, [switch]$Force, [switch]$Help ) # Config $Image = "ghcr.io/phioranex/openclaw-docker:latest" # Error handling $ErrorActionPreference = "Stop" # Functions function Write-Banner { Write-Host "" Write-Host "╔══════════════════════════════════════════════════════════════╗" -ForegroundColor Red Write-Host "║ ║" -ForegroundColor Red Write-Host "║ ____ _____ _ ║" -ForegroundColor Red Write-Host "║ / __ \ / ____| | ║" -ForegroundColor Red Write-Host "║ | | | |_ __ ___ _ __ | | | | __ ___ __ ║" -ForegroundColor Red Write-Host "║ | | | | '_ \ / _ \ '_ \| | | |/ _`` \ \ /\ / / ║" -ForegroundColor Red Write-Host "║ | |__| | |_) | __/ | | | |____| | (_| |\ V V / ║" -ForegroundColor Red Write-Host "║ \____/| .__/ \___|_| |_|\_____|_|\__,_| \_/\_/ ║" -ForegroundColor Red Write-Host "║ | | ║" -ForegroundColor Red Write-Host "║ |_| ║" -ForegroundColor Red Write-Host "║ ║" -ForegroundColor Red Write-Host "║ Docker Uninstaller by Phioranex ║" -ForegroundColor Red Write-Host "║ ║" -ForegroundColor Red Write-Host "╚══════════════════════════════════════════════════════════════╝" -ForegroundColor Red Write-Host "" } function Write-Step { param([string]$Message) Write-Host "" Write-Host "▶ $Message" -ForegroundColor Blue } function Write-Success { param([string]$Message) Write-Host "✓ $Message" -ForegroundColor Green } function Write-Warning { param([string]$Message) Write-Host "⚠ $Message" -ForegroundColor Yellow } function Write-ErrorMessage { param([string]$Message) Write-Host "✗ $Message" -ForegroundColor Red } function Confirm-Action { param( [string]$Prompt, [string]$Default = "n" ) if ($Force) { return $true } if ($Default -eq "y") { $PromptText = "$Prompt [Y/n] " } else { $PromptText = "$Prompt [y/N] " } while ($true) { Write-Host $PromptText -ForegroundColor Yellow -NoNewline $response = Read-Host if ([string]::IsNullOrEmpty($response)) { $response = $Default } switch -Regex ($response) { '^[Yy]' { return $true } '^[Nn]' { return $false } default { Write-Host "Please answer yes or no." } } } } # Show help if ($Help) { Write-Host "OpenClaw (Clawbot) Docker Uninstaller - Windows" Write-Host "" Write-Host "Usage: uninstall.ps1 [OPTIONS]" Write-Host "" Write-Host "Options:" Write-Host " -InstallDir DIR Installation directory (default: ~\openclaw)" Write-Host " -KeepData Keep configuration and workspace data" Write-Host " -KeepImage Keep Docker image" Write-Host " -Force Skip confirmation prompts" Write-Host " -Help Show this help message" return } # Main script Write-Banner Write-Host "This will uninstall OpenClaw from your system." -ForegroundColor Yellow Write-Host "" # Stop and remove containers Write-Step "Stopping and removing containers..." $ContainersRemoved = $false try { $containers = docker ps -a --format "{{.Names}}" 2>$null if ($containers -match "openclaw-gateway") { docker stop openclaw-gateway 2>$null | Out-Null docker rm openclaw-gateway 2>$null | Out-Null Write-Success "Removed openclaw-gateway container" $ContainersRemoved = $true } if ($containers -match "openclaw-socat") { docker stop openclaw-socat 2>$null | Out-Null docker rm openclaw-socat 2>$null | Out-Null Write-Success "Removed openclaw-socat container" $ContainersRemoved = $true } if ($containers -match "openclaw-cli") { docker rm openclaw-cli 2>$null | Out-Null Write-Success "Removed openclaw-cli container" $ContainersRemoved = $true } } catch { # Ignore errors } if (-not $ContainersRemoved) { Write-Warning "No OpenClaw containers found" } # Remove data directories $ConfigDir = "$env:USERPROFILE\.openclaw" if (-not $KeepData -and (Test-Path $ConfigDir)) { Write-Step "Data directories found at $ConfigDir" if (Confirm-Action "Remove configuration and workspace data? (This cannot be undone)") { Remove-Item -Path $ConfigDir -Recurse -Force -ErrorAction SilentlyContinue Write-Success "Removed data directory: $ConfigDir" } else { Write-Warning "Keeping data directory: $ConfigDir" } } elseif ($KeepData -and (Test-Path $ConfigDir)) { Write-Warning "Keeping data directory: $ConfigDir" } elseif (-not (Test-Path $ConfigDir)) { Write-Warning "No data directory found at $ConfigDir" } # Remove Docker image if (-not $KeepImage) { try { $images = docker images --format "{{.Repository}}:{{.Tag}}" 2>$null if ($images -match [regex]::Escape($Image)) { Write-Step "Docker image found: $Image" if (Confirm-Action "Remove Docker image? (You can re-download it later)") { try { docker rmi $Image 2>$null | Out-Null Write-Success "Removed Docker image" } catch { Write-Warning "Could not remove image (may be in use)" } } else { Write-Warning "Keeping Docker image: $Image" } } else { Write-Warning "No Docker image found: $Image" } } catch { Write-Warning "Could not check for Docker image" } } else { Write-Warning "Keeping Docker image: $Image" } # Remove installation directory if (Test-Path $InstallDir) { Write-Step "Installation directory found at $InstallDir" if (Confirm-Action "Remove installation directory?") { Remove-Item -Path $InstallDir -Recurse -Force -ErrorAction SilentlyContinue Write-Success "Removed installation directory: $InstallDir" } else { Write-Warning "Keeping installation directory: $InstallDir" } } else { Write-Warning "No installation directory found at $InstallDir" } # Success message Write-Host "" Write-Host "╔══════════════════════════════════════════════════════════════╗" -ForegroundColor Green Write-Host "║ ║" -ForegroundColor Green Write-Host "║ OpenClaw has been uninstalled successfully! 👋 ║" -ForegroundColor Green Write-Host "║ ║" -ForegroundColor Green Write-Host "╚══════════════════════════════════════════════════════════════╝" -ForegroundColor Green if ($KeepData -or (Test-Path $ConfigDir)) { Write-Host "" Write-Host "Data preserved:" -ForegroundColor White Write-Host " Config: $ConfigDir" -ForegroundColor Cyan Write-Host " Workspace: $ConfigDir\workspace" -ForegroundColor Cyan } Write-Host "" Write-Host "To reinstall OpenClaw:" -ForegroundColor White Write-Host " irm https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.ps1 | iex" -ForegroundColor Cyan Write-Host "" Write-Host "Thank you for using OpenClaw! 🦞" -ForegroundColor Yellow Write-Host "" ================================================ FILE: uninstall.sh ================================================ #!/bin/bash # # OpenClaw (Clawbot) Docker Uninstaller # Removes OpenClaw installation from your system # # Usage: # bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.sh) # # Or with options: # bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/uninstall.sh) --keep-data # set -e # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' BOLD='\033[1m' NC='\033[0m' # No Color # Config INSTALL_DIR="${OPENCLAW_INSTALL_DIR:-$HOME/openclaw}" IMAGE="ghcr.io/phioranex/openclaw-docker:latest" # Flags KEEP_DATA=false KEEP_IMAGE=false FORCE=false # Parse arguments while [[ $# -gt 0 ]]; do case $1 in --keep-data) KEEP_DATA=true shift ;; --keep-image) KEEP_IMAGE=true shift ;; --force|-f) FORCE=true shift ;; --install-dir) INSTALL_DIR="$2" shift 2 ;; --help|-h) echo "OpenClaw (Clawbot) Docker Uninstaller" echo "" echo "Usage: uninstall.sh [OPTIONS]" echo "" echo "Options:" echo " --install-dir DIR Installation directory (default: ~/openclaw)" echo " --keep-data Keep configuration and workspace data" echo " --keep-image Keep Docker image" echo " --force, -f Skip confirmation prompts" echo " --help, -h Show this help message" exit 0 ;; *) echo -e "${RED}Unknown option: $1${NC}" exit 1 ;; esac done # Functions print_banner() { echo -e "${RED}" echo "╔══════════════════════════════════════════════════════════════╗" echo "║ ║" echo "║ ____ _____ _ ║" echo "║ / __ \\\\ / ____| | ║" echo "║ | | | |_ __ ___ _ __ | | | | __ ___ __ ║" echo "║ | | | | '_ \\\\ / _ \\\\ '_ \\\\| | | |/ _\\\` \\\\ \\\\ /\\\\ / / ║" echo "║ | |__| | |_) | __/ | | | |____| | (_| |\\\\ V V / ║" echo "║ \\\\____/| .__/ \\\\___|_| |_|\\\\_____|_|\\\\__,_| \\\\_/\\\\_/ ║" echo "║ | | ║" echo "║ |_| ║" echo "║ ║" echo "║ Docker Uninstaller by Phioranex ║" echo "║ ║" echo "╚══════════════════════════════════════════════════════════════╝" echo -e "${NC}" } # Get user's home directory, handling sudo correctly get_user_home() { if [ -n "$SUDO_USER" ]; then # Running with sudo - use the actual user's home local user_home user_home=$(getent passwd "$SUDO_USER" | cut -d: -f6) if [ -z "$user_home" ]; then # Fallback to eval if getent fails user_home=$(eval echo ~"$SUDO_USER") fi echo "$user_home" else # Running normally echo "$HOME" fi } log_step() { echo -e "\n${BLUE}▶${NC} ${BOLD}$1${NC}" } log_success() { echo -e "${GREEN}✓${NC} $1" } log_warning() { echo -e "${YELLOW}⚠${NC} $1" } log_error() { echo -e "${RED}✗${NC} $1" } confirm() { if [ "$FORCE" = true ]; then return 0 fi local prompt="$1" local default="${2:-n}" if [ "$default" = "y" ]; then prompt="$prompt [Y/n] " else prompt="$prompt [y/N] " fi while true; do read -p "$(echo -e "${YELLOW}$prompt${NC}")" -r response response=${response:-$default} case "$response" in [Yy]* ) return 0;; [Nn]* ) return 1;; * ) echo "Please answer yes or no.";; esac done } # Main script print_banner echo -e "${YELLOW}This will uninstall OpenClaw from your system.${NC}" echo "" # Stop and remove containers log_step "Stopping and removing containers..." CONTAINERS_REMOVED=false if docker ps -a --format '{{.Names}}' | grep -q "openclaw-gateway"; then docker stop openclaw-gateway 2>/dev/null || true docker rm openclaw-gateway 2>/dev/null || true log_success "Removed openclaw-gateway container" CONTAINERS_REMOVED=true fi if docker ps -a --format '{{.Names}}' | grep -q "openclaw-socat"; then docker stop openclaw-socat 2>/dev/null || true docker rm openclaw-socat 2>/dev/null || true log_success "Removed openclaw-socat container" CONTAINERS_REMOVED=true fi if docker ps -a --format '{{.Names}}' | grep -q "openclaw-cli"; then docker rm openclaw-cli 2>/dev/null || true log_success "Removed openclaw-cli container" CONTAINERS_REMOVED=true fi if [ "$CONTAINERS_REMOVED" = false ]; then log_warning "No OpenClaw containers found" fi # Remove data directories USER_HOME=$(get_user_home) OPENCLAW_DIR="$USER_HOME/.openclaw" if [ "$KEEP_DATA" = false ] && [ -d "$OPENCLAW_DIR" ]; then log_step "Data directories found at $OPENCLAW_DIR" if confirm "Remove configuration and workspace data? (This cannot be undone)"; then rm -rf "$OPENCLAW_DIR" log_success "Removed data directory: $OPENCLAW_DIR" else log_warning "Keeping data directory: $OPENCLAW_DIR" fi elif [ "$KEEP_DATA" = true ] && [ -d "$OPENCLAW_DIR" ]; then log_warning "Keeping data directory: $OPENCLAW_DIR" elif [ ! -d "$OPENCLAW_DIR" ]; then log_warning "No data directory found at $OPENCLAW_DIR" fi # Remove Docker image if [ "$KEEP_IMAGE" = false ]; then if docker images --format '{{.Repository}}:{{.Tag}}' | grep -q "$IMAGE"; then log_step "Docker image found: $IMAGE" if confirm "Remove Docker image? (You can re-download it later)"; then docker rmi "$IMAGE" 2>/dev/null || log_warning "Could not remove image (may be in use)" log_success "Removed Docker image" else log_warning "Keeping Docker image: $IMAGE" fi else log_warning "No Docker image found: $IMAGE" fi else log_warning "Keeping Docker image: $IMAGE" fi # Remove installation directory if [ -d "$INSTALL_DIR" ]; then log_step "Installation directory found at $INSTALL_DIR" if confirm "Remove installation directory?"; then rm -rf "$INSTALL_DIR" log_success "Removed installation directory: $INSTALL_DIR" else log_warning "Keeping installation directory: $INSTALL_DIR" fi else log_warning "No installation directory found at $INSTALL_DIR" fi # Success message echo -e "\n${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}" echo -e "${GREEN}║ ║${NC}" echo -e "${GREEN}║ OpenClaw has been uninstalled successfully! 👋 ║${NC}" echo -e "${GREEN}║ ║${NC}" echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}" if [ "$KEEP_DATA" = true ] || [ -d "$OPENCLAW_DIR" ]; then echo -e "\n${BOLD}Data preserved:${NC}" echo -e " ${CYAN}Config:${NC} $OPENCLAW_DIR" echo -e " ${CYAN}Workspace:${NC} $OPENCLAW_DIR/workspace" fi echo -e "\n${BOLD}To reinstall OpenClaw:${NC}" echo -e " ${CYAN}bash <(curl -fsSL https://raw.githubusercontent.com/phioranex/openclaw-docker/main/install.sh)${NC}" echo -e "\n${YELLOW}Thank you for using OpenClaw! 🦞${NC}\n"