Provision Postgres and Redis for an app
In this guide a superuser installs PostgreSQL and Redis on the panel node, creates a database for one app, and gives the app its connection strings.
Prerequisites
Section titled “Prerequisites”- A superuser account. Databases and services are node-wide and superuser-only.
- The app you’re wiring up.
PANEL=https://panel.example.comH='Authorization: Bearer gsl_xxxxxxxxxxxxxxxx' # superuser tokenJ='Content-Type: application/json'1. Install a PostgreSQL instance
Section titled “1. Install a PostgreSQL instance”GET /db-engines/ lists the installable versions. Install one:
curl -sX POST $PANEL/databases -H "$H" -H "$J" \ -d '{"version": 16, "displayName": "Main"}'# → {"id": 2, "status": "pending", "port": …, ...}Leave out port to use the default port for that version. Installation runs in the worker.
Poll until status is running:
curl -s $PANEL/databases/2 -H "$H" | jq '{status, errorMessage}'If it fails, fix the cause and POST /databases/2/retry.
2. Create the app’s database
Section titled “2. Create the app’s database”curl -sX POST $PANEL/databases/2/dbs -H "$H" -H "$J" -d '{ "dbName": "billing", "roleName": "billing", "extensions": ["pgcrypto", "pg_trgm"]}'The panel generates a password when you leave password out. The response
includes connection.url, for example
postgresql://billing:<generated>@127.0.0.1:5433/billing. You can read it
again later with GET /databases/2/dbs/{dbId}.
To grant extra role attributes, pass roleAttributes (for example
["CREATEDB"]), or change them later with PUT /databases/2/dbs/{dbId}/role.
3. Install Redis
Section titled “3. Install Redis”curl -sX POST $PANEL/services -H "$H" -H "$J" -d '{ "serviceType": "redis", "displayName": "App Redis", "config": { "port": "6380", "bind": "127.0.0.1", "password": "<at-least-32-random-chars>", "maxmemory": "256mb", "maxmemory_policy": "noeviction", "appendonly": "true" }}'This Redis is separate from the panel’s own. Always set a password: every app
on the host can reach 127.0.0.1. Use noeviction if you use Redis as a
queue broker, so jobs aren’t evicted under memory pressure. Watch the install
on the /ws/services/{id}/logs WebSocket or in journalctl -u gisila-worker.
4. Give the app its connection strings
Section titled “4. Give the app its connection strings”curl -sX POST $PANEL/apps/42/envs -H "$H" -H "$J" -d '{ "name": "DATABASE_URL", "value": "postgresql://billing:<generated>@127.0.0.1:5433/billing", "isSecret": true}'curl -sX POST $PANEL/apps/42/envs -H "$H" -H "$J" -d '{ "name": "REDIS_URL", "value": "redis://:<password>@127.0.0.1:6380/0", "isSecret": true}'Redeploy the app so the new variables are written to its env file.
5. Schedule backups
Section titled “5. Schedule backups”curl -sX PUT $PANEL/databases/2/dbs/{dbId}/backup-schedule -H "$H" -H "$J" \ -d '{"enabled": true, "frequency": "daily", "hour": 3, "minute": 0, "scope": "full", "keepCount": 7}'frequency is hourly, daily or weekly (with weekday). scope is
full, schema or data. Take a backup now with
POST /databases/2/dbs/{dbId}/backups, download it from
…/backups/{backupId}/download (a .sql.gz), and restore with
POST …/restore ({"backupId": …}) or by uploading a dump to
POST …/restore-upload.
Backups are stored on the same server under /var/lib/gisila/backups.
Download them somewhere else too.
Verify it works
Section titled “Verify it works”From the app’s console:
EXEC=$(curl -sX POST $PANEL/apps/42/exec -H "$H" -H "$J" \ -d '{"command": "printenv DATABASE_URL"}' | jq -r .execId)And check the instance’s live metrics:
curl -s $PANEL/databases/2/metrics -H "$H" | jq .status