إعداد رفع الملفات والصور إلى 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 إعجابات

يجب تحديث هذه الرواية. أو لا أستطيع. بعد التثبيت، يتم تحميل الصور إلى الـ bucket، ولكن لا يمكنني الوصول إليها. لم ينجح أي شيء فعلته. هل جرب أي شخص هذا مؤخرًا ونجح في تشغيله؟

إعجاب واحد (1)

ماذا يحدث عندما تحاول الوصول إليها؟

هل لديك شبكة توصيل محتوى (CDN)؟

ما الخدمة التي استخدمتها؟

هل تم تحميل الصور ولا تسمح لك أذونات الحاوية برؤيتها؟

إذا كان يجب تحديث مدير المنتج (PM)، فستحتاج إلى تقديم المزيد من المعلومات حول ما فعلته وما يحدث.

هل الموقع عام؟ أين

إعجاب واحد (1)

أتبع الشرح بالضبط. أقوم بتحميل الصور. ومع ذلك، لا يمكن الوصول إلى الصور. عنوان URL للمثال: https://awssorucevap24.s3.eu-central-1.amazonaws.com/original/2X/6/62c89621b0764112e0029bc91c957dd49d75d819.jpeg

يبدو قسم الأذونات كالتالي:

لا أقوم بفتح ACL عند تثبيت Bucket، ولا توجد معلومات حوله، ولا يمكنني الوصول إليه حتى عندما أقوم بتغيير هذا الإعداد في محاولاتي السابقة.

ملاحظة إضافية: لا يوجد إعداد “الوصول البرنامجي” عند إنشاء مستخدم، لقد كان موجودًا منذ فترة طويلة، ولم يعد موجودًا. هل يمكن أن يكون هذا مرتبطًا به؟ أو هل يمكنك شرح كيفية القيام بذلك في النظام الجديد عند إنشاء مستخدم؟

لقد قمت أيضًا بإعداد CloudFront ونطاق CDN. مشكلتي الوحيدة هي عدم تمكني من الوصول إلى الملفات. آمل أن نتمكن من العثور على ما فاتني :slight_smile:

إعجاب واحد (1)

rake uploads:migrate_to_s3
FileStore::ToS3MigrationError: يرجى توفير متغيرات البيئة التالية: (FileStore::ToS3MigrationError)

  • DISCOURSE_S3_BUCKET
  • DISCOURSE_S3_REGION
    وإما
  • DISCOURSE_S3_ACCESS_KEY_ID
  • DISCOURSE_S3_SECRET_ACCESS_KEY
    أو
  • DISCOURSE_S3_USE_IAM_PROFILE

كما أرى، فإنه ليس مفتاح الوصول أو ملف تعريف IAM. في حالتي، أستخدم ملف تعريف IAM. أي توصية هنا؟

إعجاب واحد (1)

أعتقد أنك بحاجة إلى تعريف هذه البيانات في ملف yml. أولاً، تأكد من أن عملية التحميل تعمل ثم قم بالترحيل.

كيف قمت بتكوينها بالمناسبة؟ حاولت القيام بذلك، وتم تحميل الملفات ولكن لم يتم فتحها في المتصفح. كان يعطي خطأ رفض الوصول.

إعجاب واحد (1)

تمكين الوصول للقراءة العامة والتحميل يعمل بشكل صحيح.

أنا أستخدم دور وسياسة IAM المرفقة بـ EC2. أخبرني إذا كنت تريد المزيد من التفاصيل حول هذا.

آه، أعتقد أنني أعرف ما يحدث في حالتك. تحقق من هذه الإعدادات:

حظر الوصول العام (إعدادات الحاوية)

ملكية الكائن

قائمة التحكم في الوصول (ACL) – ربما هنا تكمن الحيلة بالنسبة لك

3 إعجابات

لم أر شيئًا في الشرح حول تشغيل إعداد ACL، لذلك حاولت القيام بذلك دون لمسه في كل مرة.

لم يعد هذا مهمًا بالنسبة لي، سأنتقل إلى cloudflare R2. سيكون هذا الشرح مفيدًا جدًا لشخص آخر في المستقبل. شكرًا.

إعجابَين (2)

لست متأكدًا مما إذا كان هذا هو أفضل تكوين، ولكنه الطريقة التي وجدتها حتى الآن. أريد أن أطلب من @team إلقاء نظرة وإرشادنا.

هل هذه هي أفضل طريقة للحفاظ عليها آمنة وتعمل بشكل صحيح؟

إعجابَين (2)

هل يمكنك مشاركة المزيد من التفاصيل حول هذا؟

إعجاب واحد (1)

بعد بعض الجهد، تحولت إلى R2 (دعونا لا ننسى الأصدقاء الذين ساعدوا، احترام). يتم نشر الملفات assets و uploads على clouflare. المشكلة الوحيدة هي أنني لم أتمكن من تحميل ملفات theme-javascripts و stylesheets تلقائيًا إلى R2. سأبحث في هذه المشكلة عندما يكون لدي وقت.

إعجاب واحد (1)

هل كان هذا قرارًا تقنيًا أم قرارًا يتعلق بالتكلفة أم كليهما؟

إعجاب واحد (1)

الأول تقني، لم أتمكن من تثبيت Amazon، لكنني كنت أستخدم Cloudflare بالفعل، لذلك فكرت لماذا لا أقوم بتثبيت CDN من هناك. وبعد ذلك رأيت أنه كان قرارًا جيدًا لأن Cloudflare أطلقت هذه الخدمة لمطورينا ضد أنظمة S3 السحابية باهظة الثمن. أليس هذا لطيفًا جدًا؟

إعجاب واحد (1)

إنه لطيف. سألقي نظرة أعمق عليه.

وماذا عن التكامل في الخطاب؟ كيف كانت تلك التجربة؟

