Configuration

Every setting, its default and what it does — plus the database, the image build and the security model.

How settings work#

Everything is set with environment variables. With Docker Compose they come from a file named .env next to docker-compose.yml:

Terminal
cp .env.example .env            # on your computer
cp .env.server.example .env     # on a public server
docker compose up -d            # after every change

Without a .env file the defaults below apply — the Studio works out of the box. With plain docker run, pass them as -e NAME=value. Several things can also be changed on the website by an administrator (registration, certificates, AI providers); what is set there wins over the file.

Website and accounts#

VariableDefaultMeaning
APP_NAMEEverything StudioThe name shown in the browser
STUDIO_BIND127.0.0.1Address the Studio's port is published on. 0.0.0.0 = reachable from your network.
STUDIO_PORT8080Port of the Studio on the host
PUBLIC_URL—The address people use, e.g. https://studio.example.com. Needed behind a proxy.
TRUST_PROXYfalsetrue when a reverse proxy is in front (trust X-Forwarded-*)
COOKIE_SECUREautoauto = HTTPS-only cookies when the request came over HTTPS; true / false force it
APP_SECRETgeneratedEncrypts stored keys and certificates. Left empty, one is generated once and kept in the data volume. Never change it afterwards.
ADMIN_EMAIL · ADMIN_USERNAME · ADMIN_PASSWORD—Create this admin account at the first start
REGISTRATIONclosedopen = anyone who reaches the site may register

The AI#

VariableDefaultMeaning
DEFAULT_PERMISSION_MODEbypassWhat the AI may do in new projects: bypass (autonomous), acceptEdits, ask, plan
DEFAULT_MODEL—Model for everybody (fable, opus, sonnet, haiku); empty = the account's default
CLAUDE_CODE_VERSIONlatestlatest keeps Claude Code current; an exact version pins it
CLAUDE_CODE_AUTO_INSTALL · CLAUDE_CODE_AUTO_UPDATEtrueDownload at the first start · update at start and daily
AGENTS—Other AIs switched on at the first start: codex,gemini,opencode
AGENTS_AUTO_UPDATEtrueKeep them current
AGENT_IDLE_MINUTES10How long such an AI process stays up between messages

Limits#

VariableDefaultMeaning
MAX_RUNS_PER_USER2AI runs at the same time, per user
MAX_TERMINALS_PER_USER4Open terminals per user
RUN_TIMEOUT_MINUTES60Longest AI run
TERMINAL_IDLE_MINUTES30A terminal nobody watches is closed after this time
UPLOAD_LIMIT_MB500Largest uploaded file
PACK_LIMIT_MB4096Largest pack
TRASH_DAYS7Deleted projects are kept this long
RELEASE_EXPORTS_MB1024Largest exports/ folder kept with a release
STUDIO_PIDS_LIMIT16384Processes and threads of the whole container

Servers of projects#

VariableDefaultMeaning
SERVICES_ENABLEDtrueProjects may run Node.js servers at /srv/<name>/
MAX_SERVICES_PER_USER3Servers per user
SERVICE_MEMORY_MB512Memory limit of one server

Websites and HTTPS#

VariableDefaultMeaning
SITES_ENABLEDtruePublishing websites
SITES_BIND127.0.0.1Address the website ports are published on
SITES_PORT8081HTTP port of the websites as people reach it (80 on a server)
SITES_HTTPS_PORT8443HTTPS port as people reach it (443 on a server)
SITES_TLStrueThe built-in HTTPS
SITES_HTTPSfalsetrue = a proxy in front does HTTPS; the built-in one switches itself off
SITES_BASE_DOMAIN—Every site also gets <name>.<this domain> (needs a wildcard DNS record)
STUDIO_DOMAIN—Serve the Studio itself over HTTPS under this host name
ACME_AGREE_TOS—yes accepts the certificate authority's terms and switches automatic certificates on
ACME_EMAIL—Contact address for the certificate authority
ACME_DIRECTORY_URLLet's EncryptAnother ACME authority
ACME_ORDERS_PER_HOUR40New certificate orders per hour for the whole Studio
MAX_SITES_PER_USER10Websites per user
SITE_MAX_MB500Largest published website
DOMAIN—The Studio's domain for the Caddy profile

