Skip to content

feat(backups): support generic rclone destinations - #5491

Open
tokenjunkielabs wants to merge 43 commits into
Dokploy:canaryfrom
tokenjunkielabs:canary
Open

tokenjunkielabs wants to merge 43 commits into
Dokploy:canaryfrom
tokenjunkielabs:canary

Conversation

@tokenjunkielabs

@tokenjunkielabs tokenjunkielabs commented Sep 20, 2026

Copy link
Copy Markdown

/claim #416

Closes #416

Summary

  • add a Generic rclone destination mode for configured remotes such as Google Drive, OneDrive, FTP, SFTP, and other rclone backends
  • preserve every existing S3-compatible destination path while routing connection tests, database/compose/web-server/volume backup, listing, retention, and restore through one destination resolver
  • persist the rclone config path and remote root using the existing Destination model, validate both before command construction, and keep generic credential material in the rclone config rather than command arguments
  • redact secret-like rclone flags from logged command/error text

The generic mode uses a dedicated RcloneConfig provider key so Dokploy's existing Rclone S3-compatible provider keeps its current behavior.

Review follow-up

  • expose RcloneConfig as a selectable provider without replacing the existing S3 Rclone provider
  • preserve home-relative remote: and absolute remote:/ roots when joining backup paths
  • redact provider *-pass credentials from structured backup logs
  • restore bounded retry/connect/transfer limits for connection tests only
  • document that the config path and named remote must exist on each execution host

RetriggerConfidence Score: 1/5

Fix the inaccessible provider option, incorrect bare-remote path handling, and credential-log exposure before merging.

Summary

Adds a shared destination resolver for configured rclone remotes while retaining the existing S3-compatible provider path.

  • Routes connection testing, backup uploads, listing, retention, and restores through the resolver.
  • Reuses destination fields for the config path and remote root, adds conditional form behavior, and expands credential redaction.
  • Requires fixes for the missing provider option, bare-remote path semantics, and uncovered password flags. Connection-test limits and config-placement guidance also need attention.

Reviews (1) · Last reviewed commit: "chore(backups): make upload logs destina..."

Comment on lines +125 to +126
const isGenericRclone =
form.watch("provider") === RCLONE_CONFIG_PROVIDER;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Generic provider cannot be selected

The provider dropdown still renders only S3_PROVIDERS, which contains Rclone but no RcloneConfig entry. Users creating a destination therefore cannot activate the new generic-rclone fields or credential-validation behavior. Add a separately labeled option with the exact RcloneConfig value, preserving the existing Rclone S3 provider.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed on current head 8d8bcaa86e3aa8a99bcd625a05bf95efed47e21e: the provider menu now appends a dedicated RcloneConfig option after the existing S3_PROVIDERS entries, so the existing Rclone S3 provider remains unchanged while generic configured remotes are selectable.

Comment on lines +60 to +63
export const joinRclonePath = (remoteRoot: string, path = "") => {
const normalizedRoot = remoteRoot.replace(/\/+$/g, "");
const normalizedPath = path.replace(/^\/+/, "");
return normalizedPath ? `${normalizedRoot}/${normalizedPath}` : normalizedRoot;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Bare remotes change target directory

For a configured SFTP remote such as sftp:, connection testing lists the user's home directory, but joining a backup filename produces sftp:/app/file.sql.gz, targeting the filesystem root instead. Backups can fail with permission errors or be written outside the directory that was tested and initially listed. Stripping the slash from sftp:/ also loses the distinction between absolute and home-relative roots. Preserve that distinction during resolution and joining, and use the corrected joining behavior in the MySQL/PostgreSQL restore paths too.

Knowledge Base Used: Backups and restore

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed on current head 8d8bcaa86e3aa8a99bcd625a05bf95efed47e21e: normalizeRcloneRemoteRoot preserves the remote:/ absolute-root marker, while joinRclonePath now emits remote:file for home-relative bare remotes and remote:/file for absolute roots. Backup and restore callers, including MySQL/PostgreSQL, now construct paths through this shared joiner.

.replace(/(--s3-access-key-id=)"[^"]*"/g, '$1"[REDACTED]"')
.replace(/(--s3-secret-access-key=)"[^"]*"/g, '$1"[REDACTED]"');
return command.replace(
/(--(?:s3-access-key-id|s3-secret-access-key|[a-zA-Z0-9-]*(?:password|secret|token)[a-zA-Z0-9-]*)=)(?:"[^"]*"|'[^']*'|[^\s]+)/gi,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 security Password flags remain in logs

The new generic redaction misses rclone password flags such as --sftp-pass, --ftp-pass, and --webdav-pass: none contains password, secret, or token. These flags are accepted by additionalFlags and forwarded into the command, so their credential values survive redaction and enter the structured backup log even on successful backups. Cover these password-flag names, or prohibit credential overrides and require them in the config file; add regression cases for these flags.

How this was verified: An accepted --sftp-pass=credential flag flows unchanged through the generic resolver into getBackupCommand's logged rcloneCommand because the redaction expression does not match its name.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed on current head 8d8bcaa86e3aa8a99bcd625a05bf95efed47e21e: the shared redactor now covers provider-specific *-pass flags (including --sftp-pass, --ftp-pass, and --webdav-pass) in addition to password/secret/token and S3 credential flags before command or error text reaches structured logs.

Comment on lines +53 to +55
const { flags: rcloneFlags, remoteRoot } =
getRcloneDestination(input);
const rcloneCommand = `rclone ls ${rcloneFlags.join(" ")} ${quote([remoteRoot])}`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Connection tests lose timeout limits

Switching to the shared resolver drops --retries 1, --low-level-retries 1, --timeout 10s, and --contimeout 5s. Neither resolver branch restores these test-specific limits, and the execution helpers impose no command deadline. Testing an unreachable or stalled destination now uses rclone's normal retry/timeout behavior, leaving the request and loading state pending substantially longer. Apply the connection-test limits after resolving the destination, without imposing them on actual backup transfers.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed on current head 8d8bcaa86e3aa8a99bcd625a05bf95efed47e21e: testConnection appends --retries 1, --low-level-retries 1, --timeout 10s, and --contimeout 5s only to the resolved connection-test command. Transfer commands continue using the destination's normal flags.

Comment on lines +395 to +398
<FormLabel>{isGenericRclone ? "Rclone Config Path" : "Endpoint"}</FormLabel>
<FormControl>
<Input
placeholder={"https://us.bucket.aws/s3"}
placeholder={isGenericRclone ? "/etc/dokploy/rclone.conf" : "https://us.bucket.aws/s3"}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Config placement is unexplained

The new field does not explain where the config file must exist. Self-hosted connection testing reads it locally in Dokploy's execution environment, while backups and restores for remote resources read it on their resource server. If the file exists only in the local environment, a successful connection test can be followed by a failed remote backup. Add generic-mode guidance explaining that the config and named remote must be provisioned at the specified path on each relevant execution host, and clarify where connection testing runs.

Knowledge Base Used: Backups and restore

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed on current head 8d8bcaa86e3aa8a99bcd625a05bf95efed47e21e: the generic-mode config field now explains that both the config path and named remote must exist on every execution host, and distinguishes selected-server connection tests from Dokploy-local execution.

@tokenjunkielabs

Copy link
Copy Markdown
Author

Addressed the current review blockers on this bounty carrier: RcloneConfig is now selectable with execution-host config guidance; bare vs absolute rclone remote roots are preserved and MySQL/PostgreSQL restores use the shared remote-aware joiner; *-pass rclone flags are redacted; and destination connection tests retain bounded retry/timeout flags. The PR remains linked to #416 and is ready for maintainer review/merge.

@tokenjunkielabs

Copy link
Copy Markdown
Author

Carrier follow-through on #416: the remaining live Greptile selector finding is repaired on this exact PR head 0fbfd22f7e76c70ec481b8b7a4c03fe5beda1544. The duplicate RcloneConfig provider entry was collapsed to one selectable, descriptive generic-rclone option; the earlier remote-root, credential-redaction, connection-timeout, and config-placement fixes remain on the carrier. This PR still closes the fixed $50 bounty issue and is ready for maintainer review/merge.

Copy link
Copy Markdown

The current head 8d8bcaa86e3aa8a99bcd625a05bf95efed47e21e addresses all five inline findings from the review of 75cec8: dedicated RcloneConfig selection, preserved remote: vs remote:/ semantics across backup/restore joins, *-pass credential redaction, bounded connection-test-only retries/timeouts, and execution-host config guidance. I replied on each thread with the corresponding implementation location. Please re-review this head for the $50 #416 carrier.

@tokenjunkielabs

Copy link
Copy Markdown
Author

Carrier cleanup complete for #416 at head 8d8bcaa86e3aa8a99bcd625a05bf95efed47e21e: the concurrent duplicate RcloneConfig selector and duplicate execution-host guidance were collapsed, and both temporary transport workflows were removed from the PR diff. The existing generic-rclone implementation and prior review fixes remain on this same payable carrier. PR is mergeable and ready for maintainer review/merge.

Sign up for free to 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.

Ability to backup to more destination types

2 participants