I maintain a Pritunl setup (self-hosted, behind nginx as reverse proxy) and would like feedback from the community on whether this architecture is sound / best practice, or whether I’ve introduced unnecessary complexity or security risk.
Background
We run 3 independent Pritunl instances (separate DB/session per instance):
Instance 1 – main VPN for employees, auth exclusively via SAML (Azure AD / Entra ID), used both by internal users (pulling profiles, docs) and external home-office users (VPN connection from outside). No RADIUS here — SAML is the intended auth method for this instance.
Instance 2 – supports SAML (used only for profile retrieval, exclusively through an internally-resolved domain) in addition to RADIUS. This instance only exists because Pritunl doesn’t natively support multiple auth methods at once. RADIUS is needed here because of AlwaysOn VPN — the goal is to eventually replace the existing user tunnel with it. The SAML+RADIUS combination was solved via Pritunl’s plugin system. I wasn’t able to get it working via plugin in a way where specific servers/organizations use only RADIUS while others use only SAML.
Instance 3 – fully separate, plain RADIUS server with classic MFA. The RADIUS server was already in use for other purposes, so we kept using it here — we’d actually prefer SAML for this one too, but OpenVPN itself doesn’t support SAML, and Pritunl currently has no native app for Android/iOS.
Domain structure (nginx, one server with multiple server_name blocks)
All three domains per instance ultimately proxy to the same backend instance (10.77.4.10:8443 in this example, for Instance 1), but with different location blocks / sub_filter rewrites depending on the target audience. All three instances share connect.corpvpn.example as the common public domain.
Instance 1
manage.corpvpn.example – access to the Pritunl admin UI
connect.corpvpn.example (public) – serves actual VPN client operation for home-office users; also configured as the SSO Domain in Pritunl (i.e. the domain the SAML ACS callback points back to)
Instance 2
site2-manage.corpvpn.example (admin)
site2-portal.corpvpn.example (portal/profiles)
public: connect.corpvpn.example
Instance 3
mobile-manage.corpvpn.example (admin)
mobile-portal.corpvpn.example (portal)
public: connect.corpvpn.example
Redirect logic between domains
connect.corpvpn.example (public/SSO) → key/profile paths get 302-redirected to portal.corpvpn.example, since actual profile retrieval should happen there with the customized UI
portal.corpvpn.example → paths used for VPN client communication get 302-redirected back to connect.corpvpn.example
the SAML callback path is proxied (not redirected!) on both domains, since a 301/302 on a SAML POST request would drop the body
Open questions for the community
Does this setup make sense overall, or do you see fundamental issues with the architecture?
Does the domain split make sense?
What are generally considered best practices for running Pritunl?
What are best practices for reverse proxy setup, combining SAML/RADIUS, multi-instance operation, etc.?
It’s unlikely that one single sign-on domain will work for 3 different installations. Currently only one single sign-on provider can be configured for each Pritunl installation. It can’t have RADIUS and SAML or multiple RADIUS/SAML providers. For SAML there are callbacks where it needs to go back to the correct host.
Generally there should be one domain for the web console. There isn’t any reason to separate admin and user domains. If you are concerned about the security of the admin login open to the internet the nginx server can filter /auth/session and all the authGroup paths shown in pritunl-web/handlers/handlers.go. For RADIUS you would need to allow /auth/session but as long as all the authGroup handlers are blocked there will be no access to admin paths even with a valid session. There is already an extensive dual layer design for the web console. An admin level request isn’t even forwarded past the pritunl-web process into the root pritunl process without a valid NaCl signature. Which is in addition to the HMAC based session that is checked by the root pritunl process.
Below are all the addresses and how to configure them.
Hosts Tab
Host Public Address: The public IPv4 address or domain of the Pritunl host. This should always be the public IP of the host for all configurations even when using a load balancer.
Host Public IPv6 Address: The public IPv6 address or domain of the Pritunl host. This should always be the public IP of the host for all configurations even when using a load balancer.
Host Sync Address: In the advanced host settings. The public address or domain that the web server of the Pritunl servers can be accessed from. If a load balancer is configured that address should be set here.
Top Right Settings
Single Sign-On Domain: The public address or domain that is used to validate single sign-on requests through the Pritunl web server for a new VPN connection. This should be the same domain used to access the web console. If a load balancer is configured that address should be set here. Requires valid SSL certificate.
Thanks a lot for the detailed explanation, that clarifies a lot!
A few follow-up questions:
Consolidation: Given the constraints you described (one SSO provider per installation, no mixing RADIUS/SAML, one web console domain per install), is there any way to consolidate our 3 instances into fewer installations, or does our use case inherently require 3 separate ones?
RADIUS for mobile (Android/iOS): Is there any supported way to route mobile clients through SAML instead, or is RADIUS unavoidable here given the lack of a native Pritunl app for Android/iOS?
AlwaysOn VPN / user tunnel: For our second instance, we use RADIUS specifically to be able to replace our existing (non-Pritunl) AlwaysOn VPN user tunnel. Is this achievable with SAML instead, or does AlwaysOn VPN’s user tunnel require RADIUS specifically? If RADIUS is indeed required, would it be possible to somehow implement that within our first instance instead?
Public address per instance: Since you mentioned the SSO domain should match the web console domain per installation — does that mean each of our 3 instances needs its own distinct public domain/address, rather than sharing one?
Do you have any other general best practices for Pritunl you’d recommend?
One installation will be needed for each single sign-on configuration. If you need 3 different providers it will require 3 installations.
All single sign-on should be supported for the OpenVPN mobile apps in the next release. There is code in the repository now to use the WEB_AUTH function to support this.
Connections can remain active with or without single sign-on. Standard certificate users can be created on servers that also have single sign-on configured.
Each host should have a domain assigned. This allows all the connection features to work.