> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stateset.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy iCommerce on Hetzner

> Run a persistent StateSet iCommerce Gateway on a Hetzner VPS using Docker with durable state and safe restart behavior.

# Deploy iCommerce on Hetzner

Run StateSet iCommerce 24/7 for approximately \$5/month on Hetzner. This guide walks you through deploying a persistent iCommerce Gateway on a Hetzner VPS using Docker, with durable state, baked-in binaries, and safe restart behavior.

## Goal

Deploy a production-ready StateSet iCommerce Gateway on Hetzner with:

* Persistent configuration and workspace data
* Docker-based isolated runtime
* SSH tunnel access for secure administration
* Automatic restart on failure

<Tip>
  Hetzner offers some of the most cost-effective VPS options available. Pick the smallest Debian/Ubuntu VPS that fits your workload and scale up if you encounter out-of-memory errors.
</Tip>

## What you'll build

<Steps>
  <Step title="Provision Hetzner VPS">
    Create a small Linux server with root access.
  </Step>

  <Step title="Install Docker runtime">
    Install Docker for isolated, reproducible application runtime.
  </Step>

  <Step title="Configure persistent storage">
    Mount host directories for configuration and workspace data that survives restarts.
  </Step>

  <Step title="Deploy the Gateway">
    Build and launch the iCommerce Gateway with Docker Compose.
  </Step>

  <Step title="Access securely">
    Connect via SSH tunnel from your local machine.
  </Step>
</Steps>

## Prerequisites

Before you begin, ensure you have:

* Hetzner VPS with root access
* SSH access from your local machine
* Basic familiarity with terminal commands
* StateSet API credentials
* Model provider credentials (OpenAI, Anthropic, etc.)

**Optional integrations:**

* WhatsApp Business API credentials
* Telegram bot token
* Gmail OAuth credentials

<Note>
  This guide assumes Ubuntu or Debian on Hetzner. If you're on another Linux VPS provider, map packages accordingly.
</Note>

***

## Quick path (experienced operators)

If you're familiar with Hetzner and Docker, follow this condensed workflow:

1. Provision Hetzner VPS (Ubuntu/Debian)
2. Install Docker
3. Clone the StateSet iCommerce repository
4. Create persistent host directories
5. Configure `.env` and `docker-compose.yml`
6. Bake required binaries into the image
7. `docker compose up -d`
8. Verify persistence and Gateway access

***

## 1) Provision the VPS

