Configurez la mise en ligne de fichiers et d'images vers S3

So, you want to use S3 to handle image uploads? Here’s the definitive guide, but also see Configure an S3 compatible object storage provider for uploads to see how to configure your app.yml.

S3 registration

Head over to https://aws.amazon.com/free/ and click on Create a Free Account

During the create account process, make sure you provide payment information, otherwise you won’t be able to use S3. There’s no registration fee, you will only be charged for what you use, if you exceed the AWS Free Usage Tier.

Bucket

Go to S3 and click on Create bucket, then fill out the Bucket name. Remember this name because we’ll need it for the next step.

Name of your bucket

Select a Region. You should enter the location (eg. “EU (Frankfurt)”) that is nearest to your users for better performance.

Scroll down a little until you get to the Permissions panel.

  • When you set up the permissions, make sure that you allow public ACLs, otherwise uploads will fail. Uncheck Block all public access and check the bottom two checkboxes. You’ll also have to acknowledge that your settings may make the bucket public in the warning at the top.

User creation

Creating a policy

Sign in to AWS Management Console and search for the “IAM” service to access the AWS Identity and Access Management (IAM) console which enables you to manage access to your AWS resources.

First, click Policies in the sidebar. Then, click on Create Policy and choose the JSON tab:

image

Use the following piece of code as a template for your policy document:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
               "s3:List*",
               "s3:Get*",
               "s3:AbortMultipartUpload",
               "s3:DeleteObject",
               "s3:PutObject",
               "s3:PutObjectAcl",
               "s3:PutObjectVersionAcl",
               "s3:PutLifecycleConfiguration",
               "s3:CreateBucket",
               "s3:PutBucketCORS"
      ],
      "Resource": [
        "arn:aws:s3:::=BUCKET=",
        "arn:aws:s3:::=BUCKET=/*"
      ]
    },
    {
       "Effect": "Allow",
       "Action": [
           "s3:ListAllMyBuckets",
           "s3:ListBucket"
       ],
       "Resource": "*"
    }
  ]
}

:warning: Make sure that these two lines contain the actual name of your bucket. :blush:

image

:star2: If you also intend to do S3 backups, you can include your backup bucket here too like this:

image

Then click on Review Policy and fill out the Name field. For example, you can call it s3-discourse-policy

Then click on Create Policy at the bottom.

Creating a user account

Now that you’ve created the right policy, you’re ready to create the user account. Click on the Users link on the left side of the IAM console and then the Add user button.

Type in a descriptive user name and make sure the “Programmatic access” checkbox is checked.

Setting permissions

The next step in the process is to configure the user’s permissions. Click on the button that says Next: Permissions and then click on «Attach existing policies directly»:
image

Now search for the policy name you created in the previous step (in our case it’s s3-discourse-policy). When you find it, select the checkbox and click on Next: Tags, then Next: Review, then finally Create user.

Here’s the critical step: Make sure you either download the credentials (Download .csv) or you copy and paste somewhere safe both Access key ID and Secret access key values. We will need them in the next step.

Discourse configuration

Now that you’ve properly set up S3, the final step is to configure your Discourse forum. These instructions should work, but the preferred method is to use environment variables and a CDN as described in Configure an S3 compatible object storage provider for uploads.

Make sure you’re logged in with an administrator account and go the Settings section in the admin panel.

Type in “S3” in the textbox on the right to display only the relevant settings:

You will need to:

  • Check the “enable s3 uploads” checkbox to activate the feature
  • Paste in both “Access Key Id” and “Secret Access Key” in their respective text fields
  • Enter =BUCKET= in the “s3 upload bucket” field

You need to append a prefix to the bucket name if you want to use the same bucket for uploads and backups.

Examples of valid bucket settings
  1. Different buckets

    • s3_upload_bucket: =BUCKET=
    • s3_backup_bucket: =BACKUPS=
  2. Different prefixes

    • s3_upload_bucket: =BUCKET=/uploads
    • s3_backup_bucket: =BUCKET=/backups
  3. Prefix for backups

    • s3_upload_bucket: =BUCKET=
    • s3_backup_bucket: =BUCKET=/backups

The “s3_region” setting is optional and defaults to “US East (N. Virginia)”. You should enter the location (eg. “EU (Frankfurt)”) that is nearest to your users for better performance. If you created the bucket manually, you’ll need to select the region you selected during the creation process.

Enjoy

That’s it. From now on, all your images will be uploaded to and served from S3.

Backups

Do you want store backups of your Discourse forum on S3 as well? Take a look at Configure automatic backups for Discourse.

Frequently Asked Questions

I reused the same bucket for uploads and backups and now backups aren’t working. What should I do?

