From 83a2726a30d80505419b93d2f42938d385dde481 Mon Sep 17 00:00:00 2001 From: subomi <86053854+ubmids@users.noreply.github.com> Date: Thu, 5 Nov 2026 20:07:43 +0100 Subject: [PATCH] s3: add option to disable AWS dual-stack endpoints (#22060) Co-authored-by: Michael Eischer --- changelog/unreleased/issue-5189 | 11 +++++++++++ doc/030_preparing_a_new_repo.rst | 5 +++++ internal/backend/s3/config.go | 1 + internal/backend/s3/s3.go | 6 ++++++ 4 files changed, 23 insertions(+) create mode 100644 changelog/unreleased/issue-5189 diff --git a/changelog/unreleased/issue-5189 b/changelog/unreleased/issue-5189 new file mode 100644 index 000000000..479a0f66d --- /dev/null +++ b/changelog/unreleased/issue-5189 @@ -0,0 +1,11 @@ +Enhancement: Add option to disable AWS S3 dual-stack endpoints + +Restic used dual-stack endpoints for AWS regions that have them, with no way to +opt out. VPC interface and gateway endpoints do not support dual-stack, so a +repository reachable over a VPC endpoint could not be used. + +Passing `-o s3.disable-dualstack=true` now keeps restic on the single-stack +endpoint. + +https://github.com/restic/restic/issues/5189 +https://github.com/restic/restic/pull/22060 diff --git a/doc/030_preparing_a_new_repo.rst b/doc/030_preparing_a_new_repo.rst index e5d26748a..37edb00fe 100644 --- a/doc/030_preparing_a_new_repo.rst +++ b/doc/030_preparing_a_new_repo.rst @@ -308,6 +308,11 @@ To select between path-style and virtual-hosted access, the extended option - ``dns``: Use virtual-hosted-style bucket access - ``path``: Use path-style bucket access +Amazon's dual-stack endpoints are used by default for AWS regions that have +them. VPC interface and gateway endpoints do not support dual-stack, so if +restic cannot reach your bucket from inside a VPC, pass +``-o s3.disable-dualstack=true``. + Certain S3-compatible servers do not properly implement the ``ListObjectsV2`` API, most notably Ceph versions before v14.2.5. On these backends, as a temporary workaround, you can provide the ``-o s3.list-objects-v1=true`` option to use the diff --git a/internal/backend/s3/config.go b/internal/backend/s3/config.go index 5d3d7a879..c61b0fcd1 100644 --- a/internal/backend/s3/config.go +++ b/internal/backend/s3/config.go @@ -32,6 +32,7 @@ type Config struct { Region string `option:"region" help:"set region"` BucketLookup string `option:"bucket-lookup" help:"bucket lookup style: 'auto', 'dns', or 'path'"` ListObjectsV1 bool `option:"list-objects-v1" help:"use deprecated V1 api for ListObjects calls"` + DisableDualstack bool `option:"disable-dualstack" help:"do not use AWS S3 dual-stack endpoints, which VPC endpoints do not support"` UnsafeAnonymousAuth bool `option:"unsafe-anonymous-auth" help:"use anonymous authentication"` // For testing only diff --git a/internal/backend/s3/s3.go b/internal/backend/s3/s3.go index 177503395..b56c337d9 100644 --- a/internal/backend/s3/s3.go +++ b/internal/backend/s3/s3.go @@ -89,6 +89,12 @@ func open(cfg Config, rt http.RoundTripper) (*s3, error) { return nil, errors.Wrap(err, "minio.New") } + if cfg.DisableDualstack { + // VPC interface and gateway endpoints have no dual-stack support, so + // resolving to one makes the bucket unreachable from within the VPC + client.SetS3EnableDualstack(false) + } + be := &s3{ client: client, cfg: cfg,