Run the full SentinelX stack on your own infrastructure: agent + MCP bridge + Keycloak + Postgres, all wired up with
docker-compose. No dependency on any managed hub — you own the entire stack.This is the recommended path for users who want full data sovereignty, air-gapped deployments, or simply prefer to self-host.
Built on the classic single-host SentinelX core (
sentinelx-core) and the MCP bridge (sentinelx-core-mcp). Both component repos are archived (frozen) but their code is bundled here as docker images. Functional and supported as the official self-hosted edition.For the actively-developed multi-host cloud agent (separate model, connects to a managed or self-hosted hub), see pensados/sentinelx-cloud-core.
Live product (managed cloud option): sentinelx.pensa.ar
Docker deployment stack for SentinelX Core + SentinelX Core MCP.
Lets Claude, ChatGPT and other AI clients manage your server via the Model Context Protocol (MCP) — execute commands, edit files, restart services, monitor state — all from the AI chat interface.
curl -fsSL https://raw.githubusercontent.com/pensados/sentinelx-docker/main/install.sh | bashThe interactive installer asks 3 questions (exec mode, auth mode, domain) and handles everything else: clones the repo, generates secrets, writes .env, starts the stack, and prints the exact credentials to paste into Claude or ChatGPT.
SX_YES=1 \
SX_EXEC_MODE=host \
SX_AUTH_MODE=oidc \
SX_DOMAIN_MODE=manual \
SX_BASE_DOMAIN=yourdomain.com \
bash install.sh| Variable | Values | Description |
|---|---|---|
SX_EXEC_MODE |
host / container |
How commands run (see below) |
SX_AUTH_MODE |
simple / oidc |
Authentication mode |
SX_DOMAIN_MODE |
sslip / manual / cloudflare |
Domain setup |
SX_BASE_DOMAIN |
yourdomain.com |
Required for manual and cloudflare |
SX_YES |
1 |
Skip all confirmations |
SX_SKIP_DNS_WAIT |
1 |
Skip DNS propagation wait |
Add --dry-run to generate .env without starting containers.
bash ~/sentinelx-docker/install.sh --uninstallStops all containers, removes volumes, and deletes the install directory. Prints the DNS records and nginx blocks you need to clean up manually.
# Skip confirmation prompt
SX_YES=1 bash ~/sentinelx-docker/install.sh --uninstallYou can run multiple independent SentinelX stacks on the same host. Each instance needs its own install directory, domain/subdomain, and will automatically pick free ports.
# First instance (default location)
curl -fsSL https://raw.githubusercontent.com/pensados/sentinelx-docker/main/install.sh | bash
# → installs to ~/sentinelx-docker, auto-detects free ports
# Second instance
SENTINELX_DIR=~/sentinelx2 \
curl -fsSL https://raw.githubusercontent.com/pensados/sentinelx-docker/main/install.sh | bash
# → installs to ~/sentinelx2, picks next available portsEach instance gets its own:
- Docker volumes and networks (prefixed by directory name)
- Auto-detected ports — no conflicts with existing services
- Independent
.env, secrets and Keycloak realm - nginx server block (printed at the end of install)
To uninstall a specific instance:
SENTINELX_DIR=~/sentinelx2 SX_YES=1 bash ~/sentinelx2/install.sh --uninstallA shared secret token is set in the connector config. Fast to set up, good for personal use.
Stack: 2 containers — sentinelx-core + sentinelx-mcp
Connect to Claude: claude.ai → Settings → Connectors → Add custom connector
- URL:
https://sentinelx.yourdomain.com/mcp - Token: printed at the end of install (also in
.envasSENTINEL_TOKEN)
Full OAuth2/OIDC via Keycloak (bundled in the stack). Users log in with username + password. Supports multiple users, scopes, and audit logs. Required for Claude web / ChatGPT automatic OAuth flow.
Stack: 4 containers — sentinelx-core + sentinelx-mcp + keycloak + keycloak-db
After the stack starts, keycloak-setup runs automatically. At the end of the install you'll see everything you need:
── Add to Claude ────────────────────────────────────────────
1. Go to claude.ai → Settings → Connectors → Add custom connector
2. Name: SentinelX
3. URL: https://sentinelx.yourdomain.com/mcp
4. Advanced settings → OAuth:
OAuth Client ID: sentinelx-mcp
OAuth Client Secret: <generated>
5. Log in with: admin / <generated>
── Add to ChatGPT ───────────────────────────────────────────
1. Go to chatgpt.com → Settings → Connected apps → Add
2. URL: https://sentinelx.yourdomain.com/mcp
3. OAuth Client ID: sentinelx-mcp
4. OAuth Client Secret: <generated>
5. Log in with: admin / <generated>
── Keycloak admin console ───────────────────────────────────
URL: https://auth.yourdomain.com/admin
Username: admin
Password: <generated>
The credentials are also written to .env as OIDC_CLIENT_ID, OIDC_CLIENT_SECRET and KC_ADMIN_PASSWORD.
Cloudflare users: the auth subdomain (
auth.yourdomain.com) must be set to proxied=false (grey cloud / DNS only) in Cloudflare. Cloudflare's Bot Fight Mode blocks OAuth requests without a browser User-Agent, which breaks the Claude/ChatGPT login flow.
sentinelx-core runs with pid: host and privileged: true. Every command is executed via nsenter entering PID 1's namespaces — same filesystem, same network, same services as the host. The agent behaves identically to running natively.
Commands run inside an isolated container. No host access. Good for development or sandboxed environments. The allowlist is not enforced in this mode — Docker is the security boundary.
Claude / ChatGPT (MCP client)
│
│ HTTPS /mcp
▼
[nginx / Caddy — TLS termination]
│
│ HTTP :8099
▼
sentinelx-mcp 🐳 (OIDC validation, tool proxy)
│
│ HTTP :8091 (internal)
▼
sentinelx-core 🐳 (host mode: pid=host, privileged=true)
│
│ nsenter --target 1 --mount --uts --ipc --net --pid
▼
Host system (filesystem, systemd, docker, network)
─── OIDC mode only ──────────────────────────────────────
│
▼
keycloak 🐳 (:8080 internal) ← keycloak-db 🐳
│
│ HTTPS auth.yourdomain.com (proxied=false in Cloudflare)
▼
[nginx / Caddy — TLS termination]
- Docker Engine 20.10+
- Docker Compose v2
- Linux host (host mode requires Linux PID namespaces)
- A domain with DNS pointing to your server (for OIDC mode)
- nginx or Caddy for TLS termination (install.sh prints the config blocks)
git clone --recurse-submodules https://github.com/pensados/sentinelx-docker
cd sentinelx-docker
cp .env.example .env
# Edit .env — set SENTINEL_TOKEN and auth variables
docker compose up -d --build # simple auth
docker compose -f docker-compose.yml -f docker-compose.oidc.yml up -d --build # OIDC| Variable | Description |
|---|---|
SENTINEL_TOKEN |
Internal token between MCP and core |
SENTINEL_EXEC_MODE |
host or container |
CORE_PORT |
Port for sentinelx-core (auto-detected, default 8091) |
MCP_PORT |
Port for sentinelx-mcp (auto-detected, default 8099) |
OIDC_ISSUER |
OIDC issuer URL (set by keycloak-setup) |
OIDC_JWKS_URI |
JWKS endpoint for token validation (set by keycloak-setup) |
OIDC_CLIENT_ID |
OAuth client ID (set by keycloak-setup) |
OIDC_CLIENT_SECRET |
OAuth client secret (set by keycloak-setup) |
RESOURCE_URL |
Public HTTPS URL of this MCP endpoint |
AUTH_DOMAIN |
Subdomain for Keycloak (OIDC mode only) |
KC_ADMIN_PASSWORD |
Keycloak admin password (OIDC mode only) |
KC_DB_PASSWORD |
Keycloak DB password (OIDC mode only) |
KC_PORT |
Port for Keycloak (auto-detected, default 8180) |
privileged: true gives the container full access to the host. This is intentional — SentinelX is a trusted agent for infrastructure management.
Security layers:
- Command allowlist —
core/agent_docker.pydefines which commands the agent can run - OIDC/OAuth — only authenticated users with valid tokens and correct scopes reach the agent
- Network — core and MCP ports are bound to
127.0.0.1only; external access only via TLS reverse proxy
# Check status
cd ~/sentinelx-docker && docker compose -f docker-compose.yml -f docker-compose.oidc.yml ps
# View logs
docker compose -f docker-compose.yml -f docker-compose.oidc.yml logs -f
# Restart MCP only
docker compose -f docker-compose.yml -f docker-compose.oidc.yml restart sentinelx-mcp
# Stop (keeps volumes)
docker compose -f docker-compose.yml -f docker-compose.oidc.yml down
# Uninstall (removes everything)
bash ~/sentinelx-docker/install.sh --uninstall
# Update to latest version
git pull --recurse-submodules
docker compose -f docker-compose.yml -f docker-compose.oidc.yml up -d --build- sentinelx-core — the agent
- sentinelx-core-mcp — the MCP server
MIT
Docker deployment stack for SentinelX Core + SentinelX Core MCP.
Lets Claude, ChatGPT and other AI clients manage your server via the Model Context Protocol (MCP) — execute commands, edit files, restart services, monitor state — all from the AI chat interface.
curl -fsSL https://raw.githubusercontent.com/pensados/sentinelx-docker/main/install.sh | bashThe interactive installer asks 3 questions (exec mode, auth mode, domain) and handles everything else: clones the repo, generates secrets, writes .env, and starts the stack.
SX_YES=1 \
SX_EXEC_MODE=host \
SX_AUTH_MODE=oidc \
SX_DOMAIN_MODE=manual \
SX_BASE_DOMAIN=yourdomain.com \
bash install.sh| Variable | Values | Description |
|---|---|---|
SX_EXEC_MODE |
host / container |
How commands run (see below) |
SX_AUTH_MODE |
simple / oidc |
Authentication mode |
SX_DOMAIN_MODE |
sslip / manual / cloudflare |
Domain setup |
SX_BASE_DOMAIN |
yourdomain.com |
Required for manual and cloudflare |
SX_YES |
1 |
Skip all confirmations |
SX_SKIP_DNS_WAIT |
1 |
Skip DNS propagation wait |
Add --dry-run to generate .env without starting containers.
# Uninstall — stops containers, removes volumes and install directory
bash ~/sentinelx-docker/install.sh --uninstall
# or with SX_YES=1 to skip confirmation
SX_YES=1 bash ~/sentinelx-docker/install.sh --uninstallA shared secret token is set in the connector config. Fast to set up, good for personal use.
Stack: 2 containers — sentinelx-core + sentinelx-mcp
Full OAuth2/OIDC via Keycloak (bundled in the stack). Users log in with username + password. Supports multiple users, scopes, and audit logs. Required for Claude web / ChatGPT automatic OAuth flow.
Stack: 4 containers — sentinelx-core + sentinelx-mcp + keycloak + keycloak-db
After the stack starts, keycloak-setup runs automatically and prints:
============================================================
Keycloak setup complete!
OIDC Issuer: https://auth.yourdomain.com/realms/sentinelx
Client ID: sentinelx-mcp
Client Secret: <generated>
Admin console: https://auth.yourdomain.com/admin
Admin user: admin / KC_ADMIN_PASSWORD from .env
To connect Claude or ChatGPT:
1. Add connector URL: https://sentinelx.yourdomain.com/mcp
2. Advanced OAuth settings:
OAuth Client ID: sentinelx-mcp
OAuth Client Secret: <generated>
3. Log in with: admin / KC_ADMIN_PASSWORD
============================================================
The client_id and client_secret are also written to .env as OIDC_CLIENT_ID and OIDC_CLIENT_SECRET for reference.
Cloudflare users: the auth subdomain (
auth.yourdomain.com) must be set to proxied=false (grey cloud / DNS only) in Cloudflare. Cloudflare's Bot Fight Mode blocks OAuth requests without a browser User-Agent, which breaks the Claude/ChatGPT login flow.
sentinelx-core runs with pid: host and privileged: true. Every command is executed via nsenter entering PID 1's namespaces — same filesystem, same network, same services as the host. The agent behaves identically to running natively.
Commands run inside an isolated container. No host access. Good for development or sandboxed environments. The allowlist is not enforced in this mode — Docker is the security boundary.
Claude / ChatGPT (MCP client)
│
│ HTTPS /mcp
▼
[nginx / Caddy — TLS termination]
│
│ HTTP :8099
▼
sentinelx-mcp 🐳 (OIDC validation, tool proxy)
│
│ HTTP :8091 (internal)
▼
sentinelx-core 🐳 (host mode: pid=host, privileged=true)
│
│ nsenter --target 1 --mount --uts --ipc --net --pid
▼
Host system (filesystem, systemd, docker, network)
─── OIDC mode only ──────────────────────────────────────
│
▼
keycloak 🐳 (:8080 internal) ← keycloak-db 🐳
│
│ HTTPS auth.yourdomain.com
▼
[nginx / Caddy — TLS termination, proxied=false in Cloudflare]
- Docker Engine 20.10+
- Docker Compose v2
- Linux host (host mode requires Linux PID namespaces)
- A domain with DNS pointing to your server (for OIDC mode)
- nginx or Caddy for TLS termination (install.sh prints the config)
git clone --recurse-submodules https://github.com/pensados/sentinelx-docker
cd sentinelx-docker
cp .env.example .env
# Edit .env — set SENTINEL_TOKEN and auth variables
docker compose up -d --build # simple auth
docker compose -f docker-compose.yml -f docker-compose.oidc.yml up -d --build # OIDC| Variable | Description |
|---|---|
SENTINEL_TOKEN |
Internal token between MCP and core |
SENTINEL_EXEC_MODE |
host or container |
OIDC_ISSUER |
OIDC issuer URL (set by keycloak-setup) |
OIDC_JWKS_URI |
JWKS endpoint for token validation (set by keycloak-setup) |
OIDC_CLIENT_ID |
OAuth client ID (set by keycloak-setup) |
OIDC_CLIENT_SECRET |
OAuth client secret (set by keycloak-setup) |
RESOURCE_URL |
Public HTTPS URL of this MCP endpoint |
AUTH_DOMAIN |
Subdomain for Keycloak (OIDC mode only) |
KC_ADMIN_PASSWORD |
Keycloak admin password (OIDC mode only) |
KC_DB_PASSWORD |
Keycloak DB password (OIDC mode only) |
privileged: true gives the container full access to the host. This is intentional — SentinelX is a trusted agent for infrastructure management.
Security layers:
- Command allowlist —
core/agent_docker.pydefines which commands the agent can run - OIDC/OAuth — only authenticated users with valid tokens and correct scopes reach the agent
- Network — ports
8091and8099are bound to127.0.0.1only; external access only via TLS reverse proxy
# Logs
docker compose logs -f
# Restart
docker compose restart sentinelx-mcp
# Update submodules
git submodule update --remote --merge
git add sentinelx-core sentinelx-core-mcp
git commit -m "chore: update submodules"
docker compose up -d --build- sentinelx-core — the agent
- sentinelx-core-mcp — the MCP server
MIT