Environment Variables Reference
Complete list of environment variables read by the Studio server. Unlike values you change on the screen (Settings), values here require editing the file and restarting to take effect.
Canonical location is /etc/kopens/plantpulse-studio.env
/etc/kopens/plantpulse-studio.env
.env in the repository root is no longer readSetting values in the old path (.env in the installation directory) will not take effect. If the old file still exists, the script will notify you. When changing values, use the canonical path above.
Set permissions to chmod 600 — this file contains API keys.
Images and versions
| Variable | Default | Description |
|---|---|---|
REGISTRY | docker.kopens.io/ps | Registry to pull images from. If empty, uses only local tags (for custom builds) |
TAG | (empty) | Image tag |
AGENT_SERVER_TAG | Varies by installation | Agent server image tag |
TAG is recommended to remain emptyWhen empty, bin/start.sh uses the version from VERSION file and automatically follows each release.
Setting a value here manually pins it — in fact, this has caused images from a month ago to be deployed.
To pin to a specific release point, use a snapshot tag — for example: TAG=2026.08-20260810.
Locale and timezone
Uses the same variable names as Platform and Edge.
| Variable | Default | Description |
|---|---|---|
PP_LANG | en | Web default language (ko / en). Browser-stored value takes precedence |
PP_TZ | Asia/Seoul | IANA timezone ID. Sets the basis for relative time interpretation like "today / yesterday" |
For Korean field sites, set to PP_LANG=ko.
Data storage location
| Variable | Default | Description |
|---|---|---|
DATA_ROOT | /var/lib/pp-studio | Workspace, build artifacts, state, and bundled PG data all stored below this path |
This path is the backup target → Backup and recovery.
Database — choose one of two modes
(a) Bundled PostgreSQL (default) — Studio launches its own PG container.
| Variable | Default |
|---|---|
COMPOSE_PROFILES | bundled-pg |
PG_DB | ppstudio |
PG_USER | ppstudio |
PG_PASSWORD | change-me-please — you must change this |
(b) Shared PostgreSQL — uses Platform's PG (eliminates dual infrastructure).
Delete the COMPOSE_PROFILES lines and specify only the connection address.
| Variable | Example |
|---|---|
DATABASE_URL | postgres://<user>:<password>@<db-host>:5432/ps |
Bundled PG creates accounts on first startup when it initializes the data directory. If you change only PG_PASSWORD later, the account inside the DB will be out of sync and the stack will fail to start. To change it, first update the account password inside PostgreSQL — the passwd.sh section of Change password and API keys will perform those steps for you.
Platform integration
| Variable | Example | Description |
|---|---|---|
PLATFORM_API_TARGET | https://192.168.0.41 | Platform address for real data queries and delegating login authentication |
App listener (preview and deployed apps)
| Variable | Default | Description |
|---|---|---|
APPS_PORT | 5171 | Separate listener port serving preview and deployed apps |
- Direct port access installations — you must also open this port in the firewall for preview, deployed apps, and QR access to work.
- Behind a reverse proxy — no need to open it. The proxy forwards
/container,/preview, and/appson the same domain to this listener → Domain and reverse proxy.
APPS_ORIGIN) has been removedRemoved on 2026-08-23. When that value was empty, the preview URL fell back to 요청호스트:5171, completely breaking live preview in setups that only expose 80/443. Now the client uses only relative paths.
AI providers
Values here are initial defaults. Values entered on the screen (Settings → AI) override these.
| Variable | Default | Description |
|---|---|---|
AI_PROVIDER | openai-compatible | If empty, always openai-compatible |
AI_BASE_URL | (empty) | Gateway address. no default value is set |
AI_MODEL | gpt-4o | Model name |
AI_API_KEY | (empty) | OpenAI-compatible key |
ANTHROPIC_API_KEY | (empty) | Use only when deploying cloud Claude |
AI_BASE_URLIf the gateway is not on that host, chat becomes completely fetch failed, and because the value looks plausible, diagnosing the cause is difficult. Set the actual address. You can verify your value is correct before saving using the connection test in Settings → AI tab → Settings (admin).
Previously, the provider was chosen based on which key was present, but this was removed because it was impossible to predict which provider would be used depending on the env configuration (2026-08-23).
CORS
| Variable | Default | Description |
|---|---|---|
STUDIO_CORS_ORIGINS | (empty = same-origin) | Specify only for access from a different domain |
What is not set via env
User accounts and roles are not defined via environment variables. When the server has no accounts, it seeds one admin to the DB; afterward, you add and remove users on the app's User management screen and assign roles (admin / builder / viewer) there.
Related documentation
- Installation — procedure for populating initial values
- Secrets management — where to place keys
- Settings (admin) — values you change on the screen
- Domain and reverse proxy