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:


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: hosted for SaaS, cloudflare_access for secure self-hosting, local_noauth for simple deployments
  • Configuration is environment-driven via AUTH_MODE, parsed by getAuthMode() in src/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_MODE is 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →