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.
src/Ampersand/Misc/defaultSettings.yaml— the framework's built-in defaultsgenerics/settings.json— settings generated by the Ampersand compiler from your ADL modelconfig/project.yaml— your project-specific settings- 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 variable | Setting key | Type |
|---|---|---|
AMPERSAND_DEBUG_MODE | global.debugMode | boolean |
AMPERSAND_PRODUCTION_MODE | global.productionEnv | boolean |
AMPERSAND_SERVER_URL | global.serverURL | string |
AMPERSAND_DATA_DIR | global.dataPath | string |
AMPERSAND_DBHOST | mysql.dbHost | string |
AMPERSAND_DBNAME | mysql.dbName | string |
AMPERSAND_DBUSER | mysql.dbUser | string |
AMPERSAND_DBPASS | mysql.dbPass | string |
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.
| Setting | Default | Development | Production |
|---|---|---|---|
global.debugMode | true | true | false |
global.productionEnv | false | false | true |
global.serverURL | http://localhost | local address | public domain |
global.scriptTimeout | 30 (seconds) | 0 (no limit) | 30 or higher |
mysql.dbHost | localhost | container name | production host |
mysql.dbPass | ampersand | dev password | strong 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.
| Function | Blocked by productionEnv | Gated by role |
|---|---|---|
| Reinstall database | yes | rbac.adminRoles |
| Export all population | yes | rbac.adminRoles |
| Export selection | yes | rbac.adminRoles |
| Import population file | no | rbac.importerRoles |
| Run ExecEngine | no | rbac.adminRoles |
| Check rules | no | rbac.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.