-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Proxy Guide
Bypass geographic blocks, protect your identity, and route AI traffic through any proxy — with zero configuration complexity.
OmniRoute includes a full-featured proxy management system that lets you route upstream AI provider traffic through HTTP, HTTPS, or SOCKS5 proxies. Whether you're in a blocked region, need IP rotation, or want stealth fingerprinting — this guide covers everything.
- Why Use Proxies?
- Architecture Overview
- 4-Level Proxy System
- Proxy Registry (CRUD)
- 1proxy Free Marketplace
- Proxy Rotation
- Anti-Detection & Stealth
- Upstream Proxy Modes
- Dashboard UI
- API Reference
- Environment Variables
- Troubleshooting
Many AI providers restrict access by geographic region. Developers in Russia, China, Iran, Cuba, Turkey, and other countries encounter errors like:
unsupported_country_region_territory
Even outside blocked regions, proxies are useful for:
| Use Case | Description |
|---|---|
| Geographic bypass | Access OpenAI, Anthropic, Codex, Copilot from blocked countries |
| IP rotation | Distribute requests across multiple IPs to avoid rate limiting |
| Privacy | Hide your real IP from upstream providers |
| Compliance | Route traffic through specific jurisdictions |
| Testing | Simulate requests from different regions |
┌───────────────────────────────────────────────────────────────┐
│ OmniRoute Server │
│ │
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ Proxy │ │ Proxy │ │ Proxy │ │
│ │ Registry │───▶│ Dispatcher │───▶│ Fetch (undici) │ │
│ │ (SQLite) │ │ (cached) │ │ │ │
│ └─────────────┘ └──────────────┘ └────────┬─────────┘ │
│ ▲ │ │
│ │ ▼ │
│ ┌──────┴──────┐ ┌──────────────────┐ │
│ │ 1proxy Sync │ │ Upstream │ │
│ │ (free pool) │ │ Provider API │ │
│ └─────────────┘ └──────────────────┘ │
└───────────────────────────────────────────────────────────────┘
| Component | File | Role |
|---|---|---|
| Proxy Registry | src/lib/db/proxies.ts |
CRUD for proxy entries + scope assignments |
| Proxy Dispatcher | open-sse/utils/proxyDispatcher.ts |
Creates undici ProxyAgent/SOCKS dispatchers with caching |
| Proxy Fetch | open-sse/utils/proxyFetch.ts |
Wraps fetch() with proxy dispatcher injection |
| Settings Route | src/app/api/settings/proxy/route.ts |
Legacy proxy config API (GET/PUT/DELETE) |
| Management Route | src/app/api/v1/management/proxies/route.ts |
Registry CRUD API (GET/POST/PATCH/DELETE) |
| 1proxy DB | src/lib/db/oneproxy.ts |
Free proxy marketplace persistence |
| 1proxy Sync | src/lib/oneproxySync.ts |
Fetches proxies from 1proxy API |
| 1proxy Rotator | src/lib/oneproxyRotator.ts |
Rotation strategies (quality/random/sequential) |
OmniRoute supports proxy configuration at four independent scopes, resolved in priority order:
Priority Resolution Order (highest → lowest):
1. 🔵 Account/Connection Proxy → per API key / OAuth connection
2. 🟡 Provider Proxy → per provider (e.g., all OpenAI traffic)
3. 🟠 Combo Proxy → per combo/routing configuration
4. 🟢 Global Proxy → all traffic, all providers
When OmniRoute sends a request to an upstream provider, it calls resolveProxyForConnectionFromRegistry() which checks each level in order:
- Account-level — Is there a proxy assigned to this specific connection ID?
-
Provider-level — Is there a proxy assigned to this provider (e.g.,
openai)? - Global-level — Is there a global proxy configured?
- No proxy — Direct connection to the provider.
The first match wins. This means you can set a global proxy as a fallback but override it for specific providers or connections.
| Traffic Type | Proxied? | Notes |
|---|---|---|
| Chat completions | ✅ | All /v1/chat/completions requests |
| Embeddings | ✅ | /v1/embeddings |
| Image generation | ✅ | /v1/images/generations |
| Audio (TTS/STT) | ✅ | /v1/audio/* |
| OAuth token exchange | ✅ | Solves unsupported_country_region_territory
|
| Connection tests | ✅ | "Test Connection" button uses proxy |
| Token refresh | ✅ | Background OAuth renewal |
| Model sync | ✅ | Model listing and discovery |
The proxy registry is a SQLite table (proxy_registry) that stores all your proxies. Each proxy has:
| Field | Type | Description |
|---|---|---|
id |
UUID | Unique identifier |
name |
String | Human-readable label |
type |
String | Protocol: http, https, socks5
|
host |
String | Proxy hostname or IP |
port |
Integer | Port number |
username |
String | Auth username (encrypted at rest) |
password |
String | Auth password (encrypted at rest) |
region |
String | Geographic region label |
notes |
String | Free-text notes |
status |
String |
active or inactive
|
source |
String |
manual or oneproxy
|
Via Dashboard:
- Go to Settings → Proxy
- Click Add Proxy
- Fill in the type, host, port, and optional auth credentials
- Save
Via API:
curl -X POST http://localhost:20128/api/v1/management/proxies \
-H "Content-Type: application/json" \
-d '{
"name": "US Proxy",
"type": "http",
"host": "proxy.example.com",
"port": 8080,
"username": "user",
"password": "pass",
"region": "US"
}'curl -X PATCH http://localhost:20128/api/v1/management/proxies \
-H "Content-Type: application/json" \
-d '{
"id": "proxy-uuid-here",
"host": "new-proxy.example.com",
"port": 9090
}'Note: Credentials are preserved unless you explicitly send non-empty replacements. Sending empty strings for
username/passwordwill keep the stored values.
# Fails if proxy is assigned to any scope
curl -X DELETE "http://localhost:20128/api/v1/management/proxies?id=proxy-uuid"
# Force delete (removes assignments too)
curl -X DELETE "http://localhost:20128/api/v1/management/proxies?id=proxy-uuid&force=1"curl "http://localhost:20128/api/v1/management/proxies?limit=50&offset=0"# Assign to global scope
curl -X PUT http://localhost:20128/api/settings/proxy \
-H "Content-Type: application/json" \
-d '{"level": "global", "proxy": {"type":"http","host":"proxy.example.com","port":8080}}'
# Assign to a specific provider
curl -X PUT http://localhost:20128/api/settings/proxy \
-H "Content-Type: application/json" \
-d '{"level": "provider", "id": "openai", "proxy": {"type":"socks5","host":"socks.example.com","port":1080}}'
# Assign to a specific connection/key
curl -X PUT http://localhost:20128/api/settings/proxy \
-H "Content-Type: application/json" \
-d '{"level": "key", "id": "connection-uuid", "proxy": {"type":"http","host":"key-proxy.com","port":3128}}'Check which proxy would be used for a given connection:
curl "http://localhost:20128/api/settings/proxy?resolve=connection-uuid"Returns the resolved proxy with its level (account, provider, or global) and source.
Assign one proxy to multiple providers or connections at once:
curl -X POST http://localhost:20128/api/v1/management/proxies/bulk-assign \
-H "Content-Type: application/json" \
-d '{
"scope": "provider",
"scopeIds": ["openai", "anthropic", "codex"],
"proxyId": "proxy-uuid"
}'Proxies are included in the Backup/Restore system. When you export your OmniRoute configuration:
- Go to Dashboard → Settings → Backup
- Click Export — proxy registry and assignments are included
- To restore, click Import and upload the backup file
The proxy registry also supports upsert by host+port — if you import a proxy that already exists (same host and port), it updates instead of creating a duplicate.
If you configured proxies in an older version (pre-registry), OmniRoute automatically migrates them:
Legacy key_value store → proxy_registry + proxy_assignments
This happens once on first startup after upgrade. Use migrateLegacyProxyConfigToRegistry({ force: true }) to re-run.
OmniRoute integrates with the 1proxy community platform to provide access to hundreds of free, validated proxies from around the world. This is perfect for users who don't have their own proxy infrastructure.
┌─────────────┐ Sync ┌─────────────────┐ Rotate ┌──────────┐
│ 1proxy API │ ────────────▶ │ proxy_registry │ ────────────▶ │ Provider │
│ (external) │ up to 500 │ source=oneproxy │ by quality │ API │
└─────────────┘ proxies └─────────────────┘ └──────────┘
- Sync — OmniRoute fetches validated proxies from the 1proxy API
-
Store — Proxies are saved in the same
proxy_registrytable withsource = 'oneproxy' - Filter — Filter by protocol, country, quality score
- Rotate — Pick the best proxy using quality, random, or sequential strategies
- Auto-degrade — Failed proxies get their quality score reduced; below threshold → marked inactive
Via Dashboard:
- Go to Settings → 1proxy tab
- Click "Sync Now"
- View stats: total proxies, active count, average quality, by-country breakdown
Via API:
# Trigger sync
curl -X POST http://localhost:20128/api/settings/oneproxy \
-H "Content-Type: application/json" \
-d '{}'
# Response:
# { "success": true, "added": 127, "updated": 45, "failed": 2, "total": 172 }# Filter by protocol
curl "http://localhost:20128/api/settings/oneproxy?protocol=socks5"
# Filter by country
curl "http://localhost:20128/api/settings/oneproxy?countryCode=US"
# Filter by minimum quality score
curl "http://localhost:20128/api/settings/oneproxy?minQuality=80"
# Combine filters
curl "http://localhost:20128/api/settings/oneproxy?protocol=http&countryCode=DE&minQuality=70"Each 1proxy proxy comes with metadata:
| Field | Description |
|---|---|
qualityScore |
0-100 rating from 1proxy validation |
latencyMs |
Measured network latency |
anonymity |
transparent, anonymous, or elite
|
googleAccess |
Whether the proxy can access Google services |
countryCode |
Two-letter ISO country code |
lastValidated |
Timestamp of last validation |
Quality scores are dynamically adjusted:
- Failed requests reduce the score by 10 points
-
Score drops to ≤10 → proxy is marked
inactive - Inactive proxies are excluded from rotation
# Rotate by quality (best proxy first) — default
curl -X POST http://localhost:20128/api/settings/oneproxy/rotate \
-H "Content-Type: application/json" \
-d '{"strategy": "quality"}'
# Random rotation
curl -X POST http://localhost:20128/api/settings/oneproxy/rotate \
-d '{"strategy": "random"}'
# Sequential (least recently validated first)
curl -X POST http://localhost:20128/api/settings/oneproxy/rotate \
-d '{"strategy": "sequential"}'The 1proxy sync has a built-in circuit breaker:
- After 5 consecutive sync failures, further sync attempts are blocked
- Reset with:
resetOneproxyCircuitBreaker()or restart the server - Sync status is available at
GET /api/settings/oneproxy?action=status
# Delete a single 1proxy proxy
curl -X DELETE "http://localhost:20128/api/settings/oneproxy?id=proxy-uuid"
# Clear ALL 1proxy proxies (manual proxies are untouched)
curl -X DELETE "http://localhost:20128/api/settings/oneproxy?clearAll=1"OmniRoute doesn't just route traffic through a proxy — it makes the traffic look legitimate:
Uses wreq-js to generate browser-like TLS fingerprints, bypassing bot detection systems that flag non-browser TLS handshakes.
The CLI Fingerprint Toggle (Settings → Security) reorders HTTP headers and JSON body fields to match the exact signature of native CLI binaries (Claude Code, Codex, etc.). This works on top of the proxy:
Your IP (blocked) → Proxy IP (US) → Provider API
+ TLS spoof
+ CLI fingerprint
You get both IP masking and request authenticity simultaneously.
Color-coded badges in the dashboard show which proxy level is active:
| Badge | Level | Meaning |
|---|---|---|
| 🟢 | Global | All traffic goes through this proxy |
| 🟡 | Provider | Only this provider's traffic is proxied |
| 🔵 | Connection | This specific key/account uses this proxy |
The badge also shows the resolved proxy IP for verification.
For providers that use the CLIProxyAPI pattern, OmniRoute supports three upstream proxy modes:
| Mode | Description |
|---|---|
native |
OmniRoute handles proxy routing directly (default) |
cliproxyapi |
Delegates to an external CLIProxyAPI instance |
fallback |
Tries native first, falls back to CLIProxyAPI |
Configure per-provider:
curl -X PUT "http://localhost:20128/api/upstream-proxy/openai" \
-H "Content-Type: application/json" \
-d '{"mode": "native", "enabled": true}'- Global proxy configuration (set once for all traffic)
- Per-provider proxy overrides
- Per-connection proxy assignments
- Connection test through configured proxy
- Color-coded badges showing active proxy level
- Sync Now button to fetch free proxies
- Stats cards: Total, Active, Avg Quality, Last Sync
- Filters: Protocol, Country Code, Min Quality
- Proxy table with host, protocol, country, quality score, latency, anonymity, Google access
- Sync status panel with success/failure tracking and consecutive failure count
- Clear All to remove all 1proxy entries
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/settings/proxy |
Get full proxy config |
GET |
/api/settings/proxy?level=global |
Get global proxy |
GET |
/api/settings/proxy?level=provider&id=openai |
Get provider proxy |
GET |
/api/settings/proxy?resolve=connectionId |
Resolve effective proxy |
PUT |
/api/settings/proxy |
Update proxy config |
DELETE |
/api/settings/proxy?level=provider&id=openai |
Remove proxy at level |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/management/proxies |
List all proxies |
GET |
/api/v1/management/proxies?id=uuid |
Get proxy by ID |
GET |
/api/v1/management/proxies?id=uuid&where_used=1 |
Get proxy assignments |
POST |
/api/v1/management/proxies |
Create proxy |
PATCH |
/api/v1/management/proxies |
Update proxy |
DELETE |
/api/v1/management/proxies?id=uuid |
Delete proxy |
DELETE |
/api/v1/management/proxies?id=uuid&force=1 |
Force delete |
POST |
/api/v1/management/proxies/bulk-assign |
Bulk assign |
GET |
/api/v1/management/proxies/assignments |
List assignments |
GET |
/api/v1/management/proxies/health |
Proxy health stats |
For exposing your OmniRoute instance to the public internet (Cloudflare/ngrok/Tailscale) instead of routing outbound through a proxy, see TUNNELS_GUIDE.md. The tunnel REST API lives under /api/tunnels/{cloudflared,ngrok,tailscale}/* and is orthogonal to the outbound proxy chain documented above.
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/settings/oneproxy |
List 1proxy proxies |
GET |
/api/settings/oneproxy?action=stats |
Get stats + sync status |
GET |
/api/settings/oneproxy?action=status |
Get sync status only |
POST |
/api/settings/oneproxy |
Trigger sync |
POST |
/api/settings/oneproxy/rotate |
Rotate to next proxy |
DELETE |
/api/settings/oneproxy?id=uuid |
Delete one |
DELETE |
/api/settings/oneproxy?clearAll=1 |
Clear all |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/upstream-proxy/:providerId |
Get upstream proxy config |
PUT |
/api/upstream-proxy/:providerId |
Set upstream proxy mode |
DELETE |
/api/upstream-proxy/:providerId |
Remove upstream proxy config |
| Variable | Default | Description |
|---|---|---|
ENABLE_SOCKS5_PROXY |
true |
Enable SOCKS5 proxy support (default true in .env.example) |
ONEPROXY_ENABLED |
true |
Enable 1proxy integration |
ONEPROXY_API_URL |
https://1proxy-api.aitradepulse.com |
1proxy API endpoint |
ONEPROXY_MAX_PROXIES |
500 |
Maximum proxies to sync |
ONEPROXY_MIN_QUALITY_THRESHOLD |
50 |
Minimum quality score to import |
Set ENABLE_SOCKS5_PROXY=true in your .env file and restart.
This is normal with cheap proxies that drop idle connections. OmniRoute already handles this by:
- Disabling keep-alive on proxy connections (
keepAliveTimeout: 1) - Disabling pipelining (
pipelining: 0) - Caching dispatchers to avoid repeated handshakes
If it persists, try a different proxy or use the 1proxy rotation feature.
Make sure the proxy is configured before starting the OAuth flow. OmniRoute routes OAuth token exchange through the configured proxy. Set a global or provider-level proxy first, then connect.
Check the resolution order:
- Verify with
GET /api/settings/proxy?resolve=your-connection-id - Check if the proxy
statusisactive(notinactive) - Ensure the proxy assignment scope matches your connection
Check the sync status:
curl "http://localhost:20128/api/settings/oneproxy?action=status"If consecutiveFailures >= 5, the circuit breaker has tripped. Restart the server to reset, or wait for manual reset.
CREATE TABLE proxy_registry (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
type TEXT NOT NULL DEFAULT 'http',
host TEXT NOT NULL,
port INTEGER NOT NULL,
username TEXT DEFAULT '',
password TEXT DEFAULT '',
region TEXT,
notes TEXT,
status TEXT DEFAULT 'active',
source TEXT NOT NULL DEFAULT 'manual', -- 'manual' or 'oneproxy'
quality_score INTEGER, -- 0-100 (1proxy only)
latency_ms INTEGER, -- milliseconds (1proxy only)
anonymity TEXT, -- transparent/anonymous/elite
google_access INTEGER DEFAULT 0, -- can access Google? (1proxy)
last_validated TEXT, -- ISO timestamp (1proxy)
country_code TEXT, -- ISO 2-letter code (1proxy)
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);CREATE TABLE proxy_assignments (
id INTEGER PRIMARY KEY AUTOINCREMENT,
proxy_id TEXT NOT NULL REFERENCES proxy_registry(id),
scope TEXT NOT NULL, -- 'global', 'provider', 'account', 'combo'
scope_id TEXT, -- provider ID, connection ID, or combo ID
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
UNIQUE(scope, scope_id)
);OmniRoute's proxy fast-fail mechanism (src/lib/proxyHealth.ts) detects dead proxies in <2s via a quick TCP connection check, then caches the result to avoid per-request overhead.
Request ──▶ ProxyHealthCache.get(url)
│
├─ Cache hit + fresh? ──▶ return cached status
│
└─ Cache miss / stale? ──▶ TCP connect to host:port
(timeout: FAST_FAIL_TIMEOUT_MS)
──▶ cache for HEALTH_CACHE_TTL_MS
──▶ return result
Without this, a dead proxy would block every request for the full PROXY_TIMEOUT_MS (default 30s) before failing.
| Variable | Default | Purpose |
|---|---|---|
PROXY_FAST_FAIL_TIMEOUT_MS |
2000 |
TCP connection timeout per health check |
PROXY_HEALTH_CACHE_TTL_MS |
30000 |
How long a health result is cached |
Recommended values:
| Scenario | Fast-fail timeout | Cache TTL | Reasoning |
|---|---|---|---|
| High-throughput API gateway | 1500ms | 60000ms | Aggressive fail-fast, longer cache to reduce checks |
| Geo-distributed nodes | 3000ms | 15000ms | Slower networks need more time; shorter cache for fast failover |
| Dev / testing | 1000ms | 10000ms | Quick iteration on local proxies |
| Stealth / anti-detection | 2500ms | 45000ms | Avoid rapid probing that could trigger rate limits |
import { getAllProxyHealthStatuses, invalidateProxyHealth } from "omniroute/proxyHealth";
const statuses = getAllProxyHealthStatuses();
for (const s of statuses) {
console.log(`${s.proxyUrl} → healthy=${s.healthy}, stale=${s.stale}`);
}
// Force re-check a specific proxy
invalidateProxyHealth("http://user:pass@1.2.3.4:8080");The stale flag is true when the cache entry has exceeded HEALTH_CACHE_TTL_MS and the next request will trigger a fresh check.
The health check uses sensible defaults based on the URL scheme:
| Scheme | Default port |
|---|---|
http:// |
8080 |
https:// |
443 |
socks5:// / socks5h://
|
1080 |
Custom ports in the URL (http://host:9999) always take precedence over the scheme default.
OmniRoute tracks per-proxy usage to help operators diagnose routing patterns, latency spikes, and recurring failures.
For every request through a configured proxy, OmniRoute records:
| Metric | Description |
|---|---|
proxy_url |
Full proxy URL (with auth credentials masked) |
provider |
Upstream provider ID (openai, anthropic, etc.) |
latency_ms |
Total round-trip time including proxy handshake |
connect_ms |
TCP connect time only |
status |
HTTP status code from upstream |
error |
Error class if request failed |
timestamp |
ISO 8601 UTC |
# Recent proxy events
curl -H "Authorization: Bearer $OMNIROUTE_KEY" \
"http://localhost:20128/api/usage/proxy-logs?limit=100"The real endpoint is /api/usage/proxy-logs (see src/app/api/usage/proxy-logs/route.ts). This endpoint supports:
-
GET /api/usage/proxy-logs— retrieve proxy logs -
DELETE /api/usage/proxy-logs— clear all proxy logs
Aggregate stats can be queried directly from the proxy_logs table via SQL if needed. The dashboard UI may offer aggregate views.
Detect a flapping proxy (alternates between success/failure):
SELECT proxy_url,
COUNT(*) AS total,
SUM(CASE WHEN status >= 500 THEN 1 ELSE 0 END) AS errors,
ROUND(100.0 * SUM(CASE WHEN status >= 500 THEN 1 ELSE 0 END) / COUNT(*), 1) AS error_pct
FROM proxy_logs
WHERE timestamp > datetime('now', '-1 hour')
GROUP BY proxy_url
HAVING error_pct > 5
ORDER BY error_pct DESC;Find slow proxies (p95 latency > 2s):
WITH ranked AS (
SELECT proxy_url, latency_ms,
PERCENT_RANK() OVER (PARTITION BY proxy_url ORDER BY latency_ms) AS pct
FROM proxy_logs
WHERE timestamp > datetime('now', '-24 hour')
)
SELECT proxy_url, latency_ms
FROM ranked
WHERE pct >= 0.95
ORDER BY latency_ms DESC;When multiple proxies are assigned to a scope, OmniRoute uses a rotation strategy to pick which one to use for each request. The strategy is configured at the scope level (global, per-provider, per-account, per-combo).
| Strategy | When to use | Trade-off |
|---|---|---|
quality (default) |
Production with mixed-quality proxies | Favors high-rated proxies; may starve low-rated ones |
random |
Load distribution, privacy | Even distribution; ignores quality signals |
sequential |
Debugging, deterministic testing | Cycles through proxies in order; easy to reason about |
Do you have quality scores for your proxies?
│
┌───────────┴───────────┐
│ │
YES NO
│ │
Are all proxies │
roughly equal │
in quality? │
│ │
┌────┴────┐ │
│ │ │
YES NO Use
│ │ `random`
│ │ (even spread
│ │ builds quality
│ │ data over time)
│ │
│ Use `quality`
│ (best for
│ mixed quality)
│
Use `random`
(spread load
evenly)
import { rotateOneproxyProxy } from "omniroute/oneproxyRotator";
// In a one-off script
const proxy = await rotateOneproxyProxy({ strategy: "quality" });
if (proxy) {
console.log(`Selected: ${proxy.host}:${proxy.port}, quality=${proxy.qualityScore}`);
}When using sequential strategy, the internal index accumulates. To reset:
import { resetSequentialIndex } from "omniroute/oneproxyRotator";
resetSequentialIndex();Useful when:
- Restarting a load test
- Recovering from a proxy outage (so you don't cycle through dead ones first)
- Manually rebalancing after adding new proxies
When a proxy consistently fails, mark it manually so the rotator will skip it:
import { failOneproxyProxy } from "omniroute/oneproxyRotator";
const removed = await failOneproxyProxy("1.2.3.4", 8080);
if (removed) {
console.log("Proxy marked as failed; rotator will skip it");
}The proxy is not deleted — it's marked unhealthy and won't be selected until the next successful health check (via proxyHealth.ts) or manual reset.
📖 Related documentation:
- User Guide — General setup and configuration
- API Reference — Full API documentation
- Environment Config — All environment variables
OmniRoute · Website · npm · Docker Hub
- Setup Guide
- User Guide
- Features
- Quick Start (Docker)
- Electron Desktop App
- Termux (Android)
- PWA Guide
- MCP Server
- A2A Server
- Agent Protocols
- OpenCode Plugin
- Webhooks
- Cloud Agents
- Skills
- Memory
- Evals
- Gamification
- Guardrails
- Compliance
- Error Sanitization
- Public Credentials
- Route Guard Tiers
- Stealth Guide
- CLI Token Auth