phacility/phabricator · error · PhutilArgumentUsageException

Unable to change ownership of an identity file to daemon use

Error message

Unable to change ownership of an identity file to daemon user "%s". Run this command as %s or root.

What it means

Usage exception from `bin/almanac register`: exec_manual('chown <phd.user> <tmpfile>') returned a non-zero exit code, meaning the current user cannot change ownership of the identity temp file to the daemon user. The workflow then writes device.pub/device.key/device.id with daemon ownership, so it aborts and tells you to run as the daemon user or root.

Source

Thrown at src/applications/almanac/management/AlmanacManagementRegisterWorkflow.php:96

    if (!Filesystem::pathExists($private_key_path)) {
      throw new PhutilArgumentUsageException(
        pht('No private key exists at path "%s"!', $private_key_path));
    }

    $raw_private_key = Filesystem::readFile($private_key_path);

    $phd_user = PhabricatorEnv::getEnvConfig('phd.user');
    if (!$phd_user) {
      throw new PhutilArgumentUsageException(
        pht(
          'Config option "phd.user" is not set. You must set this option '.
          'so the private key can be stored with the correct permissions.'));
    }

    $tmp = new TempFile();
    list($err) = exec_manual('chown %s %s', $phd_user, $tmp);
    if ($err) {
      throw new PhutilArgumentUsageException(
        pht(
          'Unable to change ownership of an identity file to daemon user '.
          '"%s". Run this command as %s or root.',
          $phd_user,
          $phd_user));
    }

    $stored_public_path = AlmanacKeys::getKeyPath('device.pub');
    $stored_private_path = AlmanacKeys::getKeyPath('device.key');
    $stored_device_path = AlmanacKeys::getKeyPath('device.id');

    if (!$args->getArg('force')) {
      if (Filesystem::pathExists($stored_public_path)) {
        throw new PhutilArgumentUsageException(
          pht(
            'This host already has a registered public key ("%s"). '.
            'Remove this key before registering the host, or use '.
            '--force to overwrite it.',

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Rerun as root: sudo bin/almanac register ... (or as the phd.user account itself).
  2. Confirm phd.user spells an existing local account; fix with bin/config set phd.user <correct-user> if not.
  3. In restricted containers, run registration in an init/entrypoint step that has CAP_CHOWN, or pre-place the key files with correct ownership and skip re-registration.

Example fix

# before
$ bin/almanac register --device web-001 --private-key ./device.key
Usage Exception: Unable to change ownership of an identity file to daemon user "phd-daemon". ...

# after
$ sudo bin/almanac register --device web-001 --private-key ./device.key
Defensive patterns

Strategy: try-catch

Validate before calling

// Guard: registration needs root or the phd user to chown identity files
$u = posix_getpwuid(posix_geteuid());
$phd_user = (string)PhabricatorEnv::getEnvConfig('phd.user');
if ($u['name'] !== 'root' && $u['name'] !== $phd_user) {
  throw new RuntimeException('Run register as root or '.$phd_user);
}

Try / catch

# shell wrapper
case "$(id -un)" in
  root|$PHD_USER) exec bin/almanac register "$@" ;;
  *) echo "re-run as root or $PHD_USER" >&2; exit 1 ;;
esac

Prevention

When it happens

Trigger: Running bin/almanac register as an ordinary admin shell user; running under sudo but with a phd.user whose name is misspelled so chown fails; containerized environments where chown is restricted by capability settings.

Common situations: Operators running register from their own account out of habit; hardened/immutable images without CAP_CHOWN; the phd.user account renamed after config was written.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/7abb856691f91575. Report an issue: GitHub.