One of the most persistent architectural failures in the self-hosted ecosystem is “identity sprawl.”
When engineers first begin building out a private infrastructure stack, they inevitably stand up a dozen disparate services: a chat server, a file sync instance, an email relay, and a password manager. By default, every single one of these services maintains its own isolated database of usernames, cryptographic salts, and password hashes.
For an individual hobbyist, this is an annoyance. For an organization running a zero-footprint infrastructure appliance, it is a catastrophic security vulnerability and an administrative nightmare. If a contractor is offboarded, an administrator has to manually hunt down and revoke access across five different databases. If a user has poor password hygiene on their file-sync account, it compromises the perimeter regardless of how secure their VPN key is.
When engineering the Remote Rails Sovereign Appliance, we realized that true digital sovereignty requires absolute, centralized control over the identity perimeter. You cannot claim to own your network if you are managing a dozen fractured authentication silos.
Here is how we killed the local account by architecting a Single Source of Truth (SSOT) using Defguard as an OpenID Connect (OIDC) provider, and seamlessly binding it across the entire stack—spanning Vaultwarden, Nextcloud, and Matrix—for zero-touch identity provisioning.
The Architecture: Defguard as the Identity Gatekeeper
To eliminate local accounts, you need an Identity Provider (IdP). While enterprise environments typically rely on massive, resource-heavy directories like Active Directory or Keycloak, a lean, modern sovereign stack requires something much more precise.
We utilize Defguard (defguard-core). Defguard is a rust-based, WireGuard-centric identity and access management platform. It does not just issue VPN configurations; it acts as a fully compliant OpenID Connect (OIDC) provider.
By mounting a central oidc.pem key into the Defguard container and exposing its authentication URLs via Traefik routing rules, Defguard becomes the central authority for our entire stack. No other service is allowed to authenticate a user independently.
The Ultimate Stress Test: Executing the Vaultwarden Integration
While your chat and file-sync servers are the daily workhorses of your stack, Vaultwarden (the lightweight, rust-based Bitwarden compatible server) is notoriously locked-down. We focus on its integration first because it serves as the ultimate stress test for an external IdP. Historically, binding it to an external identity provider was clunky. However, with native enterprise SSO support enabled, we can force Vaultwarden to completely abandon its local user database logic.
In our Docker stack, we apply a specific matrix of environment variables to the vaultwarden service to achieve this strict integration:
1. Establishing the Cryptographic Handshake First, we tell Vaultwarden where to look for the source of truth. We set SSO_ENABLED=true and point the SSO_AUTHORITY directly to the defguard.${DOMAIN} endpoint. We inject the SSO_CLIENT_ID and SSO_CLIENT_SECRET (generated by Defguard) to ensure Vaultwarden is securely paired with the IdP. We restrict the data exchange to the absolute minimum required by setting the SSO_SCOPES strictly to email profile.
2. Killing the Local Registration & Forcing the Bottleneck A sovereign password manager should not have a “Sign Up” button facing the web. We explicitly hardcode SIGNUPS_ALLOWED=false, completely disabling the native registration flow. We then force all authentication through Defguard by setting SSO_ONLY=true. This removes the standard username/password login form entirely, replacing it with a mandatory redirect to the Defguard OIDC portal. If a user’s Defguard session is revoked by an admin, their Vaultwarden access is instantly severed.
3. Just-In-Time (JIT) Auto-Provisioning We leverage SSO_REGISTRATION_AUTO=true combined with SSO_ALLOW_UNKNOWN_EMAIL_VERIFICATION=true. When a user successfully authenticates against Defguard for the first time, Vaultwarden intercepts the user’s verified email address and automatically provisions a new secure vault for them on the fly.
Expanding the Perimeter: The Nextcloud “Holy Grail” SSO
Once the IdP proves it can handle the strict confines of a password vault, expanding that identity layer to your file storage is the next logical step. Nextcloud is the heavy lifter of the stack, and its OIDC integration requires careful handling to ensure a premium user experience without breaking administrative fallbacks.
After installing the user_oidc app inside Nextcloud, we map the incoming Defguard payload dynamically. By configuring Nextcloud to ingest the openid email profile groups scopes, we can utilize the groups mapping to allow Defguard to automatically provision users into specific Nextcloud permission sets.
To achieve the “Holy Grail” of SSO—a seamless, enterprise-grade login screen that rejects local brute-force attacks—we take two critical steps:
- Hiding the Form: Using Nextcloud’s
occcommand line, we inject'hide_login_form' => trueinto the system configuration. This completely buries the native username and password fields, presenting the user with only a sleek “Login with Defguard” button. - Preventing the Infinite Loop: Defguard utilizes a persistent dashboard cookie (
defguard_session). If you configure standard OIDC Single Logout (SLO) within Nextcloud, logging out will trigger an infinite redirect loop. We solve this by intentionally leaving the end-session and redirect endpoints blank in the Nextcloud provider settings. When a user logs out, they land cleanly on the login screen, safely disconnected from Nextcloud, while their nativeadminfallback remains accessible via a?direct=1URL query.
Defederating Chat: Seamless Matrix Provisioning
Finally, we apply this SSOT architecture to our real-time communications layer using Tuwunel, our Matrix server engine.
Unlike older Matrix implementations that required messy external registration scripts, modern engines support deep OIDC integration. In our tuwunel.toml configuration file, we explicitly rip out the local password database by setting login_with_password = false.
We then define the [[global.identity_provider]] block, pointing it to Defguard and explicitly setting trusted = true and registration = true. This allows JIT provisioning for our chat network. When a user opens Element (or any modern Matrix client), they simply enter the homeserver domain and are routed straight to Defguard.
The integration is so deeply trusted that manual administrator assignments are unnecessary: the very first user who successfully authenticates via OIDC is automatically granted global server administrator privileges by the Matrix engine.
Layering Zero-Trust at the Network Edge
Integrating OIDC across Vaultwarden, Nextcloud, and Matrix is only half the battle; the network transport layer must reflect the same zero-trust philosophy.
While these containers are capable of fielding web traffic, we do not expose them directly to the public internet. In the Traefik routing labels within the compose file, we apply the vpn-only@docker middleware to the routers for vaultwarden, nextcloud, and tuwunel.
This means that the SSO handshakes between the user’s browser, Defguard, and the downstream applications can only occur if the user has already successfully negotiated a WireGuard tunnel into the infrastructure appliance.
The Result: A Single Pane of Glass
By deprecating the local account databases across our stack, we achieve a highly resilient, enterprise-grade identity posture.
- For the User: They memorize exactly one set of credentials (or use a hardware key/passkey) to unlock their VPN, chat, file-sync, and password vault.
- For the Administrator: Security audits are singular. Onboarding and offboarding require a single click inside the Defguard console.
Digital sovereignty is not about hoarding data in the dark; it is about building unyielding boundaries and defining exactly how, when, and by whom those boundaries are crossed. By centralizing identity via OpenID Connect, you stop managing individual applications and start managing pure access.
