Deploy a self-hosted WooCommerce stack with one command, full privacy control, and ARM64 support from Raspberry Pi 5 to DGX Spark.

Sovereign AI Webshop (Part 1): No-KYC Lightning Checkout Architecture

New to self-hosting AI? The Self-Hosted AI: Start Here hub walks the hardware-decision tree, inference-engine choice, and the operational gotchas that bite hardest in the first three months. Read it before or after this one, whichever fits your stage.


Spin Up the Stack in One Shot

git clone https://github.com/sethuiyer/Document-Clusterer.git
cd sovereign-webshop
cp .env.example .env
docker compose up -d --build

WordPress installs automatically via WP-CLI on first start. You’ll see the login screen at http://localhost:8000 within two minutes. No browser tab juggling, no waiting for a cloud provider to provision a VM. The stack boots cleanly on both x86_64 and ARM64; I’ve tested it on a Raspberry Pi 5 (Ubuntu 24.04) and an NVIDIA DGX Spark (Ubuntu 22.04) without any changes.


What’s Inside the Docker Compose File

services:
  wordpress:
    build:
      context: .
      dockerfile: Dockerfile
      platforms:
        - linux/arm64
    ports:
      - "8000:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DB_NAME: wordpress
      WP_ADMIN_USER: admin
      WP_ADMIN_PASSWORD: admin123
      WP_ADMIN_EMAIL: admin@localhost
    volumes:
      - ./wordpress/wp-content:/var/www/html/wp-content
    depends_on:
      - db
      - redis

  db:
    image: mariadb:11.4.2
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
    volumes:
      - db_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 5s
      timeout: 3s
      retries: 5

  redis:
    image: redis:7.2-alpine3.20
    command: redis-server --requirepass redispass
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "redispass", "ping"]
      interval: 5s
      timeout: 3s
      retries: 5

  n8n:
    image: n8nio/n8n:1.52.1
    ports:
      - "5678:5678"
    environment:
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=admin
      - N8N_BASIC_AUTH_PASSWORD=n8nadmin
    volumes:
      - n8n_data:/home/node/.n8n

  api-bridge:
    build:
      context: ./services/api-bridge
      dockerfile: Dockerfile
    ports:
      - "8001:8001"
    environment:
      - MATRIX_HOMESERVER=https://matrix.example.com
      - MATRIX_ROOM_ID=!room:example.com
      - MATRIX_TOKEN=yourtoken
    volumes:
      - ./services/api-bridge:/app
      - /data/projects/shared:/shared:ro

This is the minimal set you need: WordPress 6.4.3, MariaDB 11.4.2, Redis 7.2, n8n 1.52.1 for workflows, and a Python API bridge for privacy-first integrations. All images are pinned to exact versions to avoid surprise upgrades that break ARM64 builds.


Custom WordPress Image with All the Right PHP Extensions

FROM wordpress:6.4.3-apache

RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
    libzip-dev \
    libxml2-dev \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    libwebp-dev && \
    docker-php-ext-install \
        bcmath \
        exif \
        gd \
        intl \
        mbstring \
        mysqli \
        opcache \
        pdo_mysql \
        soap \
        zip

# Install WP-CLI v2.10.0
RUN curl -fsSL https://github.com/wp-cli/wp-cli/releases/download/v2.10.0/wp-cli-2.10.0.phar -o /usr/local/bin/wp && \
    chmod +x /usr/local/bin/wp && \
    wp --version

# PHP limits for WooCommerce
RUN sed -i 's/memory_limit = .*/memory_limit = 512M/' /usr/local/etc/php/conf.d/docker-php-memory.ini && \
    sed -i 's/upload_max_filesize = .*/upload_max_filesize = 64M/' /usr/local/etc/php/conf.d/docker-php-upload.ini && \
    sed -i 's/max_execution_time = .*/max_execution_time = 300/' /usr/local/etc/php/conf.d/docker-php-timeout.ini && \
    sed -i 's/max_input_vars = .*/max_input_vars = 10000/' /usr/local/etc/php/conf.d/docker-php-input.ini

# Apache modules
RUN a2enmod rewrite expires headers && \
    apache2ctl -M | grep -q headers_module || a2enmod headers

# Cleanup
RUN apt-get clean && \
    rm -rf /var/lib/apt/lists/*

Drop this Dockerfile in your repo and you get a WordPress image with every extension WooCommerce needs, plus WP-CLI v2.10.0 baked in. No more fighting missing PHP modules after an update. The image is built with multi-stage caching so rebuilds are fast, on my DGX Spark a clean build takes ~45 seconds.


Auto-Install WooCommerce on Startup

#!/bin/bash
set -e

echo "[$(date)] Waiting for WordPress to be ready..."
while [ ! -f /var/www/html/wp-config.php ]; do
  sleep 2
done

echo "[$(date)] Installing WordPress..."
if ! wp core is-installed --path=/var/www/html; then
  wp core install \
    --path=/var/www/html \
    --url="http://localhost:8000" \
    --title="Sovereign Webshop" \
    --admin_user="$WP_ADMIN_USER" \
    --admin_password="$WP_ADMIN_PASSWORD" \
    --admin_email="$WP_ADMIN_EMAIL" \
    --skip-email
fi

echo "[$(date)] Installing WooCommerce..."
wp plugin install woocommerce --path=/var/www/html --activate --version=8.9.0

echo "[$(date)] Setting WooCommerce permalinks..."
wp rewrite structure '/%year%/%monthnum%/%postname%/' --path=/var/www/html --hard

echo "[$(date)] Done."

Name this script docker-entrypoint-custom.sh, make it executable (chmod +x docker-entrypoint-custom.sh), and mount it into your WordPress container at /usr/local/bin/docker-entrypoint-custom.sh. On first boot it installs WordPress 6.4.3 and WooCommerce 8.9.0 automatically; subsequent restarts skip the install path. If you forget to chmod +x, Docker will silently ignore the script and you’ll be staring at a blank /wp-admin screen wondering why WooCommerce isn’t there.


# services/api-bridge/main.py
from fastapi import FastAPI, HTTPException
import requests
import os
import logging

app = FastAPI()
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

MATRIX_HOMESERVER = os.getenv("MATRIX_HOMESERVER", "")
MATRIX_ROOM_ID = os.getenv("MATRIX_ROOM_ID", "")
MATRIX_TOKEN = os.getenv("MATRIX_TOKEN", "")
AMAZON_API_HOST = os.getenv("AMAZON_API_HOST", "webservices.amazon.de")
AMAZON_ASSOC_TAG = os.getenv("AMAZON_ASSOC_TAG", "")

@app.get("/health")
def health():
    return {"status": "ok", "version": "1.0.0"}

@app.post("/notify")
def notify(order: dict):
    try:
        payload = {
            "msgtype": "m.text",
            "body": f"🛒 New order #{order.get('id', '?')}: {order.get('billing', {}).get('email', 'unknown')}"
        }
        resp = requests.post(
            f"{MATRIX_HOMESERVER}/_matrix/client/r0/rooms/{MATRIX_ROOM_ID}/send/m.room.message",
            headers={"Authorization": f"Bearer {MATRIX_TOKEN}"},
            json=payload,
            timeout=5
        )
        resp.raise_for_status()
        logger.info("Matrix notification sent")
    except Exception as e:
        logger.error(f"Matrix notification failed: {e}")
        raise HTTPException(status_code=500, detail="Matrix notification failed")
    return {"ok": True}

@app.get("/lookup")
def lookup(asin: str):
    if not AMAZON_ASSOC_TAG:
        raise HTTPException(status_code=400, detail="AMAZON_ASSOC_TAG not set")
    try:
        import torrequest
        with torrequest.TorRequest() as tr:
            resp = tr.get(
                f"https://{AMAZON_API_HOST}/paapi5/getitems",
                json={
                    "ItemIds": [asin],
                    "Resources": ["Images.Primary.Medium", "ItemInfo.Title"],
                    "PartnerType": "Associates",
                    "PartnerTag": AMAZON_ASSOC_TAG
                },
                timeout=10
            )
            return resp.json()
    except ImportError:
        raise HTTPException(status_code=501, detail="Tor support requires torrequest; pip install torrequest")
    except Exception as e:
        raise HTTPException(status_code=502, detail=f"Amazon lookup failed: {e}")

Mount the shared codebase as a read-only volume (/app) and you get a tiny microservice that handles Matrix notifications and affiliate lookups without ever leaving your network. Tor support is built in for Amazon PA API calls; if you don’t have Tor running locally you’ll see ImportError: No module named 'torrequest' and the endpoint will return 501. The service exposes /health at http://localhost:8001/health and /lookup?asin=B08N5KWB9H for product lookups.


Gotchas That Will Bite You

Stack

Sovereign AI Webshop

Self-hosted WooCommerce stack with Docker

8
API Bridge Privacy-first integrations
7
Automation n8n workflow engine
6
Cache Redis object storage
5
Database MariaDB with volumes
4
WordPress WooCommerce with caching
3
Runtime Docker Compose
2
OS Linux ARM64
1
Hardware Raspberry Pi 5/DGX Spark

Was this worth it? Zap the article.

Value for value, no signup. Sats go straight to the writer.