Skip to content

cmd doctor

github-actions[bot] edited this page Oct 15, 2026 · 25 revisions

nself doctor

Run full system diagnostics.

Synopsis

nself doctor <subcommand> [flags]

Description

nself doctor checks everything ɳSelf needs to function correctly and reports issues with actionable fix suggestions. It covers infrastructure prerequisites (Docker, Docker Compose, Git), Docker daemon health and permissions, disk and memory availability, network connectivity, configuration correctness, running container health, and plugin schema placement.

Run nself doctor when something is not working as expected, before deploying to a new environment, or as part of an automated health check pipeline. The --fix flag enables automatic remediation of common problems.

The --deep flag runs all 12 subsystem checks including open port analysis, weak cipher detection, exposed service bindings, container-level security, and a CIS container benchmark subset. The deep scan runs without a license key: all hardening checks are free by design.

The Generated files section compares recorded file hashes in .nself/state/generated.json with the files on disk, without querying Docker or rendering a fresh build. It lists changed or deleted recorded paths and marks changed files as hand-edited. If there is no project root, the check is skipped. nself doctor --fix repairs through the build reconcile path; a second run has no generated-file changes. nself doctor --fix --plan prints the repair plan without writing. On prod or staging, a noninteractive repair needs --yes; overwriting a hand-edited generated file needs --force in v1.5 mode.

Deep mode's automatic fixes run only validated nself commands and docker restart for containers whose Compose project label matches this project. Suggestions with shell syntax, system commands, and Docker prune are shown as manual steps. The human and JSON reports show which fixes ran or failed.

In v1.5 mode, standard and deep diagnostics report untracked manifest tables for installed plugins that declare migrations.apply: boot. For an offline install, run nself start, then nself doctor --fix: the repair waits for the affected plugins' boot migrations, tracks missing tables on Hasura's default source, and verifies the result. It never starts the stack. Already tracked plugins need no readiness wait or metadata write. Metadata repairs on prod or staging require --yes or terminal confirmation even when generated files have no drift. --fix --plan remains an offline generated-file plan; it does not inspect or repair live Hasura metadata. Deep mode includes this check with --only plugins or no section filter.

Exit Codes

Standard mode (nself doctor)

Code Meaning
0 All checks passed
1 One or more checks failed
2 Warnings only, no failures

Deep mode (nself doctor --deep)

Code Meaning
0 All checks passed
1 One or more failures (no critical findings)
2 One or more CRITICAL security findings

CRITICAL findings include: world-readable secret files, sensitive ports bound on 0.0.0.0, missing JWT secrets, and weak SSL cipher suites. These indicate an immediate security risk and must be resolved before the service is considered safe to run.

Checks Performed

Standard mode

Category What is Checked
Infrastructure docker, docker compose, git are installed
Docker Daemon running, BuildKit available, Compose v2
Disk At least 5 GB free space recommended
Memory At least 2 GB RAM recommended (with --full)
Network Internet connectivity, Docker Hub reachable (with --full)
Configuration .env exists, required vars set, password strength meets requirements, default Postgres credentials warned in prod/staging
Containers Health status of running containers, error logs for unhealthy services
Plugin schemas Warns if np_* tables are in the public schema instead of plugin schemas
License License cache age and tier
TLS Certificate each served host actually presents: expiry, served vs on disk, renewed but not installed (see below)

TLS section

The TLS section asks the nginx that is actually serving your stack, not the files on disk, which certificate it presents. For every server_name in a 443 block of the served nginx/sites/*.conf and nginx/conf.d/*.conf it opens a TLS connection with that name as SNI and prints one line:

TLS api.example.com: R11 expires 2026-12-30 (88 days)

Wildcards, IP addresses, localhost, _ and the .local, .localhost and .test names are not checked. Names that appear only in a certificate's alternative names reach the default server and are not listed.

Condition Result
21 or more days left pass
Fewer than 21 days left warn
Fewer than 7 days left, or already expired fail
nginx is running but does not answer a TLS handshake on its configured address (a wrong port included) fail; when the address refuses or times out, the remaining hosts fail with the same message without dialling again
The served certificate does not cover the host name (a wildcard covers one label) fail, on a separate TLS <host> name line
More than one running nginx container matches the stack fail, naming the containers

Two further warnings can follow a host line:

  • Served differs from disk. The certificate nginx presents is not the file named by that host's own ssl_certificate line (mapped from /etc/nginx/ssl onto the stack's ssl/ directory). nginx has not been reloaded since the file changed. Fix: reload nginx. Generated route hosts such as api.<base domain> use the base domain's certificate directory, and are compared against that file.
  • Renewed but not installed. A newer certificate covering the host exists in <ssl dir>/.acme/certificates/ or in a readable /etc/letsencrypt/live/*/cert.pem, while nginx still serves an older one. The warning names both expiry dates. Fix: install the renewed certificate into the stack's ssl/ directory and reload nginx.

