Einrichtung des Hochladens von Dateien und Bildern zu 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 „Gefällt mir“

Diese Erzählung muss aktualisiert werden. Oder ich kann nicht. Nach der Installation werden die Bilder in den Bucket hochgeladen, aber ich kann nicht darauf zugreifen. Egal was ich getan habe, es hat nicht funktioniert. Hat das jemand in letzter Zeit versucht und es zum Laufen gebracht?

1 „Gefällt mir“

Was passiert, wenn du versuchst, darauf zuzugreifen?

Hast du ein CDN?

Welchen Dienst hast du genutzt?

Sind die Bilder hochgeladen und die Bucket-Berechtigungen erlauben dir nicht, sie zu sehen?

Wenn die PM aktualisiert werden muss, musst du mehr Informationen darüber geben, was du getan hast und was passiert.

Ist die Seite öffentlich? Wo

1 „Gefällt mir“

Ich befolge die Erklärung genau. Bilder hochladen. Die Bilder sind jedoch nicht zugänglich. Beispiel-URL: https://awssorucevap24.s3.eu-central-1.amazonaws.com/original/2X/6/62c89621b0764112e0029bc91c957dd49d75d819.jpeg

Der Berechtigungsbereich sieht wie folgt aus:

Ich öffne die ACL nicht, wenn ich Bucket installiere, es gibt keine Informationen darüber und ich kann nicht darauf zugreifen, selbst wenn ich diese Einstellung bei früheren Versuchen ändere.

Zusätzlicher Hinweis: Beim Erstellen eines Benutzers gibt es keine Einstellung für „Programmatischer Zugriff“, diese gab es früher, sie ist jetzt nicht mehr vorhanden. Könnte das damit zusammenhängen? Oder können Sie erklären, wie wir dies im neuen System beim Erstellen eines Benutzers tun können?

Ich habe auch die Cloudfront- und CDN-Domain vorbereitet. Mein einziges Problem ist, dass ich keinen Zugriff auf die Dateien habe. Ich hoffe, wir können herausfinden, was ich übersehen habe :slight_smile:

1 „Gefällt mir“

rake uploads:migrate_to_s3
FileStore::ToS3MigrationError: Bitte geben Sie die folgenden Umgebungsvariablen an: (FileStore::ToS3MigrationError)

  • DISCOURSE_S3_BUCKET
  • DISCOURSE_S3_REGION
    und entweder
  • DISCOURSE_S3_ACCESS_KEY_ID
  • DISCOURSE_S3_SECRET_ACCESS_KEY
    oder
  • DISCOURSE_S3_USE_IAM_PROFILE

Wie ich sehe, ist es weder der Access Key NOCH das IAM-Profil. In meinem Fall verwende ich ein IAM-Profil. Irgendwelche Empfehlungen hier?

1 „Gefällt mir“

Ich glaube, Sie müssen diese Daten in einer YAML-Datei definieren. Stellen Sie zuerst sicher, dass der Upload-Prozess funktioniert, und migrieren Sie dann.

Wie haben Sie es übrigens konfiguriert? Ich habe versucht, dies zu tun, die Dateien wurden hochgeladen, aber sie ließen sich nicht im Browser öffnen. Es gab einen Zugriffsverweigerungsfehler.

1 „Gefällt mir“

Der Upload und der öffentliche Lesezugriff funktionieren korrekt.

Ich verwende die IAM-Rolle und -Richtlinie, die an EC2 angehängt sind. Lassen Sie mich wissen, ob Sie weitere Details dazu wünschen.

Ah, ich glaube, ich weiß, was in Ihrem Fall los ist. Überprüfen Sie diese Konfigurationen:

Öffentlichen Zugriff blockieren (Bucket-Einstellungen)

Objekteigentümerschaft

Zugriffskontrollliste (ACL) – Wahrscheinlich ist hier der Trick für Sie

3 „Gefällt mir“

Ich habe in der Erklärung nichts darüber gesehen, wie die ACL-Einstellung aktiviert wird, daher habe ich versucht, dies jedes Mal zu tun, ohne sie anzufassen.

Für mich ist das nicht mehr wichtig, ich wechsle zu Cloudflare R2. Diese Erklärung wird für jemand anderen in Zukunft sehr nützlich sein. Danke.

2 „Gefällt mir“

Ich bin mir nicht sicher, ob dies die beste Konfiguration ist, aber so habe ich sie bisher gefunden. Ich möchte das @team bitten, sich das anzusehen und uns zu leiten.

Ist dies der beste Weg, um es sicher und korrekt funktionsfähig zu halten?

2 „Gefällt mir“

Könnten Sie mehr Details dazu mitteilen?

1 „Gefällt mir“

Nach einigem Aufwand bin ich zu R2 gewechselt (vergessen wir nicht die Freunde, die geholfen haben, Respekt). Assets und Upload-Dateien werden auf Cloudflare veröffentlicht. Das einzige Problem ist, dass ich die theme-javascripts und stylesheets-Dateien nicht automatisch auf R2 hochladen konnte. Ich werde dieses Problem recherchieren, wenn ich Zeit habe.

1 „Gefällt mir“

War das eine technische oder eine Kostenentscheidung oder beides?

1 „Gefällt mir“

Der erste ist technisch, ich konnte Amazon nicht installieren, aber ich benutzte bereits Cloudflare, also dachte ich, warum nicht CDN von dort installieren. Und dann sah ich, dass es eine gute Entscheidung war, weil Cloudflare diesen Dienst für uns Entwickler gegen die überteuerten S3-Cloud-Systeme eingeführt hat. Ist das nicht sehr nett?

