Manual · 15

Account, security and API tokens

Users

Under Settings → Users you create further accounts. All accounts are admins with full access; there is deliberately no permission management.

  • Create account: username and password (at least 8 characters) – pass the credentials on to the person securely.
  • Set password: For forgotten passwords. The account is signed out on all devices in the process.
  • Delete: Signs the account out immediately; content is kept. Your own account and the last account cannot be deleted.
  • The list shows when someone last signed in.

Appearance and language

At the very bottom of the main menu – and at the top right of the sign-in page:

  • Appearance (the three icons sun, moon, screen): Light, Dark or System (default – follows the operating system’s light/dark setting and changes with it), Light or Dark. The Workflow editor, statistics and world map adapt. The code editors stay dark in both variants, as you know it from development environments – that way the syntax highlighting stays easy to read. The preview of your website stays the way the website itself looks.
  • Language of the interface (click on the flag): Browser language (default) or fixed English, German, French, Italian or Spanish. If the browser language isn’t supported, English appears.

Both apply to this browser (stored in the browser, not in the account) – on another computer, you set it there. The interface language has nothing to do with the language of your website content.

Sign-in

  • Change password: Settings → My account.
  • Login protection: After 10 failed attempts from the same IP address, logins are blocked for 15 minutes.
  • Sessions are valid for 14 days.

API tokens

For external programs (sync scripts, headless frontends, automations) you create a token under Settings → API tokens:

  • Read only – may fetch content.
  • Read + write – may create and change content, but not manage tokens or passwords.

The token is shown only once. Usage: header Authorization: Bearer <token>, for simple GET requests also as the URL parameter ?token=<token> (but it then ends up in the history and server logs – best use a read-only token). Revoke blocks it immediately. All endpoints are in the API documentation.

Integrations and atomic changes

Programs that maintain IllusionCMS via the API (e.g. IllusionPublish, n8n or your own scripts) save several changes to pages, items, global blocks, snippets and files at once with POST /batch: either everything works or nothing is changed – even if someone edited one of the affected pages in the meantime. With an idempotency key a batch can be retried safely without creating anything twice. If a token writes on behalf of a person (header X-IC-On-Behalf-Of), the revision history shows e.g. Token „Publish“ – im Auftrag von Maria Muster. GET /schema returns collections, blocks, languages and websites in one response. Details are in the API documentation. Such programs learn about changes via webhooks.

Webhooks

Webhooks notify other programs as soon as something changes: IllusionCMS then sends a POST with a JSON description of the change to an address – for example to n8n, to a service that rebuilds a static website, to IllusionPublish or to an HTTP input of one of your own workflows.

Setting up a webhook

Under Settings → Webhooks, click + Webhook and fill in a name (optional), the address (http:// or https://), the events you want and Active. Leave the secret field empty – IllusionCMS then generates one and shows it exactly once. Copy it and store it at the receiver. Later, under Edit, you can generate a New secret (the old one stops working immediately) or enter your own (at least 16 characters).

  • The secret is stored encrypted in the database only – like the S3 secret. If you move the database to another server, take IC_ENCRYPTION_KEY or data/secret.key with you (see Storing media in S3).
  • Webhooks belong to the instance, not to the content: they are not part of the bundle. In remote mode you edit the server’s webhooks.
  • At most 20 webhooks; inactive ones receive nothing (except Send test).

Webhook events

  • content.changed – pages, entries, global blocks, files, snippets or CSS/JS were created, changed, moved or deleted, also by an import, a bundle, a CSV import or a batch. Changes within about 2 seconds arrive as one delivery – saving ten entries does not trigger ten builds.
  • schema.changed – a collection was created, changed or deleted, or a block type schema changed. It includes the current schema_version from GET /schema.
  • batch.applied – a POST /batch was applied, with its results.

This is what a delivery looks like:

{ "event": "content.changed", "at": 1791572100,
  "changes": [ { "kind": "page", "action": "updated", "id": 12 },
               { "kind": "item", "action": "created", "id": 31, "collection": "blog" } ] }

All formats are described in the API documentation.

Verifying the signature

Every delivery carries the header X-IC-Signature: sha256=… – an HMAC-SHA256 of the body with your secret. The receiver recomputes it and discards anything that does not match, so nobody can inject forged events. Important: compute it over the unmodified body, not over re-generated JSON. In Node.js: We also send X-IC-Timestamp and X-IC-Signature-V2 (HMAC over timestamp.body); if you like, reject deliveries with a timestamp older than 5 minutes (protection against replay). The receiver’s response does not appear in the delivery log, only the status code.

const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex')
const ok = expected.length === header.length && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(header))

