I built this plugin to solve a boring but expensive WordPress problem: the media library keeps growing, backups get heavier, and storage on the app server turns into a bottleneck.
The core idea is simple. New and existing uploads can be pushed to an external FTP, FTPS, or SFTP destination, then served from a CDN base URL without rewriting attachment data in the database. You can see the full plugin at Nexu FTP Media.
Under the hood, I treated media offload as a pipeline instead of a one-click migration. The plugin stores connection settings securely, validates the remote path, scans the library, and builds a transfer queue. For bulk moves, it supports supervised browser-based syncing with parallel uploads, plus a background-friendly workflow for longer runs. That makes large libraries less of a black box.
The part I cared about most was compatibility. In real WordPress sites, media URLs show up in attachment functions, generated image sizes, builder output, and cached page content. Instead of mutating stored content, I rewrite media URLs on output so WordPress keeps its original references while visitors get the CDN URL. That approach is safer for sites using page builders or mixed rendering paths.
I also added rule-based controls for allowed file types, max file size, retries, chunked transfers for larger files, and optional local cleanup after a successful offload. Those details matter because media automation usually fails at the edges, not in the happy path.
Operational visibility was another pain point I wanted to fix. Bulk sync includes progress tracking, resumable behavior, and monitoring screens so you can answer basic questions quickly: is the connection healthy, is the destination writable, and what is still pending.
The result is a WordPress workflow where the media library can live on infrastructure you control, while the site keeps rendering normally and serving assets from a CDN-facing URL. For me, that was the missing piece between "we need more disk" and a predictable media architecture.
Top comments (0)