A chain that does not verify against the system roots warns on a separate TLS <host> chain line when SSL_MODE=letsencrypt (a common cause is serving cert.pem instead of fullchain.pem). For other modes, such as a private CA, it is printed as detail and does not change the verdict.

A conf that cannot be read, or a TLS host whose block names no ssl_certificate (for example one set through include), produces a warning for that file or host; the other hosts are still checked. An ssl_certificate set at http or file level is inherited by the servers below it.

Fronted projects. When NGINX_FRONTED_BY is set (the production layout, a project in nself-web/backend served by the nginx of nself-web), the check uses the fronting stack's nginx/ confs, ssl/ directory, .env files and nginx container. The dial address comes from that stack's .env, then .env.<ENV>: NGINX_HTTPS_PORT, else NGINX_SSL_PORT, else 443 on NGINX_BIND_IP (127.0.0.1 when unset or 0.0.0.0). Only that address is contacted; no public DNS or internet probe is made.

For a project that runs its own nginx, the port and bind IP come from the project's full env cascade (so .env.local overrides count), the same values compose publishes.

Skips. The section prints a single TLS: skipped (<reason>) line, and the line never affects the exit code, when SSL_MODE is local or none, when no nginx container is running for the stack, when Docker cannot be queried, when the fronting layout cannot be resolved, or when no TLS host is configured. A skip is never counted as a pass.

Because a warning or failure here is a normal doctor result, nself doctor exits 2 (warnings) or 1 (failures) when a certificate is close to expiry.

Deep mode subsections (--deep or --only <section>)

Section What is Checked
host Disk free, swap usage, CPU load, clock sync, kernel tainted flag
docker Storage driver, dangling images, container health, proxy-docker-socket (see below)
postgres pg_isready, longest running query, dead tuples, last vacuum
hasura /healthz endpoint, metadata consistency
nginx Config syntax test, served certificate expiry per domain (a TLS handshake against the served nginx, not a file probe inside the container)
ssl Certbot timer active, last renewal age
ping ping.nself.org reachable
plugins Plugin container health endpoints
license License cache present and not in grace period
monitoring Prometheus, Grafana, Loki reachable
backups Last backup age (must be under 26 hours)
security JWT secret, container user, secret file permissions, exposed ports, weak SSL ciphers, SEC-GITIGNORE-01 certificate keys and .env.secrets kept out of git (see below)
ai-safety AI plugin moderation wire-up gap (see below)
performance PERF-POOL-01: pgxpool connection cap vs postgres_max_connections
security PERM-RLS-01: RLS enforcement for np_* tables (see below)

proxy-docker-socket: Docker Socket Held by a Proxy or Plugin (P7-DEPL-21, ADR 0027)

Fires during nself doctor --deep in the docker section. No generated stack mounts the Docker socket into a proxy or plugin container, because the socket is root-equivalent on the host. The check inspects the live containers of the project (running, restarting and paused ones) and fails when a proxy (nginx, traefik) or a plugin container holds the socket: a bind of docker.sock or of a directory that holds it (/var/run, /run, /, and the /private alias on macOS), including a bind source that is a symlink to one of those, a named volume that Compose declares as backed by the socket or such a directory, or a DOCKER_HOST that points at a unix socket.

A plugin container is every service that neither the generated core stack nor the service catalog declares. A name that only docker-compose.override.yml mentions does not count as core, so a plugin whose fragment was disabled or deleted is still checked, and a label such as nself.plugin never earns an exception. The core admin service and your own CS_N custom services are not judged. Other daemon sockets (podman) and Docker data directories are not part of this check.

