Skip to Content
ConfigurationConfig File Reference

Config File Reference

settings.json is the single structured description of a SeqDesk deployment. It is the recommended place for non-secret settings you want to be reproducible.

Two things to understand before you edit it:

  • Some sections are read by the running application (pipelines, site, notifications, telemetry, runtime). Change them and restart, and the behaviour changes.
  • Other sections are install-time inputs (ena, access, auth, sequencingFiles, moduleSettings). They are applied into the database by the installer, --reconfigure, a hosted install profile, or Settings → Infrastructure → Import settings.json. Editing them on a running install changes what /api/admin/config/status reports and nothing else.

Each section below is labelled accordingly. The mechanism behind the split is explained in Configuration Sources & Priority.

File discovery

SeqDesk searches the working directory it starts in (the directory holding package.json — in a packaged install that is <install-dir>/current) in this order:

  1. settings.json (canonical)
  2. seqdesk.config.json (legacy/development fallback)
  3. .seqdeskrc
  4. .seqdeskrc.json

The first file found is used and the rest are ignored. If no config file exists, only environment variables, database settings, and built-in defaults apply.

In a packaged install the real file lives one level up, at <install-dir>/settings.json, written chmod 600; each release directory holds a relative symlink (releases/<version>/settings.json -> ../../settings.json), so an update never leaves two divergent config files behind. Replacing that symlink with a real file inside a release directory is the most common way to lose configuration at the next update.

A config file that is not valid JSON is not a fatal error. The loader logs a warning to the server log and carries on with environment variables, the database, and defaults — so a syntax error looks like “my whole config file is being ignored”. Validate before restarting: node -e “JSON.parse(require(‘fs’).readFileSync(‘settings.json’,‘utf8’))”.

Older installs may still keep their runtime config under the legacy seqdesk.config.json filename. SeqDesk continues to read it as a fallback, so existing deployments keep working — no rename is required, and the installer deliberately keeps whichever of the two names already exists so an upgrade never splits the live config in two.

Complete structure

{ "app": { "port": 8000 }, "site": { "name": "My Sequencing Facility", "dataBasePath": "/mnt/sequencing/data", "contactEmail": "facility@example.com" }, "pipelines": { "enabled": true, "databaseDirectory": "/mnt/seqdesk/pipeline-databases", "execution": { "mode": "local", "runDirectory": "./pipeline_runs", "conda": { "path": "/opt/conda", "environment": "seqdesk-pipelines", "cacheDir": "/net/shared/conda-cache" }, "slurm": { "enabled": false, "queue": "cpu", "cores": 4, "memory": "64GB", "timeLimit": 12 }, "pipelineOverrides": { "mag": { "mode": "slurm", "slurm": { "queue": "long", "cores": 16, "memory": "128GB", "timeLimit": 48 } }, "metaxpath": { "mode": "slurm" } } }, "mag": { "enabled": true, "version": "3.4.0", "stubMode": false, "skipProkka": true, "skipConcoct": true } }, "ena": { "testMode": true, "username": "", "password": "", "brokerAccount": false, "centerName": "" }, "sequencingFiles": { "extensions": [".fastq.gz", ".fq.gz", ".fastq", ".fq"], "scanDepth": 2, "ignorePatterns": ["**/tmp/**", "**/undetermined/**"], "autoAssign": false, "activeWriteMinAgeMs": 30000, "simulationMode": "auto", "simulationTemplateDir": "/opt/seqdesk/simulation-templates" }, "access": { "departmentSharing": false, "allowDeleteSubmittedOrders": false, "allowUserAssemblyDownload": false, "orderNotesEnabled": true, "postSubmissionInstructions": "" }, "auth": { "allowRegistration": true }, "moduleSettings": { "account-validation": { "allowedDomains": ["example.org"], "enforceValidation": false }, "billing-info": { "pspEnabled": false, "costCenterEnabled": false } }, "telemetry": { "enabled": false, "endpoint": "https://seqdesk.org/api/telemetry/heartbeat", "intervalHours": 24 }, "notifications": { "enabled": false, "inApp": { "enabled": true }, "provider": "seqdesk-relay", "relayUrl": "https://seqdesk.org/api/notifications/relay", "events": { "order": { "submitted": true, "statusChanged": true, "samplesSent": true }, "ticket": { "created": true, "reply": true } }, "userDefaults": { "orders": true, "support": true } }, "runtime": { "databaseUrl": "postgresql://seqdesk:replace-with-password@127.0.0.1:5432/seqdesk?schema=public", "directUrl": "postgresql://seqdesk:replace-with-password@127.0.0.1:5432/seqdesk?schema=public", "nextAuthUrl": "http://localhost:8000", "nextAuthSecret": "your-secret-here" } }

