Install with Docker
One container runs everything: IvaraBase, its own PostgreSQL 18, PostgREST and Deno. It sits behind the reverse proxy your server already has (nginx, Caddy, Traefik, Nginx Proxy Manager…). HTTPS ends at that proxy, so the container never needs ports 80/443.
Image: ghcr.io/ankittchaurasia/ivarabase:<version>-pg<postgres major>, for example 0.2-pg18, for amd64 and arm64.
Point two records at the server:
| Record | For |
|---|---|
base.example.com |
the panel, the API and MCP |
*.base.example.com |
projects, at https://<project>.base.example.com (what supabase-js uses) |
Without the wildcard, projects still work at https://base.example.com/proj/<project>, and supabase-js accepts that URL too.
Run it
Section titled “Run it”services: ivarabase: image: ghcr.io/ankittchaurasia/ivarabase:0.2-pg18 container_name: ivarabase restart: unless-stopped environment: IVARA_DOMAIN: base.example.com ports: - "127.0.0.1:8787:8787" volumes: - ivarabase-data:/data shm_size: 256mb stop_grace_period: 60svolumes: ivarabase-data:docker compose up -ddocker exec ivarabase cat /data/secrets/INITIAL_CREDENTIALS.txt # login + RECOVERY KEYSave the recovery key in a password manager, then delete the file: docker exec ivarabase rm /data/secrets/INITIAL_CREDENTIALS.txt.
To try it locally without a domain, leave out IVARA_DOMAIN and open http://127.0.0.1:8787.
Put a reverse proxy in front
Section titled “Put a reverse proxy in front”Point the proxy at http://127.0.0.1:8787 for both base.example.com and *.base.example.com, passing the original Host header and allowing WebSockets (realtime). IvaraBase prints a ready config with your domain filled in:
docker exec ivarabase ivarabase proxy-config # nginxdocker exec ivarabase ivarabase proxy-config --server caddy # CaddySee Behind a reverse proxy for what each setting does, Traefik, and hosting panels.
Direct Postgres connections (optional)
Section titled “Direct Postgres connections (optional)”To connect with psql, pg_dump or an ORM from outside the server, publish the port:
ports: - "127.0.0.1:8787:8787" - "54329:54329"Remote connections must use TLS and a password. Without certificate files, IvaraBase makes a self-signed certificate: sslmode=require encrypts, but verify-full fails. For full verification, mount the proxy’s certificate:
environment: IVARA_DOMAIN: base.example.com IVARA_TLS_CERT_FILE: /certs/fullchain.pem IVARA_TLS_KEY_FILE: /certs/privkey.pem volumes: - ivarabase-data:/data - /etc/letsencrypt/live/base.example.com:/certs:ro # wherever your proxy keeps itThe container copies the files into the volume when it starts and again every hour, so renewals are picked up. The source files can stay root-only.
Platforms
Section titled “Platforms”Any Docker host works the same way: the image, a volume on /data, port 8787 behind HTTPS.
- Portainer and similar: add a stack with the compose file above.
- Coolify / Dokploy: ready-made compose files with Traefik labels are in
deploy/. SetIVARABASE_DOMAINand an admin password, and the platform’s Traefik handles HTTPS. Project subdomains need a wildcard certificate, which Let’s Encrypt only issues through a DNS challenge; configure one for your DNS provider in the platform’s Traefik settings, or use the/proj/<project>URLs.
Running commands
Section titled “Running commands”The ivarabase CLI is inside the image and already knows where the data is:
docker exec ivarabase ivarabase token create --name claude-code --level writedocker exec ivarabase ivarabase reset-passworddocker exec ivarabase ivarabase doctordocker exec ivarabase ivarabase env # every IVARA_* settingCommands run as the ivarabase user even under docker exec, so nothing in /data ends up owned by root.
Settings
Section titled “Settings”Any IVARA_* variable overrides config.json without being saved to it, so the compose file stays the one place to change settings. The common ones:
| Variable | Default in the image | |
|---|---|---|
IVARA_DOMAIN |
none | panel domain; projects at <project>.<domain> |
IVARA_PUBLIC_URL |
https://<domain> |
override when the proxy uses another port or a path |
IVARA_ADMIN_USER / IVARA_ADMIN_PASSWORD |
admin / random |
first start only |
IVARA_TLS_CERT_FILE / IVARA_TLS_KEY_FILE |
none | the proxy’s certificate, for Postgres verify-full |
IVARA_TRUSTED_PROXIES |
loopback + private ranges | who may set X-Forwarded-For |
IVARA_PG_SHARED_BUFFERS, IVARA_PG_WORK_MEM, … |
scaled to the container’s memory | see Configuration |
IVARA_ALLOW_EPHEMERAL |
off | 1 runs without a volume (tests only) |
The full list is in Configuration.
Things Docker does differently
Section titled “Things Docker does differently”- Published ports bypass the firewall. Docker writes its own iptables rules, so a port published as
8787:8787(on0.0.0.0) is reachable from the internet even when ufw or the host firewall blocks it. Keep127.0.0.1:8787:8787. The image trustsX-Forwarded-Forfrom private networks, and that’s only safe because nothing outside the host can reach the container directly. - A volume is required. The container refuses to start when
/dataisn’t a volume or a bind mount, so adocker rmcan never silently delete your databases. - Shared memory. Docker gives containers 64 MB of
/dev/shm; Postgres needs more for large queries and parallel workers. Keepshm_size: 256mb. - Stopping.
stop_grace_period: 60sgives Postgres time to shut down cleanly. - Memory limits. Postgres tuning and the monitoring charts follow the container’s memory and CPU limits (
deploy.resources.limitsor--memory/--cpus), not the host’s. - Bind mounts. With
- ./data:/datainstead of a named volume, the container takes ownership of the folder (uid 10001) when it starts.
Updating
Section titled “Updating”docker compose pull && docker compose up -dUpdates within one Postgres major version (-pg18) need nothing else. IvaraBase migrates its own metadata on start. Take a backup first anyway: Backups → Back up + verify now.
Moving to a new Postgres major version
Section titled “Moving to a new Postgres major version”An image with a different major (for example -pg19) refuses to open a data volume created by -pg18, and says why. To move:
- On the old image, back up every project: Backups → Back up + verify now on each project, or
docker exec ivarabase ivarabase backups create --project <name> --verify. - Copy the bundles out:
docker cp ivarabase:/data/backups ./ivb-backups, or use your off-site S3 copies. - Point the compose file at the new tag and a new volume, then restore before the first start, with the recovery key of the old installation:
docker compose run --rm -v "$PWD/ivb-backups:/import:ro" ivarabase dr restore --from /import --recovery-key XXXX-XXXX-...docker compose up -dBackups are pg_dump bundles, so they restore into newer Postgres versions.
Building the image yourself
Section titled “Building the image yourself”make docker # ghcr.io/ankittchaurasia/ivarabase:<version>-pg18 for this machinemake docker-multiarch IMAGE=ghcr.io/you/ivarabase # amd64 + arm64, pushed (docker buildx)The PostgREST and Deno versions and checksums come from scripts/deps.env, the same file the native install script uses.