How these fit together: Server & HTTPS.

WordPress#

VariableDefaultMeaning
WORDPRESS_ENABLEDtrueThe WordPress area
MAX_WORDPRESS_PER_USER5WordPress sites per user
WORDPRESS_MEMORY_MB256PHP memory limit of a site
WORDPRESS_MAX_WORKERS6PHP processes a site may use at once
WORDPRESS_UPLOAD_MB64Largest upload (media, plugin zips)
WORDPRESS_IDLE_MINUTES60A site's PHP stops after this time without a visitor and starts with the next one. 0 = never stop.
WORDPRESS_PHP_HARDENINGtruePHP of a site only reaches its project folder and has no shell functions
WORDPRESS_DB_ADMIN_USER · WORDPRESS_DB_ADMIN_PASSWORD—Only with an external database server: an account that may create databases

Database#

The image contains its own database (MariaDB). It is created at the first start, its password is generated, and it has no network port — there is nothing to configure.

VariableDefaultMeaning
MYSQL_HOST—Set it to use an external MySQL or MariaDB server instead
MYSQL_PORT · MYSQL_DATABASE · MYSQL_USER · MYSQL_PASSWORD3306 · studio · studio · —Its connection
Managing the built-in database
docker compose exec studio studio-db status
docker compose exec studio studio-db list            # the Studio's and the WordPress sites' databases
docker compose exec studio studio-db shell           # an SQL prompt
docker compose exec -T studio studio-db dump --all > all.sql

Building the image#

These apply to docker compose build (or up --build):

VariableDefaultAdds
INSTALL_ANDROIDtrueJDK and Gradle (the Android SDK itself is installed at runtime)
INSTALL_DOTNETtrue.NET SDK for Windows software (about 800 MB)
INSTALL_WINDOWS_CROSStruemingw-w64 C/C++ cross compilers and NSIS
INSTALL_BROWSERStruePlaywright and Chromium, the AI's headless browser
INSTALL_WORDPRESStruePHP and WP-CLI for the WordPress area (about 120 MB)
INSTALL_WINEfalseWine, to smoke-test Windows programs (about 1 GB)
INSTALL_CLAUDE_CODEfalsePuts Claude Code into the image — for private images only, see below

What is not in the image#

Three things are downloaded by each installation from their official sources instead of being shipped:

  • Claude Code is Anthropic's proprietary software. The Studio downloads the official package at the first start; every person uses it with their own account under Anthropic's terms.
  • The Android SDK is installed once an administrator accepted Google's license (Admin → Android SDK, or ANDROID_SDK_ACCEPT_LICENSE=yes for unattended setups).
  • WordPress is downloaded from wordpress.org when a site is set up, so every site starts with the current release.

Do not publish an image built with INSTALL_CLAUDE_CODE=true. The default build is the one that may be shared.

The software the image does contain, and its licenses: docs/LICENSES.md.

Security model#

  • One Linux account per user. The AI, terminals, git, the Studio tools and every file access of a user run as that account. One user's AI cannot read another user's projects or logins.
  • No server secrets in user processes — they get a short list of environment variables, nothing else.
  • Previews and project servers are sandboxed in the browser: they run in an opaque origin and never see the Studio's login cookie.
  • Websites are separate: served on their own ports and origins, from releases nobody can change afterwards. A domain belongs to one website and never to the Studio itself.
  • WordPress: a site's PHP runs as its owner, confined to the project folder, without shell functions; uploads never execute; each site's database account sees only its own database.
  • Accounts: registration is closed by default, logins are rate-limited, and the first account from outside the private network needs a setup code from the server log.
  • The container runs with no-new-privileges, a process limit and a bounded log.

The Studio gives its users an AI that runs commands. Give accounts to people you would give a shell on that machine — and keep the image, WordPress sites and their plugins up to date.

More detail: docs/ARCHITECTURE.md. Found a problem? Security policy.

For developers#

Working on the source
cd server && npm install && npm run build      # the API server (TypeScript)
cd web && npm install && npm run dev           # the website on :5173, proxied to a Studio on :8080