Jump to
↵select↑↓navigateescclose

Reference

Dev shell options

Every perSystem.frappe-nix option that configures the development shell, the production package and the container images, with types and defaults.

Updated
Tags
  • options
  • reference
  • devenv
On this page

These options sit under perSystem.frappe-nix in your flake. The types and defaults were checked against the module by evaluating it. The prose describes what each option does. For a guided tour of the options you will touch most, see Write the flake by hand. The options under frappe-nix.secrets sit at the top level and have their own page, and the production module's options are under services.frappe.

devguard.mail.smtpPort, devguard.mail.httpPort and devguard.mail.pop3.port default to a base plus an offset hashed from benchName. The offset is between 0 and 899. devenv's port allocator walks forward if a port is taken.

Core

The options every bench sets.

OptionTypeDefaultNotes
enableboolfalseEnable the dev shell and the packages.
benchNamestrrequired (the normalized app.name in app mode)Identifier for environment names and the container image prefix. It also seeds the per-bench port offsets.
siteNamestr""FRAPPE_SITE. Empty means multi-tenancy, with the site set per shell through .env.
workspaceRootpath or nullnullThe bench root, where pyproject.toml and apps/ live, usually ./.. Required in bench mode. It must stay null in app mode, where frappe-nix assembles the workspace itself.
pythonpackagepkgs.python312Python interpreter. In app mode, the app.frappeVersion preset's.
nodejspackagepkgs.nodejs_22Node.js for frontend builds and the Node realtime server. In app mode, the app.frappeVersion preset's.
esbuildTargetstr"es2022"The target Frappe's esbuild pipeline compiles bundles for, exported as ESBUILD_TARGET in the dev shell and to builtBench. See Asset builds.

App mode

Set app.enable = true in the repository of a single Frappe app. See Develop a single app. workspaceRoot must stay null there.

OptionTypeDefaultNotes
app.enableboolfalseApp mode: this flake is one Frappe app's repository, not a bench.
app.frappepath(required in app mode)The Frappe source, as a flake = false input.
app.siblingslist of { name; src; }[ ]The other apps the bench should carry, in install order. It is a list and not an attribute set, because that order is the members' order and so the order of sites/apps.txt. name is the directory name under apps/, and src is the source, usually a flake input.
app.frappeVersiondevelop, version-15 or version-16"version-16"The row of lib/frappe-presets.json that drives python, nodejs, requires-python and override-dependencies. It does not pin Frappe: app.frappe does.
app.srcpathinputs.selfThe app's own source, which becomes apps/<NAME>. Do not filter it: app.lockDir is read out of it.
app.namestr[project].name of app.srcThe app's directory name under apps/, which is Frappe's own app name.
app.lockDirstr"nix"Where the generated-but-committed uv.lock (and node-locks/, for pins without a yarn.lock) live, relative to the repo root.
app.benchDirstr".frappe-nix/bench"Where the dev shell materializes the writable bench, relative to the repository root. Gitignore it.

The watcher

How the watch process chooses what to rebuild. See Memory and disk.

OptionTypeDefaultNotes
watch.appslist of str or nullnullApps the watch process rebuilds on save. null chooses by publisher (watch.excludePublishers). See Memory and disk.
watch.excludePublisherslist of str[ "Frappe Technologies" ]With watch.apps null, leave out every app whose hooks.py app_publisher contains one of these, ignoring case. [ ] watches everything, as bench watch does.
watch.rtlboolfalseAlso rebuild right-to-left stylesheets on save. bench build always builds them.
watch.nativeSassbooltrue where nixpkgs builds dart-sassCompile the watcher's stylesheets with native Dart Sass (lib/sass-embedded.nix) instead of Frappe's JavaScript build of it, 3 to 6 times faster per stylesheet. bench build keeps Frappe's compiler.

MariaDB

