=== Stowaway – Offload Media to Amazon S3 & CloudFront ===
Contributors: bsidesolution
Tags: s3, cloudfront, offload, media, cdn
Requires at least: 6.2
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Offload your Media Library to Amazon S3 and serve it through Amazon CloudFront. Free, AWS-only, with no license key and no paid tier.

== Description ==

Stowaway copies your uploads to your own Amazon S3 bucket and serves them to
visitors through Amazon CloudFront (or straight from S3). Your server stops
serving images, your pages load media from a CDN close to each visitor, and
nothing about how you use the Media Library changes.

It does one thing, AWS, and does not try to support every storage provider.
Every feature is free: there is no "Pro" version.

= What it does =

* **Offloads every upload**, and every size WordPress makes of it, as soon as it is uploaded. Edited and regenerated images go up too.
* **Serves media from CloudFront or S3**: attachment URLs, responsive `srcset` images, images in post content and page-builder shortcodes, and Yoast SEO's share images and schema.
* **Whole-page option** for themes and page builders that print images outside the post content, such as Divi's background images.
* **Offloads your existing library** in the background of one admin page, with a progress bar, or with `wp stowaway offload --all`.
* **Shows each file's status** in the Media Library, with "Offload now" and an "Offload to S3" bulk action.
* **Deletes files from the bucket** when you delete them from the Media Library.
* **Keeps your database clean**: posts keep their local media URLs, so turning delivery off, or removing the plugin, never breaks a page.
* **Keeps local copies** on your server as a safety net, or removes them to save disk space: your choice.
* **Survives AWS outages**: checks every hour that your images load from CloudFront. If AWS stops serving them (a suspended account, a deleted distribution, broken DNS), your site switches to its own copies, clears page caches and emails you, then switches back when AWS returns.
* **Never locks you in**: "Bring it all home" downloads every file back from the bucket, whenever you want.

= Set up in three steps =

A setup wizard walks you through it, starting from an empty AWS account. Each step explains what to make in the AWS console and links to a full guide with screenshots:

1. **Bucket**: create one with the settings that matter, and give Stowaway its name.
2. **Access key**: an AWS user just for your site, with a policy that lets it use that one bucket and nothing else. Stowaway checks the key with AWS, finds the bucket's region, and makes sure the key can use it. Keys can live in `wp-config.php` instead of the database.
3. **CloudFront**: put a distribution in front of the bucket and paste its domain. Or skip it for now: media keeps being served from your server, and new uploads are copied to the bucket for when you're ready.

Finishing runs a connection test that walks the whole path a real upload takes: it reaches the bucket, uploads a small file, loads it the way a visitor's browser would, and deletes it.

= Coming from WP Offload Media? =

Stowaway reads the settings and offload records WP Offload Media (Lite or Pro) left in your database, so media you offloaded with it keeps its exact URLs, with nothing uploaded again. It even uses the access keys already in your `wp-config.php` until you replace them.

Deactivate WP Offload Media, then choose **Import from WP Offload Media** on Settings → Stowaway.

= WP-CLI =

* `wp stowaway status`: what is configured, and how much is offloaded.
* `wp stowaway offload --all`: offload everything not yet in the bucket (or `wp stowaway offload 12 34` for specific attachments).
* `wp stowaway import-wpom`: import from WP Offload Media.
* `wp stowaway download --all`: bring every missing file back from the bucket.
* `wp stowaway remove-local --all`: remove local copies that are safely in the bucket (with Remove local copies on).
* `wp stowaway health`: check now that images load from CloudFront.

== Installation ==

1. Install and activate Stowaway from Plugins → Add New.
2. Go to **Settings → Stowaway** and follow the setup wizard.
3. To copy media you uploaded before installing Stowaway, use **Offload Existing Media** on the same screen.

