Skip to content

Conversation

@cdo256
Copy link
Contributor

@cdo256 cdo256 commented Dec 13, 2025

Description

This fixes an issue where the programs.rclone activation script unconditionally overwrote rclone.conf using install. This behavior caused minor data loss for remotes that rely on dynamic state, specifically OAuth tokens (e.g., Google Drive, OneDrive), forcing users to re-authenticate after every configuration change or system reboot.

Changes:

  • Replaced the destructive install command with rclone config update.
  • This creates a "smart merge" behavior: declarative settings from Nix are enforced, but existing dynamic keys in the file (like token) are preserved.
  • Unified the static configuration and secret injection into a single loop, removing the need for pkgs.formats.ini.

Note on Drift:
This change introduces a minor trade-off: removing a setting from home.nix will no longer automatically remove it from rclone.conf (it must be manually deleted). This is necessary to preserve the authentication tokens that Nix cannot manage.

Closes #8334

Checklist

Previously, the rclone module generated a static configuration file and
used `install` to overwrite `rclone.conf` on every activation. This
behavior caused data loss for remotes that rely on dynamic state,
specifically the `token` field used by OAuth providers (e.g., Google
Drive, OneDrive) to store rotating refresh tokens. This forced users to
re-authenticate after every configuration switch.

This change updates the activation logic to use `rclone config update`.
This command safely merges the declarative configuration defined in Nix
with the existing file, ensuring that dynamic keys like `token` are
preserved while still enforcing the managed settings.

This also simplifies the implementation by removing the need for
`pkgs.formats.ini` and unifying the static configuration and secret
injection into a single loop.

Closes nix-community#8334
@jakob1379
Copy link

How come you don't use another config, as you can separate configs from secrets fairly easily

#justconfs.conf
[gdrive]
type = drive
scope = drive
team_drive =
root_folder_id =
vfs_cache_mode = writes

And then the secrets in another

#thesecrets.conf
[gdrive]
client_id = your_client_id.apps.googleusercontent.com
client_secret = your_client_secret
token = {"access_token":"ya29...","token_type":"Bearer","refresh_token":"1...","expiry":"2025-12-14T12:00:00Z"}

@ttrssreal
Copy link
Contributor

Hi, this doesn't seem to build for me. Have you tried building it?

@ttrssreal
Copy link
Contributor

How come you don't use another config, as you can separate configs from secrets fairly easily

#justconfs.conf
[gdrive]
type = drive
scope = drive
team_drive =
root_folder_id =
vfs_cache_mode = writes

And then the secrets in another

#thesecrets.conf
[gdrive]
client_id = your_client_id.apps.googleusercontent.com
client_secret = your_client_secret
token = {"access_token":"ya29...","token_type":"Bearer","refresh_token":"1...","expiry":"2025-12-14T12:00:00Z"}

How would this work? I don't think rclone supports multiple configs (yet). I might be wrong?

@cdo256
Copy link
Contributor Author

cdo256 commented Dec 18, 2025

Hi, this doesn't seem to build for me. Have you tried building it?

Hi thanks for testing it! I must apologise because I've got a lot of mental state open right now. Are you saying that the hm module doesn't build, or that the minimal example I provided doesn't build?

It did work when used as a flake input, and I could set the new options. But it's possible that I made a mistake. I'm going to have a proper look at this again at the weekend.

If you're able to share how you are testing it specifically (i.e., what command you ran), then that would be very helpful.

@jakob1379
Copy link

How come you don't use another config, as you can separate configs from secrets fairly easily

#justconfs.conf
[gdrive]
type = drive
scope = drive
team_drive =
root_folder_id =
vfs_cache_mode = writes

And then the secrets in another

#thesecrets.conf
[gdrive]
client_id = your_client_id.apps.googleusercontent.com
client_secret = your_client_secret
token = {"access_token":"ya29...","token_type":"Bearer","refresh_token":"1...","expiry":"2025-12-14T12:00:00Z"}

How would this work? I don't think rclone supports multiple configs (yet). I might be wrong?

Actually I thought you could do this, my bad. In nix, it is not hard to merge attribute sets, so using the native home-manager rclone-config is probably the way to go and then point the the secrets path to the secrets file. Not as elegant or clean :/

@ttrssreal
Copy link
Contributor

Hi, this doesn't seem to build for me. Have you tried building it?

Hi thanks for testing it! I must apologise because I've got a lot of mental state open right now. Are you saying that the hm module doesn't build, or that the minimal example I provided doesn't build?

It did work when used as a flake input, and I could set the new options. But it's possible that I made a mistake. I'm going to have a proper look at this again at the weekend.

If you're able to share how you are testing it specifically (i.e., what command you ran), then that would be very helpful.

It doesn't seem to build due to some shellcheck failures. Heres the command to run the integration tests nix build ./tests#integration-test-rclone -L --reference-lock-file flake.lock --option sandbox false.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: programs.rclone: Activation script destroys dynamic OAuth tokens

3 participants