OptionTypeDefaultNotes
mariadb.packagepackagepkgs.mariadbMariaDB package.
mariadb.initialDatabaseslist of { name }[ ]Databases created on the first devenv up.
mariadb.durableboolfalseFlush InnoDB to disk at every commit and keep the doublewrite buffer, as production does. Off, the log is flushed once a second, which makes commits roughly 30 times faster, at the risk of the last second of commits if the machine crashes. See Memory and disk.
mariadb.noCowbooltrueOn btrfs, keep the data directory off copy-on-write (chattr +C). Set at shell entry on a directory that is missing or empty. One already holding data is reported, and frappe-nix-db-nocow migrate "$MYSQL_HOME" moves it once.

Process scope

Runs devenv up in a systemd scope of its own. See Memory and disk.

OptionTypeDefaultNotes
processScope.enablebooltrueRun devenv up in a systemd scope of its own, so the dev stack is not accounted to, and killed along with, the editor that started it. Linux with a systemd user manager and the process-compose manager; a no-op elsewhere.
processScope.memoryHighstr"40%"The scope's MemoryHigh=: past it the dev stack is throttled and reclaimed from first. A percentage is of physical RAM.
processScope.memoryMaxstr or nullnullThe scope's MemoryMax=, or none.

Node builds

OptionTypeDefaultNotes
nodeOverridesattrs of attrs{ }Per node target (an app, or app/subdir): extra attributes for the derivation that runs its yarn install --offline, such as postPatch, nativeBuildInputs or a yarnOfflineCache of your own. See Dependencies and locks.
nodeNestedFrontendExcludeslist of str[ ]Nested frontends (app/subdir) to leave out: no node_modules, no assets, and the parent's build script that drives them is dropped. See Dependencies and locks.

Packages, scripts and environment

OptionTypeDefaultNotes
pythonOverridesoverlayno-op overlayExtra Python package set overlay. Compose it with lib.overrides.
extraDevPackageslist of package[ ]Extra packages on the dev shell.
extraContainerRuntimeDepslist of package[ ]Extra runtime packages in production containers.
extraPackageslist of package[ ]Extra packages installed in both the dev shell and any production deployment of this package. The NixOS module reads them off builtBench's passthru.extraPackages, so no server-side configuration is needed.
extraLibraryPathslist of package[ ]Extra LD_LIBRARY_PATH entries (dev shell).
extraScriptsattrs{ }Extra devenv scripts, merged over the standard set.
extraEnvattrs of str{ }Extra environment variables (dev shell).

Runtime

The unified frappe-runtime process. See The unified runtime. The production counterparts are under services.frappe.runtime.

OptionTypeDefaultNotes
runtime.enablebooltrueRun one frappe-runtime process (web, realtime, jobs and scheduler) instead of the split web, socketio, worker and scheduler processes.
runtime.jobThreadsint2Concurrent background jobs inside the runtime process.
runtime.devbooltruePass --dev: reload on a Python source change, and serve /assets and /files from the runtime.
runtime.srcnull or pathruntime/ in this repositoryThe source frappe-runtime is built from, overriding the revision uv.lock resolved. null hands control back to uv.lock.

Ports and sockets

See The development shell.

OptionTypeDefaultNotes
sockets.enablebooltruePut MariaDB, Redis, the realtime server and the web server on unix sockets behind one nginx port, so several benches can run at once. Needs Frappe 15.46 or newer.
ports.baseport or nullnullFirst port this bench tries. Defaults to 8000 plus a hash of benchName.

Apps and assets

OptionTypeDefaultNotes
appsReconcile.enableboolsiteName != ""Install whatever sites/apps.txt names that siteName's site does not have installed yet, on every devenv up. See Apps in a bench.
assets.reassert.hookslist of str[ ]bench execute targets run when sites/assets/assets.json names a bundle file that does not exist on disk. Empty by default, so it names no app. See Asset builds.
assets.reassert.debounceMsint750How long assets.json must sit unmodified before the bench-watch-driven check re-reads it.

Development guard rails

