Control SSH access and sudo privileges on your Linux servers from your SSO — no more per-server keys or sudoers.
Open Bastion integrates your servers with LemonLDAP::NG (LLNG) so you manage your Linux administrators as easily as you already manage your SSO users. Administrators define access rules once in the portal; the PAM/NSS modules enforce them on every server.
- The SSO decides SSH access — no SSH keys to install or rotate on each server; group membership grants or revokes access fleet-wide.
- The SSO decides
sudotoo — nosudoersto maintain per host (local/dual management stays possible when you want it). - Recordings the user can't touch — interactive sessions are streamed to a
root sink the recorded user cannot read, alter or delete, while
~/.ssh/configkeeps access visually direct. Recording is fail-closed: if the sink is unreachable, the login is refused. Coverage has known edges — a service account's nativessh -Jforwarded channel is not recorded, and containment hardening is opt-in — see service accounts and audit trace. - Fleet deployment in one command —
ob-builder --output-ansible <role>(or a self-extracting shell installer), then roll it out to every host. - A "backup" account with access everywhere — with or without
sudo— via service accounts. - Self-service onboarding — a new admin signs their SSH key at the portal and instantly has every right their groups grant.
- One-click offboarding — close the SSO account and access is gone.
- Instant role changes — change someone's groups and, within minutes, old rights drop and new ones apply.
Two layers do this: the SSO (LLNG) decides policy centrally, the PAM/NSS modules enforce it on each server. See Access & Permissions for exactly which control lives where.
These quick-starts cover the ways to get going — try it, point it at your SSO, then deploy:
| Quick-start | Use it to… |
|---|---|
| Try it in Docker | Spin up a LemonLDAP::NG portal + a self-enrolling SSH server in ~2 minutes and log in with an LLNG token — the fastest way to see Open Bastion work. |
| Configure your SSO | On your real LemonLDAP::NG: install the required plugins, and create the OIDC client(s) that carry your machines — the prerequisite before any deployment. |
| Deploy a fleet with Ansible | Generate bastion + backend roles with ob-builder, declare your hosts and IPs, and apply with ansible-playbook — the path to a real deployment. |
| Deploy with a shell installer | Generate a self-extracting installer per role with ob-builder --output-shell, then scp + sudo-run it on each host — no Ansible control node. |
For the underlying concepts and per-step manual configuration, see PAM Authentication Modes, the Configuration Reference, and the Admin Guide.
Each server is first enrolled by an administrator — installing the package and
registering the host with the SSO (ob-enroll, or the generated ob-builder
artefacts), which is also what assigns its server group. See the
Admin Guide (or the quick-starts)
for the enrollment step. Once enrolled:
- A user authenticates to a server — with an LLNG token (used as the SSH
password) or an SSO-signed SSH certificate (self-served via
ob-ssh-cert). pam_openbastionasks LLNG/pam/authorizewhether this user may access this server group, andsudois gated the same way; an encrypted local cache keeps this working during an SSO outage.- The NSS module resolves SSO users (and key-only service accounts) so the system sees them as real Unix accounts; provisioning creates the home on first login.
- To reach a backend behind a bastion, the bastion mints a short-lived,
LLNG-signed certificate and re-originates the connection with
ob-ssh/ob-scp/ob-sftp— no user key or agent on the bastion. Backends accept only vouched bastions.1 - Sessions are recorded inside the bastion to a tamper-evident, root-owned store for audit.
See Bastion Architecture and the documentation index for the details.
- Token introspection via OIDC introspection endpoint
- Server authorization via
/pam/authorizeendpoint - Server groups support for granular access control
- Token caching to reduce server load
- Secure communication with SSL/TLS support
- Easy server enrollment with
ob-enrollscript - Offline mode:
- Encrypted authorization cache (AES-256-GCM)
- Continue SSH key authentication when LLNG server is unavailable
- Configurable cache TTL with shorter TTL for high-risk services (sudo, su)
- Cache brute-force protection with rate limiting
- NSS module:
- Resolve users from LLNG via
/pam/userinfoendpoint - Automatic UID generation from username hash
- Cross-process file cache for performance
- Resolve users from LLNG via
- Automatic user provisioning:
- Auto-create Unix accounts on first login
- Configurable shell, home directory, UID/GID ranges
- Skeleton directory support
- Group synchronization:
- Sync Unix supplementary groups from LLNG on each login
- Automatic group creation if needed
- Local whitelist for defense-in-depth (
allowed_managed_groups) - Groups outside managed pool are never modified
- Service accounts (ansible, backup, etc.):
- SSH key authentication without OIDC
- Per-server configuration file
- Fine-grained sudo permissions
- Automatic account creation
- Bastion-to-backend authentication:
- Certificate-based proof of connection origin (LLNG-signed ephemeral SSH cert, ~120 s)
- Backends only accept SSH from authorized bastions (
allowed_bastions+source-addresscritical option) - No agent forwarding or user key on the bastion required
ob-ssh/ob-scp/ob-sftpscripts for seamless bastion connections and file transfers
- Session recording (optional):
- Record all terminal I/O for audit compliance
- Written by a root sink the recorded user cannot reach (
.typescript+.json; asciinema and ttyrec are planned, and currently fall back toscript) - Session metadata with unique IDs
- Security hardening:
- Structured JSON audit logging with correlation IDs
- Rate limiting with exponential backoff
- AES-256-GCM encrypted secret storage
- Webhook notifications for security events
- Token binding (IP, fingerprint)
- SSH key policy enforcement (allowed types, minimum sizes)
- CrowdSec integration (optional):
- Pre-authentication IP blocking via CrowdSec bouncer
- Post-authentication failure reporting via CrowdSec watcher
- Auto-ban after configurable failure threshold
- Compatible with Crowdsieve for centralized alert management
- Monitoring:
- Server heartbeat via
ob-heartbeat - Statistics reporting to portal
- Server heartbeat via
Desktop SSO (LightDM workstation login) also exists but is experimental (alpha) and is deliberately not listed among the features above — see the clearly-separated Desktop SSO section near the end of this README.
Pre-built packages are available for:
- Debian/Ubuntu: Debian 12, Debian 13, Ubuntu 24.04
- RHEL/Rocky Linux: Rocky Linux 9, Rocky Linux 10
See installation instructions at: https://linagora.github.io/open-bastion/
For administrators rolling Open Bastion out to several servers, a separate
open-bastion-builder package provides an interactive CLI (ob-builder)
that generates a self-extracting shell installer and/or an Ansible role
tailored to your SSO, scenario, and target role (bastion / standalone /
backend). Install it once on an admin workstation, run the questionnaire,
then push the resulting artefact to every target machine.
See admin-builder/README.md for the questionnaire, configuration keys, and usage examples.
# Install dependencies (Debian/Ubuntu)
sudo apt-get install libcurl4-openssl-dev libjson-c-dev libpam0g-dev libssl-dev libkeyutils-dev cmake curl jq
# Build
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
make
sudo make installSet CMAKE_INSTALL_PREFIX=/usr rather than taking CMake's /usr/local default:
the paths written into the generated sshd and PAM configuration are absolute
(/usr/sbin/ob-service-account-keys, for one), so a /usr/local install leaves
them pointing at files that are not there.
The full, theme-organized index is in doc/README.md. Highlights:
- Get started — Docker demo · Shell / Ansible quick-starts · Admin guide
- Connections & architecture — Bastion architecture · PAM modes · LLNG configuration
- Access & permissions — Access & Permissions (SSO-side vs server-side) · Service accounts
- Recording & audit — Session recording · Audit trace
- Offline & resilience — Offline mode · Cache administration
- Security & hardening — Security features · Hardening · CrowdSec
- Reference — Canonical names & paths · Configuration · Troubleshooting · Desktop SSO (experimental/alpha) · Competitors
- Security analysis (EBIOS RM) — full risk study (French) · conditions of use before deploying
Logs, debug mode, endpoint tests and common issues are collected in doc/troubleshooting.md.
- A LemonLDAP::NG system >= 2.23.0 with some additional plugins installed and enabled
- libcurl, json-c, OpenSSL, libkeyutils, PAM development headers
- curl and jq (for enrollment script)
⚠️ Experimental — not production-ready. Unlike the server-side SSH/sudo features above (the validated, supported core of Open Bastion), the LightDM workstation-login greeter is an early alpha prototype. Its authentication path has not had a security review and there is no test environment for it yet. Do not rely on it to protect access to a workstation. It is documented here for experimentation only and is intentionally kept separate from the features list.
Open Bastion can authenticate desktop workstations via LemonLDAP::NG Single Sign-On using LightDM.
# Install the greeter package
sudo apt install open-bastion-desktop
# Run the setup script
sudo ob-desktop-setup -p https://auth.example.com
# For offline mode support
sudo ob-desktop-setup -p https://auth.example.com --offline- SSO Authentication: Users login with their LLNG credentials via embedded portal
- Multi-Factor Authentication: Supports TOTP, WebAuthn/FIDO2, SMS, and more
- Offline Mode: Cached credentials allow login when LLNG is unreachable
- Session Selection: Choose between multiple desktop environments
- Desktop SSO Guide - Complete setup and configuration
- Offline Mode - Cached credential authentication
- Security Architecture - Security details
# Show cache statistics
sudo ob-cache-admin stats
# List cached users
sudo ob-cache-admin list
# Invalidate a user's cache (after termination)
sudo ob-cache-admin invalidate usernameAGPL-3.0
Xavier Guimard xguimard@linagora.com
Copyright (C) Linagora
Footnotes
-
This is optional, of course: you can keep non-Open-Bastion backends and manage them the old way, with SSH keys. ↩
