Try describing what you need:

Cardea logo

Cardea

★ 37
European Union Public License 1.2Open Source — No Paywall3 Containers — 3 containers — light hosting footprintDocker · BinaryNo external DB1 active committer (12mo)

About

Cardea is an SSH bastion server aimed at small and mid-sized teams that manage infrastructure through code. It lets administrators define access rules in a text file, which makes permissions...

Community Ratings

No ratings yet

Features

  • Access control rules
  • Session recording
  • TPM-backed key protection
  • Authorized-keys-based access rules
  • Known hosts validation
  • Connection and forwarding limits
  • Rate limiting
  • Session retention
  • Health/metrics server
  • Configurable logging

Details

Last Updated
Nov 2, 2026
Created
Oct 7, 2025
Install Methods
dockerbinary
Requirements
SSH clientsTPM device (optional, for TPM mode)No databaseNo web UI
Authentication
local
Backup & Export
file-backup
Runtime / Stack
GoDocker
Privacy & Independence
No Cloud RequiredOffline Capable
Deployment

Deployment: Docker Compose ✓3 Containers — light hosting footprintRuns as 3 containers

Run Cardea yourself

Pick how much you want to manage.

1 more way to host

Some links earn us a commission. netcup pays us one and is our preferred VPS host.

Is this your project? Sponsor a listing

Run Cardea with Docker Compose

Compose file from the Cardea project repository.

3 services · 2 unclassified (prometheus, grafana)

no resource limits declared

needs persistent storage (6 volumes)

compose.yaml · @ edc427d · scanned Nov 3, 2026

# yaml-language-server: $schema=https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json
name: "cardea"

services:
  cardea:
    image: "cardea"
    pull_policy: "build"
    build: { context: "./" }
    deploy:
      mode: "replicated"
      replicas: "${CARDEA_REPLICAS:-1}"
    restart: "always"
    read_only: true
    user: "${CARDEA_UID:-1000}:${CARDEA_GID:-1000}"
    networks:
      - "cardea"
    ports:
      - "${CARDEA_SSH_PORT_RANGE:-2222-2222}:2222/tcp"
      - "127.0.0.1:${CARDEA_HTTP_PORT_RANGE:-9222-9222}:9222/tcp"
    volumes:
      - { type: "bind", source: "./data/", target: "/data/" }
      - { type: "tmpfs", target: "/run/" }
      - { type: "tmpfs", target: "/tmp/", tmpfs: { mode: 0o1777 } }
    devices:
      - "/dev/tpmrm0:/dev/tpmrm0"
    environment:
      CARDEA_NODE_ID: "${CARDEA_NODE_ID:-$${HOSTNAME}}"
      CARDEA_KEY_STRATEGY: "${CARDEA_KEY_STRATEGY:-file}"
      CARDEA_PRIVATE_KEY_PASSPHRASE: "${CARDEA_PRIVATE_KEY_PASSPHRASE:-}"
      CARDEA_TPM_PARENT_HANDLE: "${CARDEA_TPM_PARENT_HANDLE:-}"
      CARDEA_TPM_PARENT_AUTH: "${CARDEA_TPM_PARENT_AUTH:-}"
      CARDEA_TPM_KEY_AUTH: "${CARDEA_TPM_KEY_AUTH:-}"
      CARDEA_UNKNOWN_HOSTS_POLICY: "${CARDEA_UNKNOWN_HOSTS_POLICY:-tofu}"
      CARDEA_LOG_LEVEL: "${CARDEA_LOG_LEVEL:-debug}"

  prometheus:
    image: "docker.io/prom/prometheus:v3.12.0"
    profiles: ["metrics"]
    restart: "always"
    hostname: "prometheus"
    networks:
      - "cardea"
    ports:
      - "127.0.0.1:9090:9090/tcp"
    volumes:
      - { type: "volume", source: "prometheus-data", target: "/prometheus/" }
      - { type: "tmpfs", target: "/run/" }
      - { type: "tmpfs", target: "/tmp/", tmpfs: { mode: 0o1777 } }
    configs:
      - { source: "prometheus-config", target: "/etc/prometheus/prometheus.yml" }
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
      - "--storage.tsdb.path=/prometheus/"

  grafana:
    image: "docker.io/grafana/grafana:13.1.0-25893932881"
    profiles: ["metrics"]
    restart: "always"
    hostname: "grafana"
    networks:
      - "cardea"
    ports:
      - "127.0.0.1:3000:3000/tcp"
    configs:
      - { source: "grafana-datasources", target: "/etc/grafana/provisioning/datasources/datasources.yaml" }
      - { source: "grafana-dashboards", target: "/etc/grafana/provisioning/dashboards/dashboards.yaml" }
      - { source: "grafana-cardea-dashboard", target: "/var/lib/grafana/dashboards/cardea.json" }
    environment:
      GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH: "/var/lib/grafana/dashboards/cardea.json"
      GF_AUTH_ANONYMOUS_ENABLED: "true"
      GF_AUTH_ANONYMOUS_ORG_ROLE: "Viewer"
      GF_AUTH_BASIC_ENABLED: "false"
      GF_AUTH_DISABLE_LOGIN_FORM: "true"
      GF_USERS_ALLOW_SIGN_UP: "false"
      GF_USERS_ALLOW_ORG_CREATE: "false"
      GF_SECURITY_DISABLE_GRAVATAR: "true"
      GF_EXPLORE_ENABLED: "false"
      GF_PROFILE_ENABLED: "false"
      GF_SNAPSHOTS_ENABLED: "false"
      GF_UNIFIED_ALERTING_ENABLED: "false"
      GF_HELP_ENABLED: "false"
      GF_NEWS_NEWS_FEED_ENABLED: "false"
      GF_ANALYTICS_ENABLED: "false"
      GF_ANALYTICS_REPORTING_ENABLED: "false"
      GF_ANALYTICS_CHECK_FOR_UPDATES: "false"
      GF_ANALYTICS_CHECK_FOR_PLUGIN_UPDATES: "false"
      GF_ANALYTICS_FEEDBACK_LINKS_ENABLED: "false"
      GF_PLUGINS_PLUGIN_ADMIN_ENABLED: "false"
      GF_PLUGINS_PUBLIC_KEY_RETRIEVAL_DISABLED: "true"
      GF_PLUGINS_PUBLIC_KEY_RETRIEVAL_ON_STARTUP: "false"
      GF_PLUGINS_PREINSTALL: ""
      GF_PLUGINS_DISABLE_PLUGINS: >-
        elasticsearch,
        grafana-exploretraces-app,
        grafana-lokiexplore-app,
        grafana-metricsdrilldown-app,
        grafana-pyroscope-app,
        zipkin