1 „Gefällt mir“

Das ist schön. Ich werde es mir genauer ansehen.

Und wie sieht es mit der Integration in Discourse aus? Wie war diese Erfahrung?

Verwenden Sie auch Cloudflare WAF?

1 „Gefällt mir“

Nein, das habe ich nicht, tatsächlich bin ich mir nicht sicher, ob ich es brauchen werde. Aber ich benutze Cloudflare „ARGO“.

2 „Gefällt mir“

Ich habe einen S3-Bucket für Bild-Uploads mit aktivierter ACL und eine IAM-Rolle, die ordnungsgemäß konfiguriert und der EC2-Instanz zugewiesen ist, auf der meine eigenständige Instanz ausgeführt wird. Die S3-Bild-URLs in meinen Testbeiträgen sind jedoch nicht sichtbar. Ich möchte S3-Bilder in einem Bucket hosten, der nur von angemeldeten Discourse-Benutzern angezeigt werden kann. Warum enthalten URL-Referenzen zu S3-Bildern keine vorab signierte URL für den ordnungsgemäßen Zugriff? Wenn ich über die S3-Konsole auf die Datei zugreife und eine vorab signierte URL über AWS für einen definierten Zeitraum wie 10 Minuten anfordere, wird das Bild wie erwartet geladen, sodass ich weiß, dass es funktionieren kann.

1 „Gefällt mir“

Sind wir sicher, dass es in der Datei app.yml gespeichert werden muss?

Ich habe es so gemacht;

# Betreten Sie die App
cd /var/discourse
./launcher enter app

# Übergeben Sie die Umgebungsvariablen mit dem Befehl zur Laufzeit
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

Ich habe es auf diese Weise gemacht, da ich nicht wollte, dass mein Zugriffsschlüssel in der YAML-Datei verbleibt, da ich diese an verschiedenen Stellen sichere. Die Übergabe des AWS-Geheimschlüssels über die Umgebung ist ~im Allgemeinen~ etwas „sicherer“. Ich denke, oder? Ich bin mir nicht sicher, wie lange der Scrollback-Verlauf im App-Container bestehen bleibt, ich vermute, er wird nach einem Neustart des Containers gelöscht.

Ich wollte stattdessen den S3-Zugriff auf die „normale“ Weise konfigurieren, indem ich den AWS-Zugriffsschlüssel und den Geheimschlüssel in der Datei ~/.aws/credentials des Servers speichere. Ich bin mir jedoch nicht ganz sicher, wie das mit der App, die im Container läuft, funktionieren würde.

Auch gemäß der Anleitung hier werden Sie angewiesen, die Zugriffs- und Geheimschlüssel einfach in die Discourse Admin Settings-Weboberfläche zu kopieren und dort zu speichern. Es ist mir nicht klar, wo diese Schlüssel im Backend gespeichert werden, da sie nach dem Speichern hier nicht in die Datei app.yml eingetragen werden. Ich vermute also, sie sind irgendwo in der Postgres-Datenbank? Hoffentlich verschlüsselt, vielleicht?

Ich hoffe, dass ich durch die Nichtspeicherung der AWS-Zugriffs- und Geheimschlüssel in der app.yml in Zukunft keine Probleme haben werde? Gibt es einen anderen Prozess, der erfordert, dass die Schlüssel dort leben?

1 „Gefällt mir“

Ich habe AWS Cloudfront für einen CDN-Cache vor meinem S3-Bucket aktiviert, der hier beschrieben wurde. Die Konfiguration von Cloudfront erforderte jedoch einige Änderungen an den S3-Zugriffsrichtlinien. Insbesondere scheint es einige Richtlinien zu geben, die den S3-Bucket-Zugriff nur auf Cloudfront beschränken würden, anstatt auf den öffentlichen Zugriff, den diese Anleitung vorschlägt. Kann jemand überprüfen, wie die richtigen S3-Bucket-Berechtigungsrichtlinien aussehen sollten, wenn Sie Cloudfront CDN mit Ihrem S3-Bucket in Discourse verwenden? Derzeit funktioniert mein CDN, aber ich bin mir nicht sicher, ob ich überflüssige Zugriffsberechtigungen aus dem S3-Bucket entfernen muss.

1 „Gefällt mir“

Ich habe die Bucket-Richtlinie, die im ersten Beitrag dieses Themas gezeigt wurde, für einen neuen AWS-Bucket verwendet. Aber heutzutage gibt es einen JSON-Syntaxfehler.

Fehler bei der Richtlinie im OP/1. Beitrag des Themas: Gibt "Missing Principal", "Unsupported Policy" Fehler in Zeile 4, 23, 26, 29, und wenn ich diese Fehler irgendwie beheben kann, indem ich die AWS-Dokumentation lese, dann taucht am Ende des Codes ein "Json Syntax Error" auf.
{
  "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": "*"
    }
  ]
}
Die, die ich versucht habe zu erstellen, die keine Syntaxfehler in der Konsole anzeigt, außer einem "Invalid Principal" Fehler, den ich nicht überwinden konnte #### Eigene Bucket-Namen verwendet
{
  "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 „Gefällt mir“

Dieses Thema muss wirklich aufgefrischt werden – ich habe gerade in S3/IAM mit der Richtlinie herumgespielt und die Fehler bemerkt. Glücklicherweise scheint es zu funktionieren!

Ich frage mich, ob jemand mit den erforderlichen Fähigkeiten und Kenntnissen es sich ansehen und aktualisieren könnte, wie die Richtlinie sein sollte. @pfaffman?

5 „Gefällt mir“