Create an Ubuntu or Debian VPS in the [Hetzner Cloud Console](https://console.hetzner.cloud/).

### Recommended specifications

| Type | Specs           | Cost    | Notes                             |
| ---- | --------------- | ------- | --------------------------------- |
| CX22 | 2 vCPU, 4GB RAM | \~€4/mo | Recommended                       |
| CX11 | 1 vCPU, 2GB RAM | \~€3/mo | Budget option, may OOM under load |

Connect as root:

```bash theme={null}
ssh root@YOUR_VPS_IP
```

<Warning>
  This guide assumes the VPS is stateful. Do not treat it as disposable infrastructure.
</Warning>

***

## 2) Install Docker

Run the following commands on the VPS:

```bash theme={null}
apt-get update
apt-get install -y git curl ca-certificates
curl -fsSL https://get.docker.com | sh
```

Verify the installation:

```bash theme={null}
docker --version
docker compose version
```

***

## 3) Clone the repository

```bash theme={null}
git clone https://github.com/stateset/stateset-icommerce.git
cd stateset-icommerce
```

***

## 4) Create persistent host directories

Docker containers are ephemeral. All long-lived state must live on the host to survive restarts and rebuilds.

```bash theme={null}
mkdir -p /root/.stateset
mkdir -p /root/.stateset/workspace

# Set ownership to the container user (uid 1000)
chown -R 1000:1000 /root/.stateset
chown -R 1000:1000 /root/.stateset/workspace
```

<Tip>
  Setting the correct ownership is critical. The container runs as uid 1000 (node user), so the host directories must be writable by that user.
</Tip>

***

## 5) Configure environment variables

Create a `.env` file in the repository root:

```bash theme={null}
STATESET_IMAGE=stateset-icommerce:latest
STATESET_GATEWAY_TOKEN=change-me-now
STATESET_GATEWAY_BIND=lan
STATESET_GATEWAY_PORT=18789

STATESET_CONFIG_DIR=/root/.stateset
STATESET_WORKSPACE_DIR=/root/.stateset/workspace

STATESET_KEYRING_PASSWORD=change-me-now
XDG_CONFIG_HOME=/home/node/.stateset
```

Generate strong secrets:

```bash theme={null}
openssl rand -hex 32
```

<Warning>
  Do not commit the `.env` file to version control. It contains sensitive credentials.
</Warning>

***

## 6) Docker Compose configuration

Create or update `docker-compose.yml`:

```yaml theme={null}
services:
  icommerce-gateway:
    image: ${STATESET_IMAGE}
    build: .
    restart: unless-stopped
    env_file:
      - .env
    environment:
      - HOME=/home/node
      - NODE_ENV=production
      - TERM=xterm-256color
      - STATESET_GATEWAY_BIND=${STATESET_GATEWAY_BIND}
      - STATESET_GATEWAY_PORT=${STATESET_GATEWAY_PORT}
      - STATESET_GATEWAY_TOKEN=${STATESET_GATEWAY_TOKEN}
      - STATESET_KEYRING_PASSWORD=${STATESET_KEYRING_PASSWORD}
      - XDG_CONFIG_HOME=${XDG_CONFIG_HOME}
      - PATH=/home/linuxbrew/.linuxbrew/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    volumes:
      - ${STATESET_CONFIG_DIR}:/home/node/.stateset
      - ${STATESET_WORKSPACE_DIR}:/home/node/.stateset/workspace
    ports:
      # Keep the Gateway loopback-only; access via SSH tunnel
      - "127.0.0.1:${STATESET_GATEWAY_PORT}:18789"
    command:
      [
        "node",
        "dist/index.js",
        "gateway",
        "--bind",
        "${STATESET_GATEWAY_BIND}",
        "--port",
        "${STATESET_GATEWAY_PORT}"
      ]
```

<Tip>
  To expose the Gateway publicly, remove the `127.0.0.1:` prefix from the port mapping and configure firewall rules accordingly. See the [security documentation](/security) for guidance.
</Tip>

***

## 7) Bake required binaries into the image

<Warning>
  Installing binaries inside a running container is a common mistake. Anything installed at runtime will be lost on restart. All external binaries required by skills must be installed at image build time.
</Warning>

If you add new skills later that depend on additional binaries, you must:

1. Update the Dockerfile
2. Rebuild the image
3. Restart the containers

### Example Dockerfile

```dockerfile theme={null}
FROM node:22-bookworm

RUN apt-get update && apt-get install -y socat && rm -rf /var/lib/apt/lists/*

# Gmail CLI
RUN curl -L https://github.com/steipete/gog/releases/latest/download/gog_Linux_x86_64.tar.gz \
  | tar -xz -C /usr/local/bin && chmod +x /usr/local/bin/gog

# Google Places CLI
RUN curl -L https://github.com/steipete/goplaces/releases/latest/download/goplaces_Linux_x86_64.tar.gz \
  | tar -xz -C /usr/local/bin && chmod +x /usr/local/bin/goplaces

# WhatsApp CLI
RUN curl -L https://github.com/steipete/wacli/releases/latest/download/wacli_Linux_x86_64.tar.gz \
  | tar -xz -C /usr/local/bin && chmod +x /usr/local/bin/wacli

# Add more binaries as needed using the same pattern

WORKDIR /app
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
COPY ui/package.json ./ui/package.json
COPY scripts ./scripts

RUN corepack enable
RUN pnpm install --frozen-lockfile

COPY . .
RUN pnpm build
RUN pnpm ui:install
RUN pnpm ui:build

ENV NODE_ENV=production

CMD ["node","dist/index.js"]
```

***

## 8) Build and launch

```bash theme={null}
docker compose build
docker compose up -d icommerce-gateway
```

Verify binaries are installed:

```bash theme={null}
docker compose exec icommerce-gateway which gog
docker compose exec icommerce-gateway which goplaces
docker compose exec icommerce-gateway which wacli
```

Expected output:

```
/usr/local/bin/gog
/usr/local/bin/goplaces
/usr/local/bin/wacli
```

***

## 9) Verify the Gateway

Check the logs:

```bash theme={null}
docker compose logs -f icommerce-gateway
```

Success output:

```
[gateway] listening on ws://0.0.0.0:18789
```

***

## 10) Access from your local machine

Create an SSH tunnel to forward the Gateway port:

```bash theme={null}
ssh -N -L 18789:127.0.0.1:18789 root@YOUR_VPS_IP
```

Open in your browser:

```
http://127.0.0.1:18789/
```

Enter your gateway token to authenticate.

<Tip>
  The `-N` flag tells SSH not to execute a remote command, making it ideal for port forwarding only.
</Tip>

***

## Persistence reference

All long-lived state must survive restarts, rebuilds, and reboots. Docker is not the source of truth.

| Component           | Location                          | Persistence            | Notes                                |
| ------------------- | --------------------------------- | ---------------------- | ------------------------------------ |
| Gateway config      | `/home/node/.stateset/`           | Host volume mount      | Includes tokens, settings            |
| Model auth profiles | `/home/node/.stateset/`           | Host volume mount      | OAuth tokens, API keys               |
| Skill configs       | `/home/node/.stateset/skills/`    | Host volume mount      | Skill-level state                    |
| Agent workspace     | `/home/node/.stateset/workspace/` | Host volume mount      | Code and agent artifacts             |
| WhatsApp session    | `/home/node/.stateset/`           | Host volume mount      | Preserves QR login                   |
| Keyring             | `/home/node/.stateset/`           | Host volume + password | Requires `STATESET_KEYRING_PASSWORD` |
| External binaries   | `/usr/local/bin/`                 | Docker image           | Must be baked at build time          |
| Node runtime        | Container filesystem              | Docker image           | Rebuilt every image build            |
| OS packages         | Container filesystem              | Docker image           | Do not install at runtime            |

***

## Updates

To update StateSet iCommerce on the VPS:

```bash theme={null}
cd ~/stateset-icommerce
git pull
docker compose build
docker compose up -d
```

***

## Troubleshooting

### SSH connection refused

Verify the VPS is running and your IP is not blocked by any firewall rules.

```bash theme={null}
# Check if SSH is listening
netstat -tlnp | grep 22
```

### Out of memory (OOM)

If hitting OOM on a smaller VPS, upgrade to a larger instance:

1. Create a snapshot of your VPS in Hetzner Cloud Console
2. Resize or create a new VPS with more resources
3. Restore from snapshot if needed

### Container fails to start

Check logs for errors:

```bash theme={null}
docker compose logs icommerce-gateway
```

Verify environment variables are set correctly:

```bash theme={null}
docker compose config
```

### Permission denied on mounted volumes

Ensure the host directories have the correct ownership:

```bash theme={null}
chown -R 1000:1000 /root/.stateset
```

### Firewall blocking connections

If using Hetzner's firewall, ensure the required ports are open:

```bash theme={null}
# Check current firewall rules
ufw status

# Allow SSH (if using ufw)
ufw allow 22/tcp
```

***

## Hetzner-specific tips

### Enable automatic backups

Enable automatic backups in the Hetzner Cloud Console for disaster recovery. Cost is approximately 20% of VPS price.

### Use a floating IP

For production deployments, assign a floating IP to your VPS. This allows you to migrate to a new server without changing your IP address.

### Set up monitoring

Hetzner provides basic monitoring in the Cloud Console. For more detailed metrics, consider installing a monitoring agent:

```bash theme={null}
# Example: Install Netdata for real-time monitoring
bash <(curl -Ss https://my-netdata.io/kickstart.sh)
```

***

## Next steps

<CardGroup cols={2}>
  <Card title="Messaging Channels" icon="message" href="/stateset-icommerce/stateset-icommerce-messaging-channels">
    Set up WhatsApp, Telegram, and other messaging integrations.
  </Card>

  <Card title="Skills" icon="wand-magic-sparkles" href="/stateset-icommerce/stateset-icommerce-skills">
    Configure and extend agent capabilities with custom skills.
  </Card>

  <Card title="CLI Reference" icon="terminal" href="/stateset-icommerce/stateset-icommerce-cli-reference">
    Learn the full CLI command set for managing your iCommerce instance.
  </Card>

  <Card title="Security" icon="shield" href="/security">
    Review security best practices for production deployments.
  </Card>
</CardGroup>
