Engine Config File (config.json)
The Swarmfile engine reads its startup configuration from three sources, in this order of precedence:
- Environment variables (
SWARMFILE_*) - always win. - The
config.jsonfile - the subset of settings documented below. - Built-in defaults - a released build ships pointing at Swarmfile's hosted service, so an unconfigured engine connects to production rather than nothing.
Most people never touch this file: the desktop tray writes the keys it manages
for you, and a normal sign-in fills in the rest. You edit config.json
directly for headless and unattended setups - a NAS/seed node, a
render-farm worker, a VM, or any machine that boots the engine from autostart
rather than a signed-in tray session - where there's no UI to click and, on
macOS/Windows, no shell environment for the engine to inherit exported
variables from.
Where the file lives#
| Platform | Default path |
|---|---|
| macOS / Linux | ~/.config/swarmfile/config.json (respects $XDG_CONFIG_HOME) |
| Windows | %LOCALAPPDATA%\Swarmfile\config.json |
To point the engine at a specific file instead - e.g. one config per
project on a multi-tenant node - set SWARMFILE_CONFIG=/path/to/config.json.
That overrides the default location entirely.
Editing safely#
A few things are worth knowing before you hand-edit this file:
- Restart the engine after editing. The file is read once at startup. A handful of values are also applied live (cache size, throttle), but treat a restart as required for a change to take effect.
- A single syntax error discards the whole file. If the JSON doesn't
parse, the engine logs a warning and starts with defaults - the hosted
hub, but no
org_idorproject_id, so the drive has nothing behind it. One trailing comma or misspelled key silently drops those along with everything else. Validate your JSON before restarting. - A UTF-8 byte-order mark (BOM) is tolerated. Windows Notepad and
PowerShell 5.1's
-Encoding UTF8prepend one; the engine strips it. Still, prefer a plain UTF-8 editor. - Environment variables override the file. If a launcher (systemd unit,
Docker
-e, a scheduled task) setsSWARMFILE_HUB_URL, editinghub_urlin the file will appear to do nothing. Check what actually took effect with--print-env-vars(below). - Don't fight the tray. For keys the tray or
swarmfileCLI manage (mount point, seed mode, hub-only, cache size, throttle, LAN placement, branch), prefer their controls - the tray may rewrite the file and overwrite a manual edit. Hand-editing is for machines with no tray.
Connecting to the hosted service#
A released build ships pointing at Swarmfile's production service, so you do not need to configure the hub or identity provider by hand. With nothing set, the engine defaults to:
| Setting | Default |
|---|---|
hub_url | https://hub.swarmfile.com |
oidc_issuer | https://id.swarmfile.com |
oidc_client_id | swarmfile-engine |
A headless machine on the hosted service therefore only needs to say which org
and project it serves and supply a credential - org_id, project_id, and one
of SWARMFILE_API_KEY or SWARMFILE_OIDC_REFRESH_TOKEN (see below). Set
hub_url, oidc_issuer, or oidc_client_id only when you run a self-hosted
or Enterprise hub on your own domain.
Keys you can set in the file#
Every key is optional. Booleans are JSON booleans (true / false) in the
file - the true/1 string form is only for the environment-variable
equivalents.
| Key | Type | Default | Env override | What it does |
|---|---|---|---|---|
hub_url | string | https://hub.swarmfile.com | SWARMFILE_HUB_URL | Hub API base URL. Override only for a self-hosted / Enterprise hub. |
org_id | string | (none) | SWARMFILE_ORG_ID | Multi-tenant org id; the hub URL is prefixed with /orgs/{org_id}. |
project_id | string | (none) | SWARMFILE_PROJECT_ID | Scope every metadata operation to one project (required for headless/seed nodes). |
branch | string | project main | SWARMFILE_BRANCH | Branch this mount is checked out to at boot. |
office_id | string | default | SWARMFILE_OFFICE_ID | Peer-discovery grouping label. |
oidc_issuer | string | https://id.swarmfile.com | SWARMFILE_OIDC_ISSUER | OIDC issuer URL. Override only for a self-hosted IdP. |
oidc_client_id | string | swarmfile-engine | SWARMFILE_OIDC_CLIENT_ID | OIDC client id. |
encryption_project_id | string | falls back to project_id | SWARMFILE_ENCRYPTION_PROJECT_ID | Project whose hub-managed key encrypts blocks. |
read_only | bool | false | SWARMFILE_READ_ONLY | Force a kernel-level read-only mount (guest sessions). |
session_kind | owner|member|guest | owner | SWARMFILE_SESSION_KIND | Active session role (drives the tray's "Guest (read-only)" badge). |
hub_only | bool | false | SWARMFILE_HUB_ONLY | Disable all P2P (Iroh/QUIC/mDNS/gossip); serve every read over HTTPS from the hub. |
seed_mode | bool | false | SWARMFILE_SEED_MODE | Run as a NAS/seed node (pin all blocks, mirror to R2, no VFS mount). |
ec_lan_placement | bool | false | SWARMFILE_EC_LAN_PLACEMENT | Deliberately spread erasure-coded shards across LAN peers. |
lan_from_office | bool | false | SWARMFILE_LAN_FROM_OFFICE | Treat same-office peers as LAN peers even when mDNS discovery is unavailable. LAN peers are normally found by mDNS; on networks that block mDNS multicast (many corporate/VLAN'd networks) that finds nothing, so peers read as WAN and LAN shard placement has no one to spread across. Turn this on when you know your office_id members share a LAN. Pairs with ec_lan_placement. |
throttle_enabled | bool | true | SWARMFILE_THROTTLE_ENABLED | Enable bandwidth throttling / QoS. |
site_download_bandwidth_mbps | number | (unset) | SWARMFILE_SITE_DOWNLOAD_BANDWIDTH_MBPS | Download bandwidth cap in Mbps. |
site_upload_bandwidth_mbps | number | (unset) | SWARMFILE_SITE_UPLOAD_BANDWIDTH_MBPS | Upload bandwidth cap in Mbps. |
cache_max_bytes | number | 10737418240 (10 GiB) | SWARMFILE_CACHE_MAX_BYTES | Local block-cache size cap, in bytes. |
changeset_idle_secs | number | 300 | SWARMFILE_CHANGESET_IDLE_SECS | Idle seconds before a project-scoped changeset auto-commits (0 disables grouping). |
attr_cache_secs | number | 2 | SWARMFILE_ATTR_CACHE_SECS | macOS only: kernel attribute-cache ceiling (0 keeps FUSE-T's 5-60s default). |
stream_in_flight | bool | false | SWARMFILE_STREAM_IN_FLIGHT | Let this mount open a file that is still uploading - it appears at its full eventual size and reads work, waiting briefly where bytes have not landed. Off by default; see the note below before turning it on. |
mount_point | string | /tmp/swarmfile (Unix), S: (Windows) | SWARMFILE_MOUNT_POINT | Where to mount the drive - a directory on Unix, a drive letter on Windows. |
mount_point_auto | (managed) | - | - | Do not set. The engine writes this to record a drive letter it auto-selected; hand-editing it breaks the "don't relocate a letter the user chose" logic. |
Settings that are environment-variable-only#
Many settings can be tuned via SWARMFILE_* env vars but are not readable
from config.json - the file supports only the keys in the table above.
Notable env-only settings include:
- Credentials:
SWARMFILE_OIDC_REFRESH_TOKEN(non-interactive OIDC),SWARMFILE_API_KEY(project-scoped headless key - takes precedence over a refresh token),SWARMFILE_ENCRYPTION_KEY,SWARMFILE_SWARM_KEY. Credentials are deliberately kept out of the file. - Paths & identity:
SWARMFILE_CACHE_DIR,SWARMFILE_IROH_DIR,SWARMFILE_USER_ID,SWARMFILE_MACHINE_ID. - Encryption toggle/mode:
SWARMFILE_ENCRYPTION_ENABLED,SWARMFILE_EC_ENABLED(on/off/auto). - Networking:
SWARMFILE_IROH_BIND_ADDR,SWARMFILE_IROH_PUBLIC_ADDR,SWARMFILE_HEALTH_PORT. - QoS / office hours:
SWARMFILE_OFFICE_HOURS_START/_END,SWARMFILE_OFFICE_HOURS_WAN_PCT,SWARMFILE_OFF_HOURS_WAN_PCT,SWARMFILE_DSCP_INTERACTIVE,SWARMFILE_DSCP_BACKGROUND. - Seed tuning:
SWARMFILE_SEED_POLL_INTERVAL,SWARMFILE_SEED_UPLOAD_CONCURRENCY. - Runner (headless CI):
SWARMFILE_RUNNER_MODE- watchesSWARMFILE_BRANCHfor commits/tags matching a rule in.swarmfile/runner.ymland runs it. Env-only by design, noconfig.jsonkey or tray toggle - see Runner (Headless CI). Mutually exclusive withseed_mode. - Streaming an upload in progress:
SWARMFILE_STREAM_IN_FLIGHT(see the key above),SWARMFILE_STREAM_BUFFER_SECS,SWARMFILE_STREAM_READ_WAIT_SECS- env-only, noconfig.jsonkey.STREAM_BUFFER_SECS(default30) is how many seconds of playback afetch --followjob keeps buffered ahead of the reader; it is seconds rather than bytes because 30 s of a proxy and 30 s of a full-resolution master are wildly different byte counts and one figure would be wrong for both.STREAM_READ_WAIT_SECS(default15) is how long a read of a not-yet-uploaded range waits before giving up - see below. - Misc:
SWARMFILE_XREF_PREFETCH,SWARMFILE_DOCTOR_PERIOD_SECS,SWARMFILE_OTEL_ENDPOINT,SWARMFILE_OTEL_SERVICE_NAME.
A note on stream_in_flight#
Worth reading before switching it on, because the default is deliberate rather than cautious-by-habit.
A read into a range that has not been uploaded yet has to wait, and this runs
on a filesystem operation thread. An operation that waits too long does not
stall one read - it takes the whole drive with it. The wait is therefore
strictly bounded (SWARMFILE_STREAM_READ_WAIT_SECS, default 15 s, and 0 does
not mean "forever" - it falls back to the default), and a read that outruns the
upload returns a retryable "not yet" rather than an I/O error, because an
application that sees an I/O error part way through a file will usually
conclude the file is damaged and discard your document.
That bound has not yet been measured against a real editing application on both platforms. Until it has, this is something to switch on deliberately, per machine, for a project that needs it.
Scope worth knowing:
- It applies only to files with no committed version yet - a new file landing for the first time. A file you are already reading never changes size or content because somebody started a new save.
- A file that is streaming reports the size it is going to be, not
0. Without that, nothing could read it: no application asks for bytes past the end of an empty file. - If the uploading machine is on the same LAN, it serves those blocks directly from its own disk, before they reach the cloud. Over a WAN it does not - that would carry every block twice on the same contended uplink.
And the limit that no setting changes: this decides which bytes arrive first, not how fast the link is. A 4 TB file on a 100 Mbit/s uplink delivers about 12 MB/s however well it is ordered.
Engine command-line flags#
Beyond reading config.json, the swarmfile-engine binary takes a handful of
one-shot flags - useful on a headless node where there's no tray to click.
Answered immediately - about this binary, or a running engine:
| Flag | What it does |
|---|---|
--status | Engine, hub, peers, and pending work at a glance. Queries a running engine; falls back to a one-shot read of local state if none is running. |
--print-env-vars | The resolved SWARMFILE_* values this build consumed, secrets redacted, with a footer naming the config file it loaded. |
--capabilities | The compiled feature set of this binary - which optional features it was built with. |
--version, -V | Print the version and exit. |
--help, -h | Print the flag list and exit. |
Lifecycle - against a running engine:
| Flag | What it does |
|---|---|
--pause | Pause sync without unmounting the drive. |
--resume | Resume after --pause. |
--quit | Ask the running engine to drain in-flight work and stop. |
--help and --version answer before the engine reads any config, so they
work on a broken or unconfigured install. For day-to-day version-control and
mount operations, use the swarmfile CLI - it drives the
same engine over its control socket - rather than these flags.
The engine's own --help also lists offline/pinning flags (--pin,
--prepare-offline, and related). These currently run only while the engine is
stopped, so they can't be driven against a live mount and aren't part of the
normal headless workflow. To force a scope resident for offline or render-farm
use against a running engine, use swarmfile hydrate
instead.
Verifying what actually took effect#
Because three sources feed the final config, print the resolved values the engine will use - with secrets redacted, and a footer naming the config file it loaded:
swarmfile-engine --print-env-vars
swarmfile doctor (or the standalone swarmfile-doctor) then confirms the
resolved hub URL, org, and credentials actually reach the hub. See
CLI: swarmfile-doctor.
Example: a headless seed node#
On the hosted service the hub and IdP are already the defaults, so a seed node only names its org and project:
{
"org_id": "org_abc123",
"project_id": "proj_xyz789",
"seed_mode": true,
"cache_max_bytes": 107374182400
}
(On a self-hosted or Enterprise hub, add hub_url, oidc_issuer, and
oidc_client_id for your own domain.)
Pair this with a credential in the environment - SWARMFILE_API_KEY=sf_key_…
for a project-scoped key, or SWARMFILE_OIDC_REFRESH_TOKEN=… - since
credentials aren't stored in the file. See
Deployment Topologies and
Self-Hosted Seed Nodes for the full
headless-node walkthrough, Network Requirements
for exactly what a machine using this file needs to reach, and
Deploying to Your Team for pre-staging
this file across a fleet.