Skip to content
Single-Server Deployment

Single-Server Deployment

In single-server mode, one container does everything: it serves the web app, listens for native connections, records sessions, and talks to your targets. It’s the simplest way to evaluate the Bridge or run it for a small team.

This guide deploys Bridge v3.0.0. Change both britive/bridge:latest lines in the Compose file to britive/bridge:v3.0.0, so the Bridge and its export service run the same release. If you already run v2, follow Upgrade to v3 before pulling the new image.

Single-server mode does not scale across machines or survive a host failure. For production, use the AWS or Kubernetes guide.

Overview

By the end of this guide you’ll have:

  • A PostgreSQL database running in a container.
  • The Bridge running in a container next to it.
  • The web app reachable in your browser.
  • SSH access to a target working through the Bridge.

We’ll use Docker Compose, a tool that runs several containers together from one file. If you can install Docker, you can follow this guide.

Before You Begin

You need:

  • The Bridge container image - pulled automatically from Docker Hub (britive/bridge); nothing to build.
  • A Linux host (or a Mac/Windows machine) with Docker and the Docker Compose plugin installed. Run docker --version and docker compose version to confirm.
  • About 2 GB of free memory for the containers.

What is a container? A container is a lightweight, self-contained package that includes the software and everything it needs to run. Docker is the tool that runs containers. You don’t install the Bridge onto your operating system - you run its container.

Deploy the Bridge

Generate the Encryption Key

The Bridge encrypts the credentials it stores in the database. You must give it a random 32-byte key, encoded as text (base64). Generate one:

terminal
openssl rand -base64 32

Copy the output (it looks like q7Fh2...=). You’ll put it in a .env file in the next step so it’s kept out of the compose file itself.

Save this key somewhere safe and reuse the same key every time you start the Bridge. If you lose it or change it, the credentials already stored in your database can no longer be decrypted.

Create the Configuration File

Create a folder for your deployment, and inside it a file named bridge.yaml. This minimal example turns on browser SSH and native SSH, and points at the PostgreSQL container we’ll start in the next step:

bridge.yaml
server:
  listen: "443"          # the web app + browser sessions
  log_level: "info"
  tls:
    enabled: true        # serve HTTPS with an auto-generated certificate
  datastore:             # PostgreSQL connection (the db service below)
    host: "postgres"
    port: 5432
    user: "bridge"
    password: "bridge"
    name: "bridge"
    sslmode: "disable"
  recording:
    output_dir: "/data/recordings"
  auth:
    types: ["britive"]   # log in with your Britive tenant
    britive:
      tenant: "your-tenant"   # subdomain only, e.g. "acme" — see /reference/finding-your-tenant

ssh:
  native:
    enabled: true
    listen: "22"
  browser:
    enabled: true
  idle_timeout: "30m"

Replace your-tenant with your Britive tenant subdomain — see Finding Your Tenant Name. You can also use LDAP instead of or alongside Britive - see Authentication. A complete, fully commented reference of every option is available to download: bridge.reference.yaml. You can also start from this exact sample: bridge.single.yaml.

The image already carries a complete single-container configuration at /etc/britive-bridge/config.yaml, with every protocol enabled. Mounting your own file at that path replaces it, which is what the steps below do. The sample is a short starting point, not that bundled file.

Create the Compose File

In the same folder, create docker-compose.yaml. This runs PostgreSQL and the Bridge together:

