Skip to content

fix(service): default identity + cache dirs to the machine state dir for a service run - #128

Closed
MichaelTaylor3d wants to merge 1 commit into
mainfrom
fix/1928/service-state-paths
Closed

fix(service): default identity + cache dirs to the machine state dir for a service run#128
MichaelTaylor3d wants to merge 1 commit into
mainfrom
fix/1928/service-state-paths

Conversation

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor

Closes #1928.

Problem

A packaged Linux .deb install produces a node that serves content locally but never joins the P2P network — no peer_id, no relay reservation, no peers, ever. Two individually-reasonable facts are jointly fatal:

  1. The systemd unit sets ProtectHome=true (correct hardening) → systemd runs the root service with HOME=/root and /root inaccessible.
  2. Both state paths default under $HOME: the identity seed via digstore-remote::identity_dir() ($HOME/.config/dig) and the .dig cache via dig-node-core::canonical_cache_dir() ($HOME/DigNode/cache).

So load_or_create_seed() fails EROFS, Node::from_env() sets identity_seed: None, and peer bring-up refuses with "no identity seed; peer network needs a stable identity". The cache also falls back to a /tmp dir that doesn't survive a restart. Every official Linux install is a dead node on the connect leg of install→connect→read.

Fix (dig-node-only — no cross-repo release)

Both readers already honorDIG_IDENTITY_DIR / DIG_NODE_CACHE. New state::apply_service_state_env() defaults them to the machine-wide state dir (/var/lib/dig-node, /Library/Application Support/DigNode, %PROGRAMDATA%\DigNode) when this process is the installed service (DIG_NODE_RUN_CONTEXT=service) and the operator hasn't pinned them. Wired once at the top of run(), so systemd and launchd and the Windows SCM are steered from one place — the ticket's preferred shape (no per-packaging path re-derivation). ProtectHome=true stays. A bare CLI run is a no-op (keeps the shared $HOME cache, byte-identical to the browser's in-process node, #96).

No packaging edit needed: the systemd unit and launchd plist already set DIG_NODE_RUN_CONTEXT=service, and the Windows service registers with it too, so the code fix covers the whole class the ticket flagged across all three OSes.

Blast radius (checked)

apply_service_state_env is a new symbol called from exactly one site (entrypoint::run). It only sets two env vars, only for a service run, only when unset. It reuses the existing state_dir() / machine_state_dirs() (#501) resolution — no new path logic. Non-service (CLI) behavior is unchanged.

Verification

  • New regression tests (both green): service_state_env_defaults_land_under_the_machine_dir_not_home (pure placement) and apply_service_state_env_service_context_points_outside_home_and_respects_overrides (service-context lands outside $HOME, explicit override preserved, CLI no-op).
  • cargo test -p dig-node-service --lib state::34 passed, 0 failed.
  • cargo fmt clean; cargo clippy -p dig-node-service --all-targets zero warnings.

Version

0.71.10.71.2 (patchfix:, no public API change), re-locked in the same commit.

🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com


Generated by Claude Code

…for a service run
A packaged Linux .deb install never joins the P2P network. The systemd unit sets
ProtectHome=true (correctly), which blanks $HOME, but the identity seed
(digstore-remote's $HOME/.config/dig) and the .dig cache (dig-node-core's
$HOME/DigNode/cache) both default under $HOME. load_or_create_seed() then fails
EROFS, so the node loads no identity and peer bring-up refuses with "no identity
seed; peer network needs a stable identity"; the cache falls back to a /tmp dir
that does not survive a restart. Every official Linux install is therefore a node
that serves locally but never gets a peer_id, a relay reservation, or a peer.
Both readers already honor DIG_IDENTITY_DIR / DIG_NODE_CACHE, so a new
state::apply_service_state_env() defaults them to the machine-wide state dir
(/var/lib/dig-node, /Library/Application Support/DigNode, %PROGRAMDATA%\DigNode)
when this process is the installed service (DIG_NODE_RUN_CONTEXT=service) and the
operator has not pinned them. Wired once at the top of run(), so systemd, launchd,
and the Windows SCM are all steered from one place rather than each packaging
target re-deriving a path — and ProtectHome=true stays. A bare CLI run is
unaffected (keeps the shared $HOME cache, byte-identical to the browser node, #96).
Regression tests assert the service-context identity + cache paths land outside
$HOME, that an explicit override is never clobbered, and that a CLI run is a no-op.
Closes #1928
Co-Authored-By: Claude <noreply@anthropic.com>
@MichaelTaylor3dClaude

Copy link
Copy Markdown
ContributorAuthor

Closing as a duplicate — superseded by #127 (1b59a2a, shipped in v0.72.0), which landed the identical fix while this lane was building: service_data_dir_overrides() / anchor_service_data_dirs() anchors the service-run identity + cache under the machine state dir, preserves operator overrides, and no-ops for a CLI run — the same design as this PR's apply_service_state_env(), and it also updated SPEC.md (which this PR did not). No value in merging a second copy on top. #1928 is already resolved on main.


Generated by Claude Code

@MichaelTaylor3d
MichaelTaylor3d deleted the fix/1928/service-state-paths branch August 2, 2026 00:16
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@MichaelTaylor3d@claude