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:
| Check | What it looks at |
|---|---|
| APP_KEY | Set, and long and random enough to protect saved credentials |
| Saved credentials | Whether payment keys, the SMTP password, the AI key and customers' email platform keys open with the current APP_KEY |
| HTTPS and HSTS | Whether you reached the console over HTTPS, and whether browsers are told to keep using it |
| Installer | Closed once the installation finished |
| Debug and demo mode | A production build with demo mode off |
| Storage, mail, AI key | The storage driver, whether email is really sent, whether an AI key is saved |
| Rate limiting | On, unless you set RATE_LIMITING=off |
| APP_KEY rotation | The date of the last rotation, and a warning if APP_KEY_PREVIOUS was left set |
| Operator sign-in | Password-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(default1) is how many proxies in front of the app add toX-Forwarded-For. Set2with 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=offturns 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.
Back up the database and note the current
APP_KEY.Generate a new key:
openssl rand -base64 32, then write it asbase64:followed by the output.In your environment, set
APP_KEY_PREVIOUSto the old key andAPP_KEYto the new one. Restart the app. From now on it reads values sealed with either key, so nothing breaks while you work.Preview the change from the app folder, with the same environment loaded:
pnpm app-key:rotate -- --dry-runIt lists what it would re-seal and saves nothing.
Run it for real:
pnpm app-key:rotateEvery sealed value is re-sealed with the new key in one transaction. It prints what changed and never prints a key or a secret.
Delete
APP_KEY_PREVIOUSfrom 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.