Skip to main content

2026-09-22-local-environment


title: The local environment lives in deploy/config.yaml, and dartway deploy secret is now dartway secret affects: dartway_cli: "0.11.0" dartway_core_server: "0.20.0-dev.2"​

Who is affected​

Every project. Two of the three edits are required whatever you do; the third is what the change is for.

1. dartway deploy secret no longer exists — required​

The subcommand moved up, because local is now an environment like any other and "dartway deploy secret --env local" would be a lie. Change every script, alias and note:

- dartway deploy secret set SMS_API_TOKEN --env staging
+ dartway secret set SMS_API_TOKEN --env staging

- dartway deploy secret list --env staging
+ dartway secret list --env staging

init, set, list, put-file, push and pull are unchanged in everything but the prefix. Nothing on a server changes: the store, its path and its contents stay as they were.

2. The first administrator's variable is renamed — required if you adopt step 4 of the other note​

If you keep your own bootstrap code, nothing forces your hand: it reads whatever variable name you wrote. If you move to DwFirstAdministrator (see 2026-09-22-startup-steps-and-the-first-administrator.md), the name is the framework's:

dartway secret set DW_ADMIN_IDENTIFIER --env staging # the same value as APP_BOOTSTRAP_ADMIN
dartway secret list --env staging # confirm both are listed
# then, after a deploy that proves the new name works:
# remove APP_BOOTSTRAP_ADMIN from deploy/secrets.yaml and push

Do not rename it on the server first and deploy afterwards. A server started with neither name set comes up without an administrator and only warns.

3. Declare local in deploy/config.yaml — this is the point of the change​

Your entry points can now read the development coordinates from the repository instead of every developer exporting them by hand. Two files, split along the one line Git forces.

deploy/config.yaml — add a local section, and hoist requires out of the environments that repeat it:

requires: # what the project needs wherever it runs, declared once
secrets: [SMS_API_TOKEN]

local: # committed: the coordinates of your dev containers
DW_DATABASE_HOST: 127.0.0.1
DW_DATABASE_PORT: 8090
DW_DATABASE_NAME: my_app
DW_DATABASE_USER: postgres
DW_DATABASE_PASSWORD: dev_pw
DW_DATABASE_SSL: false
DW_STORAGE_ENDPOINT: http://127.0.0.1:8100
DW_STORAGE_ACCESS_KEY: dev
DW_STORAGE_SECRET_KEY: dev_storage_pw
DW_STORAGE_PROVISION: true

staging:
host: …

Take the values from your <project>_server/docker-compose.yaml and from your .vscode/launch.json — they are the same ones, which is the problem being fixed. An environment's own requires still works and adds to the project-level one.

deploy/secrets.yaml — the git-ignored half gets a local section for the keys that are yours alone. Write it with the command rather than by hand:

dartway secret set SMS_API_TOKEN --env local

Entry points — one line each, in bin/server.dart, bin/seed_dev.dart and bin/migrate.dart:

// bin/server.dart
- final env = Platform.environment;
+ final env = DwLocalEnvironment.overlay(Platform.environment);

// bin/migrate.dart
exitCode = await DwMigrationCli(
…
+ environment: DwLocalEnvironment.overlay(Platform.environment),
).run(args);

.vscode/launch.json — delete the whole "env" block of the server configuration. It is now a copy of deploy/config.yaml > local that nothing keeps in step, and a real key written there is a key committed to Git.

A real environment variable still beats both files, so DW_DATABASE_NAME=other dart run bin/server.dart keeps working and nothing you export today stops working.

How to check​

dartway secret list --env local # both halves, each key marked with its file
dartway check # localSecretMissing, devComposeDrifted

Then start the server with nothing exported: its first line says Local environment: N key(s) from deploy/config.yaml, M from deploy/secrets.yaml.