Result Meaning
pass No proxy or plugin container holds the socket
warn Only plugins in the build guard's exception table hold it; the message names the plugin, the nself version where the exception ends (v1.5.0 for forgejo and monitoring) and the ticket that removes it
fail A proxy, or a plugin without a live exception, holds it; the message names the plugin, service and container. A proxy never gets an exception, and neither does a service that two plugins declare
unknown Docker could not be inspected, a container field was missing (a mount without a source, destination or type), or the container's inspect output has an empty environment or mount list: the docker package returns empty values for omitted fields, so empty cannot prove absence and a judged container is unknown unless it lists both a non-empty environment and non-empty mounts. Bind sources this host cannot verify and every volume mount are unknown too: the docker package cannot show a volume's live backing, so a Compose declaration or a name never proves it safe. Unproven evidence outranks an exception (unknown, not warn), and a known exposure outranks both (fail). Never reported as pass
skip The project has no docker-compose.yml

nself build enforces the same rule before it writes anything. It reads the generated stack, every enabled plugin fragment and docker-compose.override.yml together, resolves YAML anchors and merge keys, and expands ${VAR} from the process environment, the project .env files and the computed plugin variables. A plugin fragment, override or stack that gives the socket to nginx, traefik or a plugin service stops the build with E130, naming the plugin and service. Relative bind paths resolve against the project directory, ~ is your home directory, and symlinks are followed before the check, so ../../var/run or a ./run link to /var/run is refused; a symlink that cannot be resolved is refused too. A named volume that is external and mounted by a proxy or plugin service is refused, because the build cannot show what backs it; an ordinary named data volume stays allowed, including one renamed with name: alone (the shipped forgejo fragment does this). A volume (renamed or not) whose device is the socket or a directory holding it is a confirmed socket exposure, like a direct bind. A service with a non-empty secrets or configs list is refused as well, because a secret or config file: can be the socket and the build does not follow them (no shipped plugin uses either; empty lists are safe), and use_api_socket set to anything but a false value (or a variable that cannot be resolved) is refused because the provider mounts the engine API socket itself. None of these can be waived by an exception, and an external volume stays unprovable even when it also names a socket device. An environment list entry is interpolated as a whole, key included (a map key is not), so ${KEY}=unix://… is judged by what KEY resolves to, and a key that cannot be resolved stops the build. DOCKER_HOST is judged by its effective value: a DOCKER_HOST entry without a value (or DOCKER_HOST: with null) forwards the environment's value, so a unix socket there is refused, and an unset or tcp:// value is accepted. ${VAR} resolves the way Compose does, from the process environment, then the .nself/compose.env this build is about to write, then the project .env. The guard runs the real compose.env writer in memory (the same plugin variables, secrets, DATABASE_URL, DOCKER_NETWORK, Hasura flags and URL-encoded twins) and uses its output, so a stale .env field never stands in for what the build writes; the previous .nself/compose.env on disk is never read, and no secret is printed or sent anywhere. A .env value that itself contains $ is trusted only when every variable it names, and every variable those names depend on in turn, is defined earlier in the same file, is defined nowhere else (no other env file, no computed value), and the process environment does not hold a different value for it (the parser expands each file alone, so anything else may not match what Compose resolves); otherwise it counts as unresolved and the build stops with E130 where the value feeds a socket mount, device or DOCKER_HOST. Doctor judges the live containers instead of predicting their environment. Long-syntax type: bind sources and volume device paths resolve against the project directory even without a leading ./. An env_file is inspected for its effective DOCKER_HOST; explicit environment values take precedence. A missing env file cannot start a container and introduces no socket exposure; present malformed or unreadable files are refused. A variable that cannot be resolved, extends, volumes_from, include and a malformed volumes or environment block also stop the build, because the build cannot show they are safe. An exception waives only a confirmed socket exposure on the excepted plugin's own service; an unresolved value or backing, an external volume, extends, volumes_from, secrets, configs or use_api_socket is refused even for forgejo and monitoring, and a proxy never gets an exception. Build and doctor use matching exception policies, checked by parity tests, so a plugin that builds with one warning shows warn here, and both turn into a refusal at the version the exception ends. Fix: remove the socket volume and the unix DOCKER_HOST from the plugin's docker-compose.plugin.yml, or remove the plugin, then run nself build. Read-only planning defers malformed override YAML to the container-impact check, which reports unknown; a write-mode build still refuses it with E130. Valid socket exposures are refused in both modes.

AI-SAFETY-01: ai+moderation Wire-Up Gap (S69-T05)

Fires during nself doctor --deep in the ai-safety section.

What it checks: If the ai plugin is loaded AND the deployment binds on a non-loopback address (e.g., 0.0.0.0) AND the moderation plugin is NOT loaded, emit a WARN.

