# Deploying wigolo using Docker for Self-Hosting: Complete Setup Guide

> Self-host wigolo easily with Docker. Follow our complete setup guide to deploy wigolo using Docker Compose, ensuring secure API tokens and persistent data for your application.

- Repository: [Towhid Khan/wigolo](https://github.com/KnockOutEZ/wigolo)
- Tags: how-to-guide
- Published: 2026-07-29

---

**Deploy wigolo by pulling the official image `ghcr.io/knockoutez/wigolo`, mounting a persistent volume at `/data`, setting a secure `WIGOLO_API_TOKEN`, and running the container with the `serve` command bound to `0.0.0.0:3333` using the Docker Compose configuration in [`packaging/compose.serve.yml`](https://github.com/KnockOutEZ/wigolo/blob/main/packaging/compose.serve.yml).**

wigolo is an open-source Node.js daemon that powers AI agents through both MCP (stdio) and HTTP REST interfaces. According to the KnockOutEZ/wigolo repository source code, the project provides a multi-stage Dockerfile with `default` (slim) and `full` targets, enabling flexible self-hosting strategies from ephemeral containers to persistent production daemons.

## Choose Your Deployment Mode

The repository supports three distinct Docker deployment patterns based on your infrastructure requirements:

- **One-off stdio client**: Use `docker run -i --rm` for quick, stateless tasks where the container exits after completion. The Chromium browser and models download on first use into the mounted volume.
- **Persistent HTTP daemon**: Run via Docker Compose for long-running services that expose REST endpoints to multiple clients. This mode binds to `0.0.0.0` inside the container and includes health checks defined in [`packaging/compose.serve.yml`](https://github.com/KnockOutEZ/wigolo/blob/main/packaging/compose.serve.yml).
- **Full image (pre-installed browser)**: Build with `--target full` to embed the Chromium binary directly in the image, eliminating volume dependencies for `--rm` scenarios or read-only filesystems.

## Pull the Docker Image

Start by fetching the latest slim image from the GitHub Container Registry:

```bash
docker pull ghcr.io/knockoutez/wigolo

```

This pulls the **default (slim)** target. The image remains lightweight because the browser binary and on-device models are cached on first use rather than baked into the layers, as specified in the root `Dockerfile`.

## Configure Data Persistence

Create a named Docker volume to persist data across container restarts:

```bash
docker volume create wigolo-data

```

The `Dockerfile` declares `VOLUME ["/data"]`, mounting this directory inside the container. This location stores the Chromium binary, on-device models, encrypted keys, and cache files, ensuring they survive image updates and container recreation.

## Set Up Authentication

The wigolo daemon implements a fail-closed security model: it refuses to bind to non-loopback interfaces unless authentication is configured. Generate a secure random token:

```bash
export WIGOLO_API_TOKEN=$(openssl rand -hex 32)

```

For production deployments, avoid passing tokens via environment variables directly. Instead, use the `WIGOLO_API_TOKEN_FILE` option to mount a secret file, as demonstrated in the [`packaging/compose.serve.yml`](https://github.com/KnockOutEZ/wigolo/blob/main/packaging/compose.serve.yml) configuration.

## Launch with Docker Compose

For production-grade self-hosting, use the provided Compose file which includes health checks and proper networking:

```bash
docker compose -f packaging/compose.serve.yml up -d

```

The [`packaging/compose.serve.yml`](https://github.com/KnockOutEZ/wigolo/blob/main/packaging/compose.serve.yml) file defines several critical configurations:

- **Command**: Executes `["serve","--host","0.0.0.0","--port","3333"]` to expose the daemon to external traffic
- **Port mapping**: Binds host port `3333` to container port `3333`
- **Environment**: Sets `WIGOLO_DATA_DIR=/data` and optionally injects `WIGOLO_API_TOKEN`
- **Healthcheck**: Probes the `/health` endpoint (defined at lines 49-58) to monitor daemon readiness

To customize authentication, edit the compose file to uncomment either:

```yaml
WIGOLO_API_TOKEN: "your-secure-random-token"

```

Or the more secure secret file approach:

```yaml
WIGOLO_API_TOKEN_FILE: /run/secrets/wigolo_token

```

## Verify and Access the Service

Confirm the container is healthy by querying the health endpoint:

```bash
curl -s http://localhost:3333/health

```

A `200 OK` response indicates the Node.js daemon is operational. The Docker Compose health check will automatically restart the container if this endpoint returns unhealthy status codes.

Once running, wigolo exposes two primary interfaces on port `3333`:

- **MCP endpoint**: `http://localhost:3333/mcp` for stdio-based agent communication
- **REST API**: `http://localhost:3333/v1/...` for HTTP-based interactions

All requests must include the bearer token in the Authorization header:

```bash
curl -H "Authorization: Bearer $WIGOLO_API_TOKEN" \
     -X POST -d '{"query":"example search"}' \
     http://localhost:3333/v1/search

```

### Running Behind a Reverse Proxy

If you run wigolo behind a reverse proxy (such as Nginx or Traefik) that handles authentication, disable the internal token requirement by setting:

```yaml
WIGOLO_SERVE_ALLOW_UNAUTHENTICATED: "1"

```

Only enable this when your external proxy enforces strict authentication, as the daemon will accept anonymous requests from any source when this variable is set.

## Update wigolo

When new versions are released, update without losing cached data:

```bash
docker pull ghcr.io/knockoutez/wigolo
docker compose -f packaging/compose.serve.yml up -d --force-recreate

```

The `wigolo-data` volume persists the browser binary and model files, so only the application code updates while the cache remains intact.

## Build the Full Image Target

For environments where volume mounts are impossible, build the full target which embeds Chromium:

```bash
docker build --target full -t wigolo:full .
docker run -i --rm -p 3333:3333 \
  -e WIGOLO_API_TOKEN=$WIGOLO_API_TOKEN \
  wigolo:full serve --host 0.0.0.0 --port 3333

```

This approach, defined in the root `Dockerfile`, produces a larger image but executes immediately without downloading dependencies, making it ideal for ephemeral CI/CD pipelines or restricted filesystems.

## Summary

- **Pull** the slim image from `ghcr.io/knockoutez/wigolo` for standard deployments, or build the `full` target for volume-less execution
- **Mount** a persistent volume at `/data` to cache the Chromium binary, models, and encrypted keys across restarts
- **Secure** the daemon by setting `WIGOLO_API_TOKEN` when binding to non-loopback interfaces, or use `WIGOLO_API_TOKEN_FILE` for production secrets management
- **Deploy** using [`packaging/compose.serve.yml`](https://github.com/KnockOutEZ/wigolo/blob/main/packaging/compose.serve.yml) for automated health checks and proper port exposure on `0.0.0.0:3333`
- **Verify** deployment via the `/health` endpoint before routing production traffic

## Frequently Asked Questions

### What is the difference between the slim and full Docker images?

The **slim** image (default) downloads the Chromium browser binary and on-device models on first use, storing them in the `/data` volume. This keeps the initial image size small but requires a writable volume. The **full** image, built by targeting `docker build --target full`, embeds the browser binary directly into the image layers according to the `Dockerfile` specification, making it suitable for ephemeral containers or environments where volume mounts are restricted, though it results in a significantly larger download size.

### Why does wigolo require an API token for Docker deployments?

According to the source code implementation in the KnockOutEZ/wigolo repository, the daemon refuses to start on non-loopback interfaces (`0.0.0.0`) unless the `WIGOLO_API_TOKEN` environment variable or `WIGOLO_API_TOKEN_FILE` secret is provided. This fail-closed security model prevents accidental exposure of the MCP and REST endpoints to untrusted networks. When running behind a reverse proxy that handles authentication, you can disable this requirement by setting `WIGOLO_SERVE_ALLOW_UNAUTHENTICATED=1`.

### How do I persist data when updating the wigolo container?

Create a named Docker volume (e.g., `wigolo-data`) and mount it at `/data` inside the container as specified in the `Dockerfile` (`VOLUME ["/data"]`). When updating images using `docker pull` and recreating containers with `docker compose up -d --force-recreate`, attach the same volume to the new container instance. The browser binary, cached models, and encrypted keys stored in `/data` remain intact across updates.

### Where is the Docker Compose configuration located in the repository?

The production-ready Docker Compose configuration is located at [`packaging/compose.serve.yml`](https://github.com/KnockOutEZ/wigolo/blob/main/packaging/compose.serve.yml) in the KnockOutEZ/wigolo repository. This file includes the recommended command arguments (`serve --host 0.0.0.0 --port 3333`), health check definitions probing the `/health` endpoint, and example configurations for both environment variable and file-based secret injection appropriate for self-hosting deployments.