You need an AWS account. The wizard walks you through creating the bucket, the access key and the CloudFront distribution; the full guide, with screenshots, is at [bsidesolution.com/stowaway/docs](https://bsidesolution.com/stowaway/docs/).

To keep your access keys out of the database (and out of database backups), add them to `wp-config.php` instead:

`define( 'STOWAWAY_ACCESS_KEY_ID', 'your-access-key-id' );`
`define( 'STOWAWAY_SECRET_ACCESS_KEY', 'your-secret-access-key' );`

== Frequently Asked Questions ==

= Which AWS permissions does Stowaway need? =

`s3:ListBucket` on the bucket, and `s3:PutObject` and `s3:DeleteObject` on the objects in it, and nothing else. The setup wizard shows the policy with your bucket's name already in it, ready to paste into AWS.

= Do I need CloudFront? =

No. Without it, media is served straight from S3, which only works if the bucket allows public reads. With CloudFront the bucket can stay private, and visitors get media from a server near them.

= Does Stowaway delete files from my server? =

Not unless you ask it to. By default your uploads stay on your server as well as in the bucket. To save disk space, turn on **Remove local copies** on the Safety tab: each file's local copy is then deleted once it loads from CloudFront. That trades away the safety net: during an AWS outage, images only in the bucket can't fall back to your server.

= What happens if AWS goes down? =

With monitoring on (the default), Stowaway loads a few of your images through CloudFront every hour. After two failed checks in a row, your site serves images from its own copies, page caches are cleared, and you get an email. When CloudFront works again, Stowaway switches back and emails you again. It also emails you (at most once a day) if AWS starts refusing uploads.

= How do I stop using Stowaway? =

If you removed local copies, first turn that off and use **Bring it all home** on the Safety tab (or `wp stowaway download --all`) to download every file back. Then deactivate Stowaway: posts store local URLs the whole time, so your site carries on serving media from your server.

= What happens if I deactivate or delete Stowaway? =

Your site goes back to serving media from your server. Posts store local media URLs the whole time, so nothing needs fixing, as long as the files are on your server (see "How do I stop using Stowaway?"). Files in the bucket are left alone.

= Some images still load from my server. Why? =

Stowaway rewrites media URLs in post content and wherever WordPress builds image URLs. Some themes and page builders print images elsewhere (Divi's background images, for example). Turn on **Whole page** in Settings → Stowaway to catch those too.

= Will offloading change my image URLs? =

Media you offload with Stowaway gets new URLs on your CloudFront domain, and posts keep pointing at it automatically. Media imported from WP Offload Media keeps the exact URLs it already had.

= What about staging copies of my site? =

Stowaway remembers which site the bucket was set up from. On a copy of the site (a staging site, or a clone) it keeps serving media as before, but stops uploading to and deleting from the bucket, so the copy can't overwrite or delete the real site's media. If the site really moved to a new address, one click resumes. Or give the copy its own bucket.

= Does it support other storage providers? =

No. Stowaway is for Amazon S3 and CloudFront only.

= Where do I get help? =

Send a support request from [Stowaway's website](https://bsidesolution.com/stowaway/support/). Settings → Stowaway → Support has a system report to paste into it. The [documentation](https://bsidesolution.com/stowaway/docs/) covers setup step by step, and troubleshooting.

= Does it work on Multisite? =

It hasn't been tested on Multisite yet.

== Screenshots ==

1. Setup starts from an empty AWS account: create a bucket, with the settings that matter.
2. An access key that can use that one bucket, with the policy ready to paste.
3. CloudFront in front of the bucket, so it stays private.
4. Settings, after a passing connection test.
5. Each file's offload status in the Media Library.
6. Offloading media that was uploaded before Stowaway was set up.
7. The Safety tab: outage monitoring, failover, alerts, and local copies.

== External services ==

Stowaway connects your site to Amazon Web Services (AWS), which you choose and pay for with your own AWS account. Nothing is sent anywhere until you enter your AWS access keys.

**Amazon S3** (the S3 API at `s3.<region>.amazonaws.com`) stores your media. Your site sends it:

* each file you upload to the Media Library, every size WordPress makes of it, and the file's name and folder, when the file is offloaded;
* requests to delete those files when you delete them in WordPress;
* requests to list your buckets and look up a bucket's region, when you set up or change the bucket;
* a small test file, uploaded and deleted again, when you run the connection test.

Requests are signed with your access keys; the secret key itself is never sent.

**Amazon CloudFront** (your distribution's domain, if you set one up) delivers the media to visitors. Their browsers load images and files from it, so CloudFront receives what any web server does: their IP address, browser details, and the address of the file. Your site itself also requests files from it:

* one test file, when you run the connection test;
* a few of your images once an hour, while outage monitoring is on (it is by default, and can be turned off on the Safety tab);
* files your server is missing, when you use "Bring it all home" or edit an image whose local copy was removed.

Outage and upload alerts are sent by your own site's email, to the address you choose; they don't go through any other service.

AWS's terms and privacy policy: [AWS Service Terms](https://aws.amazon.com/service-terms/), [AWS Privacy Notice](https://aws.amazon.com/privacy/).

Stowaway sends nothing to its author, and has no tracking or analytics.

== Changelog ==

= 1.0.0 =
* First release on WordPress.org.
* Setup wizard for an empty AWS account: bucket, an access key limited to that bucket, then CloudFront, each linked to a guide with screenshots.
* Offloads new uploads, edits and regenerated sizes; deletes from the bucket with the attachment.
* Serves media from CloudFront or S3, including srcset, post content, Yoast SEO share images and schema, and an optional whole-page mode for page builders.
* Divi: saving a page with an offloaded image no longer reports a failed save; Divi finds attachments behind CDN URLs.
* Safety: uploads never overwrite an object already in the bucket, and deleting an attachment leaves files another attachment still uses.
* Safety: on a staging copy or clone of the site, uploads and deletes pause until confirmed.
* Safety tab: hourly outage monitoring, automatic failover to local copies with page caches cleared, and email alerts.
* Optional removal of local copies to save disk space; images being edited are fetched back first.
* Bring it all home: download every missing file back from the bucket, from the Safety tab or `wp stowaway download --all`.
* A clearer settings screen: status cards for storage, delivery and the Media Library, and plain-language switches.
* Security: access keys are stored apart from the other settings, outside WordPress's autoloaded options; the IAM policy no longer needs s3:GetObject; data imported from WP Offload Media is validated.
* Offload existing media in the background, with a progress bar; Media Library status column, "Offload now" and bulk action.
* Import from WP Offload Media, keeping existing URLs.
* WP-CLI commands: status, offload, import-wpom.
* Support tab with a system report to copy into a support request; About tab.
