# How are you authenticating Discourse to AWS? Help us improve the settings!

**URL:** https://meta.discourse.org/t/how-are-you-authenticating-discourse-to-aws-help-us-improve-the-settings/385039
**Category:** Feature
**Tags:** s3
**Created:** [October 8, 2025, 3:16pm UTC](https://meta.discourse.org/t/how-are-you-authenticating-discourse-to-aws-help-us-improve-the-settings/385039 "2025-10-08T15:16:04Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![ducks](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ducks/32/518975_2.png) [@ducks](https://meta.discourse.org/u/ducks)
#### Post date: [October 8, 2025, 3:16pm UTC](https://meta.discourse.org/t/how-are-you-authenticating-discourse-to-aws-help-us-improve-the-settings/385039/1 "2025-10-08T15:16:04Z")

</div>

Howdy all,

We’re looking at improving how Discourse handles AWS \[1\] authentication, and we’d love to understand how you’re currently set up before making any changes.

## The Current Situation

Right now, there are a few ways to configure AWS authentication in Discourse:

### Option 1: Explicit Credentials (via site settings)

- set `s3_access_key_id` and `s3_secret_access_key` in your site settings
- authentication is per-site

### Option 2: Explicit Credentials (via environment variables)

- set the environment variables:  
`DISCOURSE_S3_ACCESS_KEY_ID`  
`DISCOURSE_S3_SECRET_ACCESS_KEY`
- authentication is the same for all sites in a multisite cluster

### Option 3: “Use IAM Profile” Setting

- enable `s3_use_iam_profile` site setting or set the environment variable `DISCOURSE_S3_USE_IAM_PROFILE=true`
- tells Discourse to let the AWS SDK find credentials automatically
- originally designed for EC2 instances and obtaining credentials via IMDS, but works in other environments

## Why we want to change

### 1. Confusing Setting Name

The `s3_use_iam_profile` setting has a misleading name. It suggests it only works with EC2 instance profiles, but it actually enables **any** AWS SDK [credential source](https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/credential-providers.html):

- EC2 instance profiles
- ECS task roles
- Environment variables
- AWS credential files
- IAM role assumption
- And more…

### 2. Security: Static Keys vs. Role Assumption

On our metal hosting platform we currently use access keys that get rotated on a regular basis. We’re aiming to switch that to role assumption for better isolation, better opportunities for access control, and to support a better internal process.

Disadvantages of the current approach:

- access keys do not expire (until rotated)
- have wide permission scopes
- can be compromised if leaked
- require manual rotation procedures

Advantages of instead using role assumption:

- persistent credentials can be restricted via IP address
- operations are done using temporary credentials that auto-expire (usually 1 hour)
- just-in-time access as credentials only exist when needed
- reduced blast radius since compromised temporary creds expire quickly
- no key rotation - the role assumption process handles refreshing
- better audit trails - each session gets tracked separately

## What We’re Considering

We’re thinking about either:

1. Rename the setting to something clearer like `aws_credentials_from_environment`
2. Remove the setting entirely and automatically detect when credentials should come from the environment vs. site settings

## We Need Your Input!

**Please let us know:**

1. **How do you authenticate with S3?**

2. **If you use `s3_use_iam_profile`:**

3. **Any concerns about changes to this setting?**

## Why This Matters

Better S3 authentication means:

- More secure - no static keys to manage
- Easier setup - especially for cloud deployments
- Less confusion - clearer settings and documentation
- Better support for modern AWS authentication patterns

Your feedback will help us make improvements that work for everyone. Thanks for taking the time to share your setup!

* * *

1. here read: any S3-compatible object storage provider you’re using

---

<div class="post-metadata">

### Author: ![Jagster](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jagster/32/192154_2.png) [@Jagster](https://meta.discourse.org/u/Jagster)
#### Post date: [October 8, 2025, 3:23pm UTC](https://meta.discourse.org/t/how-are-you-authenticating-discourse-to-aws-help-us-improve-the-settings/385039/2 "2025-10-08T15:23:32Z")

</div>

Easier to answer this way:

```plaintext
DISCOURSE_USE_S3: true
  DISCOURSE_S3_REGION: eu-north-1
  DISCOURSE_S3_ACCESS_KEY_ID: <something>
  DISCOURSE_S3_SECRET_ACCESS_KEY: <something>
  DISCOURSE_S3_CDN_URL: https://cdnfoorumi.katiska.eu
  DISCOURSE_S3_BUCKET: <something>
  DISCOURSE_S3_BACKUP_BUCKET: <something>
  DISCOURSE_BACKUP_LOCATION: s3
  S3_ORIGIN_ASSETS: https://foorumi.katiska.eu

```

Mine is _one man, one admin_ operation. So I don’t need anything fancy, but easiness has high value.

---

<div class="post-metadata">

### Author: ![nathank](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nathank/32/290039_2.png) [@nathank](https://meta.discourse.org/u/nathank)
#### Post date: [October 9, 2025, 3:32pm UTC](https://meta.discourse.org/t/how-are-you-authenticating-discourse-to-aws-help-us-improve-the-settings/385039/3 "2025-10-09T15:32:58Z")

</div>

I also use the ENV approach.

The key advantage is resilience / agility - as long as I have the app.yml, I can relaunch my site on a new server with minimal fuss. Or manipulate a staging server with ease.

Also, this tends to be something that you sort out once, when you establish a site. Or maybe perform as a one-off upgrade. So it suits ENV nicely.

Having said that, it is also helpful to have the settings available for troubleshooting without the need to rebuild; once the settings are stable, they can then be migrated to ENV settings.

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [October 9, 2025, 10:15pm UTC](https://meta.discourse.org/t/how-are-you-authenticating-discourse-to-aws-help-us-improve-the-settings/385039/4 "2025-10-09T22:15:20Z")

</div>

> [@ducks](#):
>
> when credentials should come from the environment vs. site settings

This may sound nitpicking but I think there are some important nuances here.  
The options that you provide are a mixture of HOW settings are being passed and WHAT settings are being passed.

With respect to HOW settings are being passed, two things apply:

1. the way environment variables are currently being used

The `DISCOURSE_WHATEVER` environment variables are currently used during the Docker build process to create entries in `discourse.conf` which are available as `GlobalSetting` or `SiteSetting` from within Discourse. Discourse does not perceive these environment variables as such.

1. the limitations of discourse.conf entries

Although GlobalSettings have the neat treat of being able to suppress and override SiteSettings, they also impose the limitation that in multisite enviroments they apply to all sites in the multisite.

These two combined mean that from within Discourse, SiteSetting is the most flexible. They can be actual SiteSettings, those can optionally come from `discourse.conf` and those entries can come from `DISCOURSE_` environment variables. IMO there is _no actual choice_ there, SiteSetting is the most flexible and does not have disadvantages since they’re a functional superset of the others. You can use GlobalSettings instead if you want, and those could be filled using environment variables.

That implies that the only actual choice is whether to use automatic discovery of credentials or not. In my personal perception, automatic discovery is always very prone to errors, so I would prefer to have something explicit.

I.e. have a SiteSetting that somehow points to actual, concrete, credentials.