configs:
  prometheus-config:
    content: |
      global:
        scrape_interval: "5s"
      scrape_configs:
        - job_name: "cardea"
          dns_sd_configs:
            - names: ["cardea"]
              type: "A"
              port: 9222
          metrics_path: "/metrics"
          scheme: "http"

  grafana-datasources:
    content: |
      apiVersion: 1
      datasources:
        - uid: "prometheus"
          name: "prometheus"
          type: "prometheus"
          access: "proxy"
          url: "http://prometheus:9090"
          isDefault: true
          editable: false
          jsonData:
            timeInterval: "5s"
            queryTimeout: "5s"

  grafana-dashboards:
    content: |
      apiVersion: 1
      providers:
        - name: "dashboards"
          type: "file"
          disableDeletion: true
          allowUiUpdates: false
          updateIntervalSeconds: 3600
          options:
            path: "/var/lib/grafana/dashboards/"
            foldersFromFilesStructure: false

  grafana-cardea-dashboard:
    content: |
      {
        "uid": "cardea", "title": "Cardea", "schemaVersion": 39, "editable": false, "refresh": "5s",
        "templating": {
          "list": [{
            "name": "datasource",
            "label": "Data source",
            "type": "datasource",
            "query": "prometheus",
            "hide": 2
          }, {
            "name": "node",
            "label": "Node",
            "type": "query",
            "datasource": { "type": "prometheus", "uid": "$${datasource}" },
            "query": "label_values(cardea_node_info, node_id)",
            "refresh": 2,
            "multi": true,
            "includeAll": true,
            "allValue": ".*"
          }]
        },
        "panels": [
          {
            "title": "Active connections and sessions", "type": "stat",
            "gridPos": { "h": 4, "w": 12, "x": 0, "y": 0 },
            "datasource": { "type": "prometheus", "uid": "$${datasource}" },
            "options": { "graphMode": "none", "textMode": "value_and_name", "wideLayout": false, "justifyMode": "center" },
            "targets": [
              { "expr": "sum(cardea_connections_active * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Connections", "refId": "A" },
              { "expr": "sum(cardea_sessions_active * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Sessions", "refId": "B" }
            ]
          },
          {
            "title": "Active forwards", "type": "stat",
            "gridPos": { "h": 4, "w": 12, "x": 12, "y": 0 },
            "datasource": { "type": "prometheus", "uid": "$${datasource}" },
            "options": { "graphMode": "none", "textMode": "value_and_name", "wideLayout": false, "justifyMode": "center" },
            "targets": [
              { "expr": "sum(cardea_port_forwards_local_active * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Local port", "refId": "A" },
              { "expr": "sum(cardea_port_forwards_remote_active * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Remote port", "refId": "B" },
              { "expr": "sum(cardea_socket_forwards_local_active * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Local socket", "refId": "C" },
              { "expr": "sum(cardea_socket_forwards_remote_active * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Remote socket", "refId": "D" }
            ]
          },
          {
            "title": "Connections and sessions", "type": "timeseries",
            "gridPos": { "h": 8, "w": 12, "x": 0, "y": 4 },
            "datasource": { "type": "prometheus", "uid": "$${datasource}" },
            "targets": [
              { "expr": "sum by (node_id) (cardea_connections_active * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Active connections ({{node_id}})", "refId": "A" },
              { "expr": "sum by (node_id) (cardea_sessions_active * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Active sessions ({{node_id}})", "refId": "B" },
              { "expr": "sum by (node_id) (rate(cardea_connections_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Connections/s ({{node_id}})", "refId": "C" },
              { "expr": "sum by (node_id) (rate(cardea_sessions_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Sessions/s ({{node_id}})", "refId": "D" }
            ]
          },
          {
            "title": "Network traffic", "type": "timeseries",
            "gridPos": { "h": 8, "w": 12, "x": 12, "y": 4 },
            "datasource": { "type": "prometheus", "uid": "$${datasource}" },
            "fieldConfig": { "defaults": { "unit": "Bps" } },
            "targets": [
              { "expr": "sum by (node_id) (rate(cardea_received_bytes_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Received ({{node_id}})", "refId": "A" },
              { "expr": "sum by (node_id) (rate(cardea_sent_bytes_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Sent ({{node_id}})", "refId": "B" }
            ]
          },
          {
            "title": "Authentication", "type": "timeseries",
            "gridPos": { "h": 8, "w": 12, "x": 0, "y": 12 },
            "datasource": { "type": "prometheus", "uid": "$${datasource}" },
            "targets": [
              { "expr": "sum by (node_id) (rate(cardea_auth_successes_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Successes/s ({{node_id}})", "refId": "A" },
              { "expr": "sum by (node_id, reason) (rate(cardea_auth_failures_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Failures/s {{reason}} ({{node_id}})", "refId": "B" }
            ]
          },
          {
            "title": "Backend errors", "type": "timeseries",
            "gridPos": { "h": 8, "w": 12, "x": 12, "y": 12 },
            "datasource": { "type": "prometheus", "uid": "$${datasource}" },
            "targets": [
              { "expr": "sum by (node_id, reason) (rate(cardea_backend_errors_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "{{reason}}/s ({{node_id}})", "refId": "A" }
            ]
          },
          {
            "title": "Port forwards", "type": "timeseries",
            "gridPos": { "h": 8, "w": 8, "x": 0, "y": 20 },
            "datasource": { "type": "prometheus", "uid": "$${datasource}" },
            "targets": [
              { "expr": "sum by (node_id) (cardea_port_forwards_local_active * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Local active ({{node_id}})", "refId": "A" },
              { "expr": "sum by (node_id) (cardea_port_forwards_remote_active * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Remote active ({{node_id}})", "refId": "B" },
              { "expr": "sum by (node_id) (rate(cardea_port_forwards_local_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Local/s ({{node_id}})", "refId": "C" },
              { "expr": "sum by (node_id) (rate(cardea_port_forwards_remote_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Remote/s ({{node_id}})", "refId": "D" }
            ]
          },
          {
            "title": "Socket forwards", "type": "timeseries",
            "gridPos": { "h": 8, "w": 8, "x": 8, "y": 20 },
            "datasource": { "type": "prometheus", "uid": "$${datasource}" },
            "targets": [
              { "expr": "sum by (node_id) (cardea_socket_forwards_local_active * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Local active ({{node_id}})", "refId": "A" },
              { "expr": "sum by (node_id) (cardea_socket_forwards_remote_active * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Remote active ({{node_id}})", "refId": "B" },
              { "expr": "sum by (node_id) (rate(cardea_socket_forwards_local_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Local/s ({{node_id}})", "refId": "C" },
              { "expr": "sum by (node_id) (rate(cardea_socket_forwards_remote_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Remote/s ({{node_id}})", "refId": "D" }
            ]
          },
          {
            "title": "Rejections", "type": "timeseries",
            "gridPos": { "h": 8, "w": 8, "x": 16, "y": 20 },
            "datasource": { "type": "prometheus", "uid": "$${datasource}" },
            "targets": [
              { "expr": "sum by (node_id) (rate(cardea_rate_limit_rejections_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Rate limit/s ({{node_id}})", "refId": "A" },
              { "expr": "sum by (node_id) (rate(cardea_connection_rejections_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Connection limit/s ({{node_id}})", "refId": "B" },
              { "expr": "sum by (node_id) (rate(cardea_session_rejections_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Session limit/s ({{node_id}})", "refId": "C" },
              { "expr": "sum by (node_id) (rate(cardea_forward_rejections_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Forward limit/s ({{node_id}})", "refId": "D" }
            ]
          },
          {
            "title": "Go concurrency",
            "type": "timeseries",
            "gridPos": { "h": 8, "w": 8, "x": 0, "y": 28 },
            "datasource": { "type": "prometheus", "uid": "$${datasource}" },
            "targets": [
              { "expr": "sum by (node_id) (go_goroutines * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Goroutines ({{node_id}})", "refId": "A" },
              { "expr": "sum by (node_id) (go_threads * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Threads ({{node_id}})", "refId": "B" },
              { "expr": "sum by (node_id) (go_sched_gomaxprocs_threads * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "GOMAXPROCS ({{node_id}})", "refId": "C" }
            ]
          },
          {
            "title": "Go GC activity",
            "type": "timeseries",
            "gridPos": { "h": 8, "w": 8, "x": 8, "y": 28 },
            "datasource": { "type": "prometheus", "uid": "$${datasource}" },
            "targets": [
              { "expr": "sum by (node_id) (rate(go_gc_cycles_total_gc_cycles_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Total GC cycles/s ({{node_id}})", "refId": "A" },
              { "expr": "sum by (node_id) (rate(go_gc_cycles_automatic_gc_cycles_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Auto GC cycles/s ({{node_id}})", "refId": "B" },
              { "expr": "sum by (node_id) (rate(go_gc_cycles_forced_gc_cycles_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Forced GC cycles/s ({{node_id}})", "refId": "C" }
            ]
          },
          {
            "title": "Go contention",
            "type": "timeseries",
            "gridPos": { "h": 8, "w": 8, "x": 16, "y": 28 },
            "datasource": { "type": "prometheus", "uid": "$${datasource}" },
            "fieldConfig": { "defaults": { "unit": "s" } },
            "targets": [
              { "expr": "sum by (node_id) (rate(go_sync_mutex_wait_total_seconds_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Mutex wait/s ({{node_id}})", "refId": "A" }
            ]
          },
          {
            "title": "Go memory usage",
            "type": "timeseries",
            "gridPos": { "h": 8, "w": 12, "x": 0, "y": 36 },
            "datasource": { "type": "prometheus", "uid": "$${datasource}" },
            "fieldConfig": { "defaults": { "unit": "bytes" } },
            "targets": [
              { "expr": "sum by (node_id) (go_gc_heap_live_bytes * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Heap live ({{node_id}})", "refId": "A" },
              { "expr": "sum by (node_id) (go_gc_scan_heap_bytes * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Scan heap ({{node_id}})", "refId": "B" },
              { "expr": "sum by (node_id) (go_gc_scan_stack_bytes * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Scan stack ({{node_id}})", "refId": "C" },
              { "expr": "sum by (node_id) (go_gc_scan_total_bytes * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Scan total ({{node_id}})", "refId": "D" },
              { "expr": "sum by (node_id) ((go_gc_gomemlimit_bytes < 9223372036854775807) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Memory limit ({{node_id}})", "refId": "E" }
            ]
          },
          {
            "title": "Go memory activity",
            "type": "timeseries",
            "gridPos": { "h": 8, "w": 12, "x": 12, "y": 36 },
            "datasource": { "type": "prometheus", "uid": "$${datasource}" },
            "targets": [
              { "expr": "sum by (node_id) (rate(go_gc_heap_tiny_allocs_objects_total[$$__rate_interval]) * on(job, instance) group_left(node_id) cardea_node_info{node_id=~\"$$node\"})", "legendFormat": "Tiny allocs/s ({{node_id}})", "refId": "A" }
            ]
          }
        ]
      }

volumes:
  prometheus-data:

networks:
  cardea:

This file may be out of date. Check the Cardea documentation for current setup steps.

Track your self-hosted stack

Bookmark software to try, rate tools you've used, and keep your collection in one place.

Metadata extracted from README on Jun 7, 2026

Alternatives to Cardea

Warpgate logo

Warpgate

8.2k
A transparent bastion host for SSH, HTTPS, Kubernetes, MySQL, and PostgreSQL that records sessions and provides a built-in web admin UI.
Remote AccessProxy ServersAuthentication Services+2
Details
Teleport logo

Teleport

21.1k
Teleport is an identity-aware access platform for securing and auditing access to infrastructure, applications, databases, Kubernetes, and cloud services.
Miscellaneous ToolsRemote AccessAuthentication Services+3
Open Core
Details
Engity's Bifröst logo

Engity's Bifröst

87
Bifröst is an advanced SSH server that can replace OpenSSH Server and adds OpenID Connect/OAuth2-based access, Docker container execution, and Kubernetes pod execution.
Remote AccessAuthentication ServicesNetwork Utilities+1
Details
ShellHub logo

ShellHub

2.2k
ShellHub is an SSH gateway for centrally managing access to Linux devices and servers behind NAT and firewalls.
Remote AccessPermissive LicenseNetwork Utilities+2
4 Containers
Details

Related Software

Infisical Community Edition logo

Infisical Community Edition

30.4k
Infisical is an open-source secret management platform for syncing secrets and configs across teams and infrastructure, with support for PKI, KMS, SSH certificates, and secret leak prevention.
Miscellaneous ToolsSecret ManagementSelf Hosting Solutions+4
FOSS with Issues
Details
Infisical logo

Infisical

30.4k
Infisical is an open-source secret management platform for centralizing application secrets, configs, and internal PKI.
Secret ManagementPermissive LicenseSelf Hosting Solutions+3
FOSS with Issues
Details
BunkerWeb logo

BunkerWeb

11.2k
BunkerWeb is an open-source web application firewall and reverse proxy based on NGINX that secures web services by default.
Web ServersCopyleft LicenseProxy Servers+1
6 ContainersOpen Core
Details
agent-vault logo

agent-vault

2.5k
An open-source HTTP credential proxy and vault that brokers API credentials for AI agents without exposing the secrets directly to the agents.
Secret ManagementProxy ServersSelf Hosting Solutions+2
2 Containers
Details
GitProxy logo

GitProxy

264
GitProxy sits between developers and a Git remote to enforce push policies and security checks on outgoing git push operations.
Proxy Servers
9 Containers
Details
sish logo

sish

4.8k
Open source SSH tunneling software for forwarding HTTP(S), WS(S), TCP, aliases, and SNI traffic using plain SSH.
Proxy ServersNetwork UtilitiesRemote Access+2
Details
Vaultwarden logo

Vaultwarden

70.5k
A self-hosted alternative server implementation of the Bitwarden Client API, compatible with official Bitwarden clients.
Password ManagersCopyleft LicenseSecret Management+1
Single Container
Details
cerbos logo

cerbos

4.7k
Cerbos is an authorization layer and policy decision point that evaluates YAML-based access control rules for application resources.
Authentication ServicesSelf Hosting SolutionsPermissive License
Telemetry: Opt-Out
Details
SWAG (Secure Web Application Gateway) logo

SWAG (Secure Web Application Gateway)

3.8k
SWAG is a LinuxServer.io container that provides an Nginx reverse proxy with PHP support, automated SSL certificate generation/renewal, and fail2ban-based intrusion prevention.
Web ServersProxy ServersSelf Hosting Solutions+4
Details
Jauth logo

Jauth

188
Jauth is a lightweight SSL/TLS reverse proxy with authorization for self-hosted applications, including optional single sign-on.
Web ServersCopyleft LicenseProxy Servers+2
Details