You do not need every section. Omitted keys fall back to their built-in defaults; the file is deep-merged over those defaults rather than replacing them.

Section reference

app — Application runtime

Install-time input. The running server does not read app.port; it is used when the installer generates start.sh and the PM2 configuration, and by Settings → Infrastructure → Import settings.json, which warns that a restart is required.

KeyTypeDefaultDescription
portinteger8000App listen port written into the generated start scripts

site — Facility information

Mixed. dataBasePath is read at runtime; name and contactEmail are applied into SiteSettings and read from there.

KeyTypeDefaultDescription
namestring"SeqDesk"Display name shown in the UI (stored in SiteSettings.siteName)
dataBasePathstring"./data"Base directory for sequencing data
contactEmailstringContact email shown to researchers

dataBasePath is special: the resolved value is used only when its source is file or env. Otherwise the SiteSettings.dataBasePath column applies, which is what Settings → Infrastructure → Data Storage edits. See Data Storage.

pipelines — Pipeline configuration

Mixed. pipelines.execution.* and pipelines.databaseDirectory are read at runtime, and this is where the config file has the most direct effect: any value set there overrides the corresponding admin-saved setting. pipelines.enabled and pipelines.mag.* are install-time inputs.

KeyTypeDefaultDescription
enabledbooleanfalseInstall-time. Decides whether the installer sets up Conda and Nextflow. false also clears the install-profile pipeline allowlist when imported.
databaseDirectorystring""Optional shared root directory for large pipeline database assets

Which pipelines a running SeqDesk offers is not decided by pipelines.enabled. It comes from the per-pipeline PipelineConfig rows edited under Settings → Pipelines, falling back to the install-profile allowlist (SiteSettings.extraSettings.installProfilePipelineAllowlist) and, if neither exists, to “all pipelines enabled”. A hosted profile or an import can set that allowlist with a pipelines.enable array of pipeline IDs.

pipelines.execution — Execution settings

KeyTypeDefaultDescription
mode"local" | "slurm""local"Where pipelines run
runDirectorystring"./pipeline_runs"Output directory for pipeline runs
pipelineOverridesobject{}Per-pipeline execution defaults keyed by pipeline ID

The built-in default for runDirectory in the configuration schema is ./pipeline_runs, but when nothing is configured anywhere the pipeline executor falls back to /data/pipeline_runs. Set this explicitly rather than relying on either default.

pipelines.execution.conda — Conda settings

KeyTypeDefaultDescription
pathstring"/opt/conda"Conda installation path
environmentstring"seqdesk-pipelines"Environment name, or an absolute environment prefix
cacheDirstring""Shared Nextflow conda cacheDir, so per-process environments are built once and reused across runs
enabledbooleanfalseAccepted for compatibility and ignored — the pipeline runtime mode is always Conda

cacheDir earns its place on clusters: a head node with network access pre-builds each per-process environment into the shared cache, and network-isolated compute nodes reuse it by content hash instead of reaching conda-forge themselves.

pipelines.execution.slurm — SLURM settings

KeyTypeDefaultDescription
enabledbooleanfalseSubmit jobs to SLURM
queuestring"cpu"Partition/queue name
coresinteger4CPUs per job
memorystring"64GB"Memory per job
timeLimitinteger12Time limit in hours
optionsstringAdditional sbatch options — not read from this file, see below

timeLimit is hours, not minutes. It is written verbatim into the job script as #SBATCH -t <N>:0:0, so a value like 60 asks for sixty hours and will sit PENDING forever on a partition with a shorter limit.

options has no built-in default, so it never receives a configuration source label and the pipeline executor discards it. Extra sbatch flags placed here are silently ignored, and there is no SEQDESK_SLURM_OPTIONS environment variable either. Set them in Settings → Infrastructure → Pipeline Runtime, or at install time with SEQDESK_EXEC_SLURM_OPTIONS.

pipelines.execution.pipelineOverrides — Per-pipeline runtime policy

Each override is keyed by pipeline ID. Use this to keep global execution local while sending large workflows such as mag or metaxpath to SLURM, or to give one heavy pipeline a bigger queue than the facility default.

KeyTypeDescription
mode"inherit" | "local" | "slurm"Execution target for this pipeline
slurmobjectOptional per-pipeline queue, cores, memory, timeLimit, options
nextflowProfilestringOptional Conda-compatible Nextflow profile for this pipeline

Flat aliases are also accepted for the nested slurm keys — slurmQueue, slurmCores, slurmMemory, slurmTimeLimit, slurmOptions, and clusterOptions (an alias for slurmOptions). Values are normalised on read: an unrecognised mode, a non-positive core or time-limit value, or an empty string is dropped rather than applied, and an override that ends up empty is removed entirely. Unlike the global slurm.options, an override’s options is read normally, because pipelineOverrides is not filtered by source.

SeqDesk uses Conda-based pipeline execution. Container profiles such as docker, singularity, apptainer, and podman are rejected when a run starts.

pipelines.mag — MAG pipeline

Install-time input, applied by a hosted install profile into the PipelineConfig row for mag. On a running install, edit these under Settings → Pipelines, or per run when you launch MAG.

KeyTypeDefaultDescription
enabledbooleantrueEnable nf-core/mag
versionstring"3.4.0"Pipeline version
stubModebooleanfalseTest mode (no real analysis)
skipProkkabooleantrueSkip Prokka annotation
skipConcoctbooleantrueSkip CONCOCT binning

ena — ENA submission

Install-time input. ENA submissions read SiteSettings.enaUsername, SiteSettings.enaPassword, and SiteSettings.enaTestMode from the database, not this section. Setting ena.username here on a running install will show up in /api/admin/config/status but will not be used by a submission.

KeyTypeDefaultStorageDescription
testModebooleantrueSiteSettings.enaTestModeUse the ENA test server
usernamestringSiteSettings.enaUsernameWebin username
passwordstringSiteSettings.enaPasswordWebin password (encrypted at rest)
brokerAccountbooleanfalseSiteSettings.extraSettings.ena.brokerAccountWebin account has ENA broker permissions
centerNamestring""SiteSettings.extraSettings.ena.centerNameSubmission center name

Do not store ENA credentials in the config file. Enter them in Settings → Data Upload (/admin/ena), where the password is encrypted before it is written to the database. See ENA Credentials.

sequencingFiles — File discovery

Install-time input. File discovery reads SiteSettings.extraSettings.sequencingFiles; this section seeds it.

KeyTypeDefaultDescription
extensionsstring[][".fastq.gz", ".fq.gz", ".fastq", ".fq"]Allowed file extensions
allowedExtensionsstring[]Alias for extensions, accepted by hosted install profiles; this is the key name used in the database
scanDepthinteger2Directory scan depth (1–10)
ignorePatternsstring[]["**/tmp/**", "**/undetermined/**"]Glob patterns to skip
autoAssignbooleanfalseAutomatically link discovered files to samples when names match
activeWriteMinAgeMsinteger30000Minimum file age in milliseconds before a file is considered stable rather than still being written
simulationMode"auto" | "synthetic" | "template""auto"Read-simulation mode (auto uses templates if available)
simulationTemplateDirstring""Directory of realistic FASTQ pairs for template-based simulation
allowSingleEndbooleanforced trueAccepted for compatibility and ignored — single-end reads are always allowed

See File Discovery for what these settings do to a scan.

access — Researcher access policy

Install-time input. The running application reads these from SiteSettings.extraSettings (and SiteSettings.postSubmissionInstructions).

KeyTypeDefaultEdited in the UI at
departmentSharingbooleanfalseSettings → Accounts → Access & Sharing (“Department Sharing”)
allowDeleteSubmittedOrdersbooleanfalseSettings → Sequencing Order Form (“Allow Deletion of Submitted Sequencing Orders”)
allowUserAssemblyDownloadbooleanfalseSettings → Accounts → Access & Sharing (“User Assembly Downloads”)
orderNotesEnabledbooleantrueSettings → Info (“Sequencing Order notes”)
postSubmissionInstructionsstringSettings → Sequencing Order Form (“Post-Submission Instructions”)

departmentSharing is the one to think hardest about: it lets every researcher in a department view and edit each other’s sequencing orders. Turn it on for a small shared lab, not for a facility serving unrelated groups. allowDeleteSubmittedOrders is useful while testing and dangerous in production — it lets facility admins delete sequencing orders after submission.

auth — Authentication

Install-time input, read at runtime from SiteSettings.extraSettings.auth.allowRegistration.

KeyTypeDefaultDescription
allowRegistrationbooleantruePublic registration enabled

The schema also accepts auth.requireEmailVerification and auth.sessionTimeout so older files still parse, but the authentication runtime implements neither. Do not use them to express a security requirement — there is currently no supported way to enforce email verification or a session lifetime. If you need to restrict who may register, enable the Account Validation module and set moduleSettings.account-validation.allowedDomains instead.

moduleSettings — Optional module settings

Install-time input, keyed by module ID. Only modules that are enabled under Settings → Modules consult their settings.

moduleSettings.account-validation

Stored as SiteSettings.extraSettings.accountValidationSettings.

KeyTypeDefaultDescription
allowedDomainsstring[][]Email domains accepted for automatic account validation
enforceValidationbooleantrueBlock registrations from other domains

An empty allowedDomains with enforceValidation: true is the trap here — set the domains at the same time you enable the module.

moduleSettings.billing-info

Stored as SiteSettings.extraSettings.billingSettings.

KeyTypeDefaultDescription
pspEnabledbooleantrueEnable PSP (project) number capture
pspPrefixRangeobject{ "min": 1, "max": 9 }Allowed range for the PSP prefix
pspMainDigitsinteger7Number of main PSP digits
pspSuffixRangeobject{ "min": 1, "max": 99 }Allowed range for the PSP suffix
pspExamplestring"1-1234567-99"Example PSP shown in the form
costCenterEnabledbooleantrueEnable cost-center capture
costCenterPatternstringRegex the cost center must match
costCenterExamplestring"12345678"Example cost center shown in the form

telemetry — Operational telemetry

Read at runtime, with inverted precedence. A value stored in SiteSettings.extraSettings.telemetry wins over this section, so a facility admin can always turn the heartbeat off from the UI.

KeyTypeDefaultDescription
enabledbooleanfalseOpt-in anonymous heartbeat reporting
endpointstringhttps://seqdesk.org/api/telemetry/heartbeatHeartbeat URL
intervalHoursinteger24Minimum hours between automatic heartbeats

SEQDESK_TELEMETRY_DISABLED=true overrides all of the above. See Operational Telemetry for what is reported.

notifications — Notifications

Read at runtime. Controls the in-app notification panel and the optional hosted email relay.

