Env vars and secrets
In this guide you configure an app with environment variables, mark the
sensitive ones as secret, import a .env file, and apply the changes.
Prerequisites
Section titled “Prerequisites”- The
developerrole on the app’s team to change env vars. Any member can list them. - An API token for the scripted examples.
PANEL=https://panel.example.comH='Authorization: Bearer gsl_xxxxxxxxxxxxxxxx'J='Content-Type: application/json'1. Set a variable
Section titled “1. Set a variable”curl -sX POST $PANEL/apps/42/envs -H "$H" -H "$J" \ -d '{"name": "LOG_LEVEL", "value": "info"}'POST /apps/{id}/envs is an upsert: setting an existing name overwrites it.
Names must be plain identifiers (letters, digits, underscores), at most 200
characters.
2. Store a secret
Section titled “2. Store a secret”curl -sX POST $PANEL/apps/42/envs -H "$H" -H "$J" \ -d '{"name": "STRIPE_KEY", "value": "<secret>", "isSecret": true}'Secret values are never returned by the API again: GET /apps/{id}/envs
lists them without value. To change only the flag, send the name and
isSecret without value. The stored value is kept.
Every value, secret or not, is encrypted at rest in Postgres with
/etc/gisila/secret.key. On the host it’s written to
/srv/apps/<user>/.env (mode 0640, readable by the app’s user), never
inlined into the world-readable unit file.
3. Import a .env file
Section titled “3. Import a .env file”POST /apps/{id}/envs/bulk takes parsed entries and upserts each one. The UI
parses a pasted .env file for you. From a script:
jq -Rn '[inputs | select(test("^[A-Za-z_][A-Za-z0-9_]*=")) | capture("^(?<name>[^=]+)=(?<value>.*)$")] | {entries: map(. + {isSecret: false})}' < .env \ | curl -sX POST $PANEL/apps/42/envs/bulk -H "$H" -H "$J" -d @-# → {"imported": 6}Entries with an empty name are skipped. Variables not in the payload are left alone.
4. Apply the changes
Section titled “4. Apply the changes”Env vars are written into the app’s .env file during a deployment. Saving
a variable doesn’t restart the app, and a plain restart reuses the existing
file. Redeploy for changes to take effect:
curl -sX POST $PANEL/apps/42/deployments/ -H "$H" -H "$J" -d '{"sourceType": "git"}'For binary and zip apps, deploy the latest artifactId again.
Env vars are also available during the build, so steps such as database migrations in a build command see the same configuration as the running app.
5. Remove a variable
Section titled “5. Remove a variable”ENV_ID=$(curl -s $PANEL/apps/42/envs -H "$H" | jq '.results[] | select(.name=="LOG_LEVEL") | .id')curl -sX DELETE $PANEL/apps/42/envs/$ENV_ID -H "$H"Then redeploy.
Variables the panel sets for you
Section titled “Variables the panel sets for you”You don’t need to define these. See the App runtime contract for details.
| Variable | When |
|---|---|
PORT |
Apps with an internal port (not static or process). |
GISILA_APP_ID |
Always. |
MEDIA_ROOT, MEDIA_URL |
When media storage is enabled, unless you set them yourself. |
<PREFIX>_ENDPOINT, _REGION, _BUCKET, _ACCESS_KEY, _SECRET_KEY, _PUBLIC_URL, _FORCE_PATH_STYLE |
When a superuser links a storage bucket to the app. |
Special variables you can set:
| Variable | Effect |
|---|---|
GISILA_SYSCALL_FILTER=off |
Drops the seccomp syscall filter for this app on the next deploy. Use only if a runtime fails with EPERM. |
FLOWER_BASIC_AUTH=user:password |
Celery apps: credentials for the Flower UI. Generated if unset. |
Verify it works
Section titled “Verify it works”From the app’s Console tab, or with the API:
EXEC=$(curl -sX POST $PANEL/apps/42/exec -H "$H" -H "$J" \ -d '{"command": "printenv LOG_LEVEL"}' | jq -r .execId)The output streams on the /ws/apps/42/exec/$EXEC WebSocket (see
View logs and metrics).