Use S3 Uploads in-place of Wordpress media directory
Deploy your own storage with RustRS S3 Storage Bucket Container
File Size Limits
The wordpress file size limits still apply to the upload (default is a puny 2M). Assuming that you're going through all the trouble to integrate a better storage solution you'll probably want to bump up this storage.
Increase Max Upload Size for Wordpress uploads
Plugin repo - https://github.com/humanmade/S3-Uploads
docker exec -it wp-williamusic-wordpress /bin/bash
Install S3 Uploads Plugin via Composer
# root@b082e6c9c8f4:/var/www/html
cat /etc/resolv.conf
# Generated by Docker Engine.
# This file can be edited; Docker Engine will not make further changes once it
# has been modified.
nameserver 127.0.0.11
search lan
options ndots:0
# Based on host file: '/etc/resolv.conf' (internal resolver)
# ExtServers: [host(192.168.1.2)]
# Overrides: []
# Option ndots from: internal
# root@b082e6c9c8f4:/var/www/html
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
# root@b082e6c9c8f4:/var/www/html
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
All settings correct for using Composer
Downloading...
Composer (version 2.9.7) successfully installed to: /usr/local/bin/composer
Use it: php /usr/local/bin/composer
# root@b082e6c9c8f4:/var/www/html#
php -r "unlink('composer-setup.php');"
# root@b082e6c9c8f4:/var/www/html#
cd /var/www/html/wp-content/plugins
## install plugin
# root@b082e6c9c8f4:/var/www/html/wp-content/plugins#
composer require humanmade/s3-uploads
## output
./composer.json has been created
Running composer update humanmade/s3-uploads
Loading composer repositories with package information
Updating dependencies
Lock file operations: 16 installs, 0 updates, 0 removals
- Locking aws/aws-crt-php (v1.2.7)
- Locking aws/aws-sdk-php (3.380.3)
- Locking composer/installers (v2.3.0)
- Locking guzzlehttp/guzzle (7.10.0)
- Locking guzzlehttp/promises (2.3.0)
- Locking guzzlehttp/psr7 (2.9.0)
- Locking humanmade/s3-uploads (3.0.13)
- Locking mtdowling/jmespath.php (2.8.0)
- Locking psr/http-client (1.0.3)
- Locking psr/http-factory (1.1.0)
- Locking psr/http-message (2.0)
- Locking ralouphie/getallheaders (3.0.3)
- Locking symfony/deprecation-contracts (v3.7.0)
- Locking symfony/filesystem (v7.4.9)
- Locking symfony/polyfill-ctype (v1.37.0)
- Locking symfony/polyfill-mbstring (v1.37.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 16 installs, 0 updates, 0 removals
As there is no 'unzip' nor '7z' command installed zip files are being unpacked using the PHP zip extension.
This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost.
Installing 'unzip' or '7z' (21.01+) may remediate them.
- Downloading composer/installers (v2.3.0)
- Downloading aws/aws-crt-php (v1.2.7)
- Downloading symfony/deprecation-contracts (v3.7.0)
- Downloading psr/http-message (2.0)
- Downloading psr/http-client (1.0.3)
- Downloading ralouphie/getallheaders (3.0.3)
- Downloading psr/http-factory (1.1.0)
- Downloading guzzlehttp/psr7 (2.9.0)
- Downloading guzzlehttp/promises (2.3.0)
- Downloading guzzlehttp/guzzle (7.10.0)
- Downloading symfony/polyfill-mbstring (v1.37.0)
- Downloading symfony/polyfill-ctype (v1.37.0)
- Downloading symfony/filesystem (v7.4.9)
- Downloading mtdowling/jmespath.php (2.8.0)
- Downloading aws/aws-sdk-php (3.380.3)
- Downloading humanmade/s3-uploads (3.0.13)
composer/installers contains a Composer plugin which is currently not in your allow-plugins config. See https://getcomposer.org/allow-plugins
Do you trust "composer/installers" to execute code and wish to enable it now? (writes "allow-plugins" to composer.json) [y,n,d,?] y
- Installing composer/installers (v2.3.0): Extracting archive
- Installing aws/aws-crt-php (v1.2.7): Extracting archive
- Installing symfony/deprecation-contracts (v3.7.0): Extracting archive
- Installing psr/http-message (2.0): Extracting archive
- Installing psr/http-client (1.0.3): Extracting archive
- Installing ralouphie/getallheaders (3.0.3): Extracting archive
- Installing psr/http-factory (1.1.0): Extracting archive
- Installing guzzlehttp/psr7 (2.9.0): Extracting archive
- Installing guzzlehttp/promises (2.3.0): Extracting archive
- Installing guzzlehttp/guzzle (7.10.0): Extracting archive
- Installing symfony/polyfill-mbstring (v1.37.0): Extracting archive
- Installing symfony/polyfill-ctype (v1.37.0): Extracting archive
- Installing symfony/filesystem (v7.4.9): Extracting archive
- Installing mtdowling/jmespath.php (2.8.0): Extracting archive
- Installing aws/aws-sdk-php (3.380.3): Extracting archive
- Installing humanmade/s3-uploads (3.0.13): Extracting archive
7 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
8 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found.
Using version ^3.0 for humanmade/s3-uploads
Install wp cli
# root@b082e6c9c8f4:/var/www/html#
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && \
chmod +x wp-cli.phar && \
mv wp-cli.phar /usr/local/bin/wp
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 6975k 100 6975k 0 0 35.5M 0 --:--:-- --:--:-- --:--:-- 35.6M
root@b082e6c9c8f4:/var/www/html# wp --info
OS: Linux 6.12.85+deb13-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.85-1 (2026-04-30) x86_64 Shell: PHP binary: /usr/local/bin/php PHP version: 8.2.31 php.ini used: MySQL binary: MySQL version: SQL modes: WP-CLI root dir: phar://wp-cli.phar/vendor/wp-cli/wp-cli WP-CLI vendor dir: phar://wp-cli.phar/vendor WP_CLI phar path: phar:///usr/local/bin/wp WP-CLI packages dir: WP-CLI cache dir: /root/.wp-cli/cache WP-CLI global config: WP-CLI project config: WP-CLI version: 2.12.0
root@b082e6c9c8f4:/var/www/html# wp --allow-root plugin activate s3-uploads Plugin 's3-uploads' activated.
Success:
Activated 1 of 1 plugins.
## inside container
# root@b082e6c9c8f4:/var/www/html#
mkdir -p /var/www/html/wp-content/mu-plugins
# root@b082e6c9c8f4:/var/www/html#
touch /var/www/html/wp-content/mu-plugins/s3-endpoint.php
touch /var/www/hthml/wp-config.php
wp-config.php
Add this to the end. You'll see the last line referenced for context.
/** S3-Uploader plugin */
define( 'S3_UPLOADS_BUCKET_URL', 'https://s3.YOURDOMAIN.site/YOUR_BUCKET_NAME' );
define( 'S3_UPLOADS_BUCKET', 'YOUR_BUCKET_NAME' );
define( 'S3_UPLOADS_REGION', 'us-east-2' ); // the s3 bucket region (excluding the rest of the URL)
// You can set access key and secret directly:
define( 'S3_UPLOADS_KEY', 'YOUR_USER_NAME' );
define( 'S3_UPLOADS_SECRET', 'SUPER_SCRET_PASSWORD' );
// Or if using IAM instance profiles, you can use the instance's credentials:
// define( 'S3_UPLOADS_USE_INSTANCE_PROFILE', true );
require_once __DIR__ . '/wp-content/plugins/vendor/autoload.php';
/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';
s3-endpoint.php
CORS
Make sure you're on the same protocol as the wp site (i.e. http vs https) or you will have problems
<?php
// Filter S3 Uploads params.
add_filter( 's3_uploads_s3_client_params', function ( $params ) {
$params['endpoint'] = 'https://s3.MYDOMAIN.site:9000';
$params['use_path_style_endpoint'] = true;
$params['debug'] = false; // Set to true if uploads are failing.
return $params;
} );
Upload existing media from local dir to bucket
## in wp container dir
docker compose restart
docker exec -it wp-williamusic-wordpress /bin/bash
#root@b082e6c9c8f4:/var/www/html#
wp --allow-root s3-uploads upload-directory wp-content/uploads/ uploads
Fix URLs
Idk if i needed this, but it may help you if you missed a step and converted to the wrong domain
docker exec -it wp-williamusic-wordpress /bin/bash
# root@b082e6c9c8f4:/var/www/html#
wp search-replace \
'https://MY_STORAGE_BUCKET.s3.amazonaws.com' \
'https://s3.MYDOMAIN.site:9000/MY_STORAGE_BUCKET' \
--all-tables \
--allow-root