docker-compose.yaml
# Britive Bridge — standalone (single-container) deployment.
# One Bridge container + PostgreSQL. See:
#   https://learn.britive.com/bridge/deploy/single
#
# Before starting:
#   1. Put your encryption key in a .env file next to this file:
#        BRIDGE_ENCRYPTION_KEY_B64=<openssl rand -base64 32>   (keep it stable)
#   2. Set your tenant in bridge.yaml (server.auth.britive.tenant).
#   3. docker compose up -d   →   open https://localhost/
services:
  export:
    image: britive/bridge:latest
    restart: unless-stopped
    environment:
      BRIDGE_ROLE: export
    user: "102:103"
    network_mode: none
    read_only: true
    cap_drop: [ALL]
    security_opt: [no-new-privileges:true]
    mem_limit: "${BRIDGE_EXPORT_MEMORY:-1g}"
    cpus: "${BRIDGE_EXPORT_CPUS:-1}"
    tmpfs:
      - /tmp:size=1g,mode=1777
    volumes:
      - recordings:/data/recordings

  postgres:
    image: postgres:17-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: bridge
      POSTGRES_PASSWORD: bridge
      POSTGRES_DB: bridge
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "bridge"]
      interval: 5s
      retries: 10

  bridge:
    image: britive/bridge:latest        # pull from Docker Hub
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      # Path to the config file inside the container
      BRIDGE_CONFIG: /etc/britive-bridge/config.yaml
      # Read from the .env file next to this compose file. The :? makes
      # `docker compose up` fail fast if it isn't set. Keep this value stable.
      BRIDGE_ENCRYPTION_KEY_B64: "${BRIDGE_ENCRYPTION_KEY_B64:?set BRIDGE_ENCRYPTION_KEY_B64 (openssl rand -base64 32) in .env}"
      # Optional — Britive platform integration. The broker-pool token runs the
      # co-located Britive broker (JIT checkout provisioning) AND enables automatic
      # license retrieval + renewal. The broker creates checkouts against the Bridge
      # private checkout API with its own local credential file.
      # BRITIVE_BROKER_AUTH_TOKEN: "your-broker-pool-token"
      # BRITIVE_BROKER_TENANT_SUBDOMAIN: "your-tenant"                # e.g. acme
      # The broker uses http://127.0.0.1:8081. Do not publish this port.
    volumes:
      - ./bridge.yaml:/etc/britive-bridge/config.yaml:ro
      - recordings:/data/recordings
    ports:
      - "443:443"     # web app (https://localhost)
      - "22:22"       # native SSH

volumes:
  pgdata:
  recordings:

Put the key from Step 1 in a .env file in the same folder - Docker Compose reads it automatically, so the key stays out of the compose file:

.env
BRIDGE_ENCRYPTION_KEY_B64=<paste-your-key-here>

Prefer to download these? Grab the ready-made docker-compose.single.yaml and bridge.single.yaml (rename it to bridge.yaml), drop them in a folder, set your tenant in the config, and put your encryption key in a .env file as shown above. The first time you start, Docker pulls britive/bridge:latest from Docker Hub automatically.

Start It

From your folder, run:

terminal
docker compose up -d

This downloads PostgreSQL, starts both containers, and runs the Bridge in the background. The first start takes a minute while the database initializes and the Bridge applies its schema.

Watch the logs to confirm it came up cleanly:

terminal
docker compose logs -f bridge

You’re looking for lines showing the database connection succeeded, migrations applied, and the server is listening. Press Ctrl+C to stop watching the logs (the container keeps running).

Verify

Open the web app

Visit https://localhost/ in your browser. Because the Bridge generated its own certificate, your browser will warn you the connection isn’t trusted - that’s expected for a self-signed certificate. Accept the warning to continue, and log in with your Britive tenant.

Check the API is healthy

From the command line:

terminal
curl -k https://localhost/api/license/status

You should get a JSON response (the -k flag tells curl to accept the self-signed certificate).

Connect through the Bridge

Once you have a checkout for an SSH target, you can connect natively:

terminal
ssh -p 22 <your-checkout-user>@localhost

Troubleshoot

Bridge waits for PostgreSQL during startup in v3.0.1 and later. A datastore not reachable yet, retrying log means startup is waiting, not that Bridge has exited. Check database reachability and status. Rejected credentials or a missing database still stop startup. See Startup recovery.

SymptomLikely CauseFix
Bridge container restarts immediatelyInvalid configuration, rejected database credentials, or a missing database. v3.0.0 also exits when the database is unreachable.Run docker compose logs bridge. Check the datastore settings match the postgres service, and that your YAML is valid.
“encryption key” error on startupBRIDGE_ENCRYPTION_KEY_B64 missing or not valid base64Regenerate with openssl rand -base64 32 and paste the full value.
Can’t open the web appPort already in use, or TLS confusionMake sure nothing else uses port 443; try https:// (not http://).
Browser says the certificate is invalidThe Bridge uses a self-signed certificateExpected in a trial. For production, put a load balancer or reverse proxy with a real certificate in front.
Login failsWrong tenant, or auth not configuredConfirm auth.britive.tenant; see Authentication.

Next Steps

Last updated on