Skip to content

deploy/systemd/sponsord.service: daemon refuses its keystore credential on systemd 255 (0440) #36

Description

@thiras

Component

sponsord (signing daemon), specifically the reference unit deploy/systemd/sponsord.service

Version

Built from 0e85070 (sponsord 0.1.0)

Operating system

Ubuntu 24.04 x86_64, systemd 255 (255.4-1ubuntu8.17)

Steps to reproduce

  1. Install the reference unit unchanged as /etc/systemd/system/sponsord.service, and the binary at /usr/local/bin/sponsord.
  2. Provision /etc/sponsord/{api-token,treasury-password,treasury-keystore.json} at 0600 (the keystore comes from decdn key-gen), and a sponsord.env with RPC URL, PaymentPool address and pool id, as the unit's header says.
  3. Run systemctl daemon-reload && systemctl start sponsord.

Expected behavior

The daemon loads the keystore credential and proceeds to the chain connection.

Actual behavior

It exits at startup, and Restart=on-failure keeps restarting it:

Error: invalid eth keystore: /run/credentials/sponsord.service/treasury-keystore.json has insecure permissions 0o440 (must be user-only, e.g. 0o600)

On this systemd, LoadCredential= files land at mode 0440. SPONSORD_TREASURY_KEYSTORE=%d/treasury-keystore.json points sponsord straight at that file. decdn's validate_keystore_file (decdn-incentive eth_identity.rs) rejects any group or other permission bit, so the keystore is refused.

On Debian 12 (systemd 252) the same credential lands at 0400 and passes, so the unit works there. I have not pinned the exact systemd release that changed the mode.

Possible fixes

  • Unit only, the workaround the decdn/devops Ansible role uses (feat(sponsord): add the sponsord role, standalone or beside a node devops#82): copy the keystore credential into a private runtime directory at 0600 before start, and point the daemon there. The file is the encrypted keystore, and the password stays in %d.
    RuntimeDirectory=sponsord
    RuntimeDirectoryMode=0700
    ExecStartPre=/usr/bin/install -m 0600 %d/treasury-keystore.json %t/sponsord/treasury-keystore.json
    Environment=SPONSORD_TREASURY_KEYSTORE=%t/sponsord/treasury-keystore.json
    Verified on systemd 252 and 255 with the real binary. It gets past credential loading, the permission check and decryption.
  • Or in code: accept group-read when the keystore is inside $CREDENTIALS_DIRECTORY. systemd already restricts that directory to the unit.

Logs

systemd 255 (255.4-1ubuntu8.17)
Error: invalid eth keystore: /run/credentials/sponsord.service/treasury-keystore.json has insecure permissions 0o440 (must be user-only, e.g. 0o600)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions