Skip to content

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.

  • A superuser account. Databases and services are node-wide and superuser-only.
  • The app you’re wiring up.
Terminal window
PANEL=https://panel.example.com
H='Authorization: Bearer gsl_xxxxxxxxxxxxxxxx' # superuser token
J='Content-Type: application/json'

GET /db-engines/ lists the installable versions. Install one:

Terminal window
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:

Terminal window
curl -s $PANEL/databases/2 -H "$H" | jq '{status, errorMessage}'

If it fails, fix the cause and POST /databases/2/retry.

Terminal window
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.

Terminal window
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.

Terminal window
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.

Terminal window
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.

From the app’s console:

Terminal window
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:

Terminal window
curl -s $PANEL/databases/2/metrics -H "$H" | jq .status