Skip to content

Deployment Guide

Version: 1.0.0 Target Audience: System Administrators / DevOps Engineers

This guide details the steps to deploy the ContextLoom Appliance in an on-premise or air-gapped environment.

  1. Container Runtime: Docker Engine (v20.10+) or Podman (v4.0+).
  2. Database (BYODB): PostgreSQL 15+ accessible from the container host.
  3. Network: outbound access to your Git Providers (GitHub/GitLab/Bitbucket) and Identity Provider (Okta/Azure AD).

The ContextLoom appliance is deployed using Docker Compose (or Podman Compose) and its configuration files.

  1. Download from GitHub: Obtain the compose.yml and .env.template files directly from the root of our public GitHub repository: https://github.com/kpruntov/context-loom
  2. Place Files: Create a directory on your server (e.g., /opt/contextloom) and place both compose.yml and .env.template inside it.

Create a deployment directory and prepare your configuration.

  1. Create .env file: Copy the .env.template to a new file named .env in the same directory.
  2. Generate Secret Key: The appliance needs a unique, secure key for signing tokens. Generate one and add it to your .env file.
    Terminal window
    # Generate a 32-byte (256-bit) hex key
    openssl rand -hex 32
    Copy the output into the SECRET_KEY variable in your .env file.
  3. Configure Database URL: Set the DATABASE_URL in your .env file to point to your existing PostgreSQL instance.

Example .env:

# --- SECURITY (Required) ---
# Paste your generated key here
SECRET_KEY=e8f9a0d1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9
# --- DATABASE (Required) ---
# Connection string to your PostgreSQL instance.
# Ensure the user has CREATE privileges on the database.
DATABASE_URL=postgresql+asyncpg://db_user:db_password@db.internal:5432/contextloom_db
# --- IDENTITY (Optional: SSO) ---
# Required if you purchased the "Identity Shield" module.
OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secret
OIDC_DISCOVERY_URL=https://company.okta.com/.well-known/openid-configuration

Step 3: Configure Deployment (docker-compose.yml)

Section titled “Step 3: Configure Deployment (docker-compose.yml)”

The standard deployment model for ContextLoom is Bring Your Own Database (BYODB). The compose.yml file is minimal, defining only the ContextLoom appliance itself.

The compose.yml you downloaded (from kpruntov/context-loom) is already configured to pull the latest image automatically.

Create a docker-compose.yml file:

version: '3.8'
services:
contextloom:
# Image will be automatically pulled from ghcr.io
image: ghcr.io/kpruntov/contextloom:latest
container_name: contextloom-appliance
restart: always
env_file:
- .env
# Port 8000 is internal only, accessed via the Proxy service.
# ports:
# - "8000:8000"
volumes:
# [Optional] Custom CA Bundle for Intranet Link
# - ./certs/corporate-ca.crt:/app/certs/custom-ca.crt:ro
extra_hosts:
# [Optional] DNS resolution for internal services if needed
# - "gitlab.internal:10.10.1.5"
proxy:
image: docker.io/library/caddy:alpine
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
depends_on:
- contextloom
volumes:
caddy_data:
caddy_config:

Create a file named Caddyfile in the same directory:

# Option 1: Automatic HTTPS (Public Domain)
# loom.example.com {
# reverse_proxy contextloom:8000
# }
# Option 2: Internal/Self-Signed HTTPS (Default)
:443 {
reverse_proxy contextloom:8000
tls internal
}
# Option 3: HTTP (Port 80)
:80 {
reverse_proxy contextloom:8000
}

Optional: Running a Local Database for Small Teams

Section titled “Optional: Running a Local Database for Small Teams”

If you do not have an existing PostgreSQL database and want to run one alongside the appliance for evaluation or a small team, you can add a db service to your compose.yml.

1. Update compose.yml: Add the db service definition to your compose.yml:

version: '3.8'
# ... volumes definition ...
services:
contextloom:
# ...
depends_on:
- db
# ...
proxy:
# ... Caddy definition ...
db:
image: postgres:15-alpine
restart: always
environment:
POSTGRES_DB: contextloom_db
POSTGRES_USER: contextloom_user
POSTGRES_PASSWORD: your-strong-password
volumes:
- db_data:/var/lib/postgresql/data
ports:
- "5432:5432"

2. Update your .env file: Ensure your DATABASE_URL matches the credentials used in the db service.

DATABASE_URL=postgresql+asyncpg://contextloom_user:your-strong-password@db:5432/contextloom_db

Note: The hostname db works because Docker Compose creates a network where services can reach each other by their service name.

Custom CA Configuration (Intranet Link): If your internal Git servers use self-signed certificates:

  1. Uncomment the volumes line in the contextloom service to mount your CA file.
  2. Add SSL_CA_BUNDLE_PATH=/app/certs/custom-ca.crt to your .env file.

If your server does not have internet access to pull the images from GitHub Container Registry:

  1. Transfer Artifacts: Copy contextloom-1.0.0.tar (provided in the release package) to the server.
  2. Load Image:
    Terminal window
    # Docker
    docker load -i contextloom-1.0.0.tar
    # Podman
    podman load -i contextloom-1.0.0.tar
  3. Start: Run docker compose up -d. The engine will use the locally loaded image.

Launch the container.

Terminal window
docker compose up -d

The first time you run this, Docker (or Podman) Compose will automatically pull the ghcr.io/kpruntov/context-loom:latest image for you.

Check the logs to ensure it started correctly and connected to the database:

Terminal window
docker compose logs -f

Success: You should see JSON logs indicating Application startup complete.


Step 5: Initialize Database (Run Migrations)

Section titled “Step 5: Initialize Database (Run Migrations)”

The database starts empty. You must apply the schema migrations to create the necessary tables.

Run the following command:

Terminal window
docker compose exec contextloom python -m alembic upgrade head

Expected Output: You will see a list of migrations being applied (e.g., ... Running upgrade -> fbc9bcfa705f ...).


The appliance comes with a locked-down “Distroless” runtime, so you cannot SSH into it. To create the initial Administrator account, you must run the ephemeral admin tool attached to the container’s network/environment.

Run the following command while the appliance is running:

Terminal window
docker compose exec contextloom python /app/admin_tools/create_superuser.py

Expected Output:

User admin@admin.com not found. Creating...
Superuser admin@admin.com created successfully.

Note: The default password is password. You must change this immediately upon login.


  1. Navigate to https://<your-server-ip> (or http if configured).
  2. Log in with:
    • Email: admin@admin.com
    • Password: password
  3. Go to Settings > Users and change your password.

Database Connection Failed:

  • Ensure the DATABASE_URL is correct.
  • Ensure the container host can reach the database port (Firewall/VPC Peering).

SSO Errors:

  • Check the OIDC_DISCOVERY_URL is reachable from inside the container.
  • Verify the OIDC_REDIRECT_URL in your Identity Provider matches https://<your-domain>/auth/oidc/callback.