When working with Strapi, you might start a project with one upload provider, like local filesystem storage during development, or Cloudinary in staging.
Later, you might need to switch to a different provider for production, such as AWS S3 or another cloud storage system.
Currently, Strapi does not offer a dedicated tool specifically for migrating uploads between providers.
In this post, I'll show you how to migrate your Strapi media files safely from one provider to another using Strapi’s built-in export and import system, without losing your files or breaking your media library.
This method works for:
- Local uploads ➔ AWS S3
- Cloudinary ➔ AWS S3
- AWS S3 ➔ Cloudinary
- Any upload provider ➔ Any upload provider
Let's dive in.
Why Just Moving Files Isn't Enough
In Strapi, uploaded media is split into two parts:
- The file itself (stored in your upload provider: local, S3, Cloudinary, etc.)
- The metadata (stored in Strapi's database:
upload_file
table)
Simply moving physical files to another provider is not enough.
Strapi needs the metadata, like filenames, URLs, file sizes, and related content types to display and manage your media correctly.
✅ Both the files and the database records must be migrated.
Overview of the Migration Strategy
Here’s the safe and simple way to migrate:
- Backup your entire Strapi project
- Install and configure your new upload provider (AWS S3, Cloudinary, etc.).
- Import your backup into the updated Strapi project.
- Strapi will re-upload your media into the new provider automatically during import.
Step 1: Prepare Your Strapi Project
For this guide, I'll demonstrate using a fresh Strapi project created with:
npx create-strapi-app@latest my-project
This project comes with a few demo images uploaded to the local filesystem by default.
Example media URL:
1http://localhost:1337/uploads/example-image.jpeg
Step 2: Backup Your Project
Before making any changes, create a backup using Strapi’s export feature:
yarn strapi export -f backup --no-encrypt
This creates a backup.tar.gz
file containing:
- Content entries (your articles, authors, etc.)
- Uploaded media files (assets)
- Relationships between entries (links)
✅ Important: you can use --no-encrypt
for easier migration.
Step 3: Install and Configure Your New Upload Provider
In this example, I migrated to AWS S3.
First, install the AWS S3 upload provider:
yarn add @strapi/provider-upload-aws-s3
Then, configure it inside config/plugins.ts
:
1export default ({ env }) => ({
2 upload: {
3 config: {
4 provider: "aws-s3",
5 providerOptions: {
6 baseUrl: env("CDN_URL"),
7 rootPath: env("CDN_ROOT_PATH"),
8 s3Options: {
9 credentials: {
10 accessKeyId: env("AWS_ACCESS_KEY_ID"),
11 secretAccessKey: env("AWS_ACCESS_SECRET"),
12 },
13 region: env("AWS_REGION"),
14 params: {
15 ACL: env("AWS_ACL", "public-read"),
16 signedUrlExpires: env("AWS_SIGNED_URL_EXPIRES", 15 * 60),
17 Bucket: env("AWS_BUCKET"),
18 },
19 },
20 },
21 actionOptions: {
22 upload: {},
23 uploadStream: {},
24 delete: {},
25 },
26 },
27 },
28});
Update your .env
file:
1AWS_ACCESS_KEY_ID=your-access-key-id
2AWS_ACCESS_SECRET=your-secret-key
3AWS_REGION=your-region
4AWS_BUCKET=your-bucket-name
Step 4: Update the Content Security Policy (CSP)
Strapi’s security middleware restricts external images by default.
You must allow your new provider’s domain to display images correctly inside the Admin panel.
Update config/middlewares.ts
:
1{
2 name: "strapi::security",
3 config: {
4 contentSecurityPolicy: {
5 useDefaults: true,
6 directives: {
7 "connect-src": ["'self'", "https:"],
8 "img-src": [
9 "'self'",
10 "data:",
11 "blob:",
12 "your-bucket-name.s3.your-region.amazonaws.com",
13 ],
14 "media-src": [
15 "'self'",
16 "data:",
17 "blob:",
18 "your-bucket-name.s3.your-region.amazonaws.com",
19 ],
20 "frame-src": ["'self'"],
21 upgradeInsecureRequests: null,
22 },
23 },
24 },
25}
✅ This ensures images from your new provider show properly inside Strapi Admin.
Step 5: Import Your Backup
Now, you are ready to re-import the backup:
yarn strapi import -f backup.tar.gz --force
Here’s what happens under the hood:
- Strapi wipes the existing database.
- Strapi re-creates all your entries (content-types, data).
- Media files from your backup are uploaded to your new provider automatically.
✅ You migrated both the database and your media to the new storage.
Step 6: Verify the Migration
You should now see media URLs like:
1https://your-bucket-name.s3.your-region.amazonaws.com/example-image.jpeg
✅ Media is loading correctly.
✅ No broken links inside the Admin panel.
✅ Your project is now using your new upload provider!
Common Pitfalls to Watch Out For
- AWS S3 permissions error:
➔ Make sure your bucket has proper public read access for uploaded files. - Images not showing in Admin panel:
➔ Check that your CSP (contentSecurityPolicy
) allows your new domain. - Access keys issue:
➔ Make sure.env
variables are correctly configured and match your IAM user's permissions.
Conclusion
Migrating media files in Strapi between different upload providers is simple, if you migrate both the files and the metadata together.
By:
- Backing up your project
- Changing the upload provider
- Re-importing your backup
you can cleanly switch from Local ➔ AWS S3, Cloudinary ➔ S3, or any provider ➔ any provider without breaking your project.
What's Next?
In a future post, I'll explore:
- How Strapi internally manages uploads
- How to surgically migrate only media files without resetting your database
- How to handle large media migrations at scale
Stay tuned! 🚀
Join the Strapi community: Come hang out with us during our "Open Office" hours on Discord.
We are there Monday through Friday from 12:30pm CST time.
Stop on by to chat, ask questions, or just say hi!
Bassel is a Software Developer at Strapi. He enjoys spending his time writing code and discussing software in general. He spends his free time playing chess or reading a book.