Skip to content

config: add optional s3 storage_class and sftp host-key validation params#122

Merged
mbertschler merged 4 commits into
offload-v1from
config-gaps
Jun 11, 2026
Merged

config: add optional s3 storage_class and sftp host-key validation params#122
mbertschler merged 4 commits into
offload-v1from
config-gaps

Conversation

@mbertschler

Copy link
Copy Markdown
Owner

Adds two optional, backward-compatible per-destination params that surfaced while drafting a deployment config. Both are generic rclone capabilities expressed as such — no provider-specific behavior is baked in.

What

  • s3 storage_class — maps to rclone's s3 storage_class config key. Accepts whatever value the backend supports (commonly STANDARD and archive tiers such as GLACIER / DEEP_ARCHIVE); absent, the backend default applies. Rendered verbatim into the s3 rclone.conf section when set.
  • sftp host-key validationknown_hosts_file and host_key_algorithms, mapping to the rclone sftp options of the same name. Rendered into the sftp section when set.

Security rationale (host-key validation)

squirrel's sftp destinations currently connect with no host-key validation — rclone accepts whatever host key the server presents, so a redirected or impersonated server is not detected. Pointing rclone at a known_hosts_file is what turns on server host-key validation; host_key_algorithms additionally pins the accepted algorithms. The param is optional and backward-compatible (absent → today's behavior), and the README recommends setting known_hosts_file.

How it's wired

All three are plain optionalString passthroughs in the existing destSchema (config/destinations.go). The schema is flat per backend type, and the existing strict unknown-field check confines each param to the right type for free: storage_class only on s3, known_hosts_file / host_key_algorithms only on sftp — anything else is rejected as an unknown field at load time. RcloneSection already renders every optionalString key verbatim into the section, so no rendering code changed.

Tests

  • config: storage_class parses + renders into the s3 section; rejected on a non-s3 (sftp) destination as an unknown field.
  • config: known_hosts_file + host_key_algorithms parse + render into the sftp section; known_hosts_file rejected on a non-sftp (s3) destination.
  • sync: end-to-end WriteRcloneConfig tests confirming both reach the written rclone.conf.
  • Existing config/rclone golden tests stay green; go vet ./..., go test ./..., golangci-lint run all clean.

Judgment calls

  • Reused the existing per-type restriction (unknown-field check) rather than adding a new per-type validation mechanism — storage_class / known_hosts_file are simply listed under the one type's optionalString, matching how region/endpoint/key_file already work. No new code path.
  • No migration (config-only change, as scoped).
  • Included host_key_algorithms alongside known_hosts_file since it is the natural companion sftp host-key option, but the security-relevant one is known_hosts_file (it is what enables validation).

…rams

s3 storage_class passes through to rclone's s3 storage_class config key
(backend-specific values). sftp known_hosts_file and host_key_algorithms
map to the rclone sftp options of the same name; pointing rclone at a
known_hosts file is what enables server host-key validation, which sftp
destinations otherwise skip. All three are optionalString passthroughs
confined to their backend type by the existing unknown-field check.
End-to-end WriteRcloneConfig tests confirming the new optional params
land in the written rclone.conf.
Note that sftp destinations skip host-key validation unless known_hosts_file
is set, and recommend setting it.
Copilot AI review requested due to automatic review settings June 11, 2026 03:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR extends the destination config schema to allow passing through additional rclone backend options on a per-destination basis, specifically adding optional parameters for S3 storage class selection and SFTP host-key verification-related settings. It also updates documentation and adds tests to ensure these parameters parse and render into the generated rclone.conf.

Changes:

  • Add optional storage_class passthrough for s3 destinations.
  • Add optional known_hosts_file and host_key_algorithms passthroughs for sftp destinations.
  • Add/extend config + sync tests and README documentation for the new parameters.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 10 comments.

File Description
config/destinations.go Extends per-type schema optional string params for s3 and sftp.
config/config_test.go Adds parsing/unknown-field tests for the new destination params.
sync/rclone_test.go Adds end-to-end WriteRcloneConfig tests ensuring params reach rclone.conf.
README.md Documents the new optional destination parameters with configuration examples.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.md

Some optional params are specific to one backend type and rejected on the others (as an unknown field):

- **`sftp` host-key validation** — `known_hosts_file` points rclone at a known_hosts file so it validates the server's host key before transferring; `host_key_algorithms` is rclone's space-separated list pinning the accepted host-key algorithms. Both map to the rclone sftp options of the same name. **Without `known_hosts_file`, rclone does not validate the server's host key** and will connect to whatever host answers — set it (recommended) so a redirected or impersonated server is rejected.
Comment thread README.md
user = "martin"
password = { env = "NAS_PASSWORD" }
root = "/volume1/squirrel"
known_hosts_file = "~/.ssh/known_hosts" # validate the server host key (recommended)
Comment thread config/destinations.go
Comment on lines +46 to +51
// known_hosts_file points rclone at a known_hosts file so it
// validates the server's host key before transferring; absent, rclone
// accepts whatever host key the server presents. host_key_algorithms
// pins the accepted host-key algorithms (rclone's space-separated
// list). Both map straight to the rclone sftp options of the same
// name. The unknown-field check confines them to this type.
Comment thread config/config_test.go
Comment on lines +450 to +454
// TestLoadDestinationSFTPHostKeyValidation parses the optional sftp
// known_hosts_file and host_key_algorithms params and confirms both render
// verbatim into the sftp section. Pointing rclone at a known_hosts file is
// what turns on server host-key validation; absent, rclone accepts any host
// key the server presents.
Comment thread config/config_test.go
user = "u"
root = "/r"
password = "p"
known_hosts_file = "~/.ssh/known_hosts"
Comment thread config/config_test.go
Comment on lines +471 to +473
if d.Params["known_hosts_file"] != "~/.ssh/known_hosts" {
t.Fatalf("known_hosts_file not resolved: %v", d.Params)
}
Comment thread config/config_test.go
Comment on lines +478 to +481
for _, want := range []string{
"known_hosts_file = ~/.ssh/known_hosts",
"host_key_algorithms = ssh-ed25519 ssh-rsa",
} {
Comment thread sync/rclone_test.go
Comment on lines +162 to +165
// TestWriteRcloneConfigRendersSFTPHostKeyValidation confirms the optional
// sftp host-key params reach the written rclone.conf: known_hosts_file is
// what enables server host-key validation, and host_key_algorithms pins the
// accepted algorithms. Absent these, rclone does no host-key validation.
Comment thread sync/rclone_test.go
user = "martin"
root = "/data"
password = "p"
known_hosts_file = "~/.ssh/known_hosts"
Comment thread sync/rclone_test.go
Comment on lines +183 to +186
for _, want := range []string{
"known_hosts_file = ~/.ssh/known_hosts",
"host_key_algorithms = ssh-ed25519 ssh-rsa",
} {
@mbertschler mbertschler merged commit f4274a2 into offload-v1 Jun 11, 2026
2 checks passed
@mbertschler mbertschler deleted the config-gaps branch June 11, 2026 03:55
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.

2 participants