Name of your bucket for backups

The easiest solution is to append a path to the s3_backup_bucket. Here’s an example of how your settings should look afterwards.

  • s3_upload_bucket: =BACKUPS=
  • s3_backup_bucket: =BACKUPS=/backups

You can use the S3 Console to move existing backups into the new folder.

Do I really need to use separate buckets for uploads and backups?

No, you don’t, but it’s usually the easiest way to set-up. Essentially you need to either use two different buckets or a prefix for the backup bucket. For example, the following combinations will work:

  1. Different buckets

    • s3_upload_bucket: =BUCKET=
    • s3_backup_bucket: =BACKUPS=
  2. Different prefixes

    • s3_upload_bucket: =BUCKET=/uploads
    • s3_backup_bucket: =BUCKET=/backups
  3. Prefix for backups (not recommended unless you previously reused the same bucket – see above question)

    • s3_upload_bucket: =BACKUPS=
    • s3_backup_bucket: =BACKUPS=/backups

I’ve enabled S3 uploads in my Discourse instance (which has been going for a while); what do I do with the existing local uploads?

To migrate your existing uploads to S3, you can do a couple of rake tasks. To perform this, you need SSH access, root permissions, and have entered the discourse app (as per Administrative Bulk Operations). Oh, and you have to set some environmental variables in app.yml. Not for the faint-hearted.

Once you have done all that you are ready for the rake tasks:

rake uploads:migrate_to_s3

Once that is done, posts that need to be rebaked will be marked accordingly and will be rebaked by a regular task. If you have resources and are in a hurry, you can issue this command (which is recommended by the above rake task):

rake posts:rebake_uncooked_posts

Once the posts are all rebaked (and the uploads are working well) you no longer need to include uploads in your backups. And as a bonus, you will be able to Restore a backup from the command line in the event of catastrophe (just keep a copy of app.yml somewhere).

One-way door

Unlike many configuration decisions in Discourse, note that using S3 is a “one-way door;” that is, a move that cannot easily be reversed. There is no safe or maintained way to move files out of S3 to be in the local uploads. In particular, the migrate_to_s3 moves more than just post images to S3; files for which there is no reverse path. (For more details, see Migrate_from_s3 problems).

Backing up your S3 assets

Using versioning, or syncing to a different region are all good strategies.

106 « J'aime »

Ce récit doit être mis à jour. Ou je ne peux pas. Après l’installation, les images sont téléchargées dans le bucket, mais je ne peux pas y accéder. Quoi que j’aie fait, cela n’a pas fonctionné. Quelqu’un a-t-il essayé cela récemment et a-t-il réussi ?

1 « J'aime »

Que se passe-t-il lorsque vous essayez d’y accéder ?

Avez-vous un CDN ?

Quel service avez-vous utilisé ?

Les images sont-elles téléchargées et les autorisations du bucket ne vous permettent-elles pas de les voir ?

Si le PM doit être mis à jour, vous devrez fournir plus d’informations sur ce que vous avez fait et ce qui se passe.

Le site est-il public ? Où

1 « J'aime »

Je suis l’explication à la lettre. J’importe des images. Cependant, les images ne sont pas accessibles. URL d’exemple : https://awssorucevap24.s3.eu-central-1.amazonaws.com/original/2X/6/62c89621b0764112e0029bc91c957dd49d75d819.jpeg

La section des autorisations ressemble à ceci :

Je n’ouvre pas l’ACL lors de l’installation du Bucket, il n’y a aucune information à ce sujet, et je n’y ai pas accès même lorsque j’ai modifié ce paramètre lors de mes précédentes tentatives.

Note supplémentaire : Il n’y a pas de paramètre « Accès programmatique » lors de la création d’un utilisateur, il était là il y a longtemps, il n’est plus là. Cela pourrait-il y être lié ? Ou pouvez-vous expliquer comment nous pouvons le faire dans le nouveau système lors de la création d’un utilisateur ?

J’ai également préparé le domaine cloudfront et cdn. Mon seul problème est que je n’ai pas accès aux fichiers. J’espère que nous pourrons trouver ce que j’ai manqué :slight_smile:

1 « J'aime »

rake uploads:migrate_to_s3
FileStore::ToS3MigrationError : Veuillez fournir les variables d’environnement suivantes : (FileStore::ToS3MigrationError)

  • DISCOURSE_S3_BUCKET
  • DISCOURSE_S3_REGION
    et soit
  • DISCOURSE_S3_ACCESS_KEY_ID
  • DISCOURSE_S3_SECRET_ACCESS_KEY
    soit
  • DISCOURSE_S3_USE_IAM_PROFILE

