Self-hosting Adminium
Ce contenu n’est pas encore disponible dans votre langue.
Adminium is a single Node process. No Redis, no external queue, no external
scheduler, no sidecar. Fastify serves the API, the WebSocket, and the dashboard
build; the engine runs in-process; jobs run on an in-process loop backed by the
adminium_jobs table.
That is the whole architecture. It fits on one small VPS.
Requirements
Section titled “Requirements”| Node.js | 22.14 or newer (for npx or a source checkout; the Docker image brings its own) |
| Port | 4600 by default |
| Meta store | PostgreSQL, MySQL/MariaDB, or SQLite |
| Source database | PostgreSQL, MySQL/MariaDB, or SQLite — external, always |
| Memory | The server holds about 245 MB of JavaScript heap from the moment it boots, so the Docker image gives Node a 512 MB heap ceiling (NODE_OPTIONS=--max-old-space-size=512). Back it with 2 GB on a server you run yourself — a VPS with Docker Compose, or Adminium with PostgreSQL and a proxy on one box — or 1 GB with swap turned on. On a managed host that runs the container for you (Render, App Platform, Fly, Railway), the limit applies to your container alone: give it 1 GB. 512 MB is not enough anywhere: Node then picks a heap ceiling near 256 MB, which a few hours of use fill. It scales with concurrent users and with your schema size, not with how many rows you have. Running from npm (npx @adminiumjs/adminium) on a small machine, set NODE_OPTIONS=--max-old-space-size=512 yourself. Setting your own NODE_OPTIONS on the container (for example to add --enable-source-maps) replaces the image’s, so keep --max-old-space-size=512 in it. |
Pick a shape
Section titled “Pick a shape”| Use when | |
|---|---|
| The npm package | A laptop, an evaluation, a machine you already manage with Node |
| A project | Somebody writes code for this admin: pages, hooks or actions you deploy from a repository |
| Docker | You would rather not manage a Node install |
| Docker Compose | A real deployment, with a meta database |
| A VPS without Docker | A real deployment on a Linux server you manage, as a systemd service |
All five run the identical process. Only the wrapper differs — a project image is the published image with the project folder copied into it.
Decide these before you commit
Section titled “Decide these before you commit”1. Where the meta store lives
Section titled “1. Where the meta store lives”The single most consequential choice, and the one that is annoying to change later. Adminium’s own tables — users, roles, connections, snapshots, page config, audit — have to live somewhere, and the default (embedded SQLite) is an evaluation default, not a production one.
2. ADMINIUM_SECRET, and where you keep it
Section titled “2. ADMINIUM_SECRET, and where you keep it”Required. It derives the AES-256-GCM key for every stored DSN and API key, and signs the session cookie.
export ADMINIUM_SECRET=${ADMINIUM_SECRET:-$(openssl rand -hex 32)}The ${VAR:-…} form matters: a bare $(openssl rand -hex 32) mints a new
secret every time the line runs, so re-running this block in the same shell
would silently orphan the setup you already had. Copy the generated value
somewhere durable before you close the terminal.
Lose it and every stored connection string and provider key becomes undecryptable — they must be re-entered. Rotate it and the same thing happens. Treat it exactly as you treat a database password: in a secret manager, backed up, not in the shell history, not in the image.
3. What role Adminium connects with
Section titled “3. What role Adminium connects with”Adminium is as powerful against your database as the role you give it, and no more. Start read-only. Grant writes to the tables you actually want editable — per table, not wholesale.
→ Read-only sources & the meta database
4. Whether it is behind TLS
Section titled “4. Whether it is behind TLS”It should be. Adminium does not terminate TLS — put Caddy or nginx in front, and
set ADMINIUM_TRUST_PROXY=on so it reads X-Forwarded-For correctly.
Health and readiness
Section titled “Health and readiness”GET /api/v1/healthzReturns JSON with ok. Check the body, not just the status code. Bare
/healthz has no route — the SPA history fallback answers it with index.html
and a 200, so a probe there reports healthy for an instance whose meta store is
unreachable.
Backups
Section titled “Backups”Three things to back up, and they are not the same thing:
| What | How | |
|---|---|---|
| The meta store | Users, roles, connections, page config, audit | Your database’s normal backup |
| The data directory | Files stored on this server’s disk, exports, installed apps and add-ons — and the embedded meta store and its pre-upgrade snapshots, if you use it | Filesystem backup of ADMINIUM_DATA_DIR |
ADMINIUM_SECRET |
The key to everything encrypted in the meta store | Your secret manager |
A meta-store backup without the secret is unreadable. Back them up together, and test the restore.
On a host with no persistent disk, such as DigitalOcean App Platform, the data directory is empty again after every deploy, so there is nothing there to back up. Keep the meta store in a managed database and files in a storage destination, and know that installed apps and some add-ons are lost at each deploy — see Installing apps and Installing add-ons. With a PostgreSQL or MySQL meta store, Adminium writes no backup of its own: back up that database with its own tools.
adminium export-zip is not a backup — it is a config bundle, and it is not
a substitute for a database backup. See
Export & restore.
What a backup does not cover
Section titled “What a backup does not cover”With no storage destination configured, every file is on this server’s own disk
under ADMINIUM_DATA_DIR/files, and the data-directory row above covers it.
Once you set ADMINIUM_STORAGE_URL — or add a destination in Studio — every
new upload, file kept with a record, export artifact, branding logo and imported
schema file goes to that bucket or that server instead (what was already written
stays where it is until you move it), and a filesystem backup of the data
directory will not contain them. Neither will the desktop app’s
backup archive, which carries the meta store, your local
SQLite databases and a redacted copy of the desktop config — and no file bytes
at all, wherever they are stored.
Those bytes are the bucket’s or the server’s own responsibility: object versioning, lifecycle rules, snapshots, whatever that storage already gives you. Adminium does not copy them anywhere on your behalf and does not pretend to.
What survives either way is the record of them. Every file’s row in the meta store carries its name, size, SHA-256, which destination it lives on and which record it is attached to, so a restore can say exactly what is missing rather than losing the reference along with the bytes.
Telemetry is off
Section titled “Telemetry is off”Adminium sends nothing anywhere unless you turn it on. There is no default-on analytics, no license check, no phone-home.
- Environment variables — the complete list
- Upgrading — forward-only migrations, and the downgrade guard
- Security hardening