KeyTypeDefaultDescription
enabledbooleanfalseMaster switch for the hosted SeqDesk email notification relay
inApp.enabledbooleantrueMaster switch for the in-app notification panel/channel
provider"seqdesk-relay""seqdesk-relay"Notification provider (only the hosted relay is supported)
relayUrlstringhttps://seqdesk.org/api/notifications/relayHosted relay endpoint
relayTokenstringScoped notification relay token — set via env, never committed
eventsobject(all on)Which events trigger notifications
userDefaultsobject{ "orders": true, "support": true }Default per-user opt-in for the orders and support channels

notifications.enabled: true is necessary but not sufficient. Email notifications are only dispatched when the setting is on, the provider is seqdesk-relay, and the Email Notifications module is enabled under Settings → Modules. A relay token is additionally required before anything is actually delivered.

notifications.events — Event toggles

KeyTypeDefaultDescription
order.submittedbooleantrueNotify when a sequencing order is submitted
order.statusChangedbooleantrueNotify when a sequencing order status changes
order.samplesSentbooleantrueNotify when samples are marked sent
ticket.createdbooleantrueNotify when a support ticket is created
ticket.replybooleantrueNotify on a ticket reply

The relay token is a secret. Set relayToken through SEQDESK_NOTIFICATION_RELAY_TOKEN — never commit it to a config file. It is masked in /api/admin/config/status responses, and the Admin UI refuses to persist it to the database.

runtime — Process environment

Applied to process.env at startup, and only for variables that are not already set. An environment variable of the same name always wins, and every value here needs a restart to take effect.

KeyMaps toDescription
databaseUrlDATABASE_URLPostgreSQL runtime connection string
directUrlDIRECT_URLDirect PostgreSQL connection for Prisma migrations
nextAuthUrlNEXTAUTH_URLNextAuth.js callback URL
nextAuthSecretNEXTAUTH_SECRETSession signing secret, and the default key material for encrypting stored secrets
anthropicApiKeyANTHROPIC_API_KEYAPI key for the optional field-validation routes
adminSecretADMIN_SECRETRelease publishing admin secret used by scripts
blobReadWriteTokenBLOB_READ_WRITE_TOKENVercel Blob token for release publishing scripts
updateServerSEQDESK_UPDATE_SERVERUpdate server URL

DIRECT_URL is derived rather than merely copied: if DATABASE_URL is supplied by the environment but DIRECT_URL is not, the environment’s DATABASE_URL is used for migrations too, so a runtime override cannot silently leave migrations pointing at a different database.

Changing nextAuthSecret on an existing install invalidates every session and, unless SEQDESK_ENCRYPTION_KEY is set separately, makes previously stored encrypted secrets (such as the ENA password) undecryptable. Set SEQDESK_ENCRYPTION_KEY if you need to rotate the auth secret independently.

Sections written by the installer

Two sections are produced by the installer rather than hand-written, and they are not part of the runtime configuration schema the app reads through /api/admin/config/status:

SectionWritten byPurpose
installProfile--profile installsHosted install-profile id, name, version, and appliedAt stamp
bootstrap.users--interactive and unattended account settingsThe admin/researcher accounts the seed creates on first run; bootstrap.users.researcher: false skips the researcher account

Leave both alone unless you are scripting installs. installProfile.id is also sent with notification-relay requests, so editing it by hand can break relay authorisation.

Validation

The loader is deliberately forgiving: a file that is not valid JSON is skipped with a console warning, and individual out-of-range values are not rejected at load time. Nothing stops you from writing scanDepth: 400.

A separate validateConfig() helper — used by tooling and the install path rather than by the loader — checks:

  • site.dataBasePath must be a string
  • pipelines.execution.mode must be one of local, slurm, kubernetes (kubernetes is accepted only so older files still parse; there is no Kubernetes execution backend — use local or slurm)
  • ena.testMode must be a boolean
  • sequencingFiles.scanDepth must be a number between 1 and 10
  • telemetry.enabled must be a boolean, telemetry.endpoint an http/https URL, and telemetry.intervalHours a number between 1 and 168
  • notifications.enabled and notifications.inApp.enabled must be booleans, notifications.provider must be seqdesk-relay, and notifications.relayUrl must be an http/https URL