fix AWS S3 startup for production deployments
Docker server image / build-and-push (push) Successful in 1m7s

Pass S3_REGION and S3_PUBLIC_USE_SSL through compose, treat blank public
SSL as unset, and skip CreateBucket when IAM only allows access to an
existing bucket.
This commit is contained in:
2026-06-17 11:55:53 -07:00
parent 1756a4a0f8
commit 26cd0ef071
4 changed files with 13 additions and 6 deletions
+2
View File
@@ -24,7 +24,9 @@ services:
S3_ENDPOINT: ${S3_ENDPOINT:-seaweedfs:8333}
S3_PUBLIC_ENDPOINT: ${S3_PUBLIC_ENDPOINT:-localhost:8333}
S3_BUCKET: ${S3_BUCKET:-officeconvert}
S3_REGION: ${S3_REGION:-}
S3_USE_SSL: ${S3_USE_SSL:-false}
S3_PUBLIC_USE_SSL: ${S3_PUBLIC_USE_SSL:-}
S3_ACCESS_KEY: ${S3_ACCESS_KEY:-minioadmin}
S3_SECRET_KEY: ${S3_SECRET_KEY:-minioadmin}
S3_SESSION_TTL_SECONDS: ${S3_SESSION_TTL_SECONDS:-3600}
+2
View File
@@ -23,7 +23,9 @@ services:
S3_ENDPOINT: ${S3_ENDPOINT:-seaweedfs:8333}
S3_PUBLIC_ENDPOINT: ${S3_PUBLIC_ENDPOINT:-localhost:8333}
S3_BUCKET: ${S3_BUCKET:-officeconvert}
S3_REGION: ${S3_REGION:-}
S3_USE_SSL: ${S3_USE_SSL:-false}
S3_PUBLIC_USE_SSL: ${S3_PUBLIC_USE_SSL:-}
S3_ACCESS_KEY: ${S3_ACCESS_KEY:-minioadmin}
S3_SECRET_KEY: ${S3_SECRET_KEY:-minioadmin}
S3_SESSION_TTL_SECONDS: ${S3_SESSION_TTL_SECONDS:-3600}
@@ -31,10 +31,10 @@ class ServerConfig:
def load_server_config() -> ServerConfig:
"""Load server configuration from environment variables."""
s3_secure = os.getenv("S3_USE_SSL", "false").lower() == "true"
public_ssl_env = os.getenv("S3_PUBLIC_USE_SSL")
public_ssl_env = os.getenv("S3_PUBLIC_USE_SSL", "").strip()
s3_public_secure = (
public_ssl_env.lower() == "true"
if public_ssl_env is not None
if public_ssl_env
else s3_secure
)
region_env = os.getenv("S3_REGION", "").strip()
@@ -86,16 +86,19 @@ class S3Store:
def ensure_bucket(self, bucket_name: str) -> None:
"""Create a bucket if it does not already exist.
Uses CreateBucket only, not HeadBucket. Some S3-compatible stores
(including SeaweedFS) mishandle or over-restrict HeadBucket; the MinIO
client's bucket_exists() maps non-NoSuchBucket errors to failures.
Idempotent create covers the same contract with fewer round trips.
Tries CreateBucket first (idempotent on SeaweedFS and when the caller
owns the bucket). AWS production IAM often grants object access only on
a pre-provisioned bucket; in that case CreateBucket returns
AccessDenied even though HeadBucket succeeds.
"""
try:
self._client.make_bucket(bucket_name)
except S3Error as exc:
if exc.code in ("BucketAlreadyOwnedByYou", "BucketAlreadyExists"):
return
if exc.code in ("AccessDenied", "Forbidden"):
if self._client.bucket_exists(bucket_name):
return
raise
def presigned_put_url(self, bucket_name: str, object_key: str, *, ttl_seconds: int) -> str: