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

# On-Premise Deployment

> Run the full AlgoVoi payment stack on your own infrastructure: a self contained Docker Compose stack with no dependency on AlgoVoi hosted services.

<Warning>
  On-premise deployment is currently in development. The Docker Compose stack and licence activation are available now for early adopters. [Contact us](mailto:hello@algovoi.co.uk) to register interest ahead of general availability.
</Warning>

The AlgoVoi on-premise stack lets regulated, enterprise, or high-volume deployments run the full payment gateway locally. After a one-time licence activation, the stack operates independently — no API calls back to AlgoVoi during payment flows.

## What runs locally

| Service             | Role                                                                                |
| ------------------- | ----------------------------------------------------------------------------------- |
| **gateway**         | x402 / MPP / AP2 / A2A payment routing, compliance screening, agent session auth    |
| **control\_plane**  | Tenant management, API key issuance, audit chain, webhook delivery                  |
| **facilitator**     | On-chain transaction verification across 7 chain families                           |
| **postgres**        | Tenant data, payment records, audit log — fully under your control                  |
| **atb-zkp-service** | Bulletproofs ZKP range proof microservice — enables Phase 2 ATB certs               |
| **bench**           | Agent Trust Bench — runs adversarial payment profiles, issues ATB Pass Certificates |

ATB and ZKP are standard services. They enable [agent session authentication](/agent-session-auth) — the mechanism by which agents authenticate once with a ZKP cert and receive a session JWT with a spend cap, without repeated API key exposure.

The on-premise stack includes **[Substrate 2](/substrate-2)**, the commercial evidence layer, with post-quantum signatures, zero-knowledge reputation, cross-issuer federation, and self-verifiable retention chains as standard. There is no separate Substrate 2 purchase; it ships as part of the Enterprise and On-premise plans.

## Prerequisites

