diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000..ede7ebc --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,110 @@ +name: Build and Push Docker Image + +on: + push: + branches: [ main ] + paths: + - 'docker/**' + + pull_request: + branches: [ main ] + paths: + - 'docker/**' + + release: + types: [ published ] + workflow_dispatch: + inputs: + manual_push: + description: 'Set to "yes" to push tag :test image to GHCR for testing before merging to main' + required: false + default: 'no' + type: choice + options: + - 'no' + - 'yes' + +jobs: + + build-test: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Build Docker image + run: | + DOCKER_URI=openclaw-webtop docker build -f ./docker/Dockerfile -t openclaw-webtop:test ./docker + + - name: Test Docker image + run: | + docker run --rm openclaw-webtop:test > /tmp/test.log & + sleep 60 + + # if grep -q "Data WebSocket Server listening on port 8082" /tmp/test.log; then + # echo "Build successful" + # else + # echo "Build failed!" + # exit 1 + # fi + + push-to-ghcr: + runs-on: ubuntu-latest + # Run if on main branch, or if manual_push is yes from workflow_dispatch + if: >- + (github.ref == 'refs/heads/main') || + (github.event_name == 'workflow_dispatch' && github.event.inputs.manual_push == 'yes') + needs: build-test + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + # 👆 This is needed ARM emulation on AMD64 runner + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + # 👆 This is need for QEMU to work + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set lowercase repository name + run: | + echo "LOWERCASE_REPO=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV + + - name: Set IMAGE_TAG for build-test + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ github.event.inputs.manual_push }}" = "yes" ]; then + echo "IMAGE_TAG=test" >> $GITHUB_ENV + elif [ "${{ github.ref }}" = "refs/heads/main" ]; then + echo "IMAGE_TAG=latest" >> $GITHUB_ENV + fi + + - name: Extract metadata for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ env.LOWERCASE_REPO }} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: ./docker + platforms: linux/amd64,linux/arm64 + file: ./docker/Dockerfile + push: true + tags: | + ghcr.io/${{ env.LOWERCASE_REPO }}:${{ env.IMAGE_TAG }} + ghcr.io/${{ env.LOWERCASE_REPO }}:${{ github.sha }} + labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4b01339 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +**/*.tar.gz \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..883fcae --- /dev/null +++ b/Makefile @@ -0,0 +1,69 @@ +DOCKER_NAME=openclaw-webtop +DOCKER_IMAGE_NAME=openclaw-webtop +VOLUME_NAME=openclaw-webtop-config +BACKUP_FILE=openclaw_config_backup.tar.gz +BACKUP_DIR=./backup + +.PHONY: backup restore clean + +colima-start: + colima start --profile openclaw-webtop --cpu 6 --memory 8 --disk 100 + +colima-stop: + colima stop --profile openclaw-webtop + +colima-delete: + colima delete -f --data --profile openclaw-webtop + +start-locally-baked: + DOCKER_URI=openclaw-webtop:latest \ + PUID=$(shell id -u) \ + PGID=$(shell id -g) \ + docker compose up -d + docker compose logs -f + +start: + PUID=$(shell id -u) \ + PGID=$(shell id -g) \ + docker compose up -d + # while ! curl -s --head http://localhost:18789 | head -n 1 | grep -q "200 OK"; do echo; sleep 5; done; + docker compose logs -f + +stop: + docker compose down + +docker-image-clean: + # docker rm -f $$(docker ps -qa) + docker rm -f $(DOCKER_NAME) + +docker-vol-clean: + docker volume rm -f $(VOLUME_NAME) + +backup: + mkdir -p $(BACKUP_DIR) + @echo "Backing up volume: $(VOLUME_NAME) to $(BACKUP_DIR)/$(BACKUP_FILE)" + docker compose down + @mkdir -p $(BACKUP_DIR) + docker run --rm \ + -v $(VOLUME_NAME):/volume \ + -v $(shell pwd)/$(BACKUP_DIR):/backup \ + alpine \ + tar czf /backup/$(BACKUP_FILE) -C /volume . + + @echo "Backup complete! Size of file: $$(du -h backup/$(BACKUP_FILE) | awk '{print $$1}')" + docker compose up -d + +restore: + @test -f "$(BACKUP_DIR)/$(BACKUP_FILE)" || (echo "Error: $(BACKUP_DIR)/$(BACKUP_FILE) does not exist" && exit 1) + @echo "Restoring volume: $(VOLUME_NAME) from $(BACKUP_DIR)/$(BACKUP_FILE)" + docker compose down + docker run --rm \ + -v $(VOLUME_NAME):/volume \ + -v $(shell pwd)/$(BACKUP_DIR):/backup \ + alpine \ + sh -c "cd /volume && rm -rf * && tar xzf /backup/$(BACKUP_FILE)" + @echo "Restore complete!" + docker compose up -d + +docker-build: + docker build -t $(DOCKER_IMAGE_NAME) -f ./docker/Dockerfile ./docker \ No newline at end of file diff --git a/README.md b/README.md index 747e503..e2b3bfd 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,51 @@ -# openclaw-webtop -Try OpenClaw for free and securely +# 🦞 OpenClaw — Web Top +Try OpenClaw securely using your own computer OR Github's CodeSpace + +
+
+
+ Brew your lobster securely without breaking your bank +
+ ++[](https://github.com/gitricko/openclaw-webtop/actions/workflows/docker-publish.yml) +[](LICENSE) +[](https://github.com/gitricko/openclaw-webtop/issues) +
+ +**OpenClaw-WebTop** runs OpenClaw securely with a need for a dedicate computer. When you are read, you can move to your own machine docker environment if you would like. + + +## Quick start (TL;DR) + +1. Open this repository in a GitHub Codespace +2. In the Codespace terminal run: + +```bash +make start +``` + +3. Wait for the OpenClaw WebTop docker to boot. When the web desktop URL appears in the Codespace `Ports` Tab, click it to open the browser desktop. + +### Will be full automated + +4. In the webtop, open a terminal and run `ollama serve` +5. Open another terminal and run `ollama signin` +6. Sign in or sign up for a ollama free account.. and you get some cloud LLM token for free (reset every day and week) +7. Download a cloud ollama model via `ollama pull kimi-k2.5:cloud` +8 Open another terminal and run `ollama launch openclaw --model kimi-k2.5:cloud` +9. Follow the instructions till completion +10. In the webtop, open a chromium browser and check if you can access this URI: http://localhost:127.0.0.1 +11. If it does not work: run `openclaw gateway run` +12. When the URL is working, run `openclaw dashboard` it will give you to URI with a token at the end. + + + +## Star History + +[](https://www.star-history.com/#gitricko/openclaw-webtop&type=date&legend=top-left) diff --git a/backup/.folderignore b/backup/.folderignore new file mode 100644 index 0000000..e69de29 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..11f1392 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,51 @@ + +name: openclaw-webtop +services: + openclaw-webtop: + # Uses the specific Ubuntu-based MATE tag from LinuxServer.io + image: ${DOCKER_URI:-ghcr.io/gitricko/openclaw-webtop:latest} + container_name: openclaw-webtop + + # Optional: Needed for some modern GUI apps to function properly on older hosts/kernels + # security_opt: + # - seccomp:unconfined + + environment: + # Set your User ID and Group ID to match the host user (run 'id $USER' in your terminal) + - PUID=${DOCKER_PUID:-501} + - PGID=${DOCKER_PGID:-20} + # Set your timezone + - TZ=America/New_York + - SUBFOLDER=/ # Optional: for reverse proxies + + volumes: + # Change /path/to/data to the directory on your host for persistent config/files + - openclaw-webtop-config:/config + - .:/codespace + # Uncomment the next line if you want to run Docker inside Webtop + - /var/run/docker.sock:/var/run/docker.sock + + ports: + # Access the Webtop GUI on port 3000 (http) + - 3000:3000 + # Optional: Access the Webtop GUI on port 3001 (https) + - 3001:3001 + # OpenClaw specific ports (adjust as needed) + - 18789:18789 + # Recommended to prevent modern web browsers from crashing + shm_size: "1gb" + + # Ensures the container restarts automatically unless you explicitly stop it + restart: unless-stopped + + networks: + - openclaw-webtop-net + +networks: + openclaw-webtop-net: + driver: bridge + +volumes: + openclaw-webtop-config: + external: false + name: openclaw-webtop-config diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..47cc24a --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,31 @@ +ARG OPENCLAW_VERSION=2026.3.13 +ARG OLLAMA_VERSION=0.18.2 +ARG NODE_VERSION=22 + +# Use the official Ollama image to get the binary +FROM ollama/ollama:${OLLAMA_VERSION} AS ollama-bin + +# Get the binaries from official Node image +FROM node:${NODE_VERSION}-slim AS node-bin + +# Use your preferred Webtop flavor as the base (e.g., Ubuntu, Alpine) +FROM lscr.io/linuxserver/webtop:ubuntu-mate + +# Copy Node.js binaries and libraries +COPY --from=node-bin /usr/local/bin/node /usr/local/bin/ +COPY --from=node-bin /usr/local/lib/node_modules /usr/local/lib/node_modules +RUN chmod +rw /usr/local/lib/node_modules -R +RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm + +# Copy the Ollama binary from the official image +COPY --from=ollama-bin /usr/bin/ollama /usr/local/bin/ollama + +# (Optional) If you want Ollama to start automatically when the desktop loads, +# you can add a custom init script to /custom-cont-init.d/ +# RUN echo 'ollama serve &' > /custom-cont-init.d/start-ollama.sh && \ +# chmod +x /custom-cont-init.d/start-ollama.sh + +RUN npm install -g openclaw@${OPENCLAW_VERSION} + +EXPOSE 11434 + diff --git a/docs/openclaw-webtop-title-logo.png b/docs/openclaw-webtop-title-logo.png new file mode 100644 index 0000000..f01b1c3 Binary files /dev/null and b/docs/openclaw-webtop-title-logo.png differ