Skip to content

Security & Hardening

BRIDGEPORT secures your infrastructure with JWT authentication, role-based access control, AES-256-GCM encryption for secrets at rest, per-environment SSH keys, and per-server agent tokens.


BRIDGEPORT uses multiple security layers to protect your deployment infrastructure:

LayerMechanismPurpose
AuthenticationJWT tokens (7-day expiry) + API tokensVerify user identity
AuthorizationRBAC with three rolesControl what users can do
EncryptionAES-256-GCM (AEAD)Protect secrets, SSH keys, and credentials at rest
TransportHTTPS via reverse proxyProtect data in transit
SSHPer-environment encrypted keysIsolate server access by environment
AgentPer-server tokens (SHA-256 hashed)Authenticate agent metric pushes
AuditComprehensive action loggingTrack who did what and when

sequenceDiagram
    participant Client
    participant BRIDGEPORT
    participant Database

    Client->>BRIDGEPORT: POST /api/auth/login (email, password)
    BRIDGEPORT->>Database: Verify credentials (bcrypt)
    Database-->>BRIDGEPORT: User record
    BRIDGEPORT-->>Client: JWT token (7-day expiry)

    Client->>BRIDGEPORT: GET /api/servers (Authorization: Bearer <token>)
    BRIDGEPORT->>BRIDGEPORT: Verify JWT or API token
    BRIDGEPORT->>BRIDGEPORT: Check RBAC role
    BRIDGEPORT->>Database: Fetch data
    BRIDGEPORT-->>Client: 200 OK (data)

BRIDGEPORT supports two authentication methods:

  1. JWT tokens — issued on login, expire after 7 days, used by the web UI
  2. API tokens — long-lived tokens created by users for programmatic access (CI/CD, scripts). Tokens are stored as SHA-256 hashes and cannot be retrieved after creation.

Both methods use the same Authorization: Bearer <token> header. BRIDGEPORT tries API token validation first, then falls back to JWT verification.


BRIDGEPORT has three roles arranged in a strict hierarchy: admin > operator > viewer.

ActionAdminOperatorViewer
View servers, services, databasesYesYesYes
Reveal secret values (if allowSecretReveal enabled)YesNoNo
View audit logsYesYesYes
Deploy servicesYesYesNo
Manage secrets (create, update, delete)YesYesNo
Create/trigger backupsYesYesNo
Run health checksYesYesNo
Manage config filesYesYesNo
Create/delete serversYesNoNo
Create/delete environmentsYesNoNo
Manage usersYesNoNo
System settingsYesNoNo
Environment settingsYesNoNo
SMTP, Slack, webhook configurationYesNoNo
Service type and database type managementYesNoNo

The RBAC middleware is enforced at the route level using requireAdmin and requireOperator preHandlers. Every route that modifies data includes explicit authorization checks.


All sensitive data stored in the database is encrypted using AES-256-GCM (Authenticated Encryption with Associated Data):

  • Secrets (key-value pairs stored in the Secrets page)
  • SSH private keys (per-environment, configured in Settings)
  • Registry credentials (tokens and passwords for container registries)
  • SMTP passwords (for email notification delivery)
  • Slack webhook URLs
  • Spaces secret keys (for S3-compatible storage)
  1. A 32-byte MASTER_KEY is provided via environment variable
  2. Each encrypted value gets a unique 12-byte random IV (initialization vector)
  3. AES-256-GCM produces both the ciphertext and a 16-byte authentication tag
  4. The IV (nonce) and ciphertext+tag are stored as separate base64-encoded fields
  • The MASTER_KEY is never stored in the database. It exists only in your .env file or environment variables.
  • If the MASTER_KEY is lost, all encrypted data becomes irrecoverable. Store it securely in a password manager or secrets vault.
  • To rotate the MASTER_KEY, you would need to decrypt all values with the old key and re-encrypt with the new one. There is currently no automated rotation command.

The MASTER_KEY is the single most critical secret in your BRIDGEPORT deployment. Back it up separately from the database. Without it, encrypted secrets, SSH keys, and registry credentials cannot be recovered.


BRIDGEPORT uses per-environment SSH keys for secure server access:

  • Each environment has its own SSH private key, configured in Settings > SSH
  • Keys are encrypted with AES-256-GCM before being stored in the database
  • When BRIDGEPORT needs to connect to a server, it decrypts the key in memory
  • Keys are never written to disk in plaintext

This design provides:

  • Environment isolation: Staging and production use different keys
  • No key files on the container filesystem: Keys exist only in encrypted database storage
  • Centralized management: Upload keys once in the UI; they work for all servers in that environment

Each server running the BRIDGEPORT monitoring agent has a unique authentication token:

  • Tokens are generated as 32-byte random values (base64url-encoded)
  • Only the SHA-256 hash of the token is stored in the database
  • The plaintext token is shown once when the agent is deployed, then discarded
  • Tokens can be regenerated from the server detail page if compromised

The agent includes the token in every metrics push to authenticate itself. BRIDGEPORT verifies the hash on each request.


