Skip to main content

Configuring Development and Production Environments

The prototype framework has two settings that control how it behaves in development versus production. This guide explains what those settings do, how the framework loads its configuration, and what you need to change when moving from a local setup to a deployed application.

The two key settings

global.debugMode controls how errors are reported. When set to true, the API returns detailed error messages including a full stack trace, which the frontend displays when you click on a red error notification. When set to false, the error message reads "An error occurred (debug information in server log files)" and the stack trace stays in the server logs. The default value is true.

global.productionEnv controls which management operations the framework allows. When set to true, reinstalling the database is permanently blocked. If the application starts and the database does not exist or is out of date, the framework throws an exception and will not start. This prevents accidental data loss in a deployed environment. The default value is false.

How the framework loads configuration

The framework loads configuration in the following order. Each step can overwrite values from the previous step.

  1. src/Ampersand/Misc/defaultSettings.yaml — the framework's built-in defaults
  2. generics/settings.json — settings generated by the Ampersand compiler from your ADL model
  3. config/project.yaml — your project-specific settings
  4. Environment variables — loaded last, always take priority

This means environment variables always win. You do not need to change a config file to switch between environments; setting the right environment variables is enough.

Environment variables

The following environment variables map directly to configuration settings:

Environment variableSetting keyType
AMPERSAND_DEBUG_MODEglobal.debugModeboolean
AMPERSAND_PRODUCTION_MODEglobal.productionEnvboolean
AMPERSAND_SERVER_URLglobal.serverURLstring
AMPERSAND_DATA_DIRglobal.dataPathstring
AMPERSAND_DBHOSTmysql.dbHoststring
AMPERSAND_DBNAMEmysql.dbNamestring
AMPERSAND_DBUSERmysql.dbUserstring
AMPERSAND_DBPASSmysql.dbPassstring

Boolean values are parsed with PHP's FILTER_VALIDATE_BOOLEAN. The strings "true", "1", "yes", and "on" all result in true; "false", "0", "no", and "off" result in false.

Settings overview

The table below lists the settings relevant to environment configuration, with their default values and recommended values for development and production.

SettingDefaultDevelopmentProduction
global.debugModetruetruefalse
global.productionEnvfalsefalsetrue
global.serverURLhttp://localhostlocal addresspublic domain
global.scriptTimeout30 (seconds)0 (no limit)30 or higher
mysql.dbHostlocalhostcontainer nameproduction host
mysql.dbPassampersanddev passwordstrong password

Setting variables in Docker Compose

The most straightforward way to switch between development and production is to set environment variables in your compose.yaml or docker-compose.yml:

services:
prototype:
environment:
- AMPERSAND_DEBUG_MODE=true
- AMPERSAND_PRODUCTION_MODE=false
- AMPERSAND_SERVER_URL=http://localhost

For production, change to:

services:
prototype:
environment:
- AMPERSAND_DEBUG_MODE=false
- AMPERSAND_PRODUCTION_MODE=true
- AMPERSAND_SERVER_URL=https://your-domain.example.com

Keep database passwords out of version control. Pass them via a .env file that is listed in .gitignore:

      - AMPERSAND_DBPASS=${MYSQL_AMPERSAND_PASSWORD}

Setting values in project.yaml

You can set values in config/project.yaml for settings that are the same across all deployments of the same project. The file is loaded after the framework defaults and the compiler-generated settings, but before environment variables. A typical use is to raise the script timeout for projects that import large data files:

settings:
global.scriptTimeout: 0

Environment variables always override values in this file, so you can use project.yaml for project-wide defaults and environment variables for per-deployment overrides.

Role-based access control

Three RBAC settings control who can reach administrative functions. All three default to null.

rbac.adminRoles names the roles that may use the Installer, the ExecEngine runner, the rule checker, and the population exporter. When set to null, every user has admin access. When set to an empty list [], nobody has access. When set to a list of role names, only sessions that have one of those roles active can reach those functions.

rbac.importerRoles names the roles that may upload population files (Excel, JSON). The same logic applies: null means unrestricted, [] means nobody, a list restricts to named roles.

rbac.accessibleInterfacesIfcId is optional. It names an interface whose expression determines which interfaces are accessible in the current session. If left null, the framework falls back to querying pf_ifcRoles[PF_Interface*Role] for every active role.

These settings belong in config/project.yaml:

settings:
rbac.adminRoles: [Administrator]
rbac.importerRoles: [Administrator, Importer]

The combined effect of productionEnv and role settings

Production mode and role settings interact in two ways.

The Installer menu item is only shown when both conditions hold: the application is not in production mode, and the user has an active admin role. Even if only one condition fails, the item disappears from the menu. The same applies to the population exporter.

At the API level, all installer and exporter endpoints call preventProductionMode() before checking roles. A request to these endpoints in production mode is blocked regardless of the caller's role. The population importer does not call preventProductionMode(), so it remains available in production — gated only by rbac.importerRoles.

FunctionBlocked by productionEnvGated by role
Reinstall databaseyesrbac.adminRoles
Export all populationyesrbac.adminRoles
Export selectionyesrbac.adminRoles
Import population filenorbac.importerRoles
Run ExecEnginenorbac.adminRoles
Check rulesnorbac.adminRoles

Warning: starting production mode with an empty database

When global.productionEnv is true and the database does not yet exist, the framework will not create it. It throws an exception on startup. You must install the database first — using the Installer in the frontend — while running in non-production mode, then switch to production mode.