Each guard is independently switchable, and devguard.enable = false turns them all off. See Development guard rails.

OptionTypeDefaultNotes
devguard.enablebooltrueMaster switch for all guard rails. See Development guard rails.
devguard.mail.enablebooltrueRoute all outgoing mail to Mailpit, and refuse IMAP and POP3.
devguard.mail.hoststr"127.0.0.1"Interface Mailpit binds and Frappe is redirected to.
devguard.mail.smtpPortport19000 plus a hash of benchNameCatcher SMTP port (per bench).
devguard.mail.httpPortport20000 plus a hash of benchNameMailpit web UI port (per bench).
devguard.mail.senderstr"notifications@example.com"From address used only on sites with no outgoing Email Account at all.
devguard.mail.unmutebooltrueIgnore mute_emails in site_config.json.
devguard.mail.pop3.enableboolfalseServe incoming mail from Mailpit's POP3 listener instead of blocking it.
devguard.mail.pop3.portport21000 plus a hash of benchNameMailpit POP3 port (per bench).
devguard.mail.pop3.userstr"dev"Mailpit POP3 username (local development only).
devguard.mail.pop3.passwordstr"dev"Mailpit POP3 password (local development only).
devguard.backups.enablebooltrueBlock Dropbox, S3, Google Drive and Frappe Cloud backup upload.
devguard.objectstore.enablebooltrueNever delete from, or overwrite in, the configured S3 bucket.
devguard.objectstore.modelocal or push"local"local: cloud_storage writes to local disk. push: new files are uploaded to the bucket (additive only).
devguard.objectstore.conditionalWritesbooltrueSend If-None-Match: * on push-mode writes. Set false for Backblaze B2, which answers it with 501.
devguard.integrations.enablebooltrueBlock outbound HTTP via frappe.integrations.utils.make_request.
devguard.integrations.allowHostslist of str[ ]Hosts to permit anyway. Loopback is always allowed.
devguard.google.enablebooltrueBlock Google Calendar, Contacts and Drive access.
devguard.webhooks.enablebooltrueDrop outbound Webhook requests.
devguard.plaid.enablebooltrueBlock Plaid bank synchronization.
devguard.scheduler.enablebooltrueSkip scheduled jobs that reach production services.
devguard.scheduler.blockServerScriptsbooltrueSkip Scheduled Job Types backed by a Server Script.
devguard.scheduler.extraBlockedJobslist of str[ ]Extra Scheduled Job Type.method values to skip (exact match).

Restore

How bench restore fetches a production backup. See Restore a production backup.

OptionTypeDefaultNotes
restore.enableboolfrappe-nix.secrets.backupAccess.enableLet bench restore fetch from the object store. See Restore a production backup.
restore.prefixstr""Path inside the bucket. Normally carried in the secret as BACKUPS_PREFIX instead.
restore.withFilesnone, private or all"none"File archives to pull by default. They are routinely tens of GB.
restore.carryConfigKeyslist of str[ "encryption_key" "backup_encryption_key" ]Allowlist of keys copied from the backup's site config.
restore.migratebooltrueRun bench migrate after restoring.
restore.requireDevguardbooltrueRefuse to write production's encryption key into an unguarded bench.

Offline migrate

Alter large tables online in front of bench migrate. See Migrate large tables online.

OptionTypeDefaultNotes
offlineMigrate.enableboolfalseRun bench-offline-migrate in front of every bench migrate, so the ALTERs of large tables cannot lock them. Adds percona-toolkit to the closure.
offlineMigrate.rowThresholdint100000Rows at which a table is altered online. 0 sends every table with a pending change through pt-online-schema-change. Overridable with FRAPPE_OFFLINE_MIGRATE_ROW_THRESHOLD or --threshold.

Containers

See Build production images.

OptionTypeDefaultNotes
containers.enableboolfalseBuild the OCI images.
containers.registrystr""Container registry URL prefix. Declared but not used: frappe-nix does not push images. See Build production images.