A complete example in JavaScript and Go is in the API documentation. Further headers: X-IC-Event (event) and X-IC-Delivery (unique ID, the same across retries – use it to detect duplicate deliveries). Workflows of this instance cannot verify the signature (the function node has no HMAC).

Testing and deliveries

  • Send test immediately sends a ping event and shows the result – HTTP status and duration, or the error.
  • Deliveries shows the last 50 deliveries since the server started: time, event, status (delivered, failed, pending, skipped), HTTP status, duration, attempts and the error including the start of the response. After a restart the list is empty.
  • If the receiver does not answer within 10 seconds, or answers 408, 429 or 5xx, IllusionCMS retries up to three times (after 2, 10 and 30 seconds). Other responses such as 404 are not retried; any 2xx response counts as delivered.
  • Loop protection: if a webhook calls one of your workflows that changes content again, this would repeat forever. That is why it stops after three deliveries in a row – further ones appear as skipped in the log.
  • To try it out without an external service: a workflow with a public HTTP input (POST) that stores msg.payload with store.set(…), and a webhook pointing to its address – that is what the test seed does too.

Security headers

Under Settings → Security you define which protective headers IllusionCMS sends along. The settings apply only to this instance and are not in the bundle, so you set them up separately for local and live. The Headers sent table shows the result.

Setting Default Effect
X-Content-Type-Options: nosniff always on Browsers don’t guess a file type; an uploaded image, for example, is never executed as a script
Referrer Default Other websites only see your domain when a link is clicked, not the exact page
Embedding (iframe) Own pages only Protects against clickjacking: other sites can’t embed yours invisibly. Specific domains allows it, e.g., for a partner (https://partner.de, *.partner.de); Allowed everywhere turns the protection off
Block browser features off Blocks camera, microphone, location, payments, USB/Bluetooth and more. Leave it off if a page uses e.g. “My location” in a map
HSTS off Browsers only open the website via HTTPS. Only sent over HTTPS, including behind a proxy that sets X-Forwarded-Proto: https. Caution: Browsers remember this for the configured duration, even if you turn HSTS off again. Only enable it once HTTPS works permanently, and start with 5 minutes to try it out
Content-Security-Policy empty Your own rules for where scripts, images, fonts … may be loaded from. With Report only, the browser blocks nothing but reports violations in the console. This is how you test a rule before you enforce it
Hide version in /healthz off Visitors only see {"status":"ok"}. Signed-in users and API tokens still see the version (so the version display in the admin keeps working)

Embedding, browser features and the CSP apply to the website pages (pages, 404, sitemap, robots.txt), not to the admin, the API, files and CSS/JS. The admin preview is not affected.

What you should know

  • HTML, CSS and JS are trusted. Anyone working in the admin can put arbitrary code on the website – grant access and write tokens accordingly.
  • Markdown fields don’t output embedded HTML; Collection entries that come in from outside via the API can’t inject code this way.
  • Uploaded SVGs are delivered with a security policy that blocks embedded scripts. Uploaded HTML, XML and files with an unknown extension are delivered without script execution and as a download (sandbox policy, no type guessing) – you can still upload and link them, but they do not run as a page in the admin’s origin.