Type to filter titles and answers. Title matches appear first.

No documentation articles match your filter. Try a shorter word or clear the box.

Getting Started

TL;DR

Cloudo is the Edge in front of your origin: manage DNS, SSL, proxy, CDN, and security in Backoffice; visitors hit Edges, not the Control Plane.

Cloudo sits in front of your website. Visitor traffic goes Visitor → Edge → Origin. The Edge is Cloudo’s public front door. The Origin is your own hosting server that actually runs the site.

You manage domains, DNS, SSL, origins, cache, and security in the Backoffice. After a successful deploy, Edges keep serving from a local last-valid configuration. Visitors do not talk to the Backoffice when they load your site.

TL;DR

Control Plane stores intent; Edges and DNS nodes serve visitors from last-valid local config — they never talk to PostgreSQL.

The Control Plane is the Backoffice, the authenticated Control API, and the database that stores the source of truth. It is where you edit settings and queue deployments.

An Edge is a public server that terminates visitor HTTP/HTTPS. Authoritative DNS (`ns1` / `ns2`) is served by dedicated DNS-capable nodes. Nodes pull configuration through the Control API. They never connect to the database themselves.

  • Control Plane: management, versions, certificates metadata, audit history.
  • Edge: live visitor HTTP/HTTPS from local files.
  • DNS nodes: live authoritative answers from local CoreDNS snapshots.
  • Origin: your backend. It is not an Edge node.

TL;DR

Already-configured visitor HTTP/HTTPS and authoritative DNS keep working. Edges and DNS nodes continue serving the last valid local configuration. New Backoffice edits and new deploys cannot run until the Control Plane…

Already-configured visitor HTTP/HTTPS and authoritative DNS keep working. Edges and DNS nodes continue serving the last valid local configuration. New Backoffice edits and new deploys cannot run until the Control Plane is back.

A Control Plane outage is not the same as a visitor outage. Sites that already deployed successfully stay up.

TL;DR

Every Edge keeps the last configuration that passed validation and activated. If a new candidate fails validation, that last valid configuration stays in place and traffic is unchanged.

Every Edge keeps the last configuration that passed validation and activated. If a new candidate fails validation, that last valid configuration stays in place and traffic is unchanged.

Validation must succeed before activation. Edges reload services after a good activation; they do not restart Nginx for a normal deploy. A restart would drop connections and is not the deploy path.

TL;DR

A Config Version is a numbered snapshot of a plane (HTTP, DNS, or mail) stored in the Control Plane. Saving and deploying creates or reuses a version. Edges report the version they currently serve and the version they…

A Config Version is a numbered snapshot of a plane (HTTP, DNS, or mail) stored in the Control Plane. Saving and deploying creates or reuses a version. Edges report the version they currently serve and the version they should serve.

Version numbers are how you compare “what is live on an Edge” with “what the Backoffice last queued.” They are not a visitor-facing setting.

TL;DR

A deployment pushes one Config Version to one Edge. The Edge generates a candidate, validates it, activates it atomically, reloads, and reports status. If validation fails, the previous working configuration stays…

A deployment pushes one Config Version to one Edge. The Edge generates a candidate, validates it, activates it atomically, reloads, and reports status. If validation fails, the previous working configuration stays active.

Save & Deploy queues work. Live visitor traffic changes only after that Edge validates and activates the new release.

TL;DR

Rollback re-queues a previous known-good Config Version to the Edge. It is another deployment of an older snapshot, not an instant undo on the visitor path.

Rollback re-queues a previous known-good Config Version to the Edge. It is another deployment of an older snapshot, not an instant undo on the visitor path.

The Edge still validates the candidate before activating the rolled-back version. If that validation fails, the currently serving configuration is kept.

TL;DR

Continue with Google appears only when an operator enables it. Linking needs recent re-auth. Privileged accounts stay blocked unless staff Google is enabled. New accounts still confirm the 6-digit code. Google does not skip two-factor or a suspension.

When Google sign-in is turned on for this Cloudo site, the sign-in page shows Continue with Google above the email and password form. When it is turned off, that button is not shown and sign-in is email and password only. The default is off.

Google sign-in asks only for openid, email, and profile. Cloudo accepts the Google account only when Google says the email is verified. Cloudo does not store Google access or refresh tokens.

A new Google user is created only while public registration is open. The new account is a Customer, the same as the registration form, and still needs the 6-digit email code before the Backoffice opens. If registration is closed, Google cannot create an account.

If the Google email already belongs to a Cloudo user, Cloudo does not connect it silently. Sign in with your password, then use Profile → Security → Connected accounts. Connecting Google is a POST with CSRF protection: accounts with a password must confirm that password (or have confirmed it within the last 10 minutes); passwordless accounts must first use Confirm with Google (Google prompts for login again) so a short-lived confirmation is stored for 10 minutes. A GET link with intent=link does not start a connection. Automatic connection on sign-in happens only when an operator has turned that option on and the Cloudo email is already verified.

Later sign-ins match the Google account id, not the email address. Changing the email at Google does not switch you to a different Cloudo user and does not change the email stored on the Cloudo account.

Suspended accounts cannot sign in with Google. Privileged accounts (staff roles, legacy administrator flag, or any granted staff permission) cannot use Google sign-in unless an operator turns staff Google sign-in on. When an optional staff email domain list is set, both the Cloudo account email domain and the Google email domain (or Google hosted-domain claim) must match that list. Google does not skip two-factor authentication: the two_factor_confirmed_at field is reserved for a future authenticator product; if it is set, Google sign-in stops and does not open a session. Cloudo does not currently offer an authenticator-app setting in Profile. Password sign-in is unchanged.

A passwordless account that sets a password from Profile → Security must confirm with Google again (within 10 minutes) or enter a 6-digit code emailed to the account email. The same confirmation applies before signing out other devices. Connecting or disconnecting Google emails an account-security notice to the account email when that notification is enabled.

You can disconnect Google from Profile → Security → Connected accounts. Disconnect is refused when Google is the only way to sign in and the account has no password. Set a password first, then disconnect. A Google sign-in failure, connection, or disconnection is written to the audit log without Google tokens.

TL;DR

After you submit the registration form, Cloudo emails a 6-digit code to confirm you control that email address. Enter the code on the verification page to finish creating your account. You do not need to click a link…

After you submit the registration form, Cloudo emails a 6-digit code to confirm you control that email address. Enter the code on the verification page to finish creating your account. You do not need to click a link in the email when using this flow.

TL;DR

Each code expires after 10 minutes. Codes are single-use. Requesting a new code invalidates older unused codes for that account.

Each code expires after 10 minutes. Codes are single-use. Requesting a new code invalidates older unused codes for that account.

  • Check spam or junk folders for mail from Cloudo.
  • Wait for the resend timer (about 60 seconds) before requesting another code.
  • Use Resend code on the verification page.
  • Confirm the email address is typed correctly. Use Change email to sign out and register again if needed.
  • There is an hourly limit on how many codes can be sent to reduce abuse.

TL;DR

No. Expired codes, codes that were already used, and codes replaced by a newer resend no longer work. Enter the latest code from your email.

No. Expired codes, codes that were already used, and codes replaced by a newer resend no longer work. Enter the latest code from your email.

TL;DR

Open Profile in the Backoffice account menu. The Logged devices section lists active sessions for your account, including browser/OS summary, approximate IP, and last activity.

Open Profile in the Backoffice account menu. The Logged devices section lists active sessions for your account, including browser/OS summary, approximate IP, and last activity.

TL;DR

Yes. On Profile → Logged devices, use Sign out next to any session that is not marked Current device. That ends only that session.

Yes. On Profile → Logged devices, use Sign out next to any session that is not marked Current device. That ends only that session.

TL;DR

It keeps you signed in on the device you are using and ends every other active session for your account. You confirm with your current password. Use this if you think an old browser or shared computer still has access.

It keeps you signed in on the device you are using and ends every other active session for your account. You confirm with your current password. Use this if you think an old browser or shared computer still has access.

TL;DR

Cloudo shows browser, operating system, last activity, and a partially masked IP from the session record. Exact city or country location is not shown when reliable GeoIP is not available for profile sessions…

Cloudo shows browser, operating system, last activity, and a partially masked IP from the session record. Exact city or country location is not shown when reliable GeoIP is not available for profile sessions. Approximate IP metadata is enough to recognize a device without sending your IP to third-party lookup APIs.

TL;DR

Support → New ticket: pick General, DNS, Proxy/CDN, Security, SSL/TLS, Account/Billing, or Technical Issue. Opening a ticket never changes live traffic.

When you open Support → New ticket, choose one category so staff can route the request: General, DNS, Proxy / CDN, Security, SSL / TLS, Account / Billing, or Technical Issue. General is the default.

Account / Billing is a triage label only; Cloudo does not sell a separate billing product from this form. See Billing / Pricing docs for the published Free / Pro / Enterprise planning tiers and FlowPay disclosure. Older tickets may still show previous category names (for example Cloudo, Gameservers, or Cashier). Those remain on historical tickets only and cannot be selected for new tickets. Creating or viewing a ticket does not change Edge traffic, DNS, or SSL.

Billing

TL;DR

Free (DNS/SSL), Pro ($20/domain/mo with reverse proxy), Enterprise (custom). Plans are listed on the Pricing page.

Cloudo publishes three planning tiers on the Pricing page (`/pricing`) and on the public homepage:

  • Free ($0/mo): authoritative DNS, Let’s Encrypt SSL, basic firewall, 1 site. Free does not include reverse proxy — you cannot enable Protection / Edge proxy on Free.
  • Pro ($20/mo per domain): everything in Free plus reverse proxy, rate limits, human verification, priority SSL renew, and analytics.
  • Enterprise (custom / talk to us): everything in Pro plus dedicated edges, custom SLAs, private onboarding, and direct operator support. Contact sales via the homepage.

There is no Business tier. Soft entitlement checks may show an upgrade message in the Backoffice when billing gates are enabled; existing grandfathered domains keep reverse proxy until a later billing phase. Signed-in See pricing links go to the Pricing page (not Dashboard).

TL;DR

Deposits via FlowPay; monthly Pro is a Cloudo wallet debit. Production billing stays off until operators enable it.

