PALO-AI Online VPS Deployment#
Status: Internet-reachable developer-preview deployment for PALO-AI v2.5. This topology provides HTTPS and network isolation, but it does not remove the blockers tracked in the public Production Readiness plan.
Live deployment status#
The reference developer-preview endpoint was deployed on 17 July 2026:
| Item | Live state |
|---|---|
| Public hostname | https://governance.paloframework.org |
| MCP transport | Streamable HTTP at /mcp, bearer-authenticated |
| Gateway | HTTPS under /gateway, bearer-authenticated and route-limited |
| Policy engine | OPA 1.17.0, Docker-internal only |
| TLS | Let's Encrypt ECDSA certificate with automatic renewal |
| Persistence | SQLite WAL reference state, transactional outbox and append-only evidence chain in a Docker volume |
| Release classification | Developer preview; non-production |
The live smoke test verifies HTTPS health, anonymous rejection and authenticated registry access. Public agent/policy/executor/verifier registration, approval resolution, approval enumeration, incident enumeration/resolution and direct evidence submission return 404. The remote MCP server exposes only six low-privilege governance tools; administrative and governed-execution MCP tools remain unavailable over the Internet.
Address model#
The deployment deliberately uses both private and public addresses:
| Address | Visibility | Purpose |
|---|---|---|
http://opa:8181 |
Docker network only | PALO-to-OPA policy evaluation |
http://palo-gateway:8787 |
Docker network only | Gateway behind the TLS proxy |
http://127.0.0.1:18877 |
Current VPS host only | Administrative profile registration over SSH |
http://127.0.0.1:18878 |
Current VPS host only | nginx-to-MCP proxy target |
http://palo-mcp:8788 |
Docker network only | MCP service behind the TLS proxy |
https://governance.paloframework.org/gateway |
Internet, authenticated | n8n/Dify adapter base URL |
https://governance.paloframework.org/mcp |
Internet, authenticated | Streamable HTTP MCP endpoint |
8181 is therefore not the public endpoint. It remains private even when the complete stack runs online on the VPS.
Private does not mean production-authenticated. The reference PALO services call OPA over HTTP inside the isolated Docker network. Before consequential deployment, threat-model sibling-container and host compromise, add authenticated policy distribution and evaluated-bundle provenance, and use mTLS or an equivalent workload-identity control when the deployment boundary requires it.
Supplied deployment#
The files under deploy/vps/palo-ai/ provide two reverse-proxy variants:
compose.host-nginx.yamlandnginx-governance.conffor the current Hostinger VPS, where nginx already serves other applications;compose.yamlandCaddyfilefor a clean VPS where PALO can own ports 80 and 443.
Both variants provide:
- Docker Compose orchestration;
- OPA 1.17.0 on a private internal network;
- PALO Gateway and MCP containers built from this repository;
- HTTPS termination and redirect through existing nginx/Certbot or Caddy 2.11.4;
- separate Docker secret files for Gateway, MCP and HMAC material;
- persistent PALO data and Caddy certificate volumes;
- non-root PALO containers, read-only filesystems, dropped capabilities and health checks;
- an explicit MCP host allowlist;
- public blocking of registry administration, policy registration, approval resolution and direct evidence submission;
- a VPS-local administration port bound only to
127.0.0.1.
The OPA and Caddy versions were current stable releases when this file was prepared. Pin image digests as well as tags before a consequential deployment.
Prerequisites#
- A Linux VPS with a public IP and SSH access.
- A dedicated hostname such as
governance.paloframework.org. - An
Arecord, and anAAAArecord only if IPv6 is correctly configured, pointing that hostname to the VPS. - TCP ports 80 and 443 reachable by Caddy; UDP 443 is optional for HTTP/3.
- Docker Engine with the Compose plugin.
- No other service occupying ports 80 or 443.
Caddy can obtain and renew a public certificate only after DNS points to the VPS and ports 80/443 are reachable.
Configure the VPS#
Clone or upload the repository, then from its root:
cd deploy/vps/palo-ai
cp .env.example .envEdit .env:
PALO_DOMAIN=governance.paloframework.org
ACME_EMAIL=security@paloframework.org
PALO_ADMIN_URL=http://127.0.0.1:18877
OPA_IMAGE=openpolicyagent/opa:1.17.0-static
CADDY_IMAGE=caddy:2.11.4-alpineGenerate protected secrets without printing them:
sh setup-secrets.shThe generated .env and secrets/ contents are ignored by Git. Back them up through a protected secret-management process; never upload or commit them.
Firewall#
Preserve SSH access before enabling a firewall. A typical UFW policy is:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 443/udp
sudo ufw enableDo not open 8181, 8787, 8788, 18877 or 18878 publicly. The Hostinger Compose variant publishes 18877 and 18878 only on the VPS loopback interface; the clean-VPS variant keeps its administration binding on loopback as documented in its Compose file.
Start the online stack#
The supplied VPS currently runs nginx and Certbot for other services. On that host, use compose.host-nginx.yaml; it binds PALO only to loopback ports 18877 and 18878, leaving the existing ports and sites untouched. The generic compose.yaml with Caddy is for a clean VPS where ports 80/443 are free.
For the existing Hostinger VPS:
docker compose -f compose.host-nginx.yaml config
docker compose -f compose.host-nginx.yaml pull
docker compose -f compose.host-nginx.yaml build --pull
docker compose -f compose.host-nginx.yaml up -dInstall nginx-governance.conf as a new site, validate with nginx -t, reload nginx, then obtain the certificate with Certbot only after DNS resolves:
sudo certbot --nginx \
-d governance.paloframework.org \
--non-interactive --agree-tos \
--email sev7en@gmail.com \
--redirectFor a clean VPS using Caddy instead:
Validate configuration, pull/build and start:
docker compose config
docker compose pull
docker compose build --pull
docker compose up -d
docker compose psFollow startup and certificate issuance:
docker compose logs --tail=100 opa palo-gateway palo-mcp caddyExpected public endpoints:
https://governance.paloframework.org/mcp-health
https://governance.paloframework.org/mcp
https://governance.paloframework.org/gateway/v1/registry
https://governance.paloframework.org/gateway/v1/actions/verifyRegister an authority profile#
Administrative registration is intentionally not exposed through the public reverse proxy. SSH into the VPS and use the loopback-only gateway. The current Hostinger deployment reads PALO_ADMIN_URL=http://127.0.0.1:18877 from .env:
sh register-profile.sh \
case-runtime-example \
../../../schemas/fixtures/palo-agentic-interface.valid.jsonThe supplied profile is development data. Before external testing, create a new versioned profile with the correct agent ID, case, tools, hosts, argument schemas, scopes and HMAC key ID.
Verify the online endpoint#
sh smoke-online.shThis checks:
- the public MCP health endpoint over HTTPS;
- rejection of an anonymous MCP request;
- authenticated access to the public Gateway registry.
Inspect service-local health when troubleshooting:
docker compose -f compose.host-nginx.yaml ps
curl --fail http://127.0.0.1:18877/healthConnect n8n#
For the current n8n alpha node, configure:
Gateway URL: https://governance.paloframework.org/gateway
Bearer Token: contents of secrets/gateway-tokenUse n8n encrypted credentials; never put the token in workflow JSON or node output.
The online /mcp endpoint uses MCP Streamable HTTP. Current n8n documentation describes an SSE endpoint for its MCP Client Tool. Until an SSE adapter or confirmed Streamable HTTP support is tested on the target n8n version, n8n should use the HTTPS Gateway integration rather than being presented as directly compatible with this MCP transport.
Connect other MCP clients#
For clients that support Streamable HTTP:
Endpoint: https://governance.paloframework.org/mcp
Authorization: Bearer <contents of secrets/mcp-token>Expose only the PALO-governed tools to an agent. Do not make equivalent privileged target tools available through a parallel ungoverned MCP server.
Public-route boundary#
The public reverse proxy currently exposes:
- MCP
/mcpand its health endpoint; the configured remote tool allowlist remains decision/status oriented and excludes administrative and execution tools; - Gateway health and authenticated registry read;
- authenticated Action Claim verification and full-cycle governed execution;
- authenticated execution detail, outcome read and explicit re-verification addressed by execution ID;
- authenticated approval status read only when addressed by approval ID;
- authenticated incident detail read only when addressed by incident ID;
- authenticated ledger verification.
It blocks public agent/policy/executor/verifier registration, approval enumeration, approval resolution, incident enumeration, incident resolution and direct evidence submission. Every non-health Gateway route still relies on one coarse preview bearer token. The execution routes are provided only for isolated n8n/Dify evaluation with mock or reversible actions; they are not a browser API or a multi-tenant authorization boundary. A future Governance Hub must call a BFF that applies OIDC, tenant context, RBAC/ABAC, redaction and separation of duties rather than placing this bearer token in browser code or storage.
Next implementation gates#
The online endpoint is ready for a controlled design-partner pilot with mock or reversible actions. The next gates are:
- install the packed
n8n-nodes-palo-aialpha in a disposable self-hosted n8n instance; - store the Gateway URL and bearer token in n8n encrypted credentials;
- register a pilot-specific authority profile through SSH, never through the public hostname;
- demonstrate
deny,pending_approvalandallowbranches with a non-consequential target tool; - add authenticated Web/mobile reviewer identity before enabling public approval resolution;
- make the governed executor unavoidable so a workflow cannot bypass PALO;
- replace preview identity, key and persistence controls before any production authorization claim.
Update and rollback#
Before an update:
docker compose ps
docker compose logs --tail=200 > pre-update.logUse an immutable Git tag or commit and pinned image digests. Then:
docker compose build --pull
docker compose up -d
sh smoke-online.shRollback means checking out the previous known-good commit and restoring the compatible data backup before rebuilding. Schema and policy migrations need an explicit compatibility plan; do not assume container rollback alone reverses stored state.
Backup warning#
The current SQLite volume is suitable only for the developer preview. Back it up while PALO services are stopped or through a SQLite-aware backup process. A production system requires a transactional database/outbox, tested restore, retention controls, key rotation and tamper-resistant evidence anchoring.
Remaining production boundary#
Putting the endpoint online does not make it production-ready. The shared-token identity model, optional n8n gate, evidence provenance, policy-bundle attestation, approval identity, cached authorization and effective resource-to-scope binding issues remain. Use mock, reversible or non-consequential actions until those findings are closed.
See the public Production Readiness route, Capability Matrix, and integration guide. Internal assessment workpapers are not published.
PALO FRAMEWORK