OpenSEO Authentication Modes: Hosted vs. Self-Hosted Deployment Guide
OpenSEO supports three authentication modes—hosted, cloudflare_access, and local_noauth—that determine how users authenticate in hosted SaaS versus self-hosted Docker or Cloudflare deployments.
The every-app/open-seo repository implements a flexible authentication system defined in src/lib/auth-mode.ts. Whether you're running the managed SaaS product or deploying your own instance, understanding these modes ensures proper security configuration for your environment.
The Three OpenSEO Authentication Modes
OpenSEO's authentication architecture centers on the AUTH_MODE environment variable. The system validates this value through a Zod schema and falls back to cloudflare_access when undefined or invalid.
Here's how each mode maps to deployment types:
| Mode | Deployment Target | Authentication Behavior |
|---|---|---|
hosted |
Every App's managed SaaS | Cloudflare Access managed by the hosted service; built-in login UI |
cloudflare_access |
Self-hosted on Cloudflare Workers | Your own Cloudflare Access organization controls authentication |
local_noauth |
Self-hosted Docker/local dev | No authentication required; requests pass through unverified |
The selection logic in getAuthMode() demonstrates this fallback behavior:
export function getAuthMode(value: string | null | undefined): AuthMode {
const parsed = authModeSchema.safeParse(value);
if (parsed.success) return parsed.data;
// fallback to cloudflare_access for invalid or missing values
return "cloudflare_access";
}
Hosted OpenSEO Authentication Mode
The hosted mode is exclusive to Every App's managed SaaS offering. When AUTH_MODE=hosted is set during build time, OpenSEO renders the Cloudflare Access login flow and enables hosted-specific features like billing and user profiles.
The helper isHostedAuthMode() in src/lib/auth-mode.ts (lines 32-34) identifies this runtime state:
import { getAuthMode, isHostedAuthMode } from "@/lib/auth-mode";
const authMode = getAuthMode(process.env.AUTH_MODE);
if (isHostedAuthMode(authMode)) {
// Hosted SaaS – enforce Cloudflare Access login
}
Client-side code uses isHostedClientAuthMode() (lines 36-43) to conditionally render UI components. This check ensures the client build matches the server runtime—preventing mismatched authentication states.
Self-Hosted OpenSEO: Two Authentication Paths
Self-hosted deployments choose between authentication based on your infrastructure and security requirements.
Docker Self-Hosting: local_noauth Mode
For simple Docker deployments or local development, local_noauth eliminates authentication entirely. Set AUTH_MODE=local_noauth or omit the variable entirely:
# Docker deployment with no authentication
echo "AUTH_MODE=local_noauth" >> .env
In this mode, src/server.ts (lines 143-151) skips authentication middleware and passes request headers unchanged. The src/middleware/ensure-user/resolve.ts (lines 14-19) allows all requests through without user resolution.
This path suits internal tools or development environments where network isolation provides sufficient security.
Cloudflare Self-Hosting: cloudflare_access Mode
For production self-hosting on Cloudflare Workers, cloudflare_access integrates with your Cloudflare Access organization:
# Cloudflare deployment with Cloudflare Access authentication
echo "AUTH_MODE=cloudflare_access" >> .env
Users authenticate through your Cloudflare Access policy before reaching OpenSEO. The same JWT tokens authorize API calls. The MCP transport layer in src/server/mcp/transport.ts (lines 64-78) uses this mode to validate incoming requests.
Documentation for these paths lives in:
web/content/docs/self-hosting/docker.md— Docker/local_noauthsetupweb/content/docs/self-hosting/cloudflare.md— Cloudflare/cloudflare_accessconfiguration
Client-Side Authentication Detection
Client builds must align with server authentication modes. Use isHostedClientAuthMode() to gate hosted-specific functionality:
import { isHostedClientAuthMode } from "@/lib/auth-mode";
if (isHostedClientAuthMode()) {
// Show hosted-only UI components (billing, user profile, etc.)
}
Telemetry also varies by mode: src/client/lib/posthog.ts (lines 49-51) disables analytics when not in hosted mode, respecting self-hosted privacy expectations.
Authentication Mode Reference: Complete Comparison
| Aspect | hosted |
cloudflare_access |
local_noauth |
|---|---|---|---|
| Infrastructure | Every App managed | Your Cloudflare Workers | Your Docker/container |
| Identity provider | Cloudflare Access (Every App org) | Cloudflare Access (your org) | None |
| Build requirement | AUTH_MODE=hosted |
AUTH_MODE=cloudflare_access |
AUTH_MODE=local_noauth or omitted |
| Login UI | Automatic | Cloudflare Access pages | None |
| API authentication | CF Access JWT | CF Access JWT | None (pass-through) |
| Billing features | Enabled | Disabled | Disabled |
| Telemetry | PostHog enabled | PostHog disabled | PostHog disabled |
Summary
- Three modes govern OpenSEO authentication:
hostedfor SaaS,cloudflare_accessfor secure self-hosting,local_noauthfor simple deployments - Configuration is environment-driven via
AUTH_MODE, parsed bygetAuthMode()insrc/lib/auth-mode.ts - Hosted mode enables additional features like billing and telemetry that are suppressed in self-hosted instances
- Self-hosted Cloudflare deployments inherit the default fallback behavior when
AUTH_MODEis unspecified - Client and server builds must agree on authentication mode; helpers like
isHostedClientAuthMode()enforce this alignment
Frequently Asked Questions
What happens if I don't set AUTH_MODE in a self-hosted deployment?
The system defaults to cloudflare_access. The getAuthMode() function in src/lib/auth-mode.ts falls back to this value when the environment variable is missing, invalid, or unparsable. This ensures self-hosted Cloudflare deployments work without explicit configuration while requiring intentional choice for unauthenticated operation.
Can I switch between authentication modes without rebuilding?
Server-side mode changes require a restart since process.env.AUTH_MODE is read at bootstrap time in src/server.ts. Client-side detection is build-time determined—changing hosted features requires recompiling with the correct AUTH_MODE environment variable.
Does local_noauth expose my deployment to security risks?
Yes, if reachable from untrusted networks. The local_noauth mode is designed for local development or Docker deployments where network isolation restricts access. For internet-facing self-hosted instances, use cloudflare_access with an appropriate Cloudflare Access policy to enforce authentication.
How does authentication affect MCP (Model Context Protocol) functionality?
The MCP transport layer in src/server/mcp/transport.ts (lines 64-78) consults the current authMode to determine credential handling. In hosted and cloudflare_access modes, it validates Cloudflare Access tokens; in local_noauth, requests proceed without authentication checks.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →