fix(storage): make s3 disks work with S3-compatible endpoints (RustFS, MinIO) and AWS_* env - #2
Merged
Conversation
…v helpers Moves `S3DiskConfig` verbatim from `facade.rs` into a new `rustasea_storage::s3` module, mirroring `sftp/config.rs`, so the S3 fix that follows has a home of its own. It stays re-exported from `facade` and the crate root, so existing paths keep working. `env_non_empty` moves from `sftp/config.rs` to `facade.rs`, and the `with_env` test helper (with its env lock) moves from `sftp/tests.rs` to a shared `test_support` module, ready for the S3 overlay. No behaviour change.
…s3 disks `s3` disks could not talk to an S3-compatible service in local development: - `object_store` only allows HTTPS unless `allow_http` is set, and `build_s3` never set it, so the documented `endpoint = "http://localhost:9000"` example failed every request with a reqwest builder error. An explicit `http://` endpoint (surrounding whitespace ignored) now enables `allow_http`; every other endpoint, and AWS itself, stays HTTPS-only. - `.env.example` documents that the `s3` disk reads `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_DEFAULT_REGION`, `AWS_BUCKET`, and `AWS_ENDPOINT` (the scaffolded docker-compose passes `AWS_ENDPOINT` to the app), but `StorageManager::from_toml_file` parses the file as-is and the builder used `AmazonS3Builder::new()`, so none were read and a disk without inline credentials fell back to EC2 instance metadata. `S3DiskConfig::apply_env` now overlays them onto every `s3` disk, mirroring the `SFTP_*` overlay. Like `SftpDiskConfig`, the config now redacts `secret_access_key` from `Debug` output and is validated after the overlay: `bucket` may be omitted when `AWS_BUCKET` supplies it, and a blank bucket is a `Config` error instead of a store with a malformed URL. A Docker-backed RustFS suite (`tests/rustfs_container.rs`, `#[ignore]`d like the SFTP one) reproduces both failures on the unfixed code and passes with the fix.
Forwards to `rustasea-storage/aws`, next to `storage-sftp`, so apps built on the facade crate can enable `s3` disks without depending on `rustasea-storage` directly. Documents the feature in the README feature table, the storage crate README, and `config/storage.toml`, including that the `aws` feature needs rustc 1.89+: `object_store`'s AWS backend pulls in `crc-fast` 1.10, whose MSRV is above the workspace's 1.88.
The `s3` and `sftp` disks sit behind `rustasea-storage`'s opt-in `aws` and `sftp` features, which the default workspace build never compiles, so a broken driver could not fail CI. `cargo xtask ci` now runs clippy on `rustasea-storage` with `--features aws,sftp`, and the test job runs its tests with both features. The Docker-backed RustFS and SFTP suites stay `#[ignore]`d. CONTRIBUTING and the README describe the new steps and the storage suites.
kangmaup
marked this pull request as draft
September 24, 2026 06:36
kangmaup
marked this pull request as ready for review
September 24, 2026 06:37
Contributor
Author
|
Heads-up on the red checks: none of them come from this PR, and all of them also fail on
I'll open a separate PR that fixes all three so |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
s3disks could not be used against an S3-compatible service in local development (RustFS, MinIO), and theAWS_*variables that.env.exampledocuments were never read. This PR fixes both. It also redacts the S3 secret fromDebugoutput, validates the bucket, adds a Docker-backed RustFS test suite and astorage-s3umbrella feature, and makes CI compile the opt-in storage drivers.Problems
http://endpoints always failed.object_storeenforces HTTPS unlessallow_httpis set (ClientOptionsbuilds its client withhttps_only(!allow_http)), andbuild_s3never set it. The documented example inconfig/storage.toml(endpoint = "http://localhost:9000") failed every request:AWS_*variables were ignored..env.examplesays "The app reads the S3 credentials from the AWS_* variables above when thes3disk is used", and the scaffoldeddocker-compose.ymlpassesAWS_ENDPOINTto the app. ButStorageManager::from_toml_fileparses the TOML as-is and the builder usedAmazonS3Builder::new()(notfrom_env()), so nothing was read. A disk without inline credentials fell back to EC2 instance metadata:Debug.S3DiskConfigderivedDebug, so any debug dump of the storage config printedsecret_access_key.SftpDiskConfigalready redacts its password.aws(orsftp) feature, so none of this was caught.Changes
Five commits:
refactor(storage), no behaviour change.S3DiskConfigmoves verbatim to a newrustasea_storage::s3module, mirroringsftp/config.rs, and stays re-exported fromfacadeand the crate root.env_non_emptyand thewith_envtest helper become shared.fix(storage):apply_env()overlaysAWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_DEFAULT_REGION,AWS_BUCKET, andAWS_ENDPOINTonto everys3disk. Blank values are ignored and env wins over the file, the same semantics as theSFTP_*overlay.http://endpoint (surrounding whitespace ignored) enablesallow_http. Any other endpoint, and AWS itself, stays HTTPS-only. No new config key.Debugimpl redactssecret_access_key.validate()runs after the overlay, as for SFTP.bucketmay be omitted whenAWS_BUCKETsupplies it, and a blank bucket is aStorageError::Configinstead of a store with a malformed URL.feat(rustasea): new umbrella featurestorage-s3 = ["rustasea-storage/aws"], next tostorage-sftp, plus docs.ci:cargo xtask cilintsrustasea-storage --features aws,sftp, and the test job runscargo test -p rustasea-storage --features aws,sftp. CONTRIBUTING and the README describe the new steps and the storage suites.docs: CHANGELOG.Testing
Unit tests (no network):
allow_httpper endpoint (http://,HTTP://, paddedhttp://,https://, none)Debugredactionbuild_s3applying the overlay (checked through the built disk's label)AWS_BUCKETMutation-checked: skipping
apply_envinbuild_s3, never enablingallow_http, and always enabling it each fail a test.tests/rustfs_container.rsagainstrustfs/rustfs:1.0.0,#[ignore]d like the SFTP suite. It round-trips put/get/exists/delete over a plain-HTTP endpoint twice: once with inline credentials, once with a disk that names only its driver and gets everything else fromAWS_*. Both tests fail onmasterwith the errors above and pass with this PR.Other checks:
cargo xtask ci,cargo test -p rustasea-storage --features aws,sftp,cargo +1.88.0 check --workspace,cargo deny check, andcargo auditpass locally.cargo test --workspace --no-fail-fast: 3 failures, and all three also fail onmaster(c501fdd) without this PR. They are why theTest (workspace)CI job is currently red there:artisan_alias_generates_livewire_app:crates/rustasea/tests/cli.rs:146still expectsfeatures = ["view", "broadcast"]. The scaffold has emitted["view", "action"]since ab02ac6, and the umbrella has nobroadcastfeature.routes::tests::two_factor::enable_confirm_challenge_and_recovery_lifecycle: login hits429, because the login rate limiter is a process-wide static shared across tests.tests::workers_renders_heartbeatsinrustasea-queue-dashboard.I'll send fixes for those in a separate PR.
Notes
AWS_*values now override the matching keys inconfig/storage.toml. The stock.env.examplesetsAWS_DEFAULT_REGION=us-east-1, so the region is changed there. With more than ones3disk,AWS_BUCKET/AWS_ENDPOINTwould override every disk; the docs say to leave them blank in that case. Happy to scope the overlay to a single disk if you prefer.awsfeature needs rustc 1.89.object_store's AWS backend depends oncrc-fast, and the lockfile has 1.10.0, which declaresrust-version = 1.89. This predates this PR, which only documents it.crc-fastto 1.9.0 (MSRV 1.81) is possible but also forcescrcdown to 3.3.0 undersqlx-core.Cargo.lockis unchanged. The RustFS suite sends its signedCreateBucketrequest throughobject_store's own HTTP client.temporary_url(presigned URLs),AWS_SESSION_TOKENand IRSA/ECS credential chains, and swapping the docker-composeminioservice for RustFS.