D’après ce que je vois, il ne s’agit ni de la clé d’accès NI du profil IAM. Dans mon cas, j’utilise le profil IAM. Des recommandations ici ?

1 « J'aime »

Je pense que vous devez définir ces données dans un fichier yml. D’abord, assurez-vous que le processus de téléchargement fonctionne, puis migrez.

Comment l’avez-vous configuré d’ailleurs ? J’ai essayé de le faire, les fichiers se téléchargeaient mais ne s’ouvraient pas dans le navigateur. Cela donnait une erreur d’accès refusé.

1 « J'aime »

Le téléchargement et l’accès en lecture publique fonctionnent correctement.

J’utilise le rôle et la politique IAM attachés à EC2. Faites-moi savoir si vous souhaitez plus de détails à ce sujet.

Ah, je pense savoir ce qui se passe dans votre cas. Vérifiez ces configurations :

Blocage de l’accès public (paramètres du compartiment)

Propriété des objets

Liste de contrôle d’accès (ACL) – C’est probablement là que se trouve l’astuce pour vous

3 « J'aime »

Je n’ai rien vu dans l’explication concernant l’activation du paramètre ACL, j’ai donc essayé de le faire sans y toucher à chaque fois.

Ce n’est plus important pour moi, je vais passer à Cloudflare R2. Cette explication sera très utile pour quelqu’un d’autre à l’avenir. Merci.

2 « J'aime »

Je ne suis pas sûr que ce soit la meilleure configuration, mais c’est ainsi que je l’ai trouvée jusqu’à présent. Je veux demander à l’@équipe de jeter un coup d’œil et de nous guider.

Est-ce la meilleure façon de la garder en sécurité et de la faire fonctionner correctement ?

2 « J'aime »

Pourriez-vous partager plus de détails à ce sujet ?

1 « J'aime »

Après quelques efforts, je suis passé à R2 (n’oublions pas les amis qui ont aidé, respect). Les fichiers assets et uploads sont publiés sur clouflare. Le seul problème est que je n’ai pas pu faire téléverser automatiquement les fichiers theme-javascripts et stylesheets vers R2. Je rechercherai ce problème quand j’aurai le temps.

1 « J'aime »

Était-ce une décision technique, une décision de coût ou les deux ?

1 « J'aime »

Le premier est technique, je n’ai pas pu installer Amazon, mais j’utilisais déjà Cloudflare, alors je me suis dit pourquoi ne pas installer le CDN à partir de là. Et puis j’ai vu que c’était une bonne décision car Cloudflare a lancé ce service pour nous, développeurs, contre les systèmes cloud S3 trop chers. N’est-ce pas très bien ?

1 « J'aime »

C’est bien. Je vais y jeter un coup d’œil plus attentivement.

Et qu’en est-il de l’intégration dans Discourse ? Comment s’est passée cette expérience ?

Utilisez-vous également Cloudflare WAF ?

1 « J'aime »

Non, je ne l’ai pas utilisé, en fait, je ne suis pas sûr d’en avoir besoin. Mais j’utilise Cloudflare “ARGO”.

2 « J'aime »

J’ai un compartiment S3 pour les téléchargements d’images avec les ACL activées et un rôle IAM correctement configuré et attribué à l’instance EC2 exécutant mon instance autonome. Cependant, les URL d’images S3 dans mes publications de test ne sont pas visibles. Je souhaite héberger des images S3 dans un compartiment qui ne peut être consulté que par les utilisateurs Discourse connectés. Pourquoi les références d’URL aux images S3 n’incluent-elles pas une URL pré-signée pour un accès approprié ? Si j’accède au fichier via la console S3 et que je demande une URL pré-signée via AWS pour une durée définie comme 10 minutes, l’image se chargera comme prévu, je sais donc que cela peut fonctionner.

1 « J'aime »

Sommes-nous sûrs que cela doit être stocké dans le fichier app.yml ?

Je l’ai fait comme ceci ;

# entrer dans l'application
cd /var/discourse
./launcher enter app

# passer les variables d'environnement avec la commande à l'exécution
DISCOURSE_S3_BUCKET=my-bucket DISCOURSE_S3_REGION=us-east-1 DISCOURSE_S3_ACCESS_KEY_ID=abcdefg DISCOURSE_S3_SECRET_ACCESS_KEY=zxywqrst rake uploads:migrate_to_s3

Je l’ai fait de cette façon car je ne voulais pas que ma clé d’accès reste dans le fichier YAML, car je la sauvegarde à divers endroits. Passer la clé secrète AWS par l’environnement est ~généralement~ un peu plus « sûr ». Je pense, non ? Je ne suis pas sûr de la durée de persistance de l’historique de défilement à l’intérieur du conteneur de l’application, je suppose qu’il est effacé après le redémarrage du conteneur.

