Mailnib docs v1.0.0

Operator guide

Security checks and rotating APP_KEY

Outcome: you can read the Security page, tune the request limits for your host, and change APP_KEY safely.

The Security page

Open Security in the console's System group. Owners and Admins can see it; Support cannot. It is read-only: it reports, and you change things in your environment or hosting settings.

Each line is Pass, Warning or Fail, with one sentence on what to do. The page checks:

CheckWhat it looks at
APP_KEYSet, and long and random enough to protect saved credentials
Saved credentialsWhether payment keys, the SMTP password, the AI key and customers' email platform keys open with the current APP_KEY
HTTPS and HSTSWhether you reached the console over HTTPS, and whether browsers are told to keep using it
InstallerClosed once the installation finished
Debug and demo modeA production build with demo mode off
Storage, mail, AI keyThe storage driver, whether email is really sent, whether an AI key is saved
Rate limitingOn, unless you set RATE_LIMITING=off
APP_KEY rotationThe date of the last rotation, and a warning if APP_KEY_PREVIOUS was left set
Operator sign-inPassword-based. Use a long, unique password and keep the number of operator accounts small.

Request limits

Sign-in, sign-up, password reset, verification email, invitations, operator sign-in, the installer, test sends, uploads, exports, imports, webhooks and every other state-changing endpoint have a limit. A refused request gets HTTP 429 with a Retry-After header and a message saying what was limited and when to try again. The limits are fixed in the product; there is nothing to tune except how the address is read.

  • Limits are per Node process. Counts live in memory, so a restart clears them, and on serverless hosting such as Vercel every instance counts separately, which makes the limits looser. A single always-on Node process, as on cPanel, Render and a VPS, gets the full effect.
  • TRUSTED_PROXY_HOPS (default 1) is how many proxies in front of the app add to X-Forwarded-For. Set 2 with a CDN such as Cloudflare in front of your host's own proxy. Set it wrongly and every visitor looks like one address, or one visitor can pick their own.
  • RATE_LIMITING=off turns every limit off. It exists for automated tests; leave it out of production, where the Security page marks it as a failure.

Browser protections

Every page and API response carries a Content Security Policy that lets only the app's own scripts run, forbids framing the app, and allows images from https: (designs may point at any photo host), Google Fonts, and the address in SAMPLE_IMAGES_URL. Over HTTPS it also sends Strict-Transport-Security for one year, without includeSubDomains. If you serve the app on a subdomain of a site that still has plain-HTTP pages, that is deliberate.

Uploaded files reach the browser through the app, so S3 or R2 storage needs no browser access of its own.

Rotating APP_KEY

APP_KEY seals the payment provider keys, the SMTP password, the AI key and the API keys customers save for publishing to email platforms. Change it if it leaked, if a person who knew it left, or as routine hygiene. Rotating is safe; simply replacing APP_KEY is not, because saved credentials would stop opening and you would have to type them all in again.

  1. Back up the database and note the current APP_KEY.

  2. Generate a new key: openssl rand -base64 32, then write it as base64: followed by the output.

  3. In your environment, set APP_KEY_PREVIOUS to the old key and APP_KEY to the new one. Restart the app. From now on it reads values sealed with either key, so nothing breaks while you work.

  4. Preview the change from the app folder, with the same environment loaded:

    pnpm app-key:rotate -- --dry-run

    It lists what it would re-seal and saves nothing.

  5. Run it for real:

    pnpm app-key:rotate

    Every sealed value is re-sealed with the new key in one transaction. It prints what changed and never prints a key or a secret.

  6. Delete APP_KEY_PREVIOUS from the environment and restart. On Security, the saved-credentials line now reads as current and the rotation date is today.

If the command says a value opens with neither key, APP_KEY_PREVIOUS is not the key your installation used before. Nothing was changed: it checks every value before it writes any. Correct APP_KEY_PREVIOUS and run it again. Running it twice is harmless.

If you lost the old key entirely, saved credentials cannot be recovered. Set the new APP_KEY, then enter the payment keys, the SMTP password and the AI key again under Settings. Customers reconnect their email platforms in their own workspace settings.

Mailnib 1.0.0 · These pages open from your download with no server and no internet connection.