Wallet deposits use FlowPay (https://flowpay.network/). Cloudo does not take card numbers; FlowPay provides crypto checkout.

Monthly Pro ($20 per domain) is a Cloudo wallet ledger debit — not a FlowPay subscription and not an automatic FlowPay charge. Enterprise stays contact-sales (no auto debit).

Production billing is not live until an explicit GO. Soft entitlement gates (CLOUDO_BILLING_GATES_ENABLED), FlowPay deposits (CLOUDO_FLOWPAY_ENABLED), and monthly debit / grace / soft proxy suspend (CLOUDO_BILLING_PHASE_C_ENABLED) stay off on production by default. Grandfathered billing-exempt domains keep reverse proxy and are never auto-suspended by Phase C.

TL;DR

Dashboard Wallet → Add credits opens Billing. Credit lands only after the signed paid webhook.

Dashboard shows your Cloudo wallet balance and + Add credits, which opens Account → Billing. When deposits are enabled for an environment (CLOUDO_FLOWPAY_ENABLED), Billing shows a Deposit action.

  • Choose an amount (minimum $5 USD by default) and start Deposit. Cloudo creates a FlowPay charge and redirects you to FlowPay hosted checkout.
  • After you pay, FlowPay sends a signed webhook (HMAC-SHA256 over the raw body). Cloudo credits your wallet only after that verified paid event — not when you land on the success return URL.
  • The same charge id cannot credit twice (idempotent ledger). Cancelled or abandoned checkouts do not change your balance.
  • Deposits fill the wallet. Upgrade to Pro on a non-exempt Free domain (when billing gates are on) debits the first Pro period from the domain owner’s wallet after confirmation. Enabling proxy/CDN can still activate Pro the same way if you skip the dedicated button. Monthly renewals (Phase C) continue as wallet debits when Phase C is enabled.

If Deposit is hidden, adding credits is not available on that environment. Billing is not live on production until operators explicitly enable it.

TL;DR

When Phase C is on, Pro renews as a $20 wallet debit; unpaid domains get grace, then soft-suspend proxy only.

When Phase C is enabled (CLOUDO_BILLING_PHASE_C_ENABLED together with CLOUDO_BILLING_GATES_ENABLED), Cloudo runs a daily job that debits $20 USD (2000¢) from your wallet for each non-exempt Pro / proxied domain that is due.

  • Enough balance: wallet is debited once per domain+period (idempotent), period end extends by 30 days, and past-due / grace / suspend flags clear.
  • Insufficient balance: the domain becomes past due once; you get a 7-day grace window and an email about the failed renew. Reverse proxy stays allowed during grace.
  • After grace ends: soft suspend — proxy is no longer entitled. On the next Edge publish / HTTP config build, reverse proxy for that domain is omitted. Authoritative DNS records stay; Cloudo does not delete your zone or DNS rows.
  • Billing-exempt (grandfathered) domains are never auto-debited or auto-suspended in this phase.
  • Enterprise is contact sales — no automatic monthly debit.
  • There is no automatic FlowPay charge for monthly Pro. Top up the wallet via FlowPay deposits when deposits are enabled.

Account → Billing lists each domain with plan, status, and Manage. Manage reuses Upgrade to Pro (confirm then owner wallet debit; Protection stays off). Switch to Free schedules cancel at the current period end when a future billing_period_end exists; otherwise it applies immediately. There is no refund. DNS records, stored SSL certificates, and origins stay. Protection flags are not changed. Phase C stops monthly debit after cancel takes effect. When Phase C is on, reverse proxy is omitted from the next Edge HTTP publish after Pro ends (nginx test then reload). If Phase C is off, existing Edge HTTP sites are not stripped by the plan change. Grandfathered exempt and Enterprise domains cannot be switched this way.

TL;DR

Use Upgrade to Pro on the domain (confirm then owner wallet debit). Protection stays off until you enable it. Free keeps DNS/SSL without Edge proxy.

Reverse proxy (Protection ON / routing visitor HTTP through Cloudo Edges) is a Pro feature. The billed amount is the configured Pro price (default $20/domain/mo). Free includes authoritative DNS, Let’s Encrypt SSL, and basic firewall — not reverse proxy. CDN requires proxy.

When a domain is not entitled and billing gates are on, Domain Overview, DNS, Origin, and CDN show “Reverse proxy requires Pro” with Upgrade to Pro and See pricing (the Pricing page). Upgrade to Pro opens a confirmation (domain, price, owner wallet, Pro entitlement). Protection is not turned on by this charge. Confirming POSTs a wallet debit for the domain owner (staff acting on a customer domain still debit the owner, not the staff wallet). Already-Pro domains are not charged again.

If the owner wallet cannot cover the first Pro period, nothing on the domain is changed. You are sent to Account → Billing to Add credits, then return and confirm Upgrade to Pro again.

If your domain was already proxied during the public beta, it may be grandfathered (billing exempt) so existing Edge routing keeps working. The Domains API still returns HTTP 402 when proxy/CDN is requested without entitlement (Prefer A — no silent DNS-only orphan when proxy was requested on create).

Turning proxy off still works. When Phase C monthly billing is enabled and a non-exempt domain stays unpaid past the 7-day grace, Cloudo soft-suspends proxy only (DNS records kept). Soft suspend is off until operators enable CLOUDO_BILLING_PHASE_C_ENABLED. Enterprise stays contact-sales (no wallet auto-activation).

TL;DR

Billing → Manage: Upgrade reuses the existing Pro confirm+POST; Free is cancel-at-period-end when a future period exists, otherwise immediate. No refund.

Account → Billing → Manage on a domain opens plan management for that hostname (not a second subscription or a second wallet).

  • Upgrade to Pro uses the existing confirmation page and POST. The domain owner’s wallet is debited for one Pro period. Protection is not enabled automatically. Staff with manage-all still debit the owner, not themselves.
  • Switch to Free shows a Before you confirm warning (timing, no refund, debit stop, DNS/SSL/origins kept, Protection flags unchanged). Phase C and nginx publish details are under Technical details. Type the domain name (the field starts empty; it turns Valid when it matches). If the current Pro period end is still in the future and reverse proxy is still allowed, cancel is scheduled: you keep Pro until that time, then the domain becomes Free. If there is no future period (or proxy is already suspended / past due with no remaining paid time), Free applies immediately.
  • There is no refund of unused Pro time. The wallet is not credited. Monthly Phase C debit stops after cancel takes effect (including domains that still have proxied DNS rows).
  • DNS records, stored SSL certificates, and origins are not deleted. Proxied flags are not turned off. Firewall and rate-limit rows stay in the Control Plane.
  • HTTPS through Cloudo Edges is not assumed to disappear at the moment you click confirm. When Phase C is on, after Pro ends the next Edge HTTP publish omits reverse proxy for that domain (nginx -t, then reload). Edge-enforced firewall, rate limits, CDN, and HTTPS through Cloudo then stop for that domain. Authoritative DNS still answers. If Phase C is off, this plan change does not strip existing Edge HTTP sites.
  • Keep Pro on the Manage page (or Upgrade to Pro while still entitled) clears a scheduled cancel without a second charge.
  • Billing-exempt (grandfathered) and Enterprise domains cannot be switched to paid Free from this page.

TL;DR

HTTP 402 means proxy/CDN was refused for billing entitlement — Prefer A refuses before creating a DNS-only orphan.

When CLOUDO_BILLING_GATES_ENABLED is on, Domains API calls that request proxy=true or cdn=true require Pro entitlement (or enough wallet balance to activate Pro for $20). Prefer A: on one-shot register with proxy, Cloudo refuses with 402 before creating a domain row if funds/entitlement are missing — so you are not left with a silent DNS-only zone.

DNS-only register (no proxy/CDN) remains available on Free. CDN always requires proxy. Credits for deposits still arrive only via the FlowPay webhook.

Developer API

Developer API Integrators · Bearer tokens · /api/v1

TL;DR

Partner Domains API under /api/v1 uses the same DNS/Edge pipeline as Backoffice. See #api-routes for the cheat sheet.

The Cloudo Developer API lets trusted integrators (for example partner platforms) manage domains on this Control Plane over HTTPS. The Domains API lives under /api/v1 and uses the same authoritative DNS and Edge deploy pipeline as the Backoffice — it does not invent a second DNS system.

Use it to register zones, read Cloudo nameservers, optionally enable Protection (reverse proxy) and static CDN, verify registrar NS delegation, and activate domains. It does not create WEB-01 nginx vhosts; that is a separate API.

For the full route list (method + path + purpose), see #api-routes.

Operator docs: docs/domains-api.md and docs/api/domains-openapi.yaml. Feature flag: CLOUDO_DOMAINS_API_ENABLED (default true). When false, Domains API routes return HTTP 503.

TL;DR

Send Authorization: Bearer <token>. Mint tokens in Account → API tokens. Scope domains or cloudo.api.

Send Authorization: Bearer <token> on every request. Create tokens in Backoffice Account → API tokens (/profile/api-tokens) as an Admin or Super Admin, or with php artisan cloudo:api-client-create --name=… --owner=email@…. Prefer Profile-managed tokens for day-to-day use.

Only a SHA-256 hash is stored (same pattern as Edge node tokens). The plaintext secret is shown once at create time and is never written to logs or audit metadata. Tokens must be at least 32 characters.

Required Domains API scope: domains or cloudo.api. Missing, short, revoked, unknown, or wrong-scope tokens return HTTP 401 or 403 with ok false.

Example header (never commit real tokens): Authorization: Bearer YOUR_TOKEN_HERE

TL;DR

Account → API tokens creates hashed, scoped tokens (optional domains, expiry, IP allowlist); the full secret is shown only once.

Account → API tokens (/profile/api-tokens) creates, lists and revokes Bearer tokens. Administrators always see it (partner scopes). When the Cloudo API is enabled (CLOUDO_CUSTOMER_API_ENABLED=true) every user sees it and can create tokens with Cloudo API scopes for their own domains. With the flag off, Customer and Support accounts get HTTP 403 and do not see the nav link.

Each token has a name, scopes, optional domain list, optional expiry date (end of that day in your timezone, at most CLOUDO_CUSTOMER_API_MAX_TOKEN_DAYS days, default 365) and optional IP allowlist (IPv4/IPv6 or CIDR). The list shows prefix (first 8 characters), scopes, domains, allowed IPs, expiry, created time and last used time + IP. The full secret is shown only once at create time — Cloudo stores only a SHA-256 hash.

Partner scopes (admins): cloudo.api (Domains + WEB-01 vhosts), domains (Domains API only), web01.vhosts (WEB-01 vhosts proxy only). Cloudo API scopes: domains:read, dns:read, dns:write, cache:purge, firewall:read, firewall:write, analytics:read. Write scopes include their read scope; cloudo.api does not include any Cloudo API scope. Revoking a token invalidates it immediately.

Operators may still mint a partner token with php artisan cloudo:api-client-create for bootstrap. That uses the same hashed storage. Edge node tokens are a different credential and are never accepted on /api/v1 (and API tokens are never accepted on /api/node).

TL;DR

Scoped per-user REST API for domains, DNS, cache purge, firewall/rate-limit rules and analytics; same validation, audit and deploy as the panel.

A versioned REST API under /api/v1 for your own domains: list domains, DNS records CRUD, cache purge, firewall and rate-limit rules CRUD, and an analytics summary. Authenticate with Authorization: Bearer <token> from Account → API tokens. OpenAPI: GET /api/v1/openapi.yaml (also docs/api/cloudo-api-v1.openapi.yaml); guide: docs/customer-api.md.

  • GET /api/v1/domains — domains:read
  • GET|POST /api/v1/domains/{id}/dns-records, PUT|PATCH|DELETE …/dns-records/{record} — dns:read / dns:write
  • POST /api/v1/domains/{id}/cache/purge — cache:purge (body purge=all|url|prefix)
  • GET|POST /api/v1/domains/{id}/firewall-rules, GET|PUT|PATCH|DELETE …/{rule} — firewall:read / firewall:write
  • GET|POST /api/v1/domains/{id}/rate-limit-rules, GET|PUT|PATCH|DELETE …/{rule} — firewall:read / firewall:write
  • GET /api/v1/domains/{id}/analytics/summary?range=1h|6h|24h|7d|30d — analytics:read

Every change uses the same validation, safety checks (for example the firewall country-impact confirmation: resend with confirm_country_impact=true), audit log and config deploy as the panel. Audit rows show source “API token <prefix>…” (actor type api_token). Responses include deployment {queued, status, error}.

A token only sees domains owned by its user — staff view-all permissions do not apply to API tokens. Other accounts’ domains return 404; domains outside the token’s domain list return 403 domain_not_allowed. Feature flag CLOUDO_CUSTOMER_API_ENABLED (default off); when off these endpoints return 503 feature_disabled.

TL;DR

Per-token 120/min (30 writes/min), per-IP brute-force limit, and one JSON error envelope with stable error codes.

Per token: 120 requests per minute and 30 writes per minute (CLOUDO_CUSTOMER_API_RATE_LIMIT_PER_MINUTE / CLOUDO_CUSTOMER_API_WRITE_RATE_LIMIT_PER_MINUTE). Over the limit: HTTP 429 rate_limited with Retry-After and X-RateLimit-* headers. Counters live in Redis (CLOUDO_API_LIMITER_STORE, falls back to the default cache store).

Brute-force protection: more than 20 failed authentications per minute from one IP (CLOUDO_API_AUTH_FAILURES_PER_MINUTE) returns 429 too_many_failed_attempts for that IP — for every /api/v1 and geo-IP API token — until the minute passes.

Errors are always JSON {ok:false, error, message, errors?}. Codes: unauthenticated (401), token_expired (401), ip_not_allowed (403), insufficient_scope (403), domain_not_allowed (403), forbidden (403), not_found (404), conflict (409), validation_failed (422), rate_limited / too_many_failed_attempts (429), feature_disabled (503).

TL;DR

URL and prefix purges delete only matching cached files on each Edge (effective: url|prefix); old agents or failures fall back to Purge All (effective: all).

POST /api/v1/domains/{id}/cache/purge accepts purge=all, purge=url with urls[] (paths or http(s) URLs on the domain or its subdomains, max 100) and purge=prefix with prefixes[] (max 30). purge=all rotates the domain cache generation (the panel Purge All).

URL and prefix purges delete only the matching cached files on every HTTP Edge — no config deploy, no nginx reload. The response says effective: "url" or "prefix" and returns purge_id; poll GET /api/v1/domains/{id}/cache/purges/{purge_id} for status (pending, succeeded, fallback_all) and files_purged per Edge. A path (/a.css) is purged for http and https on every hostname of the domain; a full URL only for that scheme and host. URL purge matches the exact path and query string — use a prefix such as /assets/app.css to drop every ?v= variant.

Fallback to Purge All (effective: "all" plus fallback_reason): selective purge is turned off (CLOUDO_CACHE_SELECTIVE_PURGE_ENABLED), an HTTP Edge runs an older agent without cache_purge_v1 (edge_agent_too_old), or an Edge cannot finish — prefix scan limit hit, error, or no report within 5 minutes (CLOUDO_CACHE_PURGE_NODE_TIMEOUT). A fallback is always a superset of what you asked for.

Purge needs static file caching turned on for the domain (otherwise 422), the same as Purge All in the panel.

TL;DR

GET /api/v1/nameservers returns this Control Plane’s NS list — production public names are ns1/ns2.cloudo.lol.

Call GET /api/v1/nameservers with a Domains-scoped Bearer token. No domain id is required — integrators can ask for NS before registering a hostname.

Response data includes nameservers (from CLOUDO_NAMESERVERS / Domain::managedNameservers for this Control Plane) and a short note to point the registrar NS at those hostnames. Production public names are ns1.cloudo.lol and ns2.cloudo.lol. DEV may differ — always use the array returned by the API.

Domain payloads (POST/GET /domains) still include nameservers[] for backward compatibility.

Example: curl -sS -H "Authorization: Bearer YOUR_TOKEN_HERE" -H "Accept: application/json" https://dev.cloudo.lol/api/v1/nameservers

TL;DR

Cheat sheet of Domains API methods and paths under /api/v1 (nameservers, domains, health, verify, activate).

All Domains API routes live under the /api/v1 prefix on this Control Plane. Authenticate with Authorization: Bearer <token> (see #api-auth). Feature flag: CLOUDO_DOMAINS_API_ENABLED (default true; when false, these routes return HTTP 503).

Method Path Purpose
GET /nameservers Public Cloudo NS for this Control Plane
POST /domains Register hostname (± proxy/cdn/origin)
GET /domains?hostname= Lookup by hostname (same owner)
GET /domains/{id} Fetch by id
GET /domains/{id}/health Partner health snapshot (fresh NS check)
GET /domains/health?hostname= Health by hostname (same owner)
POST / GET /domains/{id}/verify-dns Check NS delegation to Cloudo
POST / PATCH /domains/{id}/activate Activate after DNS valid
POST /domains/{id}/disable Soft disable (force=1 archive path)
DELETE /domains/{id} Same as disable

This list matches the live Domains API only (docs/domains-api.md, docs/api/domains-openapi.yaml, and routes/api.php). It does not create WEB-01 vhosts — see #api-not-web01. Optional proxy/CDN on POST /domains is covered in #api-proxy-cdn. Health semantics: #api-domain-health.

TL;DR

POST /api/v1/domains registers a hostname; proxy defaults ON with WEB-01 origin unless proxy=false. Optional DNS-ready gate returns 422 dns_not_ready.

POST /api/v1/domains with JSON body hostname (required), optional external_ref, and optional metadata. Hostname is normalized (scheme/www stripped when safe). Invalid hostnames return 422.

On create, Cloudo creates the managed zone, ensures default DNS records when possible, completes onboarding so the zone can enter the next DNS snapshot, and soft-queues a DNS deploy. When proxy/origin are omitted, Protection defaults ON with the product WEB-01 origin (94.130.217.180). Send proxy=false for DNS-zone-only. Status starts as pending until activate.

When CLOUDO_DOMAIN_ADD_REQUIRE_DNS is on, POST /domains that would attach proxy/origin (Active+Origin, including the default proxy=true path) is refused with HTTP 422 code=dns_not_ready (reason nameservers_pending or nameservers_mismatch) until public registrar NS show Using Cloudo DNS — same readiness check as POST /vhosts. No domain row with Origin and no Edge side effects on refusal. Explicit proxy=false (DNS-zone-only) is still allowed so you can register first, point NS, then re-POST with proxy.

Idempotency: same hostname for the same API-owner account returns 200 with created false. Another account owns it → 409. Response always includes id, hostname, nameservers, status, proxy, cdn, and origin summary.

Example: curl -sS -X POST https://dev.cloudo.lol/api/v1/domains -H "Authorization: Bearer YOUR_TOKEN_HERE" -H "Content-Type: application/json" -d '{"hostname":"shop.example.com","external_ref":"partner-42"}'

TL;DR

Optional proxy/cdn/origin on register; omitted proxy defaults ON. Billing gates can return 402. Optional DNS-ready gate returns 422 dns_not_ready.

Optional register fields: proxy (or proxied), cdn, origin, origin_port, activate. When proxy and origin are omitted, Cloudo defaults to proxy=true and origin 94.130.217.180 (WEB-01 shared hosting). Send proxy=false for DNS-zone-only. Portal may still send proxy/origin explicitly; product defaults apply when fields are omitted.

  • proxy=true (or omitted) — binds Origin (request origin, or product default 94.130.217.180 when omitted). Origin is validated and billing entitlement is checked before the domain row is created, so a refused one-shot proxy register does not leave a silent DNS-only zone. Creates/binds a default Origin via the same DomainOriginService path as Backoffice, enables Protection on apex and www (when the Cloudo www default exists), and queues DNS/HTTP deploy (soft-fail like today). Does not create WEB-01 vhosts.
  • proxy=false — DNS zone only; no Edge Protection or default origin.
  • cdn=true — sets cdn_static_enabled. Allowed with proxy=true on this request, or on an already-proxied domain without re-sending proxy. Still requires effective Protection; otherwise 422. Subject to the same reverse-proxy entitlement gate as Backoffice CDN (402 when gates refuse).
  • origin_port — optional; defaults to 80 (http) for the product default origin, or 80 when a custom origin omits the port. Port 443 uses https. Origin is required only when newly enabling proxy and no product default origin is configured.
  • Billing: when CLOUDO_BILLING_GATES_ENABLED is on and the domain is not entitled (canUseReverseProxy false), Cloudo tries a wallet Pro activation ($20). If the wallet cannot fund it, proxy or CDN enable returns 402 with “Reverse proxy requires Pro / billing entitlement”. New API domains created while gates are on are Free/non-exempt. Prefer A: one-shot register with proxy (including omitted default) refuses 402 before create when funds are missing. Grandfathered/exempt domains proceed.
  • DNS-ready gate: when CLOUDO_DOMAIN_ADD_REQUIRE_DNS is on, proxy/origin attach (including default proxy) returns 422 code=dns_not_ready until Using Cloudo DNS — same check as Partner POST /vhosts. No Active+Origin row and no Edge side effects on refusal.

Example: curl -sS -X POST https://dev.cloudo.lol/api/v1/domains -H "Authorization: Bearer YOUR_TOKEN_HERE" -H "Content-Type: application/json" -d '{"hostname":"shop.example.com","proxy":true,"cdn":true,"origin":"203.0.113.10","origin_port":443}'

Proxy without registrar NS still pointing at Cloudo will not make HTTPS live until verify-dns succeeds and Edges activate — the previous working Edge config stays until then. After activate (NS valid), Cloudo resumes HTTPS/Edge prepare for already-proxied hostnames.

TL;DR

verify-dns checks registrar NS; activate marks active and resumes HTTPS prepare for proxied zones.

  • POST or GET /api/v1/domains/{id}/verify-dns — checks public NS against Cloudo nameservers. Returns valid, details, checked_at.
  • POST or PATCH /api/v1/domains/{id}/activate — marks status active after DNS is valid (unless skip_dns_check=1) and includes the zone in the next DNS publish. For proxied domains, resumes HTTPS/Edge prepare (same happy path as Protection toggle / certificates process-ready). Still does not configure WEB-01 nginx vhosts. POST /domains/{id}/disable without force sets Paused (API status disabled) and leaves the zone out of the next DNS publish until activate.
  • Optional activate=true on register — runs activate only when public NS already delegate to Cloudo; it does not skip the DNS check. If NS are not ready, the domain stays pending and activated is false.

Recommended order: point registrar NS → register (proxy/origin default ON unless proxy=false) → verify-dns until valid → activate (HTTPS prepare resumes) → poll #api-domain-health → use WEB-01 vhosts API separately if you need shared hosting vhosts. When CLOUDO_DOMAIN_ADD_REQUIRE_DNS is on, point NS before a proxy/origin Add (or register with proxy=false first).

TL;DR

GET /domains/{id}/health returns healthy + checks; unhealthy → partner detaches in their product; Cloudo does not auto-DELETE.

Partners poll GET /api/v1/domains/{id}/health (or GET /api/v1/domains/health?hostname=…) with a Domains-scoped Bearer token. The call refreshes public NS delegation (same check as verify-dns) and returns a health snapshot. It does not disable, archive, or DELETE the domain on Cloudo.

healthy is true only when the domain is owned by the API token’s account, is not archived / pending_removal / disabled, status is active, dns_delegation_valid is true after the fresh NS check, and — when Protection/proxy is desired — proxy_effective is true and ssl_ready is true from the same Secure/HTTPS fields as Backoffice (not a synthetic badge). https_reachable may be null in v1.

  • Response fields: hostname, healthy, status, checks (dns_delegation_valid, proxy_effective, ssl_ready, https_reachable), reasons[], checked_at, and domain (same payload shape as GET /domains/{id}).
  • If healthy is false, partners should detach or stop using the hostname in their own product. Cloudo does not auto-DELETE the domain because of an unhealthy health check — call DELETE /api/v1/domains/{id} (or disable) explicitly when you want Cloudo to soft-disable or force-remove.
  • 404 means the id/hostname is not owned by this API account (or is archived). Secrets and Bearer tokens are never echoed.

Example: curl -sS -H "Authorization: Bearer YOUR_TOKEN_HERE" -H "Accept: application/json" "https://dev.cloudo.lol/api/v1/domains/123/health"

Hostname form: curl -sS -H "Authorization: Bearer YOUR_TOKEN_HERE" -H "Accept: application/json" "https://dev.cloudo.lol/api/v1/domains/health?hostname=shop.example.com"

TL;DR

Common codes: 401/403 auth, 402 billing, 409 conflict, 422 validation / dns_not_ready, 503 when Domains API is disabled.

  • 401 — missing/invalid Bearer token.
  • 402 — reverse proxy or CDN requested but billing gates require Pro / entitlement. On one-shot proxy create (including default proxy when omitted), no domain row is created.
  • 403 — token scope insufficient.
  • 404 — domain id/hostname not found for this API client owner.
  • 409 — hostname already registered to another Cloudo account.
  • 422 — invalid hostname, missing origin when newly enabling proxy with no product default, cdn without effective proxy, unsafe origin, activate before NS are valid, or domain pending removal/archived. If the zone was created but proxy apply failed, data may include id/hostname/nameservers for recovery.
  • 422 dns_not_ready — when CLOUDO_DOMAIN_ADD_REQUIRE_DNS is on, proxy/origin Add (or re-POST that would attach Origin) while NS are Pending/mismatched. Body includes code=dns_not_ready and reason (nameservers_pending|nameservers_mismatch); no Active+Origin row and no Edge side effects. Same shape as Partner POST /vhosts.
  • 503 — Domains API disabled via CLOUDO_DOMAINS_API_ENABLED.

JSON errors use { "ok": false, "message": "…" }. dns_not_ready responses also include code, reason, and details. Secrets and Bearer tokens are never echoed. An unhealthy health response is still HTTP 200 with healthy false — see #api-domain-health.

TL;DR

Domains API manages Cloudo DNS/proxy; WEB-01 nginx vhosts are a separate /api/v1/vhosts API that requires Cloudo nameservers first.

POST /api/v1/domains manages Cloudo authoritative DNS (and optional Edge Protection/CDN). It does not create nginx vhosts on WEB-01.

WEB-01 shared hosting uses a separate partner API under /api/v1/vhosts with scope web01.vhosts or cloudo.api. Registering a domain for DNS/proxy and attaching a WEB-01 vhost are independent steps.

POST /api/v1/vhosts requires public DNS to already delegate to Cloudo (Using Cloudo DNS). If nameservers are still Pending or mismatched, the Control Plane returns HTTP 422 with code dns_not_ready and does not create a WEB-01 site.

See also Domains API operator docs and the WEB-01 vhosts documentation in the repository.

TL;DR

See #api-overview for the current Developer API overview. The Domains API under /api/v1/domains registers customer hostnames on Cloudo authoritative DNS and can optionally enable Protection and static CDN. It does not…

See #api-overview for the current Developer API overview. The Domains API under /api/v1/domains registers customer hostnames on Cloudo authoritative DNS and can optionally enable Protection and static CDN. It does not create WEB-01 vhosts.

TL;DR

See #api-auth. Send Authorization Bearer tokens from Account → API tokens or cloudo:api-client-create. Scope domains or cloudo.api. CLOUDO_DOMAINS_API_ENABLED=false returns 503.

See #api-auth. Send Authorization Bearer tokens from Account → API tokens or cloudo:api-client-create. Scope domains or cloudo.api. CLOUDO_DOMAINS_API_ENABLED=false returns 503.

TL;DR

Account → Webhooks: HMAC-SHA256 signed HTTPS callbacks for SSL, origin and (staff) deploy/agent events, with retries, delivery log, test button and SSRF protection. Flag CLOUDO_WEBHOOKS_ENABLED.

Account → Webhooks (/profile/webhooks) lets every user register up to 10 HTTPS endpoints. Each endpoint has a name, URL, signing secret (shown once at create or rotate) and the events it wants: ssl.issued, ssl.failed, ssl.expiring (14 and 3 days before expiry), origin.down and origin.up for domains you own. Staff with infrastructure access can choose scope "platform" to receive these for all domains plus deploy.succeeded, deploy.failed and agent.rollback. The page is visible only when CLOUDO_WEBHOOKS_ENABLED is on (default off).

Each delivery is a JSON POST {id, type, created_at, test, domain{id,name}, data{…}} with headers Cloudo-Webhook-Id, Cloudo-Webhook-Event, Cloudo-Webhook-Timestamp and Cloudo-Signature: t=<unix>,v1=<hex>. v1 is HMAC-SHA256 of "<t>.<raw body>" with your secret. Verify with a constant-time compare, reject timestamps older than 5 minutes and de-duplicate on Cloudo-Webhook-Id (retries reuse the same id).

Any 2xx response is success. Other responses or network errors are retried with backoff (1 min, 5 min, 30 min, 2 h, 6 h; 6 attempts). Redirects are not followed. After 50 consecutive failed attempts the endpoint is disabled automatically; re-enable it with Save. Deliveries are rate-limited to 60 per minute per endpoint. Send test event performs one immediate delivery and shows the HTTP status; the last 50 deliveries are listed in the delivery log.

Safety: only https:// URLs on ports 443 or 8443, no credentials in the URL, and the host must resolve only to public addresses. Private, loopback, link-local, CGNAT, cloud metadata (169.254.169.254) and other reserved IPv4/IPv6 ranges are refused at save time and again before every delivery, and the connection is pinned to the checked address. Origin events are emitted only when origin health alerts are enabled; secrets are never included in payloads. Creating, editing, testing, rotating and deleting endpoints are recorded in the Audit Log.

TL;DR

See #api-nameservers. Prefer GET /api/v1/nameservers; domain payloads also include nameservers[]. Production public names: ns1.cloudo.lol and ns2.cloudo.lol.

See #api-nameservers. Prefer GET /api/v1/nameservers; domain payloads also include nameservers[]. Production public names: ns1.cloudo.lol and ns2.cloudo.lol.

TL;DR

See #api-add-domain, #api-proxy-cdn, and #api-verify-activate for the current register → verify → activate flow, including optional proxy/CDN on register.

See #api-add-domain, #api-proxy-cdn, and #api-verify-activate for the current register → verify → activate flow, including optional proxy/CDN on register.

TL;DR

See #api-errors for the current error table (including 402 for billing entitlement and 422 for proxy/CDN validation).

See #api-errors for the current error table (including 402 for billing entitlement and 422 for proxy/CDN validation).

Domains

TL;DR

Add the hostname, review DNS, then point registrar NS at ns1/ns2.cloudo.lol. Proxy and SSL come after onboarding.

What it does

Starts onboarding for a hostname you control. Cloudo scans existing public DNS, then you review records and save.

When to use it

When you want Cloudo to publish authoritative DNS and, after Protection and SSL, proxy HTTP through Edges.

What it protects against

Puts the domain under Cloudo management so later DNS, SSL, origin, CDN, and security settings can deploy.

What it does NOT protect against

Does not create mail, FTP, or any hosting service. Creating DNS records is not the same as creating those services.

Possible side effects

Apex A (proxied) and www CNAME (proxied) are created automatically when missing. mail and ftp records are not auto-created. You must still point the domain’s nameservers at ns1.cloudo.lol and ns2.cloudo.lol for Cloudo DNS to be authoritative.

TL;DR

Skip a slow scan to continue onboarding with defaults; background results merge later without changing registrar DNS.

After a few seconds on the scanning page, you can choose Skip and continue. Cloudo opens the review list with platform defaults so onboarding is not blocked by slow public DNS lookups.

The scan job still finishes in the background with a hard server timeout. Any records found later are merged into the review list without deleting records you already keep or edit. No live DNS at your registrar is changed by scanning or skipping.

TL;DR

Paused is not shown as Active and is left out of the next DNS publish until activate. Pending → Active is normal onboarding.

  • Pending: onboarding is not finished, or nameservers / required records are not in place yet.
  • Active: the domain is in normal operation and can be included in DNS publishes.
  • Paused: the Domains list and overview show Paused, not Active. The Domains API calls this disabled. The zone is left out of the next DNS publish until it is activated again. History is kept. Edges keep the last configuration that already activated until a new deploy succeeds. Resume with Domains API POST /domains/{id}/activate, or, for Cloudo staff who have Manage all domains, Admin → Domains → Activate. The domain owner cannot unpause from the domain page.
  • Error: a lifecycle or configuration problem needs attention.
  • Quarantined: Cloudo hid an abandoned or incomplete setup from the default Domains list (for example pending setup left unfinished). Quarantined domains stop automatic SSL and Edge retry spam. They are not visitor outages by themselves.
  • Pending removal: you confirmed delete; drop deploys are queued. The domain disappears from the active Domains list immediately. Live Edges may still serve the last valid release until those deploys activate.
  • Removed / archived: the domain is no longer an active managed domain in the Backoffice.

The Domains list search is server-side (hostname contains match) with pagination. It does not download every domain into the browser. Type a hostname fragment to find a zone among large accounts. Filter by status to show only Active, Pending, Paused, or Error. Paused is the same state the Domains API reports as disabled.

TL;DR

Cloudo can automatically quarantine domains that stay in incomplete setup (Pending, onboarding never finished, and no usable origin or SSL) after a grace period (default seven days), then soft-delete (archive) them…

Cloudo can automatically quarantine domains that stay in incomplete setup (Pending, onboarding never finished, and no usable origin or SSL) after a grace period (default seven days), then soft-delete (archive) them after a further hold. Domains whose public nameservers leave Cloudo for that same grace period are quarantined the same way (reversible if nameservers return before archive). Smoke/probe/QA leftover hostnames use a shorter TTL.

Protect list domains are never auto-quarantined or archived by this cleanup, including grandx.site, cloudo.lol, garoplay.com, aladinoplay.net, amatic365.eu, plus any hostname in the operator allowlist. Paid Pro/Enterprise and platform proxy zones are also skipped.

This cleanup is operator-controlled (feature flag, default off). When it is off, nothing is quarantined or archived automatically. Soft-delete keeps history; it is not a hard wipe of wallets, users, audit logs, or config versions. It does not mass-republish Edges. Apply on production requires an explicit operator GO.

TL;DR

New domains often sit in pending while DNS is scanned, records are reviewed, nameservers are switched, and the first deploy completes. SSL can also show pending or issuing after Protection is turned on.

New domains often sit in pending while DNS is scanned, records are reviewed, nameservers are switched, and the first deploy completes. SSL can also show pending or issuing after Protection is turned on.

Pending means work is not finished. It is not a visitor outage by itself. Traffic follows whatever the Edge last activated, and public resolvers follow whatever nameservers the registrar still has.

Protection and HTTPS badges update from deploy events plus a short transitional poll (a few seconds). Cloudo does not show Secure or Active HTTPS until the certificate and Edge path are actually live.

Turning Proxy/Protection ON once queues Edge HTTPS deploy when a covering certificate is already ready. You do not need a second DNS Save to start that deploy. Protection stays Preparing until Edges validate (nginx -t), activate with reload, and DNS switches to Edge addresses — or it shows Failed if validation fails and the previous working configuration stays live.

If you remove a domain and add the same hostname again, Cloudo reuses a still-valid certificate from the archived domain when it belongs to your account. Protection may stay Preparing until that certificate is rebound, redeployed to Edges, and public DNS switches to Edge addresses — badges do not flip to Active or Secure until that path is live. Dedicated origins (including Host/SNI) are rebound the same way so a proxied subdomain is not silently sent to the new domain default origin.

TL;DR

Type the hostname to confirm; Edges keep serving until drop deploys validate and activate. Change registrar NS separately.

What it does

Queues deploys that drop the domain’s configuration from Edges after you type the domain name to confirm. The domain is hidden from the active Domains list immediately while removal finishes.

When to use it

When you no longer want Cloudo to publish DNS or proxy HTTP for that hostname.

What it protects against

Stops Cloudo from remaining the intended publisher for that domain once drop deploys succeed and you move nameservers away.

What it does NOT protect against

Does not instantly wipe every resolver cache, registrar nameserver setting, or last-valid Edge release. Does not hard-delete history before Edges reconcile the drop. Certificate material for the hostname may remain attached to the archived domain row until you re-add the zone; then Cloudo can rebind a still-valid certificate to the new domain instead of always re-running ACME. Origins (address, port, protocol, Host header, SNI) are rebound the same way so dedicated subdomain upstreams are not replaced by a silent default.

Possible side effects

Can interrupt visitor traffic. Edges keep the last valid release until the drop deploy validates (nginx -t / CoreDNS checks) and activates with reload. External DNS may still point at Cloudo until you change the registrar.

TL;DR

Removing a domain is dangerous. It can interrupt visitor traffic once drop deploys activate. Typing the exact name is a deliberate confirmation so a misclick does not queue a drop.

Removing a domain is dangerous. It can interrupt visitor traffic once drop deploys activate. Typing the exact name is a deliberate confirmation so a misclick does not queue a drop.

If the typed name is blank or does not match, the Control Plane rejects the request. No config version, deployment, or domain status change is created until the confirmation matches.

TL;DR

Visitor traffic follows the last valid configuration already on each Edge. Editing DNS, origins, SSL, firewall, or CDN in the Backoffice does not change live traffic until a deployment validates and activates on that…

Visitor traffic follows the last valid configuration already on each Edge. Editing DNS, origins, SSL, firewall, or CDN in the Backoffice does not change live traffic until a deployment validates and activates on that Edge.

While a domain is pending removal, Edges may still serve the previous release. After a successful drop, that Edge stops serving the domain. If some Edges succeed and others fail, traffic can differ by Edge.

TL;DR

The Backoffice stores the desired snapshot. Edges only change after a deployment of that snapshot. This keeps a failed candidate from replacing a working site: validation must succeed first, then the Edge reloads.

The Backoffice stores the desired snapshot. Edges only change after a deployment of that snapshot. This keeps a failed candidate from replacing a working site: validation must succeed first, then the Edge reloads.

If you skip deploy, you have saved intent in the Control Plane but visitors still see the last activated release.

DNS

TL;DR

Editable: A, AAAA, CNAME, MX, TXT, CAA. NS/SOA are Cloudo-managed. A record does not create a service.

Customer-editable types are A, AAAA, CNAME, MX, TXT, and CAA. NS and SOA are not customer-editable; Cloudo publishes those for the zone.

Creating a record does not create a service. An MX record does not provision mailboxes. An A record for ftp does not create FTP.

Each record can exist only once per domain: the same type, name and value (and MX priority). TTL and Proxy do not make a record different. If you add a record that already exists, the Backoffice says so (for example “An A record for @ → 203.0.113.10 already exists — edit it instead.”) and highlights the existing row. Edit that row to change TTL or turn Proxy on. If the same record was found earlier but not included in your zone, adding it again simply includes it.

During the onboarding review, records you added yourself are always kept; the Keep checkboxes and “Uncheck all” only apply to records found by the scan and Cloudo defaults. If saving would leave the zone with no records, the Backoffice warns you. Records that are not published are listed under DNS → Excluded records, where Include adds them back.

TL;DR

TTL is how long resolvers may cache the record. In the Backoffice you can choose Auto or 60, 120, 300, 600, 1800, 3600, 14400, or 86400 seconds.

TTL is how long resolvers may cache the record. In the Backoffice you can choose Auto or 60, 120, 300, 600, 1800, 3600, 14400, or 86400 seconds.

Lower TTL makes later changes visible sooner after expiry, but it does not flush caches that already hold the old answer.

TL;DR

Proxy ON publishes Edge IPs. Proxy OFF publishes record Content (direct). Desired ≠ effective until DNS deploy; hosting HTTPS is required for DNS Only.

Proxy can be enabled on A, AAAA, and CNAME records when the domain is entitled to reverse proxy (Pro, Enterprise, or billing-exempt grandfathered domains). Proxied hostnames are intended to go through Cloudo Edges for HTTP/HTTPS (orange-cloud style). When Proxy is live, authoritative DNS publishes Cloudo Edge addresses for those names — not your Origin IP.

Free plan domains that are not billing-exempt cannot enable Proxy. Soft gates show an upgrade-to-Pro message when CLOUDO_BILLING_GATES_ENABLED is on. See pricing opens the Pricing page; add credits from Dashboard Wallet or Account → Billing.

Desired vs effective: the Proxy switch is your desired setting. Effective routing is what visitors get after DNS (and Edge) deploy. The DNS table shows both. Cloudo never labels a hostname as DNS only while deployed DNS still answers with Edge IPs — that transitional state shows as Switching to DNS only until the DNS deploy finishes.

Turning Proxy off (DNS Only) publishes this record’s Content as the direct hosting target. It does not invent a different hosting IP and does not publish Cloudo Edge addresses as DNS Only. If Content were somehow a Cloudo Edge IP, Cloudo refuses that as a hosting target and prefers a usable Origin address of the same family, or blocks the DNS publish with a clear error. MX, TXT, and CAA are never proxied.

DNS table labels: intentional Proxy OFF is shown as neutral DNS only with a compact amber Not protected / Direct to origin · Not protected hint (details in the tooltip). That is not Protection Error or HTTPS Error — Cloudo does not treat DNS only as a provisioning failure and does not start Edge deploy or SSL solely because a record is DNS only. Proxied healthy rows show ✓ Edge active. Genuine Edge activation failures on Proxy ON show ⚠ Edge activation failed. Domain header Protection Error / HTTPS Error badges aggregate only hostnames where Proxy is intentionally ON and activation failed; other proxied failures on the same domain still surface.

HTTPS when Proxy is off: Cloudo Edge HTTPS and HTTPS-only redirect no longer cover that hostname after DNS cutover. Visitors talk to your server directly. If that server has no valid certificate for the hostname (for example HTTP-only lobby on the same IP as other sites), browsers show a certificate warning and the request may hit the wrong HTTPS vhost. The Backoffice shows a compact Not protected hint on Proxy OFF (tooltip explains Edge HTTPS does not apply); fix hosting HTTPS before relying on DNS Only.

When you turn Proxy on for an A or AAAA record without choosing an Origin, Cloudo creates or reuses an Origin from that DNS target (same address, HTTP port 80, and for subdomains Host/SNI set to the hostname) and binds it to the record. The DNS page shows Content (the address record) and the Edge origin the proxy actually uses. Cloudo does not silently send a hostname whose target differs from the domain default to that default. Sharing an IP and port with another hostname does not copy that hostname’s Host header: apex and www keep a blank Host header so the Edge sends the visitor hostname, and each subdomain keeps its own Host/SNI. If you set Host header or SNI on the apex origin to a name that is not another hostname in the zone, automatic apex sync keeps that override and does not clear it.

CNAME Proxy does not invent an Origin from the CNAME target. Use an explicit Origin (the www companion of a proxied apex inherits the apex Origin). Edge, loopback, and other reserved addresses cannot be Origins. A/AAAA publish Edge A or AAAA respectively; proxied CNAMEs are flattened to Edge A/AAAA.

Turning Proxy off keeps the Edge HTTP site until deployed DNS no longer points at Edge (cutover hold), then removes the hostname from Edge routing on the next Edge deploy. It does not revoke certificates and does not immediately delete the Origin row — you can turn Proxy back on or remove unused Origins from the Origin page.

Deleting a DNS subdomain (or other record) that was bound to an auto-created Origin removes that Origin only after Edge deploy succeeds (nginx test, atomic activate, reload) and only when nothing else still references it — not another subdomain, the domain default, or any other DNS/proxy binding. Origins you created manually on the Origin page are kept even if orphaned. If Edge deploy fails, the previous Edge config stays live and the Origin is not removed until a later successful deploy.

TL;DR

When you add a domain, Cloudo auto-creates a proxied apex A record and a proxied www CNAME pointing at the zone apex hostname (for example www → example.com) if they are missing. mail and ftp are not created…

When you add a domain, Cloudo auto-creates a proxied apex A record and a proxied www CNAME pointing at the zone apex hostname (for example www → example.com) if they are missing. mail and ftp are not created automatically.

On create or update, a CNAME or MX target of @ is stored as the zone apex hostname. Older rows that still contain @ are expanded to the apex when Cloudo builds a DNS snapshot, so authoritative DNS agents never receive a literal @ target.

Certificate issuance may add a temporary _acme-challenge TXT record for DNS-01. That is for SSL, not a website hostname.

TL;DR

Backoffice save is instant; public resolvers wait for deploy + TTL. Confirm registrar NS are on Cloudo.

Saving in the Backoffice updates the DNS records table immediately without a full page reload. A “DNS changes pending” notice means the change is saved but not yet live on authoritative DNS until deploy finishes.

Saving in the Backoffice is not the same as every resolver on the internet updating. The change must deploy to Cloudo’s authoritative DNS nodes (`ns1` / `ns2`), then public resolvers wait until their cached TTL expires.

Your ISP or browser may still show the previous IP for minutes to hours. Check from more than one resolver, and confirm nameservers at the registrar are ns1.cloudo.lol and ns2.cloudo.lol.

TL;DR

Cloudo is authoritative only after registrar NS are ns1/ns2.cloudo.lol. Visitors follow registrar NS, not Backoffice alone.

Cloudo is authoritative only after the registrar nameservers are ns1.cloudo.lol and ns2.cloudo.lol. Until then, the old DNS host still answers the public internet, even if the Backoffice already has records.

Do not keep a second “live” copy of the zone at another DNS host expecting Cloudo proxy to apply. Visitors follow the nameservers the registrar lists.

Origins

TL;DR

An origin is your backend server for a domain — the machine that generates HTML and application responses. It is not an Edge node. Edges proxy visitors to the origin; they do not host the site for you.

An origin is your backend server for a domain — the machine that generates HTML and application responses. It is not an Edge node. Edges proxy visitors to the origin; they do not host the site for you.

TL;DR

Each origin has an address (IP or hostname), a port, and a protocol (HTTP or HTTPS) for the Edge-to-origin connection. That protocol is independent of the visitor-facing HTTPS only toggle.

Each origin has an address (IP or hostname), a port, and a protocol (HTTP or HTTPS) for the Edge-to-origin connection. That protocol is independent of the visitor-facing HTTPS only toggle.

Wrong port or protocol commonly produces 502 or 504 for visitors after deploy. Confirm the origin actually listens on that combination and allows the Edge addresses.

TL;DR

Host header and SNI are separate origin fields. Host header is what the Edge sends in the HTTP Host header. SNI is the name used on the TLS handshake when the origin protocol is HTTPS.

Host header and SNI are separate origin fields. Host header is what the Edge sends in the HTTP Host header. SNI is the name used on the TLS handshake when the origin protocol is HTTPS.

If the origin virtual-host or certificate expects a specific name, set these fields to match. Leaving them wrong can look like an origin outage even when the IP is reachable.

Two origins may share one address and port and still send different Host headers. Cloudo does not bind apex, www, or another subdomain to an origin whose Host header names a different site. An apex origin whose Host header or SNI you set explicitly keeps those values when Cloudo syncs the apex address; they are not cleared back to blank.

TL;DR

A domain can have more than one origin. Pool modes are single, round_robin, least_conn, and primary_backup (shown as Round robin, Least connections, and Primary + backup).

A domain can have more than one origin. Pool modes are single, round_robin, least_conn, and primary_backup (shown as Round robin, Least connections, and Primary + backup).

  • single: one active origin.
  • round_robin: rotate across enabled origins.
  • least_conn: prefer the origin with fewer current connections.
  • primary_backup: send traffic to the primary and use backup members when the pool is set up that way.

On the Domains list, the Origin column shows — when there is no origin, the upstream URL when there is one, the default upstream plus “+N more” when a default origin is set among several, or “N origins” when several exist without an authoritative default. It does not pick a primary from priority or role for that summary.

A proxied hostname bound to a dedicated Origin (not the domain default) keeps that Origin on the Edge even when the domain uses a multi-origin pool mode. Pool modes apply to hostnames that use the domain default Origin.

Changing pool membership or mode does not affect visitors until an HTTP deploy activates.

TL;DR

Origin health in the Backoffice is monitoring. It tells you whether Cloudo could reach the origin recently. By default it does not change which origin receives traffic.

Origin health in the Backoffice is monitoring. It tells you whether Cloudo could reach the origin recently. By default it does not change which origin receives traffic.

Health is probed from Cloudo Edge, so only origins of domains with at least one proxied (Protection ON) hostname are checked. For a DNS-only domain the origin shows “Not monitored (proxy off)” instead of Unknown.

A red or failing health badge is a signal to check the origin. It does not rewrite DNS, it does not fail or roll back an HTTP fleet release, and it does not replace Save & Deploy for normal pool or origin edits.

When health-aware origin routing is enabled, a confirmed unhealthy origin can be compiled out of the active Nginx upstream (server … down) after probe thresholds and a versioned HTTP deploy — but only when the domain uses a multi-origin pool (round robin, least connections, or primary + backup with at least two enabled origins). Single-origin mode and one-member pools stay monitoring only (Routing: Not eligible). Degraded, unknown, or stale health never removes an origin. If every pool member would become non-routable, Cloudo applies a fail-safe and keeps upstream members compiled in (Automatic failover: Degraded). On the domain Origin pool page, Role, Health, and Routing are shown separately: Routing reflects compiled upstream state (Serving, Standby, Removed, and related labels), not health alone. Health Checks uses a similar Routing column when the pilot is on.

TL;DR

Origin down shows a branded 502/504 Origin unreachable page when origin-keepalive Edge config is on (not the HV security-check 503).

If no usable origin answers, visitors see a branded Cloudo “Origin unreachable” page with HTTP 502 (connection refused) or 504 (origin timed out), Cache-Control: no-store, and a Ray ID. The page shows the hostname, not the origin IP. (Requires the domain’s Edge origin-keepalive config to be enabled; otherwise the Edge may still map origin failures through the temporary security-check page.)

That is different from Human Verification being down: when the Edge cannot finish a security check, visitors still see the temporary “security check” 503 page.

DNS and SSL can still look fine because they do not need the origin to answer public lookups or present the Edge certificate. Fix the origin (process up, firewall allows Edges, correct address/port/protocol/Host/SNI), then confirm from the domain Origin page. You do not need to delete the domain.

TL;DR

If you remove a domain and add the same hostname again, Cloudo rebinds origins that still belong to your archived domain — including Host header, SNI, protocol, and port — onto the new domain.

If you remove a domain and add the same hostname again, Cloudo rebinds origins that still belong to your archived domain — including Host header, SNI, protocol, and port — onto the new domain.

Each proxied DNS hostname keeps (or rematches) its dedicated origin when one exists. Cloudo does not silently send a subdomain to the new domain default origin when a dedicated mapping is present.

On the DNS page, Content is the DNS address record. For proxied rows, the Edge origin line shows the upstream the Edge actually uses. Those can differ on purpose (for example Content shows your server IP while Edge origin uses HTTPS on port 443 with a Host/SNI override).

Turning Proxy on for an A/AAAA without an Origin creates or reuses one from the DNS target instead of guessing the domain default when the target differs.

TL;DR

Apex and www hostnames, including grandx.site, share one player site: site key lobby, document root /var/www/lobby. They are not separate app copies. bo.* uses /var/www/bo.garoplay.com (site bo). cashier.* uses…

Apex and www hostnames, including grandx.site, share one player site: site key lobby, document root /var/www/lobby. They are not separate app copies. bo.* uses /var/www/bo.garoplay.com (site bo). cashier.* uses /var/www/cashier.garoplay.com (site cashier). Operator detail: docs/web01-domains.md.

That lobby folder is the shared player login at / and /login, plus static folders lobby1/ and lobby2/ (further lobby folders can be added the same way). After login, the player is sent to the lobby folder their point of sale is bound to. That binding is the Admin or Cashier backoffice. The vhost API does not choose the lobby folder.

Integrators should call the Control Plane partner API: POST /api/v1/vhosts with { "hostname", "site": "lobby" } for an apex hostname, or "bo" / "cashier" for those subdomains. GET /api/v1/vhosts/{hostname} returns status (present, root path, SSL state). DELETE /api/v1/vhosts/{hostname} detaches the hostname only and never deletes the shared folder. Auth is the same Profile API Bearer token as Domains (scope web01.vhosts or cloudo.api).

  • Preferred auth: Authorization Bearer from Account → API tokens. Tokens are not written to audit logs.
  • DEV bootstrap: the local web-agent on 127.0.0.1:9091 may still use CLOUDO_WEB_API_TOKEN for localhost ops. Partners should not rely on that env token — use Profile tokens against the Control Plane URL.
  • DNS gate (Control Plane): POST /api/v1/vhosts is refused with HTTP 422 and code dns_not_ready until public registrar nameservers delegate to Cloudo (Using Cloudo DNS). Pending nameserver change and Nameserver mismatch both block attach — no WEB-01 site create and no agent hop. Domains may still appear as Pending/Preparing in the UI; that does not mean the hostname is provisioned on WEB-01.
  • Validation: hostname must be a valid FQDN. Attach is refused if the name already serves a different unique document root.
  • When the DNS gate passes, the Control Plane forwards X-Cloudo-Dns-Verified: 1 to the web-agent. Direct agent attaches may still require that header when CLOUDO_WEB_REQUIRE_DNS_VERIFIED=1.
  • Reload safety: atomic nginx config write, nginx -t, then reload (not restart). Failed tests restore the previous config.
  • Nginx layout: the player lobby is hand-managed. One location uses try_files so real files under /lobby1/ and /lobby2/ are served, and / and /login fall back to the shared login page when they are not real files. Lobby folders do not replace that login page. Attach and detach only update server_name on hand-managed and SPA vhosts. They are not replaced with a PHP index.php template.
  • TLS today: HTTP attach is supported; origin HTTPS is TODO until certificates are configured (ssl.mode http_only). Edge-terminated visitor HTTPS with Proxy ON is separate.
  • Integration order: register domain → point registrar NS at Cloudo → verify-dns / health until delegated → then POST /api/v1/vhosts.

Idempotent attach/detach is safe to retry. Unknown site keys are rejected. Apex hostnames use site lobby. bo and cashier are separate catalog keys.

CDN

TL;DR

Edge caches static css/js/images/fonts, plus game/media assets when opted in (never HTML, json, or bin). Optional static cache — not a global anycast CDN.

CDN caches static files at the Edge: css, js, images, and fonts. With the per-domain opt-in "Also cache game & media assets" (off by default) it also caches mp3, ogg, wav, webm, mp4, wasm, and atlas files. HTML is not cached. JSON and bin paths are not cached. POST requests, Authorization headers, login cookies, and responses with Set-Cookie or Cache-Control private/no-store bypass or refuse cache.

This is optional static file caching on the Edge, not a global anycast CDN product. Objects larger than 512 MiB are not stored. Only those static file extensions match — not HTML documents, JSON APIs, or arbitrary paths.

Edge TTL presets (Auto, 5m, 30m, 1h, 4h, 1d) set how long the Edge keeps static files; Auto keeps the platform default (7 days). Origin Cache-Control private/no-store is still honored so those responses are not stored.

TL;DR

Edge TTL presets control static cache lifetime on the Edge; Auto = 7 days.

What it does

Chooses how long eligible static 200 responses may stay on the Edge before Nginx revalidates or refetches.

When to use it

When you want shorter cache lifetimes after deploys or longer caching for stable assets.

What it protects against

Auto uses the platform default (7 days). Other presets map directly to nginx proxy_cache_valid for static locations only.

What it does NOT protect against

Does not cache HTML. Does not respect origin Cache-Control headers in Phase 1. Does not purge individual URLs.

Possible side effects

Save & Deploy must activate on each Edge. Changing TTL does not purge existing bytes on disk — use Purge All when you need a full-domain static refresh.

TL;DR

Toggle static file cache on the domain Cache tab; Save & Deploy must activate on each Edge.

What it does

Toggles cache for static assets on the domain Cache tab and queues an HTTP deploy.

When to use it

When you want Edges to store static assets, or when you want every static request to go back to origin.

What it protects against

Can reduce origin load for cacheable static files after the deploy activates.

What it does NOT protect against

Does not cache HTML. Does not change origin files. Does not create extra Points of Presence.

Possible side effects

Save & Deploy must succeed on each Edge. Until then, the previous cache setting remains live.

TL;DR

Purge All rotates cache keys so Edges drop static files for the domain after deploy.

What it does

Bumps the cache generation for the domain and queues a new HTTP config so Edges stop serving previously cached static files for that domain.

When to use it

When visitors still see an old css/js/image/font after you updated the file on the origin.

What it protects against

Forces those static URLs to be refetched from origin after the deploy validates and activates.

What it does NOT protect against

Does not delete files on the origin. Does not delete cache files on Edges (it rotates the cache key namespace). Does not reset HTML (HTML is not cached). To drop only some files, use Purge URLs or prefixes.

Possible side effects

Nginx is reloaded, not restarted. Confirm in the modal. Origin traffic for static files will rise until the cache fills again.

TL;DR

Purge URLs or prefixes deletes only matching cached files on each Edge; falls back to Purge All when an Edge cannot.

What it does

Domain → Cache → Purge URLs or prefixes: each Edge agent deletes only the matching cached static files (cache key md5 → file path for URLs; a bounded scan of the cache KEY lines for prefixes).

When to use it

When one css/js/image changed and a full Purge All would send every static request back to origin.

What it protects against

Matching files are refetched from origin on the next request (X-Cache-Status MISS, then HIT). Other cached files keep serving as HIT. Usually done within a minute; no config deploy or nginx reload.

What it does NOT protect against

Does not purge HTML (not cached). URL purge is exact, including the query string — use a prefix for every ?v= variant. Paths apply to http and https on all hostnames of the domain; full URLs only to that host and scheme.

Possible side effects

If an Edge runs an older agent, hits the prefix scan limit (CLOUDO_CACHE_PURGE_SCAN_MAX_FILES, default 500000 files / CLOUDO_CACHE_PURGE_SCAN_SECONDS 20), errors, or does not report in 5 minutes, Cloudo falls back to Purge All for the domain. API: effective url|prefix|all. Feature flag CLOUDO_CACHE_SELECTIVE_PURGE_ENABLED (default on outside production).

TL;DR

Per-domain Edge 503 maintenance page for every visitor path, including static files.

Domain → Maintenance shows a branded HTTP 503 page at the Edge for every visitor path while you work on the origin — HTML, static files (css, js, images, fonts), game client files, and paths covered by Rules. Nothing is fetched from the origin or served from Edge cache while it is on. The page shows your title and message plus a Ray ID for support.

  • Save & Deploy queues HTTP config. Until deploy succeeds on each Edge, the previous live behavior remains.
  • Exceptions: certificate checks (/.well-known/acme-challenge/), internal Edge paths (/__cloudo/) and the Edge deploy health check keep working. Human Verification, firewall rules (a blocked path still gets the blocked page), and site-wide rate limits still screen visitors before the 503. Path-specific rate limits, DDoS static limits, and routing rules are not evaluated because every other path answers 503.
  • Responses use Cache-Control: no-store. Optional Retry-After (seconds) is sent when configured.
  • Title and message are HTML-escaped on the Edge. Leave blank to use platform defaults.
  • Turn maintenance off and Save & Deploy to restore proxy traffic.

Not available yet: per-path maintenance exceptions, scheduling, or bypass tokens.

TL;DR

Path redirects and same-domain path routing.

Domain → Rules lets you add Redirect rules (301/302 to another URL or path) and Routing rules (send a path prefix or exact path to another origin on the same domain or to the origin pool).

  • No regex patterns — exact paths or path prefixes only.
  • Lower priority numbers run first. At the same priority, exact paths beat prefixes; ties break by rule id.
  • Reserved paths (/.well-known/, /__cloudo/, deploy health) cannot be used.
  • Redirect targets must be http(s) URLs or same-host paths. Looping redirects are rejected at save time.
  • Routing rules only use origins on the same domain (or the domain origin pool).
  • Save & Deploy HTTP config is required before Edges enforce rules.
  • Untick Enabled and Save to keep a rule without enforcing it. Delete (list or edit page, with confirmation) removes it from the next Edge deploy.
  • Routed paths behave like the rest of the site: Human Verification, firewall and site-wide rate limits, websockets, static caching, and the branded blocked page all apply. If the routed origin fails, the Edge retries the domain's other enabled origins that use the same protocol before returning an error.

Not available yet: regex, cross-domain origin routing, apex↔www canonical redirects, or per-URL analytics breakdown.

TL;DR

When static cache is on, responses can include X-Cache-Status with HIT, MISS, BYPASS, EXPIRED, or STALE.

When static cache is on, responses can include X-Cache-Status with HIT, MISS, BYPASS, EXPIRED, or STALE.

  • HIT: served from Edge cache.
  • MISS: not in cache; fetched from origin and eligible to store.
  • BYPASS: not stored (HTML, POST, Authorization, login cookies, oversized, or unknown length).
  • EXPIRED / STALE: cache entry was old; Edge is revalidating or serving stale per Nginx cache rules.

SSL

  • pending: issuance has not finished; HTTP may still be serving without the new certificate.
  • issuing: ACME is in progress (DNS-01 challenge).
  • ready: a certificate was issued and is waiting to be activated on Edges.
  • active: Edges are presenting the certificate for visitor HTTPS.
  • failed: issuance, activation, or certificate material could not be used (for example stored cert material Control Plane cannot decrypt). The last valid certificate stays in use on Edges if one exists. Cloudo does not keep retrying undecryptable material on every background tick.

TL;DR

ACME DNS-01 issues customer certs after NS are on Cloudo. Protection ON prepares a certificate automatically.

Customer certificates use ACME DNS-01. Cloudo publishes an _acme-challenge TXT record on the authoritative nameservers, the certificate authority checks it, then the certificate is stored and deployed to Edges.

Nameservers must be ns1.cloudo.lol and ns2.cloudo.lol for DNS-01 to succeed. Turning Protection ON prepares a certificate automatically. Certificate secrets are never displayed in the Backoffice.

TL;DR

Pending/issuing is normal during DNS-01 and deploy; an older valid cert can still serve HTTPS.

Pending or issuing is normal while DNS-01 runs and while the certificate is staged, nginx -t succeeds, the Edge reloads, and the live TLS fingerprint is confirmed. It does not always mean the site is down. If a previous certificate is still valid, visitors can keep using HTTPS on that last valid certificate.

An unrelated origin timeout or 503 does not leave SSL stuck on Deployment pending after the Edge has confirmed the live certificate fingerprint. If nameservers are not on Cloudo yet, or _acme-challenge cannot be seen publicly, issuance stays pending or fails.

Staged means the Edge has the certificate files and nginx accepted them, but Control Plane has not yet seen the live TLS fingerprint. The Edge Node SSL summary counts the Control Plane deployment status (succeeded, staged, failed, untracked), not the Edge agent’s local labels. A www host served by the apex certificate counts as succeeded, and hosts that are no longer in the Edge config drop out of the summary. Operators can list never-completable open rows with php artisan ssl:supersede-stale-deployments --dry-run and close them with --apply.

TL;DR

Cloudo renews certificates before they expire using the same ACME DNS-01 path. You do not upload files to Edges. Failed renewal keeps the last valid certificate until it expires.

Cloudo renews certificates before they expire using the same ACME DNS-01 path. You do not upload files to Edges. Failed renewal keeps the last valid certificate until it expires.

Watch SSL status and expiry on the domain SSL page. Do not delete the domain to “force” renewal.

TL;DR

HTTPS only redirects visitor HTTP→HTTPS after a cert is active; it does not issue certificates by itself.

What it does

When On, visitors who request HTTP are redirected to HTTPS. Origin protocol is still configured under Origins.

When to use it

When you want all visitor traffic on HTTPS after a certificate is active.

What it protects against

Avoids lingering HTTP for visitors once HTTPS is working.

What it does NOT protect against

Does not issue a certificate by itself. Does not change the origin’s HTTP vs HTTPS setting.

Possible side effects

Queues an HTTP deploy. If HTTPS is not active yet, forcing redirect too early can make HTTP users fail to upgrade cleanly.

TL;DR

Failed issuance keeps the last valid certificate on the Edge if one exists. The site does not automatically fall back to a blank or self-signed cert from this failure path.

Failed issuance keeps the last valid certificate on the Edge if one exists. The site does not automatically fall back to a blank or self-signed cert from this failure path.

Check nameservers, DNS deploy status, _acme-challenge, and the certificate error on the SSL page. If the SSL page shows that certificate material cannot be decrypted, contact support — Cloudo does not delete the row and does not keep retrying that certificate every few minutes.

Archived certificates are ignored by automatic process-ready, Protection resume, and expiry watchdog loops. Fix the cause and retry when the certificate is eligible. Do not restart Nginx from the Backoffice — there is no such button, and normal deploys reload only after validation succeeds.

TL;DR

A daily watchdog (certificates:watchdog --edges, 04:47 server time) checks every live panel certificate and the certificates that are really served. It opens a TLS connection to each online HTTP Edge for each hostname…

A daily watchdog (certificates:watchdog --edges, 04:47 server time) checks every live panel certificate and the certificates that are really served. It opens a TLS connection to each online HTTP Edge for each hostname deployed there. It also checks the extra hosts in CLOUDO_SSL_WATCHDOG_TARGETS and CLOUDO_SSL_WATCHDOG_EXTRA_TARGETS, for example the Control Panel and mail STARTTLS on port 25.

Operators get an alert when a certificate has 14 days left, and again at 3 days (CLOUDO_SSL_WATCHDOG_THRESHOLDS). They also get one when an Edge serves a different certificate than the panel expects, or one that expires sooner than the panel certificate, and when an Edge handshake fails. Each alert is sent once per certificate and tier.

The Dashboard shows a Certificate expiry card with the open issues and the certificates that expire soonest. The SSL page lists the same warnings. To fix a mismatch, redeploy the certificate to that Edge from the SSL deployment view. The watchdog never changes certificates or Nginx itself.

Security

TL;DR

Domain Security: DDoS, firewall, rate limits, Phase 1 managed WAF/bot score, shadow Smart Detection, and Threat Intelligence. Human Verification is the shared challenge engine.

Domain Security covers DDoS Protection (automatic and manual Layer 7 mitigation), firewall rules, rate limiting, Security Phase 1 managed WAF / basic bot scoring (opt-in), Smart Detection (shadow only), and related Edge enforcement. Human Verification is the shared browser-challenge engine used by DDoS Under Attack / Automatic escalation and by firewall, rate-limit, managed WAF, or bot Managed Challenge actions — it is not a separate top-level product. IP Lists are account-level reusable lists you can attach from firewall conditions.

Firewall and rate limits match request metadata (IP, country, host, path, method, rate). Security Phase 1 managed WAF inspects URI and query (and limited safe request metadata) using Cloudo’s catalog — not a full application payload WAF and not OWASP CRS. Origin application hardening still belongs on your origin.

TL;DR

Read-only account security view. Incident counts come from Smart Detection transitions. Other zeros are stored telemetry. No GeoIP lookup and no Edge deploy.

Security → Threat Intelligence is a read-only page in the global navigation. It shows security telemetry for domains on your account. Staff who can view all domains see those accounts; a customer sees only their own domains. It does not change firewall rules, rate limits, or Edge configuration, and it does not deploy.

Blocked, challenged, request, and DDoS numbers come from stored security events, open DDoS attack events, and per-minute HTTP request totals. Empty values for those cards are zeros from those tables. The map uses the country code already stored on each event by the Edge. The page does not call a GeoIP service and does not show ASN. The country map is drawn from files shipped with the Backoffice. It does not load a map from an external network.

Active incidents come from Smart Detection transitions for domains that still have Smart Detection enabled. A domain counts while its latest transition is Elevated or Under attack. Turning Smart Detection off for that domain removes it from this list. If you set an operator override on that domain, the override is the state that counts. Under attack is the critical count. When the transition table is not installed, the incidents card says “Smart Detection not installed” and that card is not shown as zero. Other telemetry still appears.

Cards labeled “now” are active incidents, open critical alerts, current requests per second (the last full UTC minute, summed across edges that served the selected domains), domains under attack, and active edges. Domains under attack counts each of your domains once when either an open DDoS attack event exists or Smart Detection is enabled and the state is Under attack (shadow mode included). Turning Smart Detection off drops that domain from the Smart Detection part of the count. An active edge is one with a fresh heartbeat that also served your domains in the selected period. Cards labeled “selected period” are blocked, challenged, and suspicious percent. Suspicious percent is blocked plus challenged events divided by HTTP requests in that same window. Log-only managed WAF matches are not included in blocked, challenged, suspicious percent, or the map’s blocked and challenged counts. The map and country chart label those log-only matches separately. Query strings are removed from paths, and angle brackets are removed from paths and user agents before they are shown as text. A source IP is included only when you can already view that domain. A role without that access does not receive the address.

The event list shows UTC time, Ray ID, domain, IP when permitted, country, edge, method, path, rule, bot score when one was stored, action, reason, and user agent. Click a linked row to open Domain → Security → Events for that domain (filtered by Ray ID when the event has one). Rows without a working domain link are not clickable. Filter by time range, domain, and edge. Choosing another account’s domain or edge does not reveal that account. Search and country clicks narrow the list. Older pages and the live poll use a time-and-id cursor so two events at the same second are not skipped or repeated. The live poll is rate limited.

The domain filter is a search box. With the box empty, it lists up to 20 of your domains that had the most security events and HTTP requests in the selected time range, and it says “Type to search”. Typing a name waits about a quarter of a second, then matches domain names you can view (managed domains on your account, or every managed domain for staff who can view all domains). At most 50 matches are returned. The domain you pick is shown as a chip; clearing it returns to all domains. The page address keeps domain_id, so a refresh stays on that domain. All-domains totals count every domain you can view. They are not cut off after a fixed number of domains. When more than 20 edges appear in the period, the edge filter is a search box with the same keyboard behavior. With 20 or fewer edges, it stays a dropdown. Clearing an edge chip returns to all edges.

The page refreshes about every 5 seconds while the tab is visible, asking only for rows newer than the last cursor. The badge reads LIVE after a fresh response, RECONNECTING while a retry is backing off, DATA DELAYED when the tab is hidden or the last response is stale, and OFFLINE after repeated failures. Hidden tabs pause polling. Stale data is not labeled LIVE.

If the Control Plane is unavailable, this page cannot refresh. Edges keep serving the last deployed configuration. Traffic on the site does not depend on this dashboard.

TL;DR

Security Phase 1 is Cloudo’s opt-in managed WAF catalog plus a basic deterministic bot score. It is not ModSecurity, not OWASP CRS, and not a customer-editable signature product. Patterns come only from Cloudo’s…

Security Phase 1 is Cloudo’s opt-in managed WAF catalog plus a basic deterministic bot score. It is not ModSecurity, not OWASP CRS, and not a customer-editable signature product. Patterns come only from Cloudo’s versioned catalog (CLOUDO-WAF-001…005, plus the log-only CLOUDO-WAF-006…010 when coverage v3 is enabled). Bot protection uses exactly two rules (CLOUDO-BOT-001 / CLOUDO-BOT-002).

Enforcement reuses existing Edge pieces: nginx → http-agent / Human Verification auth_request for challenge/block, and AnalyticsBlockedEvent ingest for blocked/challenge rows (sources waf and bot_security). There is no separate SecurityEvent table and no per-request Control Plane call.

On Domain → Security the Phase 1 tabs are Overview (opt-in + 24h metrics + bot rule summary), WAF Rules (enable/disable and action log / challenge / block only — no regex editor), Events (recent blocked/challenge rows), and Firewall & DDoS (classic controls). Save draft stores Control Plane state; Save & Deploy is still required before Edges enforce. High-confidence catalog matches use the selected action; lower-confidence matches log only.

Not included in Phase 1: ML scoring, ASN/IP reputation, broad POST-body WAF, ModSecurity/CRS, customer-editable signatures, reverse-DNS verification for claimed bots, automatic enablement on production customer domains, or a parallel event platform.

TL;DR

Phase 1 uses two independent gates. Both must be true before Edges put rules into the live snapshot and enforce them.

Phase 1 uses two independent gates. Both must be true before Edges put rules into the live snapshot and enforce them.

  • Platform flag CLOUDO_SECURITY_PHASE1_ENABLED — Control Plane env; default false. When false, rule drafts and Overview/WAF/Events UI stay available for review, but Phase 1 rules do not enter Edge snapshots.
  • Per-domain opt-in — Domain → Security → Overview checkbox; default false. Cloudo enables it per domain while the feature is rolled out.

Either gate alone is not enough. Flag OFF does not remove admin UI routes or hide the Phase 1 tabs; operators can still open Overview, WAF Rules, and Events to inspect configuration and past events. Enforcement stays off until the platform flag is on, the domain is opted in, and a successful Save & Deploy activates the snapshot on each Edge.

When the platform flag is off, Overview shows a warning and opt-in / rule Save controls stay disabled so drafts cannot be mistaken for live protection.

TL;DR

The managed catalog blocks only on the URI and query (decoded once). SQLi, XSS and command-injection rules also inspect raw and double-encoded variants, cookies, referer, user-agent and small urlencoded/JSON request…

The managed catalog blocks only on the URI and query (decoded once). SQLi, XSS and command-injection rules also inspect raw and double-encoded variants, cookies, referer, user-agent and small urlencoded/JSON request bodies (first 16 KB), but those matches are always Log only and are shown with their source in Security Events. Static assets are inspected only when they carry a query string. It is not a full application-body WAF.

  • CLOUDO-WAF-001 Sensitive files — probes for secrets/VCS/config paths (.env, .git, backups, wp-config, id_rsa).
  • CLOUDO-WAF-002 Path traversal — directory traversal and sensitive absolute paths in URI/query.
  • CLOUDO-WAF-003 SQL injection (high confidence) — high-confidence SQLi tokens; lower-confidence matches log only.
  • CLOUDO-WAF-004 Cross-site scripting (high confidence) — high-confidence XSS markers; lower-confidence matches log only.
  • CLOUDO-WAF-005 Command injection (high confidence) — high-confidence shell/command tokens in URI/query.

When the platform enables managed WAF coverage v3, five more rules appear. They default to Log and never block unless you change the action: CLOUDO-WAF-006 Sensitive files (case-insensitive, normalised path), CLOUDO-WAF-007 Backup and dump files, CLOUDO-WAF-008 SQL injection (comment-obfuscated), CLOUDO-WAF-009 JNDI / Log4Shell lookups, CLOUDO-WAF-010 Command pipes and chaining.

Harmless SQL-ish marketing copy in a query (for example “select your plan”) is allowed. Only high-confidence catalog matches can block or challenge; lower-confidence matches never escalate beyond log. You can enable/disable each rule and choose log / challenge / block on Domain → Security → WAF Rules. Signature patterns are not editable. Challenge reuses Human Verification.

TL;DR

When domain opt-in includes Basic bot score, the Edge computes a deterministic 0–100 score (no ML). Bands: roughly 0–39 allow, 40–59 log, 60–79 mid-band action, 80–100 block only when confidence is high.

When domain opt-in includes Basic bot score, the Edge computes a deterministic 0–100 score (no ML). Bands: roughly 0–39 allow, 40–59 log, 60–79 mid-band action, 80–100 block only when confidence is high.

In the mid-band (about 60–79), browser-capable clients are challenged (Human Verification); script / empty / malformed User-Agents are rate_limited (typically HTTP 429) instead of challenged. That split is intentional in Phase 1.

  • CLOUDO-BOT-001 — rapid 404 / path scanner signals (many probe paths in a short window).
  • CLOUDO-BOT-002 — high-rate non-browser automation.

User-Agents that claim Googlebot/Bingbot (and a few related crawlers) are tagged claimed_good_bot only. Phase 1 does not perform reverse-DNS verification and does not grant a full bypass. Claimed good bots are never hard-blocked in this phase; a would-be block is downgraded to challenge.

TL;DR

Phase 1 does not create a parallel event platform. Blocks and challenges are stored in the existing analytics blocked-event table (AnalyticsBlockedEvent / analytics_blocked_events — same ingest as firewall / rate limit…

Phase 1 does not create a parallel event platform. Blocks and challenges are stored in the existing analytics blocked-event table (AnalyticsBlockedEvent / analytics_blocked_events — same ingest as firewall / rate limit / HV). Open Domain → Security → Events or Analytics blocked drill-down and filter sources such as waf and bot_security.

On Security → Events, filter by Ray ID to find the request a visitor reported. Click a row to open a detail drawer with safe fields only: when, source, action, Ray ID, rule id/name, reason, mode, zone, method/path, bot_score, managed WAF / bot rule keys, claimed_good_bot, HV outcome, edge, and a clipped User-Agent. Esc, the backdrop, or Close clears the selection. Auth cookies, passwords, tokens, Authorization headers, and full request bodies are not shown and are not stored.

Safe metadata may include managed_rule_key, bot_score, bot_rule_key, claimed_good_bot, action, request_id, method, path, domain, edge, and a clipped User-Agent. Auth cookies, passwords, tokens, Authorization headers, and full request bodies are not stored.

Managed WAF rules set to Log (and lower-confidence matches, which always log) are also stored, as “logged” events: rule, domain, client IP, User-Agent, method, path (never the query string), Ray ID and time, kept for the same 30 days. Use the Outcome filter on Security → Events (Blocked / challenged vs Logged only) to review what a rule would have blocked before switching it to Block. Logged events never count as blocked or challenged in Overview or Analytics. To limit volume, at most one logged event per client IP, rule and minute is kept, plus a per-domain cap per minute.

Hit counters stay hot on Redis/local Edge state and flush asynchronously. PostgreSQL is not written on every Edge request. Duplicate event ids are accepted once then counted as duplicates on re-ingest.

TL;DR

After a successful deploy, Edges serve Phase 1 rules from the local last-valid snapshot. Visitor HTTP does not call the Control Plane, PostgreSQL, or Redis on the request path for these decisions. If the Control Plane…

After a successful deploy, Edges serve Phase 1 rules from the local last-valid snapshot. Visitor HTTP does not call the Control Plane, PostgreSQL, or Redis on the request path for these decisions. If the Control Plane is unavailable, Edges keep the last deployed local rules.

Every HTTP config activation still requires nginx -t to succeed. If validation fails, the Edge does not activate the new config, keeps the previous working configuration, and reports the deployment error.

Cloudo verifies Phase 1 on live Edges using internal QA hostnames when needed. It is not a customer-facing product feature and does not mean Phase 1 is enabled for customer domains. Platform flag and per-domain opt-in both default false; production customer sites stay off unless staff explicitly enable both gates and deploy.

Possible side effects when both gates are on and deployed: real visitors can be challenged or blocked by catalog/bot matches; scripts may see 429 mid-band rate limits; mistaken opt-in on a busy domain can interrupt traffic. Undo by turning domain opt-in off (or the platform flag) and Save & Deploy so Edges drop Phase 1 from the snapshot.

TL;DR

Human Verification is Cloudo’s shared browser-challenge engine on the Edge. It is not configured as a standalone Security product. DDoS Protection (Automatic escalation and Under Attack), firewall Managed Challenge…

Human Verification is Cloudo’s shared browser-challenge engine on the Edge. It is not configured as a standalone Security product. DDoS Protection (Automatic escalation and Under Attack), firewall Managed Challenge, and rate-limit Challenge all reuse the same engine, cookies, and passage duration.

When a browser must complete the check, a normal visitor is not held for 30 seconds. The page usually finishes in about 1–2 seconds (Managed Challenge proof-of-work difficulty 3), sets a verification cookie, and continues. Under Attack uses a harder proof (difficulty 5) that can take longer but stays bounded. If the check cannot finish within about 8 seconds, it stops and shows a retry — it does not keep spinning until a long timeout.

Challenge, Access denied, and rate-limit pages show the Cloudo logo inline (no remote image fetch), a “Protected by Cloudo” link to https://cloudo.lol, a Ray ID, the visitor IP, and the UTC time. If the checker itself is down, the Edge still shows a branded unavailable page with a Ray ID. The same Ray ID is returned in the cloudo-ray response header. Search it on Domain → Security → Events or in Analytics blocked detail. The page does not show internal rule names.

Challenge start and complete use internal /__cloudo/* locations that turn off recursive auth_request and do not apply visitor DDoS or rate-limit zones. Those paths talk only to the local verifier; they do not bypass protection on normal customer URLs.

A successful complete sets the HttpOnly __cloudo_verified cookie (Secure on HTTPS, SameSite=Lax). Later requests with a valid cookie pass auth without repeating the challenge until passage TTL expires. Challenge passage (how long a visitor stays verified) is set on Domain → Security → DDoS Protection. Default is 30 minutes. Protection must be ON for challenges to affect visitors.

If a challenge feels slow: confirm Managed Challenge vs Under Attack, check that /__cloudo/challenge/start and /complete respond quickly, and ensure the browser is not blocked from running the challenge script. This is application-layer (HTTP) mitigation on Cloudo Edge. It does not replace provider-level volumetric L3/L4 DDoS protection.

TL;DR

Per-IP request limits on a path (optional /*), optionally only for some countries, Block or Managed Challenge, applied per Edge after deploy.

What it does

Limits how many HTTP requests a client IP can make to a path (optional trailing /*) during an interval, per Edge. Action is Block (typically 429 Too Many Requests) or Managed Challenge. Duration is an extra ban window in seconds after a Challenge limit is exceeded; 0 means no extra ban beyond the interval.

When to use it

Login, search, and API paths that should not accept unlimited attempts from one IP.

What it protects against

Credential stuffing, abusive crawlers, and simple Layer 7 request floods against a path.

What it does NOT protect against

Distributed floods from many IPs, volumetric DDoS, and slow connection exhaustion (that is connection limiting). Limits are per Edge, not a global cluster counter.

Possible side effects

Legitimate users behind a shared NAT can hit 429. Aggressive limits break APIs. Warning: This action can interrupt visitor traffic.

Path /* means the whole site. Cloudo merges that rule into the single authoritative nginx location / on the Edge (together with the default origin proxy). It does not emit a second root location — duplicate location / would fail nginx -t and the previous working config would stay active. More specific paths (for example /login or /api/*) still get their own locations. Exact path / is an exact-match location and can sit beside location /.

Countries (optional): a rule can count only requests from some countries (“Only these countries”) or from every country except some (“All except these countries”). Requests outside that scope are not counted and are never limited by that rule. Country comes from the Edge GeoIP lookup, which is approximate (VPN or proxy location may differ). An unknown country is never inside a country scope, for either option. Preview shows the share of the domain’s requests from Analytics (last 24h and 7 days) that the rule would count, and the audit log records the scope and that share. While Cloudo rolls out the matching Edge agent, the Countries field may not be shown yet. Rules without a country scope work exactly as before.

Domain → Security shows Blocked (24h) per rate-limit rule the same way as firewall rules: exact rule id correlation from Edge security events, optional 1h/7d ranges, and a click-through to Analytics blocked detail. Challenge rate-limit hits are labeled challenged.

TL;DR

Connection limiting is not a separate editor. It follows the DDoS mode deployed to the Edge: Standard and Medium allow 512 concurrent connections per client address, Hard allows 256, and Under Attack allows 128…

Connection limiting is not a separate editor. It follows the DDoS mode deployed to the Edge: Standard and Medium allow 512 concurrent connections per client address, Hard allows 256, and Under Attack allows 128. Automatic uses the Standard ceiling until you choose another mode and deploy. You cannot type a custom number in the Backoffice.

This is separate from rate-limit rules. Hitting the connection ceiling looks like errors or stalled requests, not a Backoffice “connection limit” page.

TL;DR

Allow / block / Managed Challenge rules on country, IP, host, path, method — evaluated by priority after deploy.

Each rule has an action (allow, block, or Managed Challenge) and conditions: country, IP, CIDR, hostname, path, and/or method. Lower priority numbers are evaluated first. The stored action value for Managed Challenge remains `challenge` for compatibility.

Rules compile onto the Edge and take effect after deploy. An allow that matches stops later block/challenge from applying to that request. A mistaken allowlist or deny can lock out real users or staff.

On Domain → Security, Blocked (24h) shows how many Edge security events matched that rule’s stable rule id in the selected range (1h / 24h / 7d). Zero means none. Allow rules show — because they do not block or challenge. Challenge rules show challenged hits (labeled) instead of hard blocks. Events without a rule id are never attributed to a rule. Click a count to open Analytics blocked detail for that domain, range, source, and exact rule id — detail rows load only after you click.

TL;DR

Domain → Security shows a Blocked (24h) column on firewall and rate-limit rules (optional 1h or 7d via the Counters selector). Counts come from stored Edge security events in PostgreSQL, grouped by exact rule id and…

Domain → Security shows a Blocked (24h) column on firewall and rate-limit rules (optional 1h or 7d via the Counters selector). Counts come from stored Edge security events in PostgreSQL, grouped by exact rule id and block source (firewall or rate_limit) — not by rule name.

  • 0 means the rule had no matching block or challenge events in the range. It is not shown as —.
  • — with a tooltip means the counter does not apply (for example Allow firewall rules) or detail is unavailable for that row.
  • Block rules count hard blocks. Managed Challenge rules count challenge events and show a challenged label so they are not confused with 403 blocks.
  • Clicking a count opens Domain Analytics blocked drill-down scoped to this domain, the selected range, firewall or rate_limit source, and that exact rule id. Per-request rows load only on click.
  • Older aggregate blocked totals can exist without per-request detail (before security-event ingest, or after retention). Those historical events without a rule id are never assigned to a current rule. The Analytics drawer explains when aggregates exist but detail rows do not.

TL;DR

Lets matching requests skip later firewall deny/challenge for this rule set.

What it does

Lets matching requests skip later firewall deny/challenge for this rule set.

When to use it

When you need a known office CIDR, IP list, or path to pass while other traffic is challenged or blocked.

What it protects against

Keeps trusted clients from being blocked by later rules.

What it does NOT protect against

Is not an “IP list is an allowlist” by itself. IP lists only store addresses until a rule uses them.

Possible side effects

Too-broad allows (whole countries, 0.0.0.0/0) weaken later blocks. Deploy required.

TL;DR

Denies matching requests (typically HTTP 403).

What it does

Denies matching requests (typically HTTP 403).

When to use it

When you need to refuse a country, CIDR, path, or method after deploy.

What it protects against

Stops matching visitor requests from reaching origin.

What it does NOT protect against

Does not stop volumetric floods that saturate the uplink before Nginx. Does not replace origin firewalls.

Possible side effects

Can interrupt real traffic if conditions are too wide. Live change only after a successful HTTP deploy.

TL;DR

Sends matching requests through the shared Human Verification engine instead of a hard deny.

What it does

Sends matching requests through the shared Human Verification engine instead of a hard deny.

When to use it

When you want suspicious traffic to prove it is a browser without immediately 403ing everyone.

What it protects against

Reduces automated hits that cannot complete the challenge.

What it does NOT protect against

Does not replace rate limits. Does not inspect application payloads.

Possible side effects

Real users must complete a short browser check (normally 1–2 seconds, not a 30-second hold). Combined with DDoS Under Attack it can feel heavy. Deploy required.

TL;DR

IP Lists are reusable collections of IPs and CIDRs at account level. A list is not an allow or a block by itself. Firewall rules (or other attachments) decide the action.

IP Lists are reusable collections of IPs and CIDRs at account level. A list is not an allow or a block by itself. Firewall rules (or other attachments) decide the action.

Edit the list, then ensure a rule references it, then deploy the domain security snapshot. An empty or wrong list can allow or deny the wrong people.

TL;DR

Country conditions use Edge GeoIP. It is approximate. Some visitors are classified as XX (Unknown). XX never matches a real country rule, so “block Greece” will not match Unknown, and “allow only US” will not allow XX.

Country conditions use Edge GeoIP. It is approximate. Some visitors are classified as XX (Unknown). XX never matches a real country rule, so “block Greece” will not match Unknown, and “allow only US” will not allow XX.

VPNs, mobile carriers, and anycast clients are often mislocated. Treat geo rules as coarse, not legal-grade location.

Before you save a country rule, Impact preview on the rule form shows how many of this domain’s requests the country conditions would have matched in the last 24 hours and 7 days. The numbers come from Analytics, not from a live test. When the rule also has IP, path, host, or method conditions, only the country part is counted, so the real number is lower.

A Block or Managed Challenge rule that would have matched more than 20% of the domain’s requests needs the confirmation box ticked before it saves. A Block rule that covers every country, or that would have blocked every visitor with a known country in the last 7 days, cannot be saved. Turning a rule off is always allowed. Saves are recorded in the audit log with the previewed share.

TL;DR

DDoS Under Attack, Automatic escalation during an attack, a firewall Managed Challenge action, a rate-limit challenge, or (when Phase 1 is dual-gated on and deployed) a managed WAF / bot mid-band challenge can show a…

DDoS Under Attack, Automatic escalation during an attack, a firewall Managed Challenge action, a rate-limit challenge, or (when Phase 1 is dual-gated on and deployed) a managed WAF / bot mid-band challenge can show a JavaScript/browser check. Bots and clients that do not run it fail or retry.

A real browser is not paused for 30 seconds. The check normally completes in about 1–2 seconds, then the Edge issues a cookie and sends the visitor back to the page they requested. If verification cannot finish within about 8 seconds, the page shows a retry instead of waiting longer.

On domains with the branded challenge page enabled, visitors see a Cloudo-branded page (not a third-party widget). Copy follows Accept-Language (English or Greek when supported). Each page shows an opaque Cloudo ID you can share with support; Edge logs use the same ID for correlation.

If everyone is challenged, check DDoS Protection mode and firewall/rate-limit rules. Leave Under Attack when the attack ends, or add an allow for known office IPs, then deploy.

TL;DR

Shadow-only Control Plane classifier. It records a recommendation and does not change Edge traffic.

Smart Detection is a Control Plane shadow classifier on Domain → Security → Smart Detection. It runs once a minute on aggregates Edges already upload (minute HTTP totals, blocked-event counts, and DDoS event rows). It does not run on the Edge, does not add nginx configuration, and does not change visitor traffic.

Two gates both default off. The platform flag SMART_DETECTION_ENABLED must be on, and the per-domain toggle must be on, before the minute job records a state. When the platform flag is off, the page shows a notice and generated Edge configuration stays unchanged. Turning the domain toggle off stops new evaluations for that domain, sets the detected state back to Normal, clears the would-mitigate value and attack timestamps, and stores a transition with reason “disabled”. That domain no longer appears as an open Threat Intelligence incident. Turning the toggle on again starts a new warm-up.

The only mode that runs is Shadow. The page shows Automatic, and that choice is disabled. Shadow stores a “would mitigate” value (medium, under_attack, or recover) and applies nothing: DDoS mode, firewall rules, rate limits, and managed WAF settings stay as you saved them. A shadow Under attack state still counts on Threat Intelligence → Domains under attack so you can see it. Nothing is applied on the Edge.

  • States are Normal, Elevated, Under attack, and Recovery. A change is stored with the reason, confidence, UTC time, and evidence. Transitions are kept for 90 days.
  • Confidence is round(100 × the number of independent signals that are on ÷ 6). The six signals are managed WAF block or challenge matches (log-only matches do not count), bot rule hits, a 4xx ratio shift, path scanning (CLOUDO-BOT-001), rate-limit hits, and recent DDoS events. When the state is Under attack and at least three of those signals are on, the shown confidence is at least 60. The classifier does not add signals to reach that number. Request volume or GET volume alone cannot leave Normal. One anomalous minute stays Normal. Elevated requires a second consecutive anomalous minute, and Under attack needs a further minute with enough signals. Static and game-asset bursts are treated as volume. Origin 5xx or origin timeouts alone stay Normal (an origin issue, not an attack).
  • The traffic baseline ignores minutes while the state is not Normal, and it leaves out minutes that are already a large burst or a 4xx spike. An attack or a short legitimate spike does not become the new normal and hide a later attack.
  • A new or newly enabled domain stays at Normal during warm-up (15 minutes, the same baseline window DDoS automatic mode uses) and until there is enough recent minute data.
  • Sensitivity is Low, Balanced, or High. Low asks for more agreeing signals. High lowers the per-signal counts. Every sensitivity still needs more than one signal, and still needs two consecutive anomalous minutes.
  • You can set a manual override. Detection never changes that override, the domain toggle, sensitivity, or mode. While an override is set, it is the state shown on the page and Under attack alerts are not sent. Saving the toggle, sensitivity, or override stores the previous values and the new values on the operator audit row.
  • Under attack alerts (email and Telegram through the existing operator alerts) are sent only when CLOUDO_SMART_DETECTION_ALERTS is true. Repeat alerts for the same open state are suppressed. Alerts are off by default.
  • Transition history is deleted by the hourly analytics cleanup after 90 days.

Decisions use closed 60-second buckets and 1, 5, and 15 minute windows. The 10-second DDoS counter window is not used. If the temporary store used for the overlap lock is unavailable, the job pauses and does not record a new state. If the Control Plane is down, Edges keep serving the last deployed configuration; Smart Detection has not changed that configuration.

This is not a promise of zero false positives, and it does not block attacks by itself. Leaving Shadow requires a future version; Automatic mitigation is not currently supported.

TL;DR

Edge Layer-7 limits per browser, with Standard, Medium, Hard, and Under Attack. Not a marketed global scrubbing network.

DDoS Protection is Cloudo’s HTTP / application-layer mitigation on the Edge. Modes: Automatic (default), Standard, Medium, Hard, and Under Attack. Older configurations stored as High are treated as Hard.

Limits are the same for every customer. Counting uses a 10-second window and a per-browser cookie (cloudo_vid) plus the client address. Browsers that present a valid cookie are not added to the shared per-address safety net in Standard, Medium, or Hard, so many computers behind one address (a café or CGNAT) are not challenged or banned as one client. Under Attack does count those browsers in the per-address net. Requests with no valid cookie use the per-address net.

The same cloudo_vid cookie is accepted on every Edge. The Control Plane sends one shared signing key; each Edge stores it locally the next time it checks in. You do not copy a key onto each Edge. Until that key has arrived, that Edge counts requests on the per-address net. A key that existed only on one Edge is not used, because a browser moving between Edge addresses would lose the cookie and fall into that shared net.

  • Standard: no per-browser cap (over-limit is log only). Cookieless safety net 500 requests/second, log only. Login and API paths (/login, /signin, /auth, /api/, /wp-login.php, /xmlrpc.php) 10 requests/second, log only.
  • Medium: 100 requests/second per browser (1000 in 10 seconds) challenges that browser. Cookieless safety net 500 requests/second challenges. Login and API 5 requests/second.
  • Hard: 50 requests/second per browser (500 in 10 seconds) challenges that browser. A temporary ban is applied only if the challenge fails. Cookieless safety net 250 requests/second challenges. Login and API 2 requests/second.
  • Under Attack: visitors are challenged. 20 requests/second per browser (200 in 10 seconds). Per-address safety net 100 requests/second can temporarily ban the address, including browsers that have a cookie. Login and API 1 request/second.

Static files (.js, .css, images, audio, .wasm, fonts, .json, .atlas, .bin) and paths under /gameclient/ are not counted in those limits and are not challenged. They have their own ceiling of 500 requests/second per address. Going over that ceiling is a short 429 and does not add a ban strike.

Temporary bans last 60 seconds, then 5 minutes, then 15 minutes. There is no 1-hour ban. Strikes reset after 1 hour with no new strike for that browser or address.

Automatic behaves as Standard. It escalates to Medium or Hard only when site-wide traffic stays above the domain baseline (about 30 seconds to escalate, about 5 minutes of normal traffic to relax). One busy visitor does not escalate the site. Automatic does not turn on Under Attack. Under Attack is manual.

Challenge passage on the same card sets how long a visitor remains verified after completing a challenge (default 30 minutes). Choosing Under Attack does not shorten that passage. Configured mode and effective Edge mitigation are separate.

Save draft stores mode and challenge passage in the Control Plane only. Save & Deploy stores those settings and queues the normal Edge config deployment. Live visitor mitigation changes only after each Edge validates and activates the new release. If a deploy fails validation, Edges keep the previous working configuration.

Cloudo protects traffic that reaches Cloudo Edge nodes (application-layer / L7). Very large network-layer volumetric attacks that saturate uplink capacity need upstream/provider mitigation. This is not unlimited DDoS protection and it does not promise zero false positives.

If the Control Plane is offline, Edges keep serving with their last valid configuration and local protection. Open attack events close when you leave Under Attack or another manual mode, when the Edge verifier starts, and when an event has no update for longer than the recovery window.

Recent attack events appear on Domain → Security → DDoS Protection. A blocked or challenged request shows a Ray ID on the Edge page, in the cloudo-ray response header, and on Domain → Security → Events (search the Ray ID). SSL, ACME, and existing cache bypass rules are unchanged by DDoS settings.

TL;DR

Security Phase 1 provides a managed WAF catalog (sensitive files, traversal, high-confidence SQLi/XSS/command-injection patterns on URI/query) and basic bot scoring. It is dual-gated (platform flag + per-domain…

Security Phase 1 provides a managed WAF catalog (sensitive files, traversal, high-confidence SQLi/XSS/command-injection patterns on URI/query) and basic bot scoring. It is dual-gated (platform flag + per-domain opt-in), not ModSecurity/CRS, and not a full body-inspecting WAF. See “What is Security Phase 1 (Managed WAF + Bot score)?”, the dual-gate article, and the CLOUDO-WAF-001…005 catalog article.

There is still no customer regex editor, no broad POST-body WAF, and no dedicated brute-force product. Application hardening still belongs on the origin.

Analytics

TL;DR

Analytics shows time-bucketed HTTP requests and DNS queries for managed domains. HTTP includes Cache HIT %, Origin %, status classes (2xx / 3xx / 4xx / 5xx), estimated Unique Visitors, countries, hostnames, methods…

Analytics shows time-bucketed HTTP requests and DNS queries for managed domains. HTTP includes Cache HIT %, Origin %, status classes (2xx / 3xx / 4xx / 5xx), estimated Unique Visitors, countries, hostnames, methods, and paths.

The domain filter is a typeahead search (type at least 2 characters). Cloudo does not load every domain into a dropdown. Your last selected domain can be remembered in the browser for the next visit; leave it on All domains for account-wide totals.

The DNS tab loads DNS query volume and DNS breakdowns (name, type, record, country, node). Unique Visitors and HTTP path/status cards are calculated on HTTP Traffic and Overview. Security counters are calculated on Overview and Security. The DNS tab does not calculate those HTTP-only figures. Analytics page numbers can lag up to about 30 seconds because the page caches and refreshes on that interval. An open drill-down panel keeps the rows from its last load until you change its filters, change page, or open it again — the main charts still refresh on the 30-second poll. The home Dashboard 24h HTTP/DNS/blocked/average-response cards use a separate cache of about 45 seconds and do not calculate Unique Visitors. The origin map does not make a second Analytics request.

Blocked requests on Dashboard and Analytics open a detail drawer (same API). Aggregate cards stay on rollups; per-request reason detail loads only on open. See Blocked requests drill-down.

There is no general visitor IP panel and no Bandwidth card. Serving does not depend on this page. If Analytics is slow or empty, Edges can still be serving traffic.

TL;DR

Unique Visitors is an approximate count of distinct client IPs for the selected range. The Edge updates a privacy-preserving HyperLogLog sketch in memory, then discards the raw IP before aggregation. Control Plane…

Unique Visitors is an approximate count of distinct client IPs for the selected range. The Edge updates a privacy-preserving HyperLogLog sketch in memory, then discards the raw IP before aggregation. Control Plane never stores visitor IPs for Unique Visitors — only mergeable sketches. Separately, blocked-request detail rows may retain client IPs for investigation (limited retention); that is not used for Unique Visitors.

The figure is shown on HTTP Traffic and Overview. The DNS and Security tabs do not calculate Unique Visitors.

The figure is an estimate, not a guaranteed unique-human count. Shared NATs, CGNAT, VPNs, and rotating IPs can under- or over-count relative to people.

  • When sketches are present for every traffic bucket in the range, Analytics shows the merged estimate.
  • When some buckets predate this feature (or an Edge has not started sending sketches yet), the card shows — instead of inventing a number.
  • Empty ranges with no HTTP requests show 0.

TL;DR

HTTP status is not the same as a Security action. An origin can return 403 or 429 without Cloudo counting a Firewall Block or Rate Limit Block. See Security counters in Analytics.

  • 2xx: success.
  • 3xx: redirects (including HTTPS only).
  • 4xx: client errors or Edge policy responses (including origin 403/429, Cloudo firewall/WAF denies, rate-limit rejects, and Human Verification challenge pages).
  • 5xx: Edge or origin failures (502/504 when origin is down or slow).

HTTP status is not the same as a Security action. An origin can return 403 or 429 without Cloudo counting a Firewall Block or Rate Limit Block. See Security counters in Analytics.

TL;DR

The Security tab counts the effective Cloudo decision for each HTTP request from Edge access-log fields (nginx location tags and Human Verification actions). Each request increments at most one of these counters. HTTP…

The Security tab counts the effective Cloudo decision for each HTTP request from Edge access-log fields (nginx location tags and Human Verification actions). Each request increments at most one of these counters. HTTP status charts stay separate.

  • Total IP blocks: distinct blocked client IPs in the selected range from security-event detail (firewall / WAF / rate_limit blocks), not request volume. Same IP blocked by firewall and rate limit counts once. Challenge-only and missing-IP rows are excluded. When detail has not been stored yet or has aged out, the card shows 0 — it never invents IPs from rollup request counts.
  • Firewall Allow: Cloudo did not apply a firewall/WAF deny, rate-limit block/challenge, or Human Verification challenge/fail on that request.
  • Firewall Block: Cloudo firewall path-block, WAF deny, or HV deny — not an origin 403.
  • Firewall Challenge: Cloudo firewall challenge path when that action is logged.
  • Rate Limit Block: Cloudo nginx limit_req / DDoS rate reject (often logged as rate_limit or rl_block). Status may be 403 or 429; do not infer the subsystem from status alone.
  • Rate Limit Challenge: Cloudo rate-limit challenge when that action is logged.
  • Human Verification shown / passed / failed: HV lifecycle outcomes from the Edge verifier.

If Human Verification allows a request and a later rate-limit stage blocks it, Analytics attributes the request to Rate Limit Block (not Firewall Allow).

Origin-generated 403/429 still appear under HTTP status traffic. They do not increment Firewall Block or Rate Limit Block unless Cloudo itself generated the response.

Authoritative Edge log fields include status, upstream response time, sec (location security tag), and hv (Human Verification action). Troubleshooting: compare client status → Edge JSON access log → collector batch → Analytics Security cards.

TL;DR

Click Blocked requests on the Dashboard (24h) or Analytics (Blocked card, Security block/challenge counters, or the Blocked chart legend) to open a detail drawer for the selected time range and domain.

Click Blocked requests on the Dashboard (24h) or Analytics (Blocked card, Security block/challenge counters, or the Blocked chart legend) to open a detail drawer for the selected time range and domain.

Detail rows come from Edge security events stored in PostgreSQL (not Redis). Aggregate counts on cards stay on rollups (fw_block, rl_block, challenges, HV) so the main page stays fast; detail loads only when you open the drawer.

  • Each row can include timestamp, domain, client IP, country, method, host, path, HTTP status, Edge node, action, block source, reason, matched rule id/name, rate-limit rule, WAF/firewall reason, Human Verification outcome, user agent, request/trace id, and Ray ID when the Edge sent them. The search box matches path, host, reason, and Ray ID.
  • Block sources are normalized to: firewall, rate_limit, ddos, waf, human_verification, ip_list, geo_rule, bot_security, other.
  • Clicking a Security counter scopes the entire drawer to that card: title (for example Rate Limit Blocks), Aggregate count, block-source filter, detail rows, and Block source breakdown all use the same domain, time range, and metric. Total IP blocks → firewall + waf + rate_limit (distinct IPs on the card; drawer lists matching detail rows). Firewall Block → firewall + waf (fw_block); Rate Limit Block → rate_limit (rl_block); Rate Limit Challenge → rate_limit challenges; Human Verification shown/failed → human_verification. The main Blocked card (no source filter) still uses fw_block + rl_block.
  • When the drawer is already scoped to a single source (for example rate_limit), the Block source breakdown is hidden so firewall/WAF totals cannot appear beside a Rate Limit card. For Firewall Block (firewall + waf), the breakdown only lists firewall and waf within that scope.
  • Filters: time range (from the page), domain (page scope), block source, rule, status, IP, and country. Pagination is server-side (25/50/100). Changing block source in the drawer clears the card metric so you can explore other sources without inventing rows.
  • Row click opens a fuller detail panel for that event. Reasons are only shown when the Edge sent them — missing fields stay blank or use the historical fallback below. Detail rows are never invented to match an aggregate.

Aggregate card counts can be higher than detail rows when per-request events were not stored yet or have aged out of retention. The drawer shows both Aggregate and Detail rows for the same scoped metric so you can see that gap.

Reasons are never invented. If a scoped aggregate count exists but no detail row is available (events from before security-event ingest, or aged out of retention), the drawer explains that historical detail is missing while keeping Aggregate and filters on the clicked card.

Paths are normalized and query strings are not stored. Client IPs appear only on blocked-detail rows for investigation and are retained for a limited period (default 30 days). Unique Visitors still never stores visitor IPs — only HyperLogLog sketches.

TL;DR

Country breakdown uses the same approximate GeoIP as security. XX is Unknown and is labeled that way. It is not a country you can target with a firewall rule.

Country breakdown uses the same approximate GeoIP as security. XX is Unknown and is labeled that way. It is not a country you can target with a firewall rule.

Top countries lists the countries with the most requests in the selected range, with each country’s share of requests, requests blocked by Cloudo (firewall, WAF, or rate limit), and the share of other 4xx and of 5xx responses. Blocked, 4xx, and 5xx per country are counted by Edges running HTTP agent v49 or newer. For older data they show — instead of a number. On a domain, Rule… opens a new firewall rule for that country with the impact preview.

TL;DR

Cache HIT % is the share of HTTP requests served from Edge static cache. Origin % is the share that went to origin. HTML, POST, Authorization, and login-cookie requests count toward origin / bypass, not HIT.

Cache HIT % is the share of HTTP requests served from Edge static cache. Origin % is the share that went to origin. HTML, POST, Authorization, and login-cookie requests count toward origin / bypass, not HIT.

Purge All or disabling cache will drop HIT % until (or unless) static cache fills again.

TL;DR

On domains where the preview is enabled, Domain → Analytics → HTTP shows an enhanced traffic overview. Other domains keep the standard Analytics layout until the preview is rolled out to everyone.

On domains where the preview is enabled, Domain → Analytics → HTTP shows an enhanced traffic overview. Other domains keep the standard Analytics layout until the preview is rolled out to everyone.

Cache HIT % uses the same rollup counters as account Analytics: HIT + STALE + UPDATING + REVALIDATED divided by total HTTP requests. MISS and BYPASS percentages use only requests that have a cache dimension (Edge blocks do not emit cache dims).

Average origin latency uses upstream response time sums from existing HTTP rollups (not a separate metric). Visitor IP lists are not shown — HTTP rollups keep HyperLogLog sketches only. Country breakdown appears when GeoIP produced a real ISO-2 code in the range.

Top paths strip query strings at the Edge before aggregation. Quick range links (1h / 24h / 7d) filter the same JSON API as the range dropdown.

TL;DR

Opt-in daily/weekly analytics emails (digest or per domain) at 08:00 in your timezone, with a signed unsubscribe link.

Yes, when CLOUDO_EMAIL_REPORTS_ENABLED is on (default off). Account → Notifications → Email reports: tick Daily (last 24 hours) and/or Weekly (last 7 days), then choose one account digest for all your domains or a separate report for each selected domain. Only domains you own can be selected; archived domains are left out. A digest totals every domain and lists the 15 busiest in a per-domain table (+N more).

Reports are sent at 08:00 in your profile timezone (UTC when the profile timezone is Auto; CLOUDO_EMAIL_REPORTS_SEND_HOUR). Weekly reports go out on Monday (CLOUDO_EMAIL_REPORTS_SEND_WEEKDAY, ISO 1–7). A scheduler job runs hourly and queues each report once per day/week, so re-runs never double-send.

Contents come from the same analytics rollups as the Analytics page and the API summary: requests, bandwidth, cache hit ratio, 4xx/5xx share, blocked requests (WAF/firewall, rate limit, human verification), top countries, top 4xx/5xx paths, origin health incidents (origins that reported unhealthy in the period) and active certificates expiring within 21 days (CLOUDO_EMAIL_REPORTS_CERT_EXPIRY_DAYS). The window is the 24 hours / 7 days before the send time; recent minutes may still be catching up.

Every email has a signed unsubscribe link (no login needed): it asks for confirmation and can stop this report or all reports. Mail clients that support one-click unsubscribe (List-Unsubscribe-Post) unsubscribe directly. Changes are audited (user.email_reports.updated / user.email_reports.unsubscribed).

Edge Nodes

TL;DR

An Edge node is Cloudo infrastructure that serves visitor HTTP/HTTPS. Authoritative DNS is served by dedicated DNS-capable nodes (`ns1` / `ns2`). An Edge is not your origin and not a customer server you SSH to from the…

An Edge node is Cloudo infrastructure that serves visitor HTTP/HTTPS. Authoritative DNS is served by dedicated DNS-capable nodes (`ns1` / `ns2`). An Edge is not your origin and not a customer server you SSH to from the Backoffice.

Staff see Edge Nodes globally. Domain owners work through domain pages; the Edge list is infrastructure.

TL;DR

Online means the Control Plane has received a heartbeat from the node within about 3 minutes. Offline means heartbeats stopped on a node that still serves HTTP or DNS. Retired or Disabled means the node is…

Online means the Control Plane has received a heartbeat from the node within about 3 minutes. Offline means heartbeats stopped on a node that still serves HTTP or DNS. Retired or Disabled means the node is intentionally not a production HTTP/DNS plane (for example a lab leftover kept for history). Offline Control Plane connectivity is not automatically a visitor outage: the node can still serve its last valid local configuration.

Health is the last monitor evaluation and is only shown as current while the node is Online. When Offline or Retired, Health is Unknown so a stale snapshot is not mistaken for a live Healthy node. Nginx and CoreDNS badges appear only for nodes with HTTP or DNS capability.

You cannot manage new deploys to a node that cannot reach the Control API, but existing traffic can continue.

TL;DR

Two optional Edge features, both off by default: Brotli compression (CLOUDO_EDGE_BROTLI_ENABLED) and HTTP/3 over QUIC (CLOUDO_EDGE_HTTP3_ENABLED). With both flags off the published Edge configuration is byte-identical…

Two optional Edge features, both off by default: Brotli compression (CLOUDO_EDGE_BROTLI_ENABLED) and HTTP/3 over QUIC (CLOUDO_EDGE_HTTP3_ENABLED). With both flags off the published Edge configuration is byte-identical to before.

Each Edge turns a feature on only when its nginx can run it: Brotli needs the ngx_brotli filter module loaded, HTTP/3 needs nginx 1.25 or newer built with the http_v3 module. A node without the capability keeps serving exactly as before (HTTP/2 plus whatever gzip nginx.conf already has). Nodes that can run a feature report edge_brotli_v1 / edge_http3_v1 in their heartbeat features.

  • Brotli compresses text, CSS, JavaScript, JSON, XML, SVG, WASM and font responses of 256 bytes or more for browsers that send Accept-Encoding: br. Responses the origin already compressed are passed through untouched (no double compression), and gzip keeps serving other clients.
  • HTTP/3 adds a QUIC listener on UDP 443 next to the existing HTTP/2 listener and sends Alt-Svc: h3=":443"; ma=86400 on HTTPS responses only. Browsers keep using HTTP/2 until they have seen that header, and fall back to it automatically if UDP 443 is blocked.
  • HTTP/3 also needs UDP 443 open in the host firewall and the provider firewall. Without it browsers simply stay on HTTP/2.

TL;DR

Requests through the Edges can carry a body of up to 100 MB by default (it used to be 30 MB). A larger upload is refused with HTTP 413 before it is sent to your origin. Your origin still applies its own limit, so raise…

Requests through the Edges can carry a body of up to 100 MB by default (it used to be 30 MB). A larger upload is refused with HTTP 413 before it is sent to your origin. Your origin still applies its own limit, so raise it there too if you accept large uploads.

Administrators can set a different limit for one domain on its Origin page, from 1 to 512 MB; leave it empty to use the default. Every change is written to the audit log (domain.client_max_body_changed). The Cloudo platform host itself cannot be given an override and keeps tighter fixed limits: 64 MB overall, and only a few kilobytes on sign-in, register and password forms.

  • Optional protections, all off by default and enabled per platform flag: a per-visitor limit on parallel big uploads (about 8 at once, extra requests get HTTP 429), shorter body timeouts, and a dedicated disk for upload buffering.
  • The dedicated upload disk reports its usage in the Edge heartbeat; the node turns warning at 70% and critical at 85%.
  • An Edge running an older agent keeps the old 30 MB limit and ignores per-domain overrides until the new agent version is published.

TL;DR

The Edge Nodes list defaults to Active: HTTP and DNS traffic-plane nodes that are not retired or disabled. The Dashboard Edge Nodes panel uses the same Active set.

The Edge Nodes list defaults to Active: HTTP and DNS traffic-plane nodes that are not retired or disabled. The Dashboard Edge Nodes panel uses the same Active set.

Retired shows nodes kept for history (retired or disabled status, or mail-only leftovers without HTTP/DNS). All shows every registered node. Switching filters does not delete nodes, change DNS delegation, or change visitor traffic.

On Retired rows, Nginx/CoreDNS service badges stay blank when the node has no HTTP/DNS capability, and Sync is labeled Historical so an old successful deploy is not read as current.

TL;DR

Out of Sync means the version the Edge currently serves does not match the desired version in the Control Plane. Visitors still see the current local version, not the unapplied draft.

Out of Sync means the version the Edge currently serves does not match the desired version in the Control Plane. Visitors still see the current local version, not the unapplied draft.

Queue or retry the matching HTTP/DNS/mail deploy. Do not delete the domain to “resync.”

TL;DR

HTTP deploys generate a candidate Nginx config, run nginx -t, and only then activate and reload. If nginx -t fails, the previous working config is kept and the deployment is reported failed. Operator alerts put the…

HTTP deploys generate a candidate Nginx config, run nginx -t, and only then activate and reload. If nginx -t fails, the previous working config is kept and the deployment is reported failed. Operator alerts put the first fatal nginx [emerg] line (file and line) above deprecation warnings and keep the full validation output.

After nginx -t, atomic activate, and reload, the Edge probes only the local path /__cloudo_health (nginx returns 200 on the Edge; it does not proxy to your origin). TLS fingerprint is checked when HTTPS is active. If that local probe or nginx -t fails, the Edge rolls back to the last-known-good release. A timeout or 503 from a customer origin does not fail or roll back the fleet release. Origin health stays on the Origins / Health Checks pages. Normal deploys reload Nginx; they do not restart it.

TL;DR

After an HTTP agent publish, canary, promote, or node pin, the Control Plane watches every online HTTP Edge whose agent version changes. The Edge must send a heartbeat with the new version and checksum, agent status…

After an HTTP agent publish, canary, promote, or node pin, the Control Plane watches every online HTTP Edge whose agent version changes. The Edge must send a heartbeat with the new version and checksum, agent status ok, Nginx active, and Human Verification up within the deadline (10 minutes by default, CLOUDO_AGENT_AUTO_ROLLBACK_MINUTES).

A rollout fails if the Edge reports agent status failed (activation failed or the version was quarantined), if Nginx is inactive or nginx -t fails, or if Human Verification is down while the new version runs. Each of these must show in two separate heartbeats. A rollout also fails if no healthy heartbeat arrives before the deadline.

CLOUDO_AGENT_AUTO_ROLLBACK sets the mode: off, shadow, or enforce. Production defaults to shadow, which only sends an operator alert. In enforce mode, Cloudo pins the failing Edge back to the version it last reported as healthy. It also halts further publish and promote until an operator clicks Resume rollouts on the Edge Nodes page. Each rollback writes an audit entry (http_agent.auto_rollback) and sends an operator alert.

Each Edge also protects itself. An agent that fails to compile, start, or bring Human Verification back is restored to the previous release and quarantined. The bootstrap guard also restores a new release that keeps crashing: three failed runs within 30 minutes of activation.

TL;DR

The public status page at /status (and /status.json) shows Edge network, DNS, and Control Panel & API status with 90-day uptime. Status comes from Edge heartbeats, external uptime probes, and scheduler and queue…

The public status page at /status (and /status.json) shows Edge network, DNS, and Control Panel & API status with 90-day uptime. Status comes from Edge heartbeats, external uptime probes, and scheduler and queue heartbeats. Uptime is sampled every 5 minutes and kept for 90 days. Backups stay internal unless CLOUDO_STATUS_PAGE_SHOW_BACKUPS is on.

Publish incidents and scheduled maintenance on Monitoring → Status page. An open incident raises the affected components to its impact. Active maintenance shows them as Maintenance. Every change writes an audit entry. Unpublished entries stay hidden.

The page needs no login, is cached for 60 seconds, and is rate limited per client. It never shows IP addresses, hostnames, node names, versions, or error text. CLOUDO_STATUS_PAGE_ENABLED is off on production until the status.cloudo.lol host is live.

TL;DR

Edge AAAA records for proxied records, gated by CLOUDO_EDGE_IPV6_ENABLED and a per-Edge IPv6 health probe.

When CLOUDO_EDGE_IPV6_ENABLED is on, proxied A and CNAME records also publish AAAA records pointing at Edge IPv6 addresses. An Edge is only included when its IPv6 address is set (php artisan cloudo:edge-ipv6 <node> --set=<v6>) and the Control Plane IPv6 probe passes: HTTPS /__cloudo_health returns 200 and port 80 answers (needed for ACME HTTP-01 over IPv6). The probe runs every minute and needs 2 passes to add and 2 failures to withdraw. A result older than 15 minutes counts as not healthy.

DNS is reconciled automatically. When an Edge passes, its AAAA is added; when it fails, or the flag is turned off, AAAA is withdrawn on the next run (about 1 minute, plus the 300 s record TTL). IPv4 A records are never changed. A customer AAAA record on the same name wins over the Edge AAAA. A proxied AAAA record is withheld while no Edge IPv6 is healthy.

The Edge node page shows the IPv6 address, the last probe result, and whether AAAA is published, withheld, or off. Smoke tests add an "over IPv6" check per Edge (FAIL only while AAAA is published). The status page adds Edge network (IPv6) only while the flag is on; an IPv6 problem shows as Degraded because IPv4 keeps serving.

Egress

TL;DR

Hides the outbound TCP source address of an approved call. It does not hide the payload or headers you send.

The egress gateway lets an approved caller send an HTTPS request through an Edge to a destination that staff have approved. The Edge opens a new TCP connection to that destination. The provider sees an Edge address as the TCP source. A route path cannot contain .., an encoded dot, slash, or backslash, a semicolon, or a double slash.

This hides the outbound TCP source address only. The body, the headers you choose to send, TLS fingerprint, and timing can still identify the caller. It is not a general proxy. You cannot type a URL, use CONNECT, or send an absolute URL as the request target.

Staff approve every destination and route. A customer account sees Account → Egress only after staff create an active grant for that account. The page lists that account’s routes, credential prefixes, and hourly usage. It does not list other accounts, and it has no destination editor.

The platform switch CLOUDO_EGRESS_ENABLED defaults to off. While it is off, visitor sites are unchanged. Port 8443 is not opened on the production Edge firewall by this feature. Calling the gateway on Edge-01 or Edge-02 is not available until a later production review opens that listener.

TL;DR

The provider sees the IPv4 address of the Edge that opens the connection. There are two Edges. A route is pinned to one Edge unless staff explicitly unpin it. Failover of a pinned route is a staff change of that pin…

The provider sees the IPv4 address of the Edge that opens the connection. There are two Edges. A route is pinned to one Edge unless staff explicitly unpin it. Failover of a pinned route is a staff change of that pin, which publishes a new egress version.

An unpinned route can be answered by either Edge. That means two possible source addresses, and each Edge applies its own full rate and concurrency quota, so the quota is doubled compared with a pinned route. The route page states that warning before staff can unpin.

IPv6 is not used for these outbound connections. This is not a fixed contractual address and it is not anycast.

TL;DR

Nobody can call a route without a grant. Staff bind one account to one or more approved routes, set a caller CIDR allowlist, and set how long credentials on that grant may live. An empty allowlist is rejected. A call…

Nobody can call a route without a grant. Staff bind one account to one or more approved routes, set a caller CIDR allowlist, and set how long credentials on that grant may live. An empty allowlist is rejected. A call from an address outside the allowlist is forbidden.

A missing grant, a revoked grant, or a route that is not on the grant returns a generic forbidden or not-found response. The gateway does not return the provider error, the address it refused, or any part of the credential.

Customers cannot create destinations or routes. Support staff can view the staff panel. Changing destinations, routes, grants, and credentials requires the manage permission.

TL;DR

A credential is shown once, in the Backoffice, when it is created or rotated. After that the page shows the prefix and the key id. The plaintext is not stored and is not written to the audit log.

A credential is shown once, in the Backoffice, when it is created or rotated. After that the page shows the prefix and the key id. The plaintext is not stored and is not written to the audit log.

A lifetime is required. The default is 7 days. Staff can set a shorter or longer lifetime on the grant, up to 30 days. A credential without an expiry cannot be created. A grant can have at most 5 active credentials, including one that is still inside its rotation overlap. Revoke one before creating or rotating another when the grant is already at that limit. An account can create at most 10 credentials in an hour.

Send it only as Authorization: Bearer. Putting it in the query string is rejected and is not written to the access log.

Rotation keeps the previous credential working for an overlap. The default overlap is 15 minutes and the maximum is 24 hours. After the overlap, only the new credential works. Revoking a credential removes it from the next snapshot on each Edge. While the Control Plane is unreachable, an Edge keeps the last snapshot it loaded and still enforces the credential expiry, so a revoked credential can keep working only until that expiry.

TL;DR

Each route has a request rate, a concurrency cap, a 1 MiB default request body limit, and a separate 1 MiB default response limit. Exceeding the rate or the concurrency returns HTTP 429. When the Edge is already…

Each route has a request rate, a concurrency cap, a 1 MiB default request body limit, and a separate 1 MiB default response limit. Exceeding the rate or the concurrency returns HTTP 429. When the Edge is already authenticating too many calls, the caller also gets HTTP 429 with a Retry-After header, not a forbidden response and not a successful one. A denied or missing credential stays forbidden. Any other authentication error is refused and is not sent to the provider. A larger body is rejected as too large. A response over the response limit is unavailable. A slow provider returns a timeout. The gateway does not retry the provider.

These counters are per Edge. They are not shared between Edge-01 and Edge-02. Pin the route when the quota must not be doubled.

Usage on the page is an hourly total per grant, route, and Edge (requests, bytes, and selected status counts). Edges upload those aggregates in batches; there is no per-request log. If nothing has been counted, or the platform switch is off, the total is zero.

Provider redirects are returned to the caller as-is. The gateway does not follow them.

TL;DR

The Backoffice pages are available with the permissions and grants described above. Production Edges do not listen for egress calls yet: the platform switch defaults to off, and the firewall on Edge-01 and Edge-02 is…

The Backoffice pages are available with the permissions and grants described above. Production Edges do not listen for egress calls yet: the platform switch defaults to off, and the firewall on Edge-01 and Edge-02 is not opened for TCP 8443.

Turning the switch off keeps visitor HTTP and HTTPS on the existing Nginx. An egress failure does not roll back a visitor site. While the switch is off, Edges do not accept egress calls and do not upload usage. If the Control Plane is down, an Edge that already has a snapshot keeps using that snapshot until credentials expire, and any local usage spool stays on the Edge until upload succeeds later.

The resolver used for these lookups is a local recursive resolver on the Edge (127.0.0.1 port 5353) with DNSSEC validation. It does not forward to the authoritative DNS servers.

Deployments

TL;DR

Backoffice Save & Deploy stores a Config Version and queues a job per Edge. The Edge writes a candidate, validates, activates atomically, reloads, and reports back. Visitor traffic changes only after a successful…

Backoffice Save & Deploy stores a Config Version and queues a job per Edge. The Edge writes a candidate, validates, activates atomically, reloads, and reports back. Visitor traffic changes only after a successful activation on that Edge.

HTTP, DNS, and mail are separate planes. Deploying DNS does not by itself update Nginx, and the reverse is also true.

Mail routing deploys only to Edge Nodes that have the mail capability and are not Retired or Disabled. A retired mail leftover (for example an old lab node after the mail MTA moved) is not a deploy target. If no active mail-capable node is registered, Save & Deploy reports that clearly instead of queuing a doomed job.

Synchronization is hybrid: an optional push client wakes the agent immediately via /api/node/events (Redis wake-up only; no new public management port), and the ~30s agent timer remains the pull fallback. Rapid republishes are coalesced so agents are not flooded. A deployment that stays pending until Control Plane marks it timed out usually means the agent or push client was not running, or the node is not an active target — not that the snapshot itself is invalid.

HTTP Edges prepare in parallel. Each node activates atomically on its own; Control Plane never interrupts a deploy that is already activating. When a newer version replaces a still-pending older one, the older row becomes superseded (not failed).

If the desired checksum is already active and consistent on a node, that node skips reload and ACKs success immediately. If the agent finishes after Control Plane already marked a timeout failure, a late success ACK (or a matching heartbeat current version) reconciles the deployment to succeeded and advances the node’s current version when that version is not older than the one already active. That late success is not left as a permanent false failure.

Saving again when the Edge or DNS snapshot checksum has not changed does not publish another config version and does not queue another deployment. A newer config version supersedes older pending rows for that node, and any row older than the version the node already runs, so those rows finish as Superseded instead of all timing out. The Control Plane does not hand an Edge a config version older than the version that node is already running. Rollback publishes the older snapshot forward as a new version number, then queues that. Visitor traffic stays on the last valid local config until the new one passes validation and reloads. Nginx is not restarted.

TL;DR

Once a deployment has a finished time, Backoffice stops showing it as Pending or Deploying, including when the status field was still pending. Refresh the page if a live badge was left on Pending after the stale window…

  • pending: queued, not started on the Edge yet.
  • deploying: the Edge is generating, validating, or activating.
  • succeeded: validation passed and the new version is current on that Edge.
  • failed: validation or activation failed, or the agent did not ACK within the stale window; previous config remains.
  • rolled_back: a previous known-good snapshot was published forward as a new version and that deploy completed.
  • superseded: a newer desired version replaced this still-pending row, or the row was older than the version already active. It is not a failure, not still pending, and not a reason to retry the old version.

Once a deployment has a finished time, Backoffice stops showing it as Pending or Deploying, including when the status field was still pending. Refresh the page if a live badge was left on Pending after the stale window (about five minutes).

The Edge deployment detail page shows desired version, running version on that node, duration, whether an ACK was received, and whether the HTTP fleet is synced. Partial means some nodes succeeded and others failed. Manual Retry re-queues the failed version on that node and still runs nginx -t (or DNS/mail validation). Never assume a failed node silently “took” the new config.

Timeout failures distinguish “still pending / agent never started” from “deploying / agent started but did not finish”. Raising the Control Plane stale window alone does not fix a stopped agent or a retired target. Agent API backoff after HTTP 429 is scoped per class (events, analytics, SSL/cert, desired-config/config, heartbeat, deploy ACK) with bounded exponential delay and jitter: a rate limit on telemetry must not stop heartbeat or deploy ACK, and Edges do not retry in lockstep.

TL;DR

Publishes a previous known-good snapshot as a new, higher Config Version and queues that version to the Edge. The version number does not go backwards.

What it does

Publishes a previous known-good snapshot as a new, higher Config Version and queues that version to the Edge. The version number does not go backwards.

When to use it

When a new version activated but behaves badly, or when you need to return to the last good snapshot.

What it protects against

Restores a previously validated snapshot if the rollback deploy itself validates.

What it does NOT protect against

Does not instantly rewind every resolver cache or every browser. Does not skip nginx -t. Does not re-dispatch a version number the node has already passed.

Possible side effects

If rollback validation fails, the currently serving configuration stays. Confirm which version each Edge reports before changing origins or DNS again.

Audit Logs

TL;DR

Audit Logs record who did what, when, on which target, and with what result. Typical entries are domain, DNS, SSL, firewall, CDN, and deploy actions.

Audit Logs record who did what, when, on which target, and with what result. Typical entries are domain, DNS, SSL, firewall, CDN, and deploy actions.

They are not traffic logs. They do not list visitor IPs or replace Analytics. Use them to see administrative history, not to debug a single HTTP 502.

TL;DR

Append-only audit history; with CLOUDO_AUDIT_EXTENDED_ENABLED also failed sign-ins, lockouts, password resets, IP filter, CSV export and optional retention.

Audit rows are append-only: the application cannot edit or delete them (row updates and bulk updates/deletes are refused). The only deletion path is the optional retention job. Secrets such as passwords, tokens, private keys and webhook secrets are removed before a row is stored, and before/after values on settings changes only list the fields that changed.

When CLOUDO_AUDIT_EXTENDED_ENABLED is on, the log also records failed sign-ins (attempted email, reason, IP and browser; never the password), sign-in lockouts after too many attempts, password reset requests for existing accounts and completed resets. Failed sign-in rows are capped at 30 per IP per minute so a brute force cannot flood the log. Staff can filter by IP address and download the filtered list as CSV (Export CSV, up to 50,000 rows, newest first); every export is itself audited.

Retention: CLOUDO_AUDIT_RETENTION_DAYS (default 0 = keep forever). When set, cloudo:audit-prune runs daily at 04:25 and deletes rows older than that many days; values below 90 are treated as 90. Each prune writes an audit row with the number of deleted rows. Use php artisan cloudo:audit-prune --dry-run to see the count first.

Troubleshooting

What it usually means

Public resolvers still have the previous answer, or the registrar is not using Cloudo nameservers.

What to check

Registrar NS should be ns1.cloudo.lol and ns2.cloudo.lol. Compare several resolvers. Check TTL and last DNS deploy status.

Whether visitor traffic is likely affected

Visitors using cached or old nameservers may hit the wrong place. Visitors using Cloudo NS see current published records.

Safe next action

Wait for TTL, confirm nameservers, and do not delete records to “force” propagation. Avoid lowering TTL repeatedly without deploying.

What it usually means

The browser, OS, or a local resolver cached the old A/AAAA. Sometimes HTTP/HTTPS connection reuse keeps the old path briefly.

What to check

Try another network or a public lookup. Confirm the Backoffice record and that DNS actually deployed. Flush local DNS only on your machine if you understand that it is local-only.

Whether visitor traffic is likely affected

Usually only your session. Other visitors may already see the new address.

Safe next action

Do not remove the domain. Check DNS deploy succeeded, then wait out TTL.

What it usually means

ACME DNS-01 or certificate deploy has not finished. Status pending or issuing is expected for a while after Protection ON while the cert is staged and the Edge confirms the live TLS fingerprint. An unrelated origin failure does not keep SSL on Deployment pending after that fingerprint is confirmed. After removing and re-adding the same domain, Protection/HTTPS can also stay Preparing until a still-valid archived certificate is rebound to the new domain and Edge+DNS catch up.

What to check

Nameservers on Cloudo, DNS and Edge deploy status, certificate ownership after a remove/re-add, _acme-challenge visible, SSL page error empty.

Whether visitor traffic is likely affected

If a last valid certificate exists, HTTPS visitors may be fine. Brand-new domains may still be HTTP-only until active. While Preparing, public DNS for proxied hostnames may still publish the origin address until Edge is ready.

Safe next action

Wait for issuing and Protection resume to finish. Do not delete the domain to “reset” ACME if a valid certificate already exists. Retry only after nameservers and DNS deploys look correct.

What it usually means

DNS-01 could not complete, or the new certificate could not activate. The last valid certificate remains if one exists.

What to check

SSL error text, nameservers, _acme-challenge, and whether HTTP/SSL deploys failed validation.

Whether visitor traffic is likely affected

Existing HTTPS often keeps working on the last valid cert. First-time issuance leaves HTTP until a cert is active.

Safe next action

Fix DNS/nameservers, retry issuance. Do not restart Nginx and do not wipe the last valid certificate to “start over.”

What it usually means

The Edge cannot get a valid response from the configured origin address, port, protocol, Host header, or SNI.

What to check

Origin process, origin firewall (allow Edge IPs), Origin page fields, and health monitoring (monitoring only).

Whether visitor traffic is likely affected

Yes for HTTP(S) that must reach origin. DNS and cached static files (if CDN HIT) may still look alive.

Safe next action

Repair the origin. Do not change nameservers as the first step. Deploy origin edits after they are saved.

What it usually means

The Edge current version is behind the desired Config Version (Out of Sync), or a newer save was never deployed.

What to check

Deployments page: pending/deploying/failed vs succeeded. Edge current versus desired version.

Whether visitor traffic is likely affected

Visitors see the last valid activated config, which may be older than the Backoffice form.

Safe next action

Retry the failed or missing deploy of the latest config only. Do not re-queue an older version that the node has already passed. Failed validation keeps the old config on purpose.

TL;DR

Release accept uses only the Edge-local /__cloudo_health path (200). That is different from origin health monitoring on the Origins page, which still compares against the Origin’s configured expected status and never…

What it usually means

Candidate config failed validation or activation. For HTTP, nginx -t did not succeed, or the post-reload local /__cloudo_health probe failed (not 200, TLS error, or timeout on that Edge path). Previous config is still live. A customer origin 503 or timeout does not fail the fleet deploy.

What to check

The first fatal validation line (for HTTP, nginx [emerg] with file and line), the full validation output under any warnings, post-reload local health errors, recent DNS/SSL/origin/firewall edits, and whether only some Edges failed (partial).

Whether visitor traffic is likely affected

Visitors keep the last valid release on failed Edges. Succeeded Edges may already be on the new version.

Safe next action

Read the first fatal error, fix the snapshot, retry. Retry still runs nginx -t and the local /__cloudo_health probe. Identical failures of the same desired version are not re-emailed on every retry. Do not restart Nginx to “make it take.”

Release accept uses only the Edge-local /__cloudo_health path (200). That is different from origin health monitoring on the Origins page, which still compares against the Origin’s configured expected status and never rolls back an HTTP release.

For mail, a failure that says the Postfix mail system is not running usually means the agent tried to reload maps on a host where Postfix is intentionally stopped (for example after an MTA cutover). Fix the mail node registration or restore Postfix on the intended mx host; do not treat a retired leftover as the live mail plane.

For mail (or HTTP/DNS), a failure that says the deployment timed out before the Edge agent started usually means the agent timer or push client was not running, or Control Plane targeted a node that should not receive deploys. A timeout while deploying means the agent started but did not finish within the stale window. Late success ACKs after a timeout are reconciled to succeeded when the agent reports success and the version is not older than the one already active. A row marked Superseded was replaced by a newer version and is not a visitor outage.

What it usually means

Usually a firewall block matched the request (country, IP/CIDR, IP list, hostname, path, or method).

What to check

Security firewall rules, rule priority (lower first), IP Lists, and whether an allow should have matched first.

Whether visitor traffic is likely affected

Yes for matching visitors. Others are unaffected.

Safe next action

Add a more specific allow or relax the block, then Save & Deploy. Avoid deleting all rules in a panic.

What it usually means

A rate-limit rule with Block was exceeded for that client IP on that Edge, or a platform connection/rate ceiling was hit.

What to check

Rate-limit threshold, interval, action, and whether many users share one NAT IP. Connection limiting is a baseline 64 concurrent per IP and has no UI editor.

Whether visitor traffic is likely affected

Yes for IPs over the limit. Others are fine.

Safe next action

Raise the limit or switch Block to Challenge if appropriate, then deploy. Aggressive limits will 429 real users.

What it usually means

The Edge connected toward origin but got an invalid or immediate failure (origin down, wrong port/protocol, crashed app).

What to check

Origin address, port, protocol, Host header, SNI, origin process, and origin health monitoring.

Whether visitor traffic is likely affected

Yes for uncached dynamic requests. Static CDN HIT may still succeed.

Safe next action

Fix origin first. Changing SSL or deleting DNS will not start the origin.

What it usually means

The Edge timed out waiting for origin. The origin is too slow, overloaded, or a firewall is dropping the connection.

What to check

Origin load, timeouts, firewall between Edge and origin, and whether only one origin in a pool is sick.

Whether visitor traffic is likely affected

Yes for those requests. Other Edges or cached static files may still work.

Safe next action

Repair or scale the origin. Switching pool mode requires deploy and does not magically speed a dead primary.

What it usually means

Static css/js/image/font is still a cache HIT from before you updated the origin file.

What to check

Cache is On, X-Cache-Status is HIT, and HTML is not the stale asset (HTML is not cached).

Whether visitor traffic is likely affected

Visitors can see old static assets until Purge All deploys or the Edge TTL / inactive expiry elapses.

Safe next action

Use Purge All (confirms, bumps generation, queues HTTP deploy). It does not delete origin files and does not SSH.

What it usually means

That Edge missed heartbeats (~3 minutes). It may still be serving last valid local config, or it may be actually down.

What to check

Edge status, last heartbeat, whether the other Edge is online, and whether public DNS still lists both addresses.

Whether visitor traffic is likely affected

Possibly for visitors who land on the down Edge. The other Edge can still serve. Control Plane offline ≠ this symptom.

Safe next action

Treat as infrastructure. Do not remove the domain. If the node is truly down, traffic to its IP fails until it recovers.

What it usually means

This is expected. Edges serve last valid local configuration without the Backoffice, API, or database on the visitor path.

What to check

Whether Backoffice loads, whether Edge heartbeats are stale, and whether deploys are stuck pending.

Whether visitor traffic is likely affected

Usually no for already-deployed sites. New edits cannot publish until the Control Plane returns.

Safe next action

Do not rebuild domains. Wait for Control Plane recovery. Avoid making registrar NS changes unless DNS was never on Cloudo.

What it usually means

Drop deploys have not activated on every Edge, resolver TTL has not expired, or the registrar still points at Cloudo nameservers.

What to check

Domain status pending removal vs removed, DNS deployment status on each Edge, registrar NS, and TTL.

Whether visitor traffic is likely affected

Yes — visitors may still hit Cloudo until drop deploys activate and caches expire. Removal can interrupt traffic.

Safe next action

Wait for queued drop deploys. Change registrar nameservers when you intend to leave Cloudo. Do not assume confirmation typing instantly clears the internet.

Safety

TL;DR

These Backoffice actions can interrupt visitor traffic or lock people out. They require deploy (and often typing the domain name). Edges keep last valid config until a new release actually activates — that is safety…

These Backoffice actions can interrupt visitor traffic or lock people out. They require deploy (and often typing the domain name). Edges keep last valid config until a new release actually activates — that is safety, not a reason to click twice.

  • Remove domain: type the name to confirm. Queues drop config. Can interrupt visitor traffic. Live Edges serve last valid release until the drop activates. External DNS may still point here.
  • Delete DNS records: removing proxied apex/www or NS-relevant records can take the site or mail off-air after DNS deploy and TTL. Creating records does not create mail or FTP services.
  • Origin changes: wrong address, port, protocol, Host header, or SNI yields 502/504 after HTTP deploy. Health is monitoring only.
  • Firewall deny / block: wide country or CIDR blocks 403 matching visitors. Lower priority runs first.
  • Allowlist mistakes: a missing office allow, or an allow that is too broad, either locks you out or disables later blocks. IP lists are not allows by themselves.
  • Aggressive rate limits: Block 429 or Challenge per IP per Edge can hit shared NATs. Duration adds extra challenge ban.
  • Purge All: bumps generation and deploys; origin is not wiped; no SSH. Static files refetch; origin load rises.
  • SSL: failed issuance keeps last valid cert. Turning HTTPS only on before a cert is active can strand HTTP users. Do not delete domains to retry ACME.
  • Rollback: re-queues previous known-good version; still validates (nginx -t). Partial Edge success means mixed live versions.

Prefer: inspect current state, deploy once, wait for status, keep the previous working configuration when validation fails. Reload is the success path; restart is not.