Je voulais plutôt configurer l’accès S3 de la manière « normale » en stockant la clé d’accès AWS et la clé secrète dans le fichier ~/.aws/credentials du serveur, cependant, je ne suis pas tout à fait sûr comment cela fonctionnerait avec l’application s’exécutant à l’intérieur du conteneur.

De plus, conformément au guide ici, vous êtes instruit de simplement copier/coller les clés d’accès et secrètes dans l’interface utilisateur des paramètres d’administration de Discourse et de les enregistrer là-bas ; il ne m’est pas clair où ces clés sont stockées en backend, car les enregistrer ici ne remplit pas le fichier app.yml avec elles. Je suppose donc qu’elles sont quelque part dans la base de données Postgres ? Espérons qu’elles sont chiffrées, peut-être ?

J’espère qu’en ne stockant pas les clés d’accès et secrètes AWS dans le fichier app.yml, je n’aurai aucun problème à l’avenir ? Y a-t-il un autre processus qui nécessite que les clés y résident ?

1 « J'aime »

J’ai activé AWS Cloudfront pour un cache CDN devant mon bucket S3, configuré comme décrit ici. Cependant, la configuration de Cloudfront a nécessité des modifications des politiques d’accès S3. En particulier, il semble y avoir des politiques qui restreindraient l’accès au bucket S3 uniquement à Cloudfront, au lieu de l’accès public suggéré par ce guide. Quelqu’un peut-il examiner quelles devraient être les bonnes politiques d’autorisations du bucket S3 si vous utilisez le CDN Cloudfront avec votre bucket S3 sur Discourse ? Actuellement, mon CDN fonctionne, mais je ne suis pas sûr de devoir supprimer des autorisations d’accès superflues du bucket S3.

1 « J'aime »

J’ai utilisé la politique de bucket présentée dans le premier post de ce sujet, sur un nouveau bucket AWS. Mais aujourd’hui, elle génère une erreur de syntaxe JSON.

Erreur de politique donnée dans le post initial/1er post du sujet : Donne des erreurs "Principal manquant", "Politique non prise en charge" dans les lignes 4, 23, 26, 29, et lorsque j'arrive à corriger ces erreurs d'une manière ou d'une autre en lisant la documentation AWS, une "Erreur de syntaxe JSON" apparaît vers la fin du code.
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
               "s3:List*",
               "s3:Get*",
               "s3:AbortMultipartUpload",
               "s3:DeleteObject",
               "s3:PutObject",
               "s3:PutObjectAcl",
               "s3:PutObjectVersionAcl",
               "s3:PutLifecycleConfiguration",
               "s3:CreateBucket",
               "s3:PutBucketCORS"
      ],
      "Resource": [
        "arn:aws:s3:::your-uploads-bucket",
        "arn:aws:s3:::your-uploads-bucket/*"
      ]
    },
    {
       "Effect": "Allow",
       "Action": [
           "s3:ListAllMyBuckets",
           "s3:ListBucket"
       ],
       "Resource": "*"
    }
  ]
}
Celle que j'ai essayé de créer, qui ne montre aucune erreur de syntaxe dans la console, sauf une erreur "Principal invalide", que je n'ai pas pu surmonter #### J'ai utilisé mes propres noms de bucket
{
  "Id": "Policy1725098748430",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1725098741436",
      "Action": [
        "s3:AbortMultipartUpload",
        "s3:CreateBucket",
        "s3:DeleteObject",
        "s3:GetObject",
        "s3:List*",
        "s3:ListBucket",
        "s3:ListBucketMultipartUploads",
        "s3:PutBucketCORS",
        "s3:PutLifecycleConfiguration",
        "s3:PutObject",
        "s3:PutObjectAcl",
        "s3:PutObjectVersionAcl"
      ],
      "Effect": "Allow",
      "Resource": [
	"arn:aws:s3:::t9478010203",
	"arn:aws:s3:::t9478010203/backups/",
	"arn:aws:s3:::t9478010203/uploads/"
	],
      "Principal": {
        "AWS": [
          "123456789012"
        ]
      }
    }
  ]
}
1 « J'aime »

Ce sujet a vraiment besoin d’une mise à jour - je viens d’être dans S3/IAM en bidouillant la politique et j’ai également remarqué les erreurs. Heureusement, cela semble fonctionner correctement !

Je me demande si quelqu’un ayant les compétences et les connaissances requises voudrait bien jeter un œil et mettre à jour ce que la politique devrait être. @pfaffman ?

5 « J'aime »