Skip to content

Container deployment

Tagged releases publish a Linux container image to:

text
registry.gitlab.com/bella.network/passbeyond:<version>

Images are available for the release architectures and run as the unprivileged passbeyond user with UID and GID 65532. Pin a release tag in production; latest can change without an explicit deployment edit.

Container filesystem

PathPurpose
/passbeyondExecutable and image entry point
/etc/passbeyond/Recommended read-only static configuration mount
/var/lib/passbeyond/Working directory and persistent dynamic state
/config/config.yamlExample file included in the image; not loaded automatically

PassBeyond defaults to ./config.yaml in its working directory. Select a mounted file explicitly with PASSBEYOND_CONFIG.

Prepare configuration and state

Create a static file named passbeyond.yaml:

yaml
domain: "myapp.example.com"
idpMetadataURL: "https://sso.example.com/path/to/metadata.xml"
configPath: "/var/lib/passbeyond/myapp.json"

proxy:
  listenAddress: ":8123"
  targetURL: "http://backend:8080"
  targetDisableSSLVerify: false
  stripVersionHeaders: true
  useBasicAuth: false
  trustedProxies:
    - "172.20.0.0/24"

sessionTimeout: 1440
samlRequestSigning: false

Use the real, narrow subnet or IP of the TLS proxy instead of the example CIDR. The backend name must resolve on the container network.

Prepare a persistent directory writable by the image user:

bash
mkdir -p ./passbeyond-state
sudo chown 65532:65532 ./passbeyond-state
sudo chmod 0750 ./passbeyond-state

Keep the static file outside the image and protect it when it contains passthrough tokens.

Run with Docker or Podman

Create a private network shared with the TLS proxy and backend:

bash
docker network create passbeyond-net

Run a pinned version:

bash
docker run -d \
  --name passbeyond-myapp \
  --restart unless-stopped \
  --network passbeyond-net \
  -p 127.0.0.1:8123:8123 \
  -e PASSBEYOND_CONFIG=/etc/passbeyond/myapp.yaml \
  -v "$PWD/passbeyond.yaml:/etc/passbeyond/myapp.yaml:ro" \
  -v "$PWD/passbeyond-state:/var/lib/passbeyond" \
  registry.gitlab.com/bella.network/passbeyond:<version>

Replace <version> with a release tag. Binding the published port to loopback is suitable when the TLS proxy runs on the host. When the TLS proxy is another container, do not publish the port publicly; route over the private network instead.

Podman accepts the same core options. On SELinux systems, add an appropriate volume label such as :Z according to the host policy.

Docker Compose example

yaml
services:
  passbeyond:
    image: registry.gitlab.com/bella.network/passbeyond:<version>
    restart: unless-stopped
    environment:
      PASSBEYOND_CONFIG: /etc/passbeyond/myapp.yaml
    volumes:
      - ./passbeyond.yaml:/etc/passbeyond/myapp.yaml:ro
      - ./passbeyond-state:/var/lib/passbeyond
    networks:
      - protected
    expose:
      - "8123"

  backend:
    image: your-backend-image:<version>
    restart: unless-stopped
    networks:
      - protected

networks:
  protected:
    internal: true

Attach the TLS proxy to protected as well, or use a second network that permits only the required path. Do not publish the backend port.

Environment-only configuration

Environment mode is accepted only when the required environment set is complete. It is not merged with YAML. Dynamic state still needs a writable file:

yaml
environment:
  PASSBEYOND_DOMAIN: myapp.example.com
  PASSBEYOND_IDP_METADATA_URL: https://sso.example.com/metadata.xml
  PASSBEYOND_CONFIG_PATH: /var/lib/passbeyond/myapp.json
  PASSBEYOND_PROXY_LISTEN_ADDRESS: :8123
  PASSBEYOND_PROXY_TARGET_URL: http://backend:8080
  PASSBEYOND_SESSION_TIMEOUT: "1440"

Prefer a mounted secret or orchestrator secret facility for passthrough tokens. Environment variables can be visible through container inspection and operational tooling.

Persistence and replicas

The dynamic JSON file contains the JWT secret, SAML private key, certificate, instance ID, and remote metadata cache. Without persistent storage, every recreated container rotates those values and invalidates sessions.

Run one active replica per instance. PassBeyond does not coordinate concurrent writes to a shared JSON file, and independent replicas generate incompatible session secrets. See Known limitations.

Health and readiness

The image has no built-in HEALTHCHECK, and PassBeyond has no dedicated health endpoint. A container being “running” proves only that the process has not exited.

Use layered checks:

  • process/container state;
  • /saml/metadata.xml through the private or public route;
  • metadata refresh and proxy error logs;
  • an external end-to-end authentication test.

Do not restart an otherwise healthy instance solely because the IdP is temporarily unavailable when cached metadata remains usable.

Logs

PassBeyond writes to standard output and error:

bash
docker logs --since 15m passbeyond-myapp
docker logs -f passbeyond-myapp

Configure rotation in the container runtime or log driver. See Logging and monitoring before exporting logs to a central system.

Upgrade

  1. Back up static configuration and the dynamic volume.
  2. Pull a reviewed, pinned release tag.
  3. Recreate the container without deleting its state volume.
  4. Inspect startup and metadata logs.
  5. Complete a test login, backend request, and logout.

Never use docker compose down -v during a routine upgrade; -v deletes the dynamic state volume.

Continue with Reverse proxies and Backup and restore.

Released under the MIT License.