Rclone mount:almost identical service files produce different auth behavior depending on unit name

Environment

  • NixOS: 25.11
  • Home Manager: 25.11
  • rclone: 1.73.5 (from nixpkgs-unstable)
  • Remote: WebDAV (Caddy server with openlist)

Problem Summary

When using Home Manager’s programs.rclone.remotes.<name>.mounts."/" (mounting the WebDAV remote at its root path), the generated systemd service fails with 401 Unauthorized.

The Authorization header only contains the username (stars:), the password is completely missing from the Base64 encoding.

However, using any other mount name (e.g., mounts."/test") works perfectly. Manual systemd units also work.


Config A (Broken)

# home.nix
{
  programs.rclone = {
    enable = true;
    remotes.nixnasoplst = {
      config = {
        type = "webdav";
        url = "https://example.com/dav";
        user = "stars";
        vendor = "other";
      };
      secrets.pass = "/path/to/secret";   # actual password file
      mounts = {
        "/" = {                              # <-- mount name is "/"
          enable = true;
          mountPoint = "/home/user/nixNAS/openlist";
        };
      };
    };
  };
}

Home Manager generates:

~/.config/systemd/user/rclone-mount:.@nixnasoplst.service

Service file content:

[Service]
Environment=PATH=/run/wrappers/bin
Environment=RCLONE_LOG_LEVEL=DEBUG
ExecStart=/nix/store/.../rclone mount --cache-dir %C/rclone --rc --vfs-cache-mode full nixnasoplst:/ /home/user/nixNAS/openlist
ExecStartPre=/nix/store/.../mkdir -p /home/user/nixNAS/openlist
Restart=on-failure
Type=notify

Debug Log (Broken Case)

From journalctl --user -u rclone-mount:.@nixnasoplst.service -f:

DEBUG : HTTP REQUEST (req 0x3c52baed4000)
DEBUG : PROPFIND /dav/ HTTP/1.1
Host: example.com
User-Agent: rclone/v1.73.5
Content-Length: 139
Authorization: Basic c3RhcnM6          # <-- decodes to "stars:" (missing password!)
Depth: 0
Referer: https://example.com/dav/
Accept-Encoding: gzip

DEBUG : HTTP/2.0 401 Unauthorized
ERROR : webdav root '': Statfs failed: 401 Unauthorized

Base64 decoding:

$ echo "c3RhcnM6" | base64 -d
stars:

The colon (:) is there, but nothing after it — the password is completely omitted.


Config B (Working — Same config, different mount name)

mounts = {
  "test" = {                              # <-- changed mount name to "test"
    enable = true;
    mountPoint = "/home/user/nixNAS/openlist";
  };
};

Generated service:

~/.config/systemd/user/rclone-mount:.test@nixnasoplst.service

Log (Working):

Authorization: Basic c3Rh******ZUg==   # <-- full credentials with password
HTTP/2.0 207 Multi-Status              # <-- success!

Manual Testing (All Work)

1. Running ExecStart command directly

/nix/store/.../rclone mount --cache-dir /home/user/.cache/rclone --dump headers,auth --poll-interval 0 --rc --retries 5 --timeout 5s --vfs-cache-mode full nixnasoplst:/ /home/user/nixNAS/openlist

:white_check_mark: Works. Full password appears in Authorization header.

2. Using systemd-run

systemd-run --user --pty rclone config show nixnasoplst

Output:

[nixnasoplst]
type = webdav
url = https://example.com/dav
user = stars
vendor = other
pass = *** ENCRYPTED ***

:white_check_mark: rclone can read the config file (~/.config/rclone/rclone.conf).

3. Writing a custom systemd unit manually

cat ~/.config/systemd/user/rclone-custom.service
[Unit]
Description=Rclone FUSE daemon for nixnasoplst:/

[Service]
Environment=PATH=/run/wrappers/bin
Environment=RCLONE_LOG_LEVEL=DEBUG
ExecStart=/nix/store/.../rclone mount --cache-dir %C/rclone --vfs-cache-mode full nixnasoplst:/ /home/user/nixNAS/openlist
ExecStartPre=/nix/store/.../mkdir -p /home/user/nixNAS/openlist
Restart=on-failure
Type=notify

[Install]
WantedBy=default.target
systemctl --user daemon-reload
systemctl --user start rclone-custom.service

:white_check_mark: Works perfectly.

What I’ve Tried (Still Fails)

Adding extra options to force config loading:

options = {
  rc = true;
  poll-interval = 0;
  retries = 5;
  timeout = "5s";
  dump = "headers,auth";
  rc-no-auth = true;
};

The service still fails with 401. The Authorization header remains Basic c3RhcnM6 (no password).


Using rclone rc to debug

rclone rc config/dump

Returns the full config with encrypted password. But the rclone still 401.TAT

$ rclone rc config/dump
{
        "nixnasoplst": {
                "pass": "1*******0",
                "type": "webdav",
                "url": "https://******.top/dav",
                "user": "stars",
                "vendor": "other"
        }
}

Hypothesis

Home Manager uses the mount name to generate the systemd service instance name:

rclone-mount:.{mountName}@{remoteName}.service

When mountName = "/":

  1. The service name becomes rclone-mount:.@nixnasoplst.service — note the empty string between . and @
  2. Something in the systemd unit generation or environment variable parsing corrupts how rclone reads the password from the config file
  3. The password is completely omitted from the Authorization header

When mountName = "/test":

  • Service name: rclone-mount:.test@nixnasoplst.service — works fine

The colon (:) in the service name might be the culprit? Or Home Manager’s escaping logic fails when the mount name contains special characters (like /).


Workaround

Use any mount name other than /:

mounts = {
  "root" = {                              # or anything except "/"
    enable = true;
    mountPoint = "/home/user/nixNAS/openlist";
  };
};

Questions

  1. Is this a bug in Home Manager’s rclone module? Specifically, when the mount name is exactly "/", the password fails to be loaded from the secrets file.

  2. Where should I look to debug this? The service file looks identical (except the mount name in arguments), but the behavior is completely different.

  3. Has anyone else experienced this? Any insight into why the mount name would affect rclone’s ability to read rclone.conf?


Broken Log

May 04 17:01:38 hklnix .rclone-wrapped[18773]: DEBUG : HTTP REQUEST (req 0x3c52baed4000)
May 04 17:01:38 hklnix .rclone-wrapped[18773]: DEBUG : PROPFIND /dav/ HTTP/1.1
                                                Host: example.com
                                                User-Agent: rclone/v1.73.5
                                                Content-Length: 139
                                                Authorization: Basic c3RhcnM6
                                                Depth: 0
                                                Referer: https://example.com/dav/
                                                Accept-Encoding: gzip
May 04 17:01:38 hklnix .rclone-wrapped[18773]: DEBUG : HTTP/2.0 401 Unauthorized
May 04 17:01:38 hklnix .rclone-wrapped[18773]: ERROR : webdav root '': Statfs failed: 401 Unauthorized

Working Log (with mount name test)

May 04 19:07:04 hklnix .rclone-wrapped[14817]: DEBUG : PROPFIND /dav/ HTTP/1.1
                                                Host: example.com
                                                User-Agent: rclone/v1.73.5
                                                Content-Length: 139
                                                Authorization: Basic c3Rh******ZUg==
                                                Depth: 0
May 04 19:07:04 hklnix .rclone-wrapped[14817]: DEBUG : HTTP/2.0 207 Multi-Status

Thanks for reading! Any help or insight would be greatly appreciated.

> translated by LLM.