Self-hosted single-user deployments on loopback are explicitly exempted, this is a legitimate use case.

Status Meaning
pass ai not loaded, or deployment is loopback-bound, or moderation is wired
warn ai loaded on public-bound deployment without moderation , consider installing the moderation plugin

Fix:

nself plugin install moderation
nself build && nself start

The check reads NSELF_AI_LOADED, PLUGIN_AI_INTERNAL_URL, NSELF_MODERATION_LOADED, PLUGIN_MODERATION_INTERNAL_URL, and NSELF_BIND_ADDRESS from the environment.

Detection fixture:

set -a && source test/fixtures/ai-public-no-mod.env && set +a
nself doctor --deep
# Emits: "moderation not wired on public-bound deployment with ai loaded"

PERF-POOL-01: Pool Sizing Check

Fires during nself doctor --deep in the performance section.

What it checks: Total configured pgxpool MaxConns across all active services must not exceed POSTGRES_MAX_CONNECTIONS. Default Postgres ships with max_connections=100. With 23 enabled services at the default cap of 10 connections each, total = 230, exceeding the limit causes random 503 errors under load.

Recommended cap formula: min(10, floor(postgres_max_connections / num_active_services))

Status Meaning
pass Total pool capacity ≤ postgres_max_connections
warn Total pool capacity > postgres_max_connections , reduce per-service pool or raise POSTGRES_MAX_CONNECTIONS

Fix: Raise POSTGRES_MAX_CONNECTIONS in .env or reduce per-plugin pool size. The check emits a FixCmd suggestion with the exact value to set.

# Skip the pool sizing check (not recommended in production)
nself doctor --deep --skip-pool

PERM-RLS-01: RLS Enforcement Check (S74-T02 + S74-T-PERM-01)

Fires during nself doctor --deep in the security section.

What it checks:

  1. For every np_* table: pg_class.relrowsecurity = true (RLS enabled) and at least one policy exists.
  2. For every np_* table with a tenant_id column: pg_class.relforcerowsecurity = true (FORCE RLS, prevents table owner from bypassing policies).
  3. For every np_* table with a tenant_id column: Hasura metadata has a select permission for the user role with a tenant_id row filter ({"tenant_id": {"_eq": "X-Hasura-Tenant-Id"}}).

Security-Always-Free Doctrine: this check runs without a license key.

Status Meaning
pass All np_* tables have RLS enabled, at least one policy, and Hasura tenant_id filters where applicable
warn Violation found (default); use --strict to escalate to fail
fail Violation found with --strict flag

Violation output format:

RLS-DISABLED table=np_chat_messages
RLS-FORCE-MISSING table=np_claw_cost_events role=user
HASURA-FILTER-MISSING table=np_claw_cost_events role=user

Env vars read:

  • NSELF_DB_URL or DATABASE_URL, Postgres connection string
  • HASURA_GRAPHQL_URL, Hasura endpoint (default: http://127.0.0.1:8080)
  • HASURA_GRAPHQL_ADMIN_SECRET, required for Hasura metadata query; if absent, Hasura filter check is skipped with a warning

Fix:

# Fix missing FORCE RLS on a table — enables RLS and applies FORCE ROW LEVEL
# SECURITY plus the four standard Hasura-compatible policies
nself db rls apply-table public np_chat_messages

# Re-run the check after fixing
nself doctor --deep --only security

See also: multi-tenant conventions for the canonical wall doc on source_account_id vs tenant_id.


SEC-GITIGNORE-01: Certificate Keys and Secrets Out of Git

Fires during nself doctor --deep in the security section.

nself init writes /ssl/ and .env.secrets into the .gitignore of a new project only. A project created before that, or one whose .gitignore was edited, can still commit ssl/certificates/<domain>/privkey.pem. The check asks git itself, so nested .gitignore files, ! negations and your global excludes count the way git counts them:

  1. git check-ignore --no-index on ssl/privkey.pem, ssl/certificates/x/privkey.pem and .env.secrets: each must be ignored.
  2. git ls-files -- ssl/ .env.secrets: must list nothing.

It reads only; it never edits .gitignore or the index. Outside a git work tree, or without git installed, it passes as skipped.

Status Meaning
pass All three paths are ignored and nothing under ssl/ or .env.secrets is tracked
warn A path is not ignored, or a key or secret file is already tracked

Fix:

# 1. Ignore the paths (a leading / keeps src/ssl/ trackable)
printf '/ssl/\n.env.secrets\n' >> .gitignore

# 2. If the check listed tracked files, untrack them (the files stay on disk)
git rm --cached -r --ignore-unmatch -- ssl/ .env.secrets
git commit -m "chore: stop tracking certificate keys and secrets"

A key or secret that was committed stays in git history, and anyone with a clone has it. Rotate it: replace the certificate with one issued on a new private key, and replace every secret that was in the committed file.


DEFAULT-CREDS-01: Postgres Default Username Warning

Fires during nself doctor (standard and deep) in the Configuration section.

What it checks: If POSTGRES_USER equals the default value postgres and NSELF_ENV is prod or staging, the check emits a WARN. The default is appropriate for dev; in production it is a predictable attack surface.

This does not change the default or block deployment — it is an advisory warning only.

Status Meaning
pass POSTGRES_USER is not the default postgres, or environment is dev
warn POSTGRES_USER=postgres in prod or staging — set a unique username

Fix: Set POSTGRES_USER=<unique-name> in your .env before nself build:

# .env
POSTGRES_USER=myprod_db_user

Then rebuild: nself build && nself start.


--install-check: 6-stage onboarding funnel

nself doctor --install-check runs a focused readiness check that maps to the 6-stage onboarding funnel. It is invoked automatically by the Homebrew post_install hook after brew install nself. You can also run it manually at any time.

$ nself doctor --install-check

Onboarding Funnel Check
  Stage 1 — Install       v1.1.1 (darwin/arm64)
  Stage 2 — Activation    2 projects initialized
  Stage 3 — First-use     first start 3 days ago
  Stage 4 — First-plugin  no plugins installed
    → Run: nself plugin install ai  (or any plugin)
  Stage 5 — First-value   (skipped, prior stage failed)
  Stage 6 — Habit         (skipped, prior stage failed)

Funnel position: Stage 3/6. Next: nself plugin install ai  (or any plugin)

Each stage prints PASS, FAIL, UNKNOWN, or SKIPPED:

Status Meaning
PASS Stage completed
FAIL Not yet reached , remediation hint shown
UNKNOWN Cannot determine (e.g. Stage 5 when Hasura telemetry hook is not wired)
SKIPPED A prior stage failed; this stage was not evaluated

Stage 5 shows UNKNOWN (not FAIL) when the query-count file is absent. This avoids penalising self-hosters who have not wired the optional Hasura telemetry hook.

Pass --json for machine-readable output:

nself doctor --install-check --json

Exit codes: 0 = all 6 stages pass; 1 = one or more stages fail.

--check-legacy: v0.9 global host scan

nself doctor --check-legacy scans the host machine for stale v0.9 global paths that persist after migration:

Path scanned What it indicates
~/.nself/ v0.9 global config directory
~/.nself/plugins/ v0.9 plugin install directory
~/.config/nself v0.9 XDG config file (v1 uses a directory)
/usr/local/share/nself v0.9 shared data directory

For each path found, the output shows the path, its type, and a cleanup hint. The check is read-only: it never deletes anything automatically.

$ nself doctor --check-legacy
WARNING: Found 2 v0.9 stale artifact(s) on this host:
  [dir]  /Users/me/.nself  — safe to remove: rm -rf ~/.nself (after verifying no custom config)
  [file] /usr/local/share/nself  — safe to remove: sudo rm -f /usr/local/share/nself

Run the cleanup commands above, then re-run `nself doctor --check-legacy` to confirm.

If no stale paths are found, the command exits 0 with No v0.9 global artifacts detected. Clean install.

This flag exits early without running any other doctor checks. Combine with other checks by running them separately.

JSON Output

When --json is passed, the command writes a single JSON object to stdout and produces no other output. The JSON schema is:

{
  "timestamp": "2026-04-17T12:00:00Z",
  "checks": [
    {
      "name": "[security] Exposed port 5432 (Postgres)",
      "status": "critical",
      "message": "Postgres port 5432 is bound on 0.0.0.0 — bind to 127.0.0.1",
      "detail": "docker stop nself_postgres && nself build && nself start"
    }
  ],
  "summary": {
    "total": 42,
    "passed": 39,
    "warnings": 1,
    "failed": 1,
    "critical": 1
  }
}

Status values: pass, warn, fail, critical.

Envelope and exit codes (v1.5)

With NSELF_V15=1 (the default from v1.5.0), doctor --json and doctor --format json write the v1 envelope instead of the bare report (see JSON-Output). data is the report above plus state, and passed-check lines go to stderr so stdout stays one document:

{ "schema_version": "1", "command": "doctor", "data": { "timestamp": "...", "checks": [], "summary": {}, "state": "warnings" } }
data.state Meaning Exit status (v1.5 mode)
ok every check passed 0
warnings warnings only, no failures 12
unhealthy at least one check failed 10

In v1.4 mode --json prints the bare report and exits 0, and human mode exits 1 (failures) or 2 (warnings only). NSELF_V15=1 NSELF_JSON_LEGACY=1 prints the bare report without state for one more minor release (removed in v1.6.0). --install-check and --ai keep their own JSON shapes. The schema is schemas/commands/doctor.v1.schema.json. See Exit-Codes.

Flags

Name Shorthand Type Default Env Escalates to JSON override Description
--ai bool false write legacy Run the AI first-run wizard (install Ollama, setup Gemini pool, verify)
--alerts bool false Check monitoring alert rules are loaded
--check-legacy bool false Scan host for v0.9 stale paths (global scan, not per-project)
--deep bool false Alias for --full (run all checks)
--fix bool false write Auto-fix safe issues
--force bool false With --fix, overwrite hand-edited generated files
--format string "" Output format: json, text (default text)
--full bool false Run all checks including network and memory (slower)
--headless bool false Print OAuth URL instead of opening browser (for SSH/headless servers)
--install-check bool false legacy Run 6-stage onboarding funnel check (used by Homebrew post-install hook)
--json bool false JSON output
--only string "" Run only a specific subsystem check (host, docker, postgres, hasura, nginx, ssl, ping, plugins, license, monitoring, backups, security)
--plan bool false With --fix, show generated-file repair plan without writing
--quick bool false Fast check: infrastructure, disk, ports, config, plugins, license, container health only (the default check set; explicit opt-in overrides --full/--deep)
--section string "" Run only a specific section (system, core, backups, license, plugins, monitoring, security)
--skip stringSlice [] Skip specific check sections
--skip-ollama bool false Skip local Ollama installation step
--skip-pool bool false Skip Gemini pool setup step
--verbose bool false Detailed diagnostics
--yes bool false Non-interactive mode: accept all defaults (for CI/scripts)
--help -h bool false Show help

Subcommands

Name Description
heal Run targeted self-healing routines for ɳSelf components
images Check availability of every locked image
report Write a redacted support bundle (tar.gz) to share in an issue
security Diagnose server security

Contract

  • Side effect: read
  • Output: document
  • JSON: envelope (data schema)
  • Exit codes: 10: one or more checks failed, 12: warnings only, no failures

Examples

# Quick diagnostic
nself doctor

# Full diagnostic (includes network and memory checks)
nself doctor --full

# Full hardening scan across all 12 subsystems
nself doctor --deep

# Deep scan, one subsystem only
nself doctor --deep --only security

# Verbose output with details per check
nself doctor --verbose

# JSON output for automated monitoring
nself doctor --json

# Auto-fix safe issues
nself doctor --fix

# Deep scan with JSON output, useful for CI security gates
nself doctor --deep --json

# First-run AI wizard (installs Ollama, sets up Gemini pool)
nself doctor --ai

# First-run AI wizard, non-interactive
nself doctor --ai --yes

See Also

← Commands | Home →

Home


Getting Started


Commands


Features


Configuration


Plugins (87 + 10 monitoring)

Free (25)
Pro (62)
Planned (26)
  • plugin-audit
  • plugin-blog
  • plugin-checkout
  • plugin-commerce
  • plugin-drm
  • plugin-export
  • plugin-flow
  • plugin-import
  • plugin-ldap
  • plugin-mailgun
  • plugin-media
  • plugin-oauth-providers
  • plugin-pages
  • plugin-postmark
  • plugin-rate-limit
  • plugin-reports
  • plugin-saml
  • plugin-scheduler
  • plugin-sendgrid
  • plugin-sso
  • plugin-subscription
  • plugin-thumb
  • plugin-transcoder
  • plugin-twilio
  • plugin-waf
  • plugin-watermark

Guides


Architecture


Reference


Machine interface


Licensing


Security


Brand


Operations


Contributing


Admin


Changelog


All commands (21)

Clone this wiki locally