هل تستخدم أيضًا Cloudflare WAF؟

إعجاب واحد (1)

لا، لم أستخدمه، في الواقع لست متأكدًا مما إذا كنت سأحتاجه. لكني أستخدم Cloudflare “ARGO”.

إعجابَين (2)

لديّ حاوية S3 لتحميلات الصور مع تمكين ACL ودور IAM تم تكوينه وتعيينه بشكل صحيح لمثيل EC2 الذي يشغل مثيلي المستقل. ومع ذلك، لا يمكن عرض عناوين URL لصور S3 في مشاركات الاختبار الخاصة بي. أود استضافة صور S3 في حاوية لا يمكن رؤيتها إلا من قبل مستخدمي Discourse المسجلين. لماذا لا تتضمن مراجع عناوين URL لصور S3 عنوان URL موقع مسبقًا للوصول المناسب؟ إذا قمت بالوصول إلى الملف عبر وحدة تحكم S3 وطلبت عنوان URL موقع مسبقًا عبر AWS لمدة محددة مثل 10 دقائق، فسيتم تحميل الصورة كما هو متوقع، لذا أعرف أنها يمكن أن تعمل.

إعجاب واحد (1)

هل نحن متأكدون من أنه يجب تخزينها في ملف app.yml؟

لقد فعلت ذلك بهذه الطريقة؛

# الدخول إلى التطبيق
cd /var/discourse
./launcher enter app

# تمرير متغيرات البيئة مع الأمر في وقت التشغيل
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

لقد فعلت ذلك بهذه الطريقة لأنني لم أرغب في أن تبقى مفتاح الوصول الخاص بي في ملف YAML لأنني أقوم بعمل نسخة احتياطية منه في أماكن مختلفة. تمرير مفتاح AWS السري عبر البيئة هو ~ بشكل عام ~ أكثر أمانًا قليلاً. أعتقد، صحيح؟ لست متأكدًا من مدة استمرار سجل التمرير داخل حاوية التطبيق، وأفترض أنه يتم مسحه بعد إعادة تشغيل الحاوية.

أردت بدلاً من ذلك تكوين الوصول إلى S3 بالطريقة “العادية” عن طريق تخزين مفتاح الوصول إلى AWS والمفتاح السري في ملف ~/.aws/credentials الخاص بالخادم، ومع ذلك، لست متأكدًا تمامًا من كيفية عمل ذلك مع تشغيل التطبيق داخل الحاوية.

أيضًا، وفقًا للدليل هنا، يُطلب منك نسخ ولصق مفاتيح الوصول والمفتاح السري في واجهة مستخدم إعدادات مسؤول Discourse وحفظها هناك؛ ليس من الواضح لي أين يتم تخزين هذه المفاتيح في الواجهة الخلفية، حيث أن حفظها هنا لا يملأ ملف app.yml بها. لذا أفترض أنها في قاعدة بيانات Postgres في مكان ما؟ نأمل أن تكون مشفرة، ربما؟

آمل أنه بعدم تخزين مفاتيح الوصول إلى AWS والمفتاح السري في ملف app.yml، لن أواجه أي مشاكل في المستقبل؟ هل هناك أي عملية أخرى تتطلب وجود المفاتيح هناك؟

إعجاب واحد (1)

لقد قمت بتمكين AWS Cloudfront مؤخرًا لاستخدام ذاكرة التخزين المؤقت لشبكة توصيل المحتوى (CDN) أمام حاوية S3 الخاصة بي، والتي تم إعدادها كما هو موضح هنا. ومع ذلك، فإن تكوين Cloudfront تطلب بعض التعديلات على سياسات الوصول إلى S3. على وجه الخصوص، يبدو أن هناك بعض السياسات التي تقيد الوصول إلى حاوية S3 إلى Cloudfront فقط، بدلاً من الوصول العام الذي يقترحه هذا الدليل. هل يمكن لأي شخص مراجعة سياسات أذونات حاوية S3 الصحيحة إذا كنت تستخدم شبكة توصيل المحتوى Cloudfront مع حاوية S3 الخاصة بك على Discourse؟ حاليًا، تعمل شبكة توصيل المحتوى الخاصة بي، لكنني لست متأكدًا مما إذا كنت بحاجة إلى إزالة أي أذونات وصول إضافية من حاوية S3.

إعجاب واحد (1)

لقد استخدمت سياسة الحاوية هذه الموضحة في المنشور الأول لهذا الموضوع، على حاوية AWS جديدة. ولكن في هذا اليوم، فإنها تعطي خطأ في بناء جملة Json.

السياسة التي تعطي خطأ كما هو موضح في المنشور الأول للموضوع: تعطي أخطاء "Missing Principal" و "Unsupported Policy" في الأسطر 4 و 23 و 26 و 29، وعندما أتمكن من إصلاح تلك الأخطاء بطريقة ما عن طريق قراءة وثائق AWS، ظهر "Json Syntax Error" في نهاية الكود.
{
  "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": "*"
    }
  ]
}
التي حاولت إنشائها، والتي لا تظهر أي أخطاء في بناء الجملة في وحدة التحكم، باستثناء خطأ واحد "Invalid Principal"، والذي لم أتمكن من التغلب عليه #### استخدمت أسماء الحاويات الخاصة بي
{
  "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)

تحتاج هذه المقالة حقًا إلى تحديث - لقد كنت للتو في S3/IAM أعبث بالسياسة ولاحظت الأخطاء أيضًا. يبدو أنها تعمل بشكل جيد لحسن الحظ!

أتساءل عما إذا كان شخص ما يتمتع بالمهارات والمعرفة المطلوبة سيأخذ نظرة ويحدث السياسة التي يجب أن تكون. @pfaffman؟

5 إعجابات