* Docker Engine 24+ and Docker Compose v2
* An AlgoVoi account with an active API key — [sign up](https://dash.algovoi.co.uk/signup)
* A wallet address on at least one supported chain (Algorand, VOI, Solana, Base, Stellar, Hedera)
* An AlgoVoi licence token (see [Step 1](#step-1-activate-your-licence) below)

## Quickstart

### Step 1 — Activate your licence

Call `POST /atb/license/activate` on the AlgoVoi gateway with your API key. This issues a Falcon-1024 signed licence token that your local gateway validates on startup.

```bash theme={null}
curl -X POST https://api.algovoi.co.uk/atb/license/activate \
  -H "X-Tenant-Id: <your-tenant-id>" \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
```

Response:

```json theme={null}
{
  "licence_token": "eyJhbGciOiJGYWxjb24tMTAyNCIsInR5cCI6ImxpY2VuY2UifQ...",
  "expires_at": "2027-06-03T00:00:00Z",
  "operator_did": "did:web:your-gateway.example.com"
}
```

Save `licence_token` — you will need it in Step 3. The token is valid for one year and must be renewed before expiry.

Fetch the AlgoVoi public key for licence verification:

```bash theme={null}
curl https://api.algovoi.co.uk/.well-known/pqc-keys.json | jq '.keys[0].public_key_b64'
```

Save this value as `ATB_LICENSE_PK_B64` in your `.env.local`.

### Step 2 — Download the deployment files

You receive two files with your licence — `docker-compose.local.images.yml` and `env.local.template`. No source code is required or provided.

```bash theme={null}
mkdir algovoi-local && cd algovoi-local

# Log in to the AlgoVoi container registry (credentials provided with your licence)
docker login ghcr.io -u <your-username> --password <registry-token>

# Copy the env template (provided with your licence package)
cp env.local.template .env.local && chmod 600 .env.local
```

Open `.env.local` and fill in the required values. Generate the cryptographic keys:

```bash theme={null}
# JWT signing key
python3 -c "import secrets; print(secrets.token_hex(32))"

# Facilitator HMAC secret (shared between gateway and facilitator)
python3 -c "import secrets; print(secrets.token_hex(32))"

# HMAC encryption key
python3 -c "import secrets; print(secrets.token_hex(16))"

# KYB encryption key
python3 -c "import secrets; print(secrets.token_hex(16))"

# Admin API key
python3 -c "import secrets; print('admin_' + secrets.token_hex(24))"

# Database password
python3 -c "import secrets; print(secrets.token_hex(32))"
```

Generate your ATB bench Falcon-1024 keypair:

```bash theme={null}
pip install pqcrypto>=0.4.0
python3 scripts/generate_atb_keypair.py
# Paste ATB_BENCH_SK_B64 and ATB_BENCH_PK_B64 output into .env.local
```

Set your facilitator wallet addresses for the chains you want to support:

```bash theme={null}
# .env.local
FACILITATOR_ADDRESS_ALGORAND_MAINNET=YOURALGOWALLET...
FACILITATOR_ADDRESS_BASE_MAINNET=0xYourBaseWallet...
# Leave unsupported chains blank
```

Set the licence fields:

```bash theme={null}
ATB_LICENSE_TOKEN=eyJhbGciOiJGYWxjb24tMTAyNCIsInR5cCI6ImxpY2VuY2UifQ...
ATB_LICENSE_PK_B64=CnEa4uG4HHA...
```

Set your gateway's public URL (used in hosted checkout links):

```bash theme={null}
GATEWAY_PUBLIC_URL=https://payments.your-domain.com
```

### Step 3 — Run migrations

```bash theme={null}
docker compose --env-file .env.local -f docker-compose.local.images.yml run --rm migrations
```

This applies all 118 database migrations to a fresh postgres instance. Safe to run again — all migrations are idempotent.

### Step 4 — Start the stack

```bash theme={null}
docker compose --env-file .env.local -f docker-compose.local.images.yml up -d
```

Check all services are healthy:

```bash theme={null}
docker compose -f docker-compose.local.images.yml ps
```

Expected output:

```
NAME                                 STATUS
algovoi-local-postgres-1             Up (healthy)
algovoi-local-control_plane-1        Up (healthy)
algovoi-local-facilitator-1          Up (healthy)
algovoi-local-atb-zkp-service-1      Up (healthy)
algovoi-local-bench-1                Up (healthy)
algovoi-local-gateway-1              Up (healthy)
```

### Step 5 — Verify

```bash theme={null}
curl http://localhost:8080/health
# {"status":"ok","service":"gateway",...}

curl http://localhost:8080/.well-known/did.json
# Your local DID document

curl http://localhost:8080/.well-known/atb-federation.json
# {"hub":"did:web:payments.your-domain.com","atb_version":"2.0","zkp":{...}}

curl http://localhost:8090/health
# {"ok":true,"service":"algovoi-bench"}
```

Create your first tenant via the admin API:

```bash theme={null}
curl -X POST http://localhost:8080/signup/create \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","company":"Acme Ltd","password":"..."}'
```

## Chain support

The stack ships with free-tier public node defaults for all 7 chains. For production workloads, replace with dedicated node endpoints in `.env.local`:

| Chain    | Default node          | Recommended for production                                           |
| -------- | --------------------- | -------------------------------------------------------------------- |
| Algorand | Algonode free tier    | [Nodely](https://nodely.io) or [NFD](https://algonode.io) dedicated  |
| VOI      | Nodely free tier      | Nodely dedicated                                                     |
| Solana   | Public RPC            | [Helius](https://helius.dev) or [QuickNode](https://quicknode.com)   |
| Base     | Public RPC            | [Alchemy](https://alchemy.com) or [QuickNode](https://quicknode.com) |
| Stellar  | Horizon public        | [SatoshiPay](https://stellarbeat.io) dedicated                       |
| Hedera   | SDK default (mainnet) | [Hedera mirror node](https://docs.hedera.com)                        |

Unsupported chains (no wallet address set) are silently disabled — payment requests on those chains return a clear error rather than failing silently.

## Licence mechanics

The local gateway validates `ATB_LICENSE_TOKEN` on startup using the embedded `ATB_LICENSE_PK_B64` public key. Verification is fully offline — no network call required.

* **Token lifetime:** 1 year from issuance
* **Renewal:** call `POST /atb/license/activate` with your API key before expiry; update `ATB_LICENSE_TOKEN` in `.env.local` and restart the gateway
* **Failure mode:** if the token is absent, expired, or invalid the gateway starts in restricted mode — health check passes but payment routes return `503`

## Agent session auth

Agent session authentication is enabled by default. The `atb-zkp-service` and `bench` are standard services in the stack.

Once the stack is running, agents can:

1. Complete ATB evaluation at `http://localhost:8090`
2. Receive a Falcon-1024 signed ZKP cert
3. Exchange the cert for a session JWT at `POST http://localhost:8080/auth/token`
4. Use the session JWT on all payment routes with the configured spend cap

See [Agent Session Authentication](/agent-session-auth) for the full flow and request/response shapes.

## Stopping the stack

```bash theme={null}
# Stop, keep data
docker compose -f docker-compose.local.images.yml down

# Stop and remove all data (irreversible)
docker compose -f docker-compose.local.images.yml down -v
```

## Updates

Pull the latest images and restart:

```bash theme={null}
# Pull new images
docker compose -f docker-compose.local.images.yml pull

# Restart with updated images
docker compose --env-file .env.local -f docker-compose.local.images.yml up -d

# Run migrations to pick up any schema changes
docker compose --env-file .env.local -f docker-compose.local.images.yml run --rm migrations
```

To pin to a specific version rather than `latest`, set `ALGOVOI_VERSION` in your `.env.local`:

```bash theme={null}
ALGOVOI_VERSION=v1.2.0
```

## Security hardening

<Warning>
  The default configuration binds the gateway to `127.0.0.1` only and includes no TLS. **You must add TLS termination before handling real payments.** Plain HTTP connections expose API keys, session tokens, and payment receipts.
</Warning>

### TLS termination (required for production)

Front the gateway with nginx. A reference config is included in `docs/nginx.local.conf`.

```bash theme={null}
# Install nginx and certbot
apt install nginx certbot python3-certbot-nginx

# Obtain a Let's Encrypt certificate
certbot --nginx -d payments.your-domain.com

# Copy the reference config
cp docs/nginx.local.conf /etc/nginx/sites-available/algovoi-local
# Edit server_name to match your domain
nginx -t && systemctl reload nginx
```

Set in `.env.local`:

```bash theme={null}
GATEWAY_BIND=127.0.0.1   # gateway only reachable via nginx
BEHIND_PROXY=true          # trust X-Forwarded-For / X-Forwarded-Proto
GATEWAY_PUBLIC_URL=https://payments.your-domain.com
```

For internal deployments without a public domain, use a self-signed certificate:

```bash theme={null}
mkdir -p /etc/ssl/algovoi
openssl req -x509 -newkey rsa:4096 \
  -keyout /etc/ssl/algovoi/key.pem \
  -out /etc/ssl/algovoi/cert.pem \
  -days 365 -nodes \
  -subj "/CN=algovoi-local"
```

### Protect `.env.local`

The `.env.local` file contains all cryptographic keys. Restrict access immediately after creation:

```bash theme={null}
chmod 600 .env.local
echo ".env.local" >> .gitignore   # never commit it
```

For production deployments, use a secrets manager rather than a flat file:

* **HashiCorp Vault** — inject secrets via `vault agent` or `envconsul`
* **AWS Secrets Manager** — use `aws secretsmanager get-secret-value` in an entrypoint script
* **Docker Secrets** (Swarm mode) — use the `secrets:` block in docker-compose

### Licence revocation

The gateway checks `ATB_LICENSE_REVOCATION_URL` on startup and every `ATB_LICENSE_REVOCATION_INTERVAL_SECS` (default 24 h):

* **Network unreachable** → fail-open, gateway continues operating
* **`{"revoked": true}`** → gateway enters restricted mode, payment routes return `503`
* **Licence token expired** → restricted mode on next startup

Renew your licence token before expiry:

```bash theme={null}
curl -X POST https://api.algovoi.co.uk/atb/license/activate \
  -H "X-Tenant-Id: <tenant-id>" \
  -H "Authorization: Bearer <api-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
# Update ATB_LICENSE_TOKEN in .env.local and restart the gateway
```

### Admin API key

The `ADMIN_API_KEY` grants full tenant provisioning access. Treat it as a break-glass credential:

* Use a strong random value (48+ hex chars): `python3 -c "import secrets; print('admin_' + secrets.token_hex(24))"`
* Do not embed it in automation scripts
* Rotate it after any suspected exposure via the admin API

### Resource limits

The compose file sets CPU and memory limits per service. Adjust for your hardware:

| Service        | Default CPU limit | Default memory limit |
| -------------- | ----------------- | -------------------- |
| postgres       | 1 core            | 512 MB               |
| control\_plane | 2 cores           | 512 MB               |
| facilitator    | 2 cores           | 512 MB               |
| gateway        | 4 cores           | 1 GB                 |

### Audit chain trust model

<Warning>
  The on-premise audit chain does not have the same tamper-evidence guarantees as the hosted platform.
</Warning>

On the hosted AlgoVoi platform, the audit chain (SHA-256 JCS hash-chained rows) is stored in Backblaze B2 with Object Lock COMPLIANCE mode — making it immutable for the statutory 7-year retention period and independently verifiable by a third party.

On an on-premise deployment, the operator controls the database. The hash chain is technically correct (each row's `content_hash` and `prev_hash` are cryptographically linked), but a database administrator with write access could truncate or modify rows.

**Mitigations available:**

* Enable periodic export of the audit chain to an immutable external store (S3 Object Lock, Backblaze B2 COMPLIANCE, Azure Immutable Blob)
* Use the `algovoi-audit-verifier` package to run independent chain verification on a schedule
* For MiCA / PSD2 compliance, document your immutability controls in your DPIA

### GDPR / data controller responsibility

When you run the stack on your own infrastructure, you become the **data controller** for:

* Tenant account data and API keys
* Payer references (content-addressed `sha256:{hex}` — not raw wallet addresses)
* Compliance screen results (ALLOW / REFER / DENY) and their timestamps
* Webhook delivery logs

AlgoVoi's role shifts from data controller to **data processor** (or is eliminated entirely if you hold no data on our systems).

You are responsible for:

* Retaining payment records for the statutory period (MiCA Art. 80: 5 years; UK FCA: 6 years)
* Implementing a GDPR deletion path for `REFER` screening records
* Notifying your DPA of the deployment if required under GDPR Art. 30

The `algovoi-audit-verifier` package assists with statutory retention verification.

### Supply chain integrity

The deployment uses pre-built images from `ghcr.io/chopmob-cloud`. Source code is not distributed with the on-premise package.

To verify image integrity:

```bash theme={null}
# Check the image digest matches the release manifest provided with your licence
docker inspect ghcr.io/chopmob-cloud/algovoi-gateway:latest \
  --format '{{index .RepoDigests 0}}'
# Compare against the SHA-256 digest in your licence release notes
```

Image signing via Sigstore / Cosign is on the roadmap for the GA release. Signed manifests will allow cryptographic verification without trusting the registry.

## See also

* [Agent Session Authentication](/agent-session-auth) — session tokens and spend caps
* [ATB Pass Certificate](/atb-reputation-credential) — reputation-gated pricing
* [Canonicalisation substrate](/canonicalisation-substrate) — the JCS discipline underlying all receipts
* [Substrate authorship and provenance](/substrate-authorship-provenance) — AlgoVoi authorship record
