Databases and services
What it is
Section titled “What it is”Besides apps, a panel node can run shared infrastructure for the apps on it. None of it belongs to a team, so only superusers manage it:
| Area | What you get | API |
|---|---|---|
| Applications (runtimes) | Toolchains for dart, go, rust, node, bun, python, celery, zig, binary, static, several versions side by side |
/applications |
| PostgreSQL | Clusters for versions 14 to 18, each on its own port. Databases with a login role, extensions, role attributes, tunable settings, backups, restores, backup schedules, optional public TLS exposure | /databases |
| MongoDB | Instances for versions 6.0, 7.0 and 8.0, databases with an authenticated user, roles, backups, schedules, public exposure | /mongo |
| Managed services | redis, memcached, smtp relay settings, mailpit, pgbouncer, pgadmin, mongo-express |
/services |
| Object storage | A self-hosted Garage S3 server or an external S3 endpoint, buckets with scoped keys, buckets linked to apps | /storage |
| Postfix, Dovecot and OpenDKIM for your domains: mailboxes, DKIM keys and the DNS records to publish | /mail |
When to use it
Section titled “When to use it”- You want each app’s database on the same box, with backups, without running a separate database server.
- An app needs Redis for caching or a gisila_queue broker.
- An app stores uploads in S3 and you want credentials injected automatically.
- You want to send and receive mail for your domains from the same server.
When not to use it
Section titled “When not to use it”- For production data you can’t afford to lose, a managed database with point-in-time recovery may be the better trade. Apps can connect to any external database through env vars.
- Don’t point apps at the panel’s own Redis or Postgres. Install separate ones for apps. The panel’s Redis holds its job queues, and an app with access could inject jobs.
How it works
Section titled “How it works”Everything is local and on loopback
Section titled “Everything is local and on loopback”Every instance the panel installs is created by the agent on this host, gets
its own systemd unit and data directory, and listens on 127.0.0.1 unless you
expose it. Apps on the same host reach it at 127.0.0.1:<port>. The sandbox
allows outbound TCP, so no extra wiring is needed.
PostgreSQL
Section titled “PostgreSQL”POST /databasesinstalls a version ({"version": 16, "displayName": "Main"}). The first instance becomes the default.POST /databases/{id}/dbscreates a role and database. Leave outpasswordand the panel generates one. The response includes aconnectionobject withhost,port,database,username,passwordand a readyurl(postgresql://…). Copy the URL into the app’sDATABASE_URLenv var.- Backups (
full,schemaordata) are gzip’d dumps stored under/var/lib/gisila/backups, downloadable, and restorable in place. A schedule (hourly,dailyorweekly, keeping the newestkeepCount) runs them automatically.
The panel also lists its own cluster (the one in
/etc/gisila/database.yaml) as a read-only “system” instance. You can’t
stop, uninstall or expose it. If it lives on another host, the panel can only
read its metrics and back it up. It can’t create databases there or restore
into it.
Public exposure. POST /databases/{id}/expose with
{"isPublic": true, "domain": "db.example.com"} enables TLS, adds an SSL-only
hostssl rule and opens the port in ufw. The connection info then includes a
publicUrl with sslmode=verify-full.
MongoDB
Section titled “MongoDB”The same model, with a database plus an authenticated user and a list of
built-in roles (["readWrite"]).
Managed services
Section titled “Managed services”GET /services/catalog lists each service type with its config schema.
POST /services installs one:
{ "serviceType": "redis", "displayName": "App cache", "config": { "port": "6380", "password": "<long-random>", "maxmemory": "256mb" }}The Redis service runs as its own systemd instance, separate from the panel’s
Redis. It defaults to port 6380 and bind address 127.0.0.1. An empty
password disables authentication. Set one, since every app on the host can
reach loopback.
The worker installs the service in the background. Install output streams on
the WebSocket /ws/services/{id}/logs. Health is probed periodically
(GET /services/{id}/health), and an unhealthy service is restarted, then
reinstalled.
Object storage
Section titled “Object storage”Install Garage (POST /storage/providers/garage) or register an external S3
endpoint (POST /storage/providers/external). Create a bucket to get a scoped
access key. Linking a bucket to an app (POST /storage/apps/{appId}/links,
superuser) injects these env vars, with the prefix you choose (default S3):
S3_ENDPOINT S3_REGION S3_BUCKET S3_ACCESS_KEY S3_SECRET_KEYS3_PUBLIC_URL S3_FORCE_PATH_STYLERuntimes
Section titled “Runtimes”Apps can only target an installed runtime. A superuser installs a runtime with a version, can install more versions next to it, picks the default version for new apps, and can set default build and start commands. A version can’t be removed while an app pins it.
Example
Section titled “Example”Give an app its own Postgres database:
H='Authorization: Bearer gsl_xxxxxxxxxxxxxxxx' # a superuser's tokenJ='Content-Type: application/json'
curl -sX POST https://panel.example.com/databases/1/dbs -H "$H" -H "$J" \ -d '{"dbName": "billing", "roleName": "billing"}' | jq -r .connection.url# postgresql://billing:<generated>@127.0.0.1:5432/billing
curl -sX POST https://panel.example.com/apps/42/envs -H "$H" -H "$J" \ -d '{"name": "DATABASE_URL", "value": "postgresql://billing:<generated>@127.0.0.1:5432/billing", "isSecret": true}'