From 1d748c624dbd59d2b311b818ee20099b81a8f86f Mon Sep 17 00:00:00 2001 From: Alfred Gutierrez Date: Mon, 23 Mar 2026 15:32:08 +0900 Subject: [PATCH 1/4] bugfix(config): address issue where production environment is not uploading nor loading profile images from s3/minio. --- docker-compose.prod.yml | 1 + interview_service/settings/base.py | 1 + interview_service/settings/dev.py | 5 ++++- interview_service/settings/prod.py | 8 +++++--- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index ba16238..eef728b 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -51,6 +51,7 @@ services: /bin/sh -c " mc alias set myminio http://minio:9000 $${MINIO_ACCESS_KEY} $${MINIO_SECRET_KEY}; mc mb myminio/$${MINIO_BUCKET_NAME} --ignore-existing; + mc anonymous set public myminio/$${MINIO_BUCKET_NAME}; exit 0; " diff --git a/interview_service/settings/base.py b/interview_service/settings/base.py index 82238cb..9156490 100644 --- a/interview_service/settings/base.py +++ b/interview_service/settings/base.py @@ -18,6 +18,7 @@ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", + "storages", # Local apps "accounts", "interviewers", diff --git a/interview_service/settings/dev.py b/interview_service/settings/dev.py index 8325784..ac0d994 100644 --- a/interview_service/settings/dev.py +++ b/interview_service/settings/dev.py @@ -25,4 +25,7 @@ MIDDLEWARE += ["django_browser_reload.middleware.BrowserReloadMiddleware"] # noqa: F405 # Use local file storage in development -DEFAULT_FILE_STORAGE = "django.core.files.storage.FileSystemStorage" +STORAGES = { + "default": {"BACKEND": "django.core.files.storage.FileSystemStorage"}, + "staticfiles": {"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage"}, +} diff --git a/interview_service/settings/prod.py b/interview_service/settings/prod.py index 762a0a1..298952d 100644 --- a/interview_service/settings/prod.py +++ b/interview_service/settings/prod.py @@ -28,16 +28,18 @@ # WhiteNoise for static files MIDDLEWARE.insert(1, "whitenoise.middleware.WhiteNoiseMiddleware") # noqa: F405 -STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" # MinIO / S3 storage for media files -DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" +STORAGES = { + "default": {"BACKEND": "storages.backends.s3boto3.S3Boto3Storage"}, + "staticfiles": {"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage"}, +} AWS_ACCESS_KEY_ID = os.environ.get("MINIO_ACCESS_KEY") AWS_SECRET_ACCESS_KEY = os.environ.get("MINIO_SECRET_KEY") AWS_STORAGE_BUCKET_NAME = os.environ.get("MINIO_BUCKET_NAME", "interview-service") AWS_S3_ENDPOINT_URL = os.environ.get("MINIO_ENDPOINT_URL") +AWS_S3_CUSTOM_DOMAIN = os.environ.get("MINIO_PUBLIC_URL") AWS_S3_FILE_OVERWRITE = False -AWS_DEFAULT_ACL = None AWS_S3_SIGNATURE_VERSION = "s3v4" AWS_S3_REGION_NAME = "us-east-1" From a27438afda9482ebccb1c0550da694c0203ad0fd Mon Sep 17 00:00:00 2001 From: Alfred Gutierrez Date: Mon, 23 Mar 2026 15:47:35 +0900 Subject: [PATCH 2/4] config: add AWS_DEFAULT_ACL back in. --- interview_service/settings/prod.py | 1 + 1 file changed, 1 insertion(+) diff --git a/interview_service/settings/prod.py b/interview_service/settings/prod.py index 298952d..2668b07 100644 --- a/interview_service/settings/prod.py +++ b/interview_service/settings/prod.py @@ -40,6 +40,7 @@ AWS_S3_ENDPOINT_URL = os.environ.get("MINIO_ENDPOINT_URL") AWS_S3_CUSTOM_DOMAIN = os.environ.get("MINIO_PUBLIC_URL") AWS_S3_FILE_OVERWRITE = False +AWS_DEFAULT_ACL = "public-read" AWS_S3_SIGNATURE_VERSION = "s3v4" AWS_S3_REGION_NAME = "us-east-1" From 631290c81299fc7f28c1ea2f7a83ba443fb8fb3b Mon Sep 17 00:00:00 2001 From: Alfred Gutierrez Date: Mon, 23 Mar 2026 15:53:03 +0900 Subject: [PATCH 3/4] feat: add new MINIO_PUBLIC_URL to the example env file. --- .env.example | 1 + 1 file changed, 1 insertion(+) diff --git a/.env.example b/.env.example index fb4f039..fcf6385 100644 --- a/.env.example +++ b/.env.example @@ -15,6 +15,7 @@ MINIO_ACCESS_KEY=your-minio-access-key MINIO_SECRET_KEY=your-minio-secret-key MINIO_BUCKET_NAME=interview-service MINIO_ENDPOINT_URL=http://minio:9000 +MINIO_PUBLIC_URL=your-domain.com/interview-service # Stripe STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key From 267e49f2bb466c9806e1161dc22e0ec4f7030311 Mon Sep 17 00:00:00 2001 From: Alfred Gutierrez Date: Mon, 23 Mar 2026 16:58:02 +0900 Subject: [PATCH 4/4] feat: switch back to pre-signed urls for s3/minio storage. --- .env.example | 1 - docker-compose.prod.yml | 1 - interview_service/settings/prod.py | 3 +-- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.env.example b/.env.example index fcf6385..fb4f039 100644 --- a/.env.example +++ b/.env.example @@ -15,7 +15,6 @@ MINIO_ACCESS_KEY=your-minio-access-key MINIO_SECRET_KEY=your-minio-secret-key MINIO_BUCKET_NAME=interview-service MINIO_ENDPOINT_URL=http://minio:9000 -MINIO_PUBLIC_URL=your-domain.com/interview-service # Stripe STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index eef728b..ba16238 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -51,7 +51,6 @@ services: /bin/sh -c " mc alias set myminio http://minio:9000 $${MINIO_ACCESS_KEY} $${MINIO_SECRET_KEY}; mc mb myminio/$${MINIO_BUCKET_NAME} --ignore-existing; - mc anonymous set public myminio/$${MINIO_BUCKET_NAME}; exit 0; " diff --git a/interview_service/settings/prod.py b/interview_service/settings/prod.py index 2668b07..c2ea5a6 100644 --- a/interview_service/settings/prod.py +++ b/interview_service/settings/prod.py @@ -38,9 +38,8 @@ AWS_SECRET_ACCESS_KEY = os.environ.get("MINIO_SECRET_KEY") AWS_STORAGE_BUCKET_NAME = os.environ.get("MINIO_BUCKET_NAME", "interview-service") AWS_S3_ENDPOINT_URL = os.environ.get("MINIO_ENDPOINT_URL") -AWS_S3_CUSTOM_DOMAIN = os.environ.get("MINIO_PUBLIC_URL") AWS_S3_FILE_OVERWRITE = False -AWS_DEFAULT_ACL = "public-read" +AWS_DEFAULT_ACL = None AWS_S3_SIGNATURE_VERSION = "s3v4" AWS_S3_REGION_NAME = "us-east-1"