BRIDGEPORT can expose a curated subset of its API to AI agents via the Model Context Protocol. It is disabled by default and is a network-exposed surface, so treat enabling it as a deliberate security decision.

  • Off unless explicitly enabled. The /mcp route is registered only when MCP_ENABLED is true/1. The flag is strict-parsed and fails closed — a literal MCP_ENABLED=false (or 0, empty, or unset) keeps it off, and requests return 404. It is a deployment-level kill switch (an env var, not a runtime setting): flipping it off and restarting removes the endpoint entirely.
  • Same auth, same scopes. Every tool replays a real internal API request carrying the caller’s bearer token, so role/scope enforcement, validation, idempotency, and audit logging behave exactly as for a REST call — there is no separate MCP permission model. Mint a dedicated, environment-scoped, role-capped API token per client rather than reusing an admin credential; an env-scoped token is shown only the tools it can actually call.
  • Secrets never leave the host. A boundary redactor strips every secret-named field from all tool and resource output; list_secrets/list_vars return no values, and the admin-only secret-reveal endpoint is not exposed as a tool. Decrypted secrets cannot be read through MCP.
  • Mind data egress. Tool outputs — including container logs and audit entries, which can contain sensitive application output — are sent to whatever model the connected client uses. Only enable MCP, and only mint tokens, for operators you trust to route that data to their model.
  • Harden remote exposure. When reaching MCP through a reverse proxy, set MCP_ALLOWED_HOSTS to the public hostname(s) to enable DNS-rebinding protection, and terminate TLS exactly as for the REST API. MCP_ALLOWED_HOSTS is the public hostname, not the bind address (HOST).

Status, the live endpoint URL, and the full exposed tool/resource inventory are visible to admins at Admin > MCP Server (/admin/mcp). See the MCP Server Reference for client setup, the scope-to-tool mapping, and the full data-egress detail.


Use this checklist to secure your BRIDGEPORT deployment:

  • Run behind a reverse proxy with HTTPS — BRIDGEPORT itself serves HTTP. Use Caddy, nginx, or Traefik to terminate TLS. The included docker-compose.yml ships with a Caddy configuration.

  • Set strong MASTER_KEY and JWT_SECRET — Generate with openssl rand -base64 32. Never reuse these values across deployments.

  • Change default admin credentials — Set ADMIN_EMAIL and ADMIN_PASSWORD in your .env before first boot, then change the password via the UI.

  • Configure CORS_ORIGIN — Set this to your specific domain (e.g., https://deploy.example.com). In production, BRIDGEPORT defaults to rejecting cross-origin requests from unknown domains.

  • Run as non-root — The Docker image already runs as the node user (UID 1000). The docker-compose.yml sets user: "1000:1000".

  • Restrict network access — Limit access to port 3000 (or your reverse proxy port) to trusted networks. BRIDGEPORT is an internal tool, not a public-facing service.

  • Lock down the MCP server (only if enabled) — The MCP server is off by default. If you set MCP_ENABLED=true, mint a dedicated env-scoped, role-capped API token per client (never reuse an admin credential), set MCP_ALLOWED_HOSTS when exposing it through a reverse proxy, and remember that tool outputs — including logs — are sent to the connected client’s model. Leave it disabled if you don’t use it.

  • Set up firewall rules for SSH — BRIDGEPORT connects to your servers via SSH. Ensure only BRIDGEPORT’s IP (or network) can reach port 22 on managed servers.

  • Protect the Docker socket — If using socket mode for host container management, understand that mounting /var/run/docker.sock gives BRIDGEPORT full Docker daemon access.

  • Enable Sentry for error monitoring — Set SENTRY_BACKEND_DSN and SENTRY_FRONTEND_DSN to catch errors before your users do. Verify end-to-end delivery from Admin > Notifications > Sentry using the per-side test buttons.

  • Back up the SQLite database regularly — See Backup & Restore for automated backup strategies.

  • Review audit logs periodically — Check Admin > Audit for unexpected activity. Configure retention via System Settings.

  • Keep BRIDGEPORT updated — Pull the latest image regularly to get security patches. See Upgrades.


BRIDGEPORT maintains a comprehensive audit trail of all significant actions.

CategoryActions Tracked
Deploymentsdeploy, restart, rollback
Secretscreate, update, delete, access (reveal)
User Managementcreate, update, delete (users and API tokens)
Configurationcreate, update, delete (servers, services, environments, config files)
Backupsbackup, restore, schedule changes
Registriescreate, update, delete, credential changes
System SettingsAll changes to system-wide and environment settings
StorageSpaces configuration and per-environment toggle changes

Each audit log entry includes:

FieldDescription
actionWhat happened (deploy, create, update, delete, access)
resourceTypeWhat was affected (server, service, secret, environment, etc.)
resourceIdID of the affected resource
resourceNameHuman-readable name for display
detailsJSON string with additional context
successWhether the action succeeded
errorError message if it failed
userIdWho performed the action
environmentIdWhich environment was affected
createdAtWhen it happened
  • UI: Navigate to Admin > Audit. Filter by environment, resource type, action, and date range.
  • API: GET /api/audit-logs with query parameters for filtering.

Audit log retention is configurable via Admin > System Settings (auditLogRetentionDays). The default is 90 days. Set to 0 to keep audit logs forever. Cleanup runs automatically once per day.


If you discover a security vulnerability in BRIDGEPORT, please report it responsibly. See SECURITY.md for reporting instructions, response timeline expectations, and the scope of what constitutes a security issue.