Runtime configuration

An application's runtime configuration is a single config.yml. The database, secrets, initial administrator and other fields are the same in every deployment method; what differs is where the file is located and how it is generated.

MethodConfiguration file locationHow it is generated
app-installerconfig.yml in the installation directory, shared by all releasesGenerated by app-installer; values set with --set and --set-from-env
DockerA file on the host, mounted read-only at /app/config.ymlWritten by hand; checked with the image's config check before starting
Node.jsconfig.yml beside dist/, specified by APP_CONFIG_FILEGenerated with node dist/cli/index.js config init; values set with config set
Hub-hostedStored by Hub; entered in the console at deployment or submitted with --configHub completes the secrets; --config replaces the whole document

Generate and check with the CLI

The archive and the Docker image both contain the application CLI: it is invoked as node dist/cli/index.js inside dist/ and as pnpm nocobase in the source project.

CommandEffect
config init [--dialect <dialect>]Generates config.yml from config.example.yml with random secrets; installs no driver
config set <path>=<value>Changes one field; --from-env <path>=<VARIABLE> reads the value from an environment variable, for passwords and other secrets
config checkLoads the configuration the way the service does and connects to every database except SQLite; exits non-zero with the cause when a problem is found
config envLists every environment variable the application reads, its configuration path, and whether it is set
config variablesDescribes every environment variable for a deployment: description, secret, required, generated or read only on the first start; dist/variables.json

Database

The main database is configured under database.connections.main. pnpm nocobase config init --dialect supports sqlite, postgres, mysql, mssql, oracle, dameng, kingbase and oceanbase. Every driver except SQLite must be added to the project before building, as @nocobase/db-<dialect>; the archive and the image contain only the drivers installed at build time.

database:
  default: main
  connections:
    main:
      dialect: postgres
      host: db.internal
      port: 5432
      database: crm
      username: crm
      password: REPLACE_WITH_DATABASE_PASSWORD
      schemaManagement: managed
      migrations:
        autoRun: true
      seeds:
        autoRun: true

SQLite uses dialect: sqlite with the absolute file path in database; the file should be located under storage/. In Docker, use the in-container path /app/storage/database.sqlite.

  • Address: host must be reachable from the application's runtime environment; localhost inside a container refers to the container itself.
  • Permissions: with automatic migrations enabled, the database account needs permission to create and alter tables.
  • Migrations and seeds: migrations.autoRun applies pending migrations at startup and seeds.autoRun runs the seed tasks, such as creating the administrator account. When the release process runs them separately, set both to false and run node dist/cli/index.js db apply before starting.

Secrets

secrets:
  keys:
    - version: 1
      key: REPLACE_WITH_OPENSSL_RAND_HEX_32

secrets.keys holds the master keys the application encrypts stored secrets with, such as plugin credentials, model keys and OAuth tokens; the sign-in and session keys are derived from them as well. The first key is current and seals everything new; the others only decrypt. A key is at least 32 bytes: generate one with openssl rand -hex 32. SECRETS_KEYS=2:<key>,1:<key> sets the list from the environment, current key first.

config init and app-installer generate the first key, and Hub completes a missing or placeholder secrets.keys for the applications it hosts. Keys remain unchanged across restarts and upgrades, are backed up together with the configuration and separately from the database, and are not committed to the repository. A placeholder, a key shorter than 32 bytes or a repeated version causes the application to fail at startup, and config check reports it.

To rotate, put a new key first with a version higher than every other and keep the old ones after it, restart, run node dist/cli/index.js secrets rotate (pnpm nocobase secrets rotate in a source checkout) until secrets status reports nothing left to reseal, then remove the old key. Rotation can run beside the application and can be repeated. Changing the current key signs every user out once, because sign-in cookies are signed with it.

auth.secret and session.secret are optional. An application configured with auth.secret before secrets.keys existed keeps it beside the keys, so that authentication data encrypted under it still decrypts; adding secrets.keys to such an application signs every user out once.

Initial administrator

users:
  initialAdmin:
    username: my_admin
    email: admin@example.com
    password: REPLACE_WITH_INITIAL_ADMIN_PASSWORD

This configuration applies only when the seed task runs against an empty user table; changing these fields on an existing application does not reset the account. The template default is the user nocobase, the email admin@nocobase.com and the password admin123; if unchanged, the password should be changed immediately after the first sign-in.

Addresses and environment variables

VariableExampleDescription
APP_PUBLIC_ORIGINhttps://apps.example.comThe public scheme and host, without the mount path
APP_BASE_PATH/crmThe mount path, read at startup without a rebuild; /main by default, /hub for a Hub
APP_SERVER_HOST127.0.0.1The listen address; 0.0.0.0 inside a container
APP_SERVER_PORT13000The listen port
APP_CONFIG_FILE/srv/nocobase/crm/config.ymlSelects the configuration file; when unset, the application looks for a configuration file such as config.yml in the deployment root and reuses its saved secrets across restarts
APP_STORAGE_DIR/srv/nocobase/crm/storageThe persistent directory; storage/ under the deployment root by default
NODE_ENVproductionMarks the session cookie Secure, so sign-in is possible only over HTTPS or localhost
NOCOBASE_STRICT_STARTUPtrueExits non-zero when startup fails, so that the service manager restarts the application

When a setting appears both in the file and in its environment variable, the environment variable takes precedence; SECRETS_KEYS, for example, overrides secrets.keys. Only the variables listed by config env are recognized; do not infer names. A Hub-hosted application sets none of these variables: Hub assigns the path, and app.publicOrigin in the configuration specifies the public origin.

HTTPS and reverse proxy

The following example assumes Nginx on the same server as the application, with the map in the http context:

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    listen 443 ssl;
    server_name apps.example.com;
    ssl_certificate /etc/nginx/certs/fullchain.pem;
    ssl_certificate_key /etc/nginx/certs/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:13000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_read_timeout 300s;
    }
}

proxy_pass appends no path, so the application's /crm prefix is preserved; Upgrade and Connection support WebSocket. When several applications share one domain, each uses one location /crm/ forwarding to its own port. For a Hub, forward the entire site and add client_max_body_size 260m;. Run nginx -t to check the configuration before reloading.