Deploy a project
Ce contenu n’est pas encore disponible dans votre langue.
A project deploys like any other Node application, in one of two shapes:
- the image the project’s own
Dockerfilebuilds, which is the official Adminium image plus your folder. Every host below takes it; - a checkout with Node:
npm ci,npm run build,npm start, under systemd or whatever runs your other services.
Either way the folder is read-only in production: a server applies the page files it was deployed with and never writes them. Edits people make in Studio on that server are kept and flagged, so you can pull them back into the repository.
What every host needs
Section titled “What every host needs”ADMINIUM_SECRET |
Required. It derives the key encrypting every stored connection string and API key. Generate it once per server (openssl rand -hex 32) and never change it. |
DATABASE_URL |
Whatever adminium.config.ts reads for each database — DATABASE_URL for main, plus one variable per other key. |
| A durable data folder or a meta store | Adminium’s own tables go to /data/meta.db in the image unless you set ADMINIUM_META_URL to a PostgreSQL or MySQL database. On a host with no disk, the managed database is the only durable option. |
| Somewhere for files | Uploads, attachments, exports and the branding logo are written under the data folder unless ADMINIUM_STORAGE_URL points at an S3-compatible bucket or WebDAV server. Where your files are stored. |
| One instance | Keep the service at a single replica: a disk belongs to one machine, and live updates are shared inside one process. |
The image listens on PORT (4600 by default) as the node user, answers
/api/v1/healthz for liveness and /api/v1/readyz for readiness — the latter
checks the meta store, so it is the one a load balancer should watch.
Docker
Section titled “Docker”adminium new writes the Dockerfile:
FROM node:22-slim AS buildWORKDIR /projectCOPY package.json package-lock.json ./RUN npm ciCOPY . .RUN npx --no-install adminium build && rm -rf node_modules
FROM ghcr.io/mosofi/adminium:0.3.21COPY --from=build --chown=node:node /project/ /project/ENV ADMINIUM_PROJECT_DIR=/projectThe first stage installs the project and builds it. The second is the official
image — the server, the dashboard, the bundled add-ons, the unprivileged user,
the /data volume and the health check — with your folder copied in and
ADMINIUM_PROJECT_DIR pointing at it. Nothing of the build stage’s
node_modules survives: your hooks and actions are bundled with the npm
packages they import.
docker build -t my-admin .docker run -p 4600:4600 \ -e ADMINIUM_SECRET=$(openssl rand -hex 32) \ -e DATABASE_URL=postgres://user:password@db.internal:5432/shop \ -v my-admin-data:/data \ my-adminWith Compose:
services: admin: build: . ports: ['4600:4600'] environment: ADMINIUM_SECRET: ${ADMINIUM_SECRET:?generate one with openssl rand -hex 32} DATABASE_URL: ${DATABASE_URL:?set the database the admin is built from} volumes: - admin-data:/datavolumes: admin-data:Compose reads those ${…} values from the shell or from a .env file beside
compose.yaml. Keep the image tag in the Dockerfile equal to the Adminium
version in package.json; npm run check compares them.
Render
Section titled “Render”Commit a Blueprint next to the project and create the service from it:
services: - type: web name: my-admin runtime: docker dockerfilePath: ./Dockerfile plan: starter healthCheckPath: /api/v1/readyz envVars: - key: ADMINIUM_SECRET generateValue: true - key: DATABASE_URL sync: false disk: name: adminium-data mountPath: /data sizeGB: 1generateValue mints the secret once and keeps it stable across deploys, which
is the one property the meta store’s encryption depends on. sync: false makes
Render ask you for the database URL instead of keeping it in the repository. The
disk holds Adminium’s own database, your files and any installed apps and
add-ons; keep it even if you move the meta store to a managed PostgreSQL.
Fly.io
Section titled “Fly.io”fly launch --no-deploy # writes fly.toml; it finds the Dockerfilefly volumes create adminium_data --size 1fly secrets set ADMINIUM_SECRET=$(openssl rand -hex 32) \ DATABASE_URL=postgres://user:password@host:5432/shopfly deployapp = "my-admin"primary_region = "iad"
[build] dockerfile = "Dockerfile"
[[mounts]] source = "adminium_data" destination = "/data"
[http_service] internal_port = 4600 force_https = true auto_stop_machines = false min_machines_running = 1
[[http_service.checks]] interval = "30s" timeout = "5s" grace_period = "40s" method = "get" path = "/api/v1/readyz"A Fly volume is attached to one machine in one region and is not replicated.
Scale to a second machine and it gets its own empty volume, so stay at one — or
move the meta store to a managed database and the files to a bucket.
fly storage create provisions Tigris and writes the credentials Adminium’s
first boot reads, with nothing else to configure.
DigitalOcean App Platform
Section titled “DigitalOcean App Platform”App Platform containers have no persistent disk, so the meta store has to be a managed database and files need a bucket:
spec: name: my-admin services: - name: admin github: repo: you/my-admin branch: main deploy_on_push: true dockerfile_path: Dockerfile http_port: 4600 instance_size_slug: basic-xxs instance_count: 1 health_check: http_path: /api/v1/readyz envs: - key: ADMINIUM_SECRET scope: RUN_TIME type: SECRET - key: DATABASE_URL scope: RUN_TIME type: SECRET - key: ADMINIUM_STORAGE_URL scope: RUN_TIME type: SECRET - key: ADMINIUM_META_URL scope: RUN_TIME value: ${adminium-meta.DATABASE_URL} databases: - name: adminium-meta engine: PG production: falseCreate it with doctl apps create --spec .do/app.yaml, and set the three
secrets in the control panel. ${adminium-meta.DATABASE_URL} is DigitalOcean’s
own binding for the managed database above — never point a source database at
it.
ADMINIUM_STORAGE_URL is required here, not optional, and it has to exist
before the first boot: point it at a Space or any other S3-compatible bucket.
One more thing the missing disk costs you: apps and add-ons you install are
lost on every deploy, because their packages live in the data folder. Studio
still lists them and the boot log names each one. If you install any, use a host
with a disk, or build your own image carrying those packages —
deploy/README.md
has the recipe.
Railway
Section titled “Railway”There is no config file for Railway; set the service up in its dashboard:
- New project → Deploy from GitHub repo, pointing at the project. Railway
builds the
Dockerfileit finds at the root. - Attach a volume to the service with the mount path
/data. - Add the variables:
ADMINIUM_SECRET(generated once),DATABASE_URL, andRAILWAY_RUN_UID=0— Railway mounts volumes as root, and the image runs as an unprivileged user that could not write to the volume otherwise. - Generate a public domain. Railway sets
PORT, and Adminium listens on it.
For a PostgreSQL meta store instead of the volume’s SQLite, add Railway’s
Postgres and set ADMINIUM_META_URL=${{Postgres.DATABASE_URL}}. Keep the volume
anyway: installed apps and add-ons live on it.
A VPS without Docker
Section titled “A VPS without Docker”Follow A VPS without Docker for Node, the meta database, the settings file, the service and Caddy. Three things differ for a project.
Install the project, not the package:
sudo git clone https://github.com/you/my-admin.git /opt/my-admincd /opt/my-adminsudo npm cisudo npm run buildThe folder belongs to root and the service only reads it. The build has to run
on the server (or be copied there): .adminium/ is not in git.
Name the project in the settings file, since the service does not start in the folder, and add the database the admin is built from:
ADMINIUM_PROJECT_DIR=/opt/my-adminDATABASE_URL=postgres://user:password@127.0.0.1:5432/shopADMINIUM_SECRET=…ADMINIUM_META_URL=postgres://adminium:…@127.0.0.1:5432/adminium_metaADMINIUM_DATA_DIR=/var/lib/adminiumHOST=127.0.0.1PORT=4600ADMINIUM_TRUST_PROXY=onADMINIUM_DATA_DIR matters more here than it does without a project: unset, a
project keeps its data inside the folder, which is exactly where a deploy should
not write.
Run the CLI from the project’s own node_modules:
ExecStart=/usr/bin/node /opt/my-admin/node_modules/@adminiumjs/adminium/dist/cli/index.js startTo deploy a change: sudo git pull, sudo npm ci, sudo npm run build,
sudo systemctl restart adminium, all in /opt/my-admin.
Before a deploy, pull what changed
Section titled “Before a deploy, pull what changed”A deploy never overwrites a page somebody edited on the server — it keeps the server’s copy and shows a conflict instead. So the habit worth having is:
npm run pull -- --from https://admin.example.comgit diff # review, merge if you had changed the same pagegit commit -am "pull server edits"Then deploy. Once the deployed files match, the flags clear by themselves. Details: Pull and check.
Upgrading Adminium
Section titled “Upgrading Adminium”The version is pinned in two places, and they must agree:
npm install --save-exact @adminiumjs/adminium@0.3.21# then change the Dockerfile's FROM tag to 0.3.21npm run check # this is what compares the twonpm run buildMeta-store migrations run when the new version starts and cannot be undone, so back the meta store up first and read Upgrading. A build made by another Adminium version is refused: the deploy rebuilds it.