Moodle file storage on S3 and Azure with objectfs

Moving Moodle file storage to Amazon S3 or Azure Blob Storage with the Object storage file system plugin lowers local storage load and lets sites share files across instances. Confirm your Moodle version is supported by the plugin before you plan the move.

On this page

How Moodle file storage on S3 and Azure works with objectfs

Moodle administrators usually look at object storage when course files outgrow the local disks of their web and database servers. The Object storage file system plugin, tool_objectfs, is the method this page covers. It is maintained by Catalyst IT and supports Amazon S3 and Azure Blob Storage. Sites use it to offload large files from the Moodle file store, deduplicate content across Moodle instances and speed up environment refreshes when a staging copy is built from production. Keep one point in view from the start: tool_objectfs is a file system plugin, not a Moodle core feature. Its compatibility and upgrades follow the plugin's own maintenance, so they do not move in step with Moodle HQ's release cycle alone.

This page explains the supported method, the prerequisites, the setup order, how Moodle file records map to objects in a bucket or container, the security controls around storage credentials, how to test the result and where deployments tend to fail. Start with version support. The plugin directory listing shows support for Moodle 2.7 to 4.5. If your site runs a newer release, such as a 5.x version listed in the Moodle release notes, confirm in writing with Catalyst IT or in the plugin's current listing that a build exists for your exact Moodle version before you plan the work. A version mismatch found after a production upgrade is far more expensive to fix than one found during planning.

Several decisions come before any configuration. Decide which AWS account or Azure subscription will hold the objects, and confirm that it sits in infrastructure your organization controls and that its region meets your data residency rules. Decide who owns the access keys, how they are issued and how they are rotated. Decide whether the bucket or container is private with no public read access, and whether the existing moodledata directory stays in place as a fallback during cutover. Cloud costs recur: the provider bills for stored capacity, requests and data transfer out of the cloud, so the storage model should be sized against your actual file volumes and refresh frequency.

When you request a quote, ask for the scope in writing: the Moodle and plugin versions covered, the cloud accounts and networks involved, the cutover and rollback steps, the testing evidence delivered, and who restores backups if the object store is lost. Plan for the known failure points: credentials that expire or are rotated without updating Moodle, web nodes that cannot reach the storage endpoint, and backups that capture the database but not the offloaded objects. Each of these is easier to design out before go-live than to diagnose during a live class.

What your Moodle version and storage account must support first

Check these items before you plan the migration, because each one can change the design or the schedule. Confirm the plugin version first, since it decides whether the rest of the plan applies to your site. Then confirm the server, database, storage and network requirements for your target Moodle release.

Plugin compatibility for your Moodle version

The Object storage file system plugin (tool_objectfs) lists support for Moodle 2.7 to 4.5 in the plugins directory, while Moodle 5.1 and 5.3 are current releases. Confirm that your exact Moodle version is supported on the plugin page and with Catalyst IT before you size the project. If your site runs a version outside the listed range, treat compatibility as an open question that must be answered in writing before planning starts.

Moodle 5.1 web root change

From Moodle 5.1, the web server document root must point to the /public directory instead of the main Moodle folder. If it does not, the site can show directory listings or errors, and a storage cutover may look like a plugin fault. Identify every web server, reverse proxy and container image that serves Moodle, and plan this change in staging before the storage migration begins.

Database and PHP versions for the target release

Moodle 5.1 requires 64-bit PHP 8.2 or later and supports PostgreSQL 15, MySQL 8.4, MariaDB 10.11 or SQL Server 2017 or later. Moodle 5.3 requires 64-bit PHP 8.3 or later and supports PostgreSQL 17, MySQL 8.4, MariaDB 11.4 or SQL Server 2019 or later. Sites must run Moodle 4.2.3 or later to upgrade to 5.1, and Moodle 4.4 or later to upgrade to 5.3. Compare your current versions with the target release before you schedule any upgrade.

Bucket or container with scoped credentials

Object storage needs a bucket on Amazon S3 or a container in Azure Blob Storage, created for this Moodle site. Create credentials that can access only that location, and record who rotates them and where they are stored. Decide the region, retention and lifecycle settings before the first file is copied, because changing them later can mean moving data again.

Network paths to the storage endpoint

Both the web servers and the cron servers must reach the storage endpoint, because file requests and scheduled background tasks both read and write objects. Confirm outbound routes, DNS resolution, TLS trust and any proxy or firewall rules from every node that runs Moodle, including the cron host. Run the connection test from each server using the same credentials the site will use.

How to configure objectfs in the right order

This sequence moves Moodle file storage from the local filedir to Amazon S3 or Azure Blob Storage while keeping a working copy at every stage. Each step ends with a check, so the team confirms what passed before the next step starts. Versions and plugin support come first because they shape every later decision.

  1. Confirm Moodle and PHP versions first

    The Moodle administrator records the current Moodle release, PHP version and database version, then checks each against the release notes for the target Moodle release. The plugin's directory listing shows support for Moodle 2.7 to 4.5, so confirm with the plugin maintainer, Catalyst IT, which plugin version supports your Moodle release before you go further. On Moodle 5.1 or later, confirm the web server document root points to the /public directory. The step is done when a written compatibility record lists every version and the plugin release chosen for it.

  2. Back up the database and filedir

    The Moodle administrator takes a complete backup of the database and the filedir, the directory where Moodle stores uploaded files, so both describe the same point in time. Store the backup in a location the migration cannot change, then restore it into a scratch environment to prove it works. Compare the file count and total size of the restored filedir with the source. The step is done when the restore completes and the scratch site opens a sample course with its files intact.

  3. Create the bucket and a least-privilege identity

    The cloud or storage administrator creates the S3 bucket or Azure Blob container in a region that meets your data residency rules. They then create an identity that can reach only that bucket or container, grant only the object actions the plugin needs, and store the access keys in your secrets manager. Confirm the scope with a test upload that succeeds and a request to a neighboring bucket that is denied. The step is done when both results match the expected outcome.

  4. Install the plugin on a staging copy

    The Moodle administrator copies the production code and a recent database snapshot into a staging environment that matches production's PHP, database and web server settings. They install the object storage plugin through the standard Moodle plugin installation, complete the upgrade, and review the checks on the site administration pages. They confirm the staging site loads, logs in and serves a course page before continuing. The step is done when the plugin installs with no errors and the site behaves as it did before.

  5. Configure the S3 or Azure connection

    In staging, the administrator enters the connection details for the chosen service: endpoint, region, bucket or container name and the scoped identity. They run the plugin's own connection test and fix any reported errors before moving a file. They then upload a small test file through Moodle, such as a PDF added to a test course, and open it from the course page in a private browser window. The step is done when the connection test passes and the test file is stored in the bucket or container and served through Moodle.

  6. Migrate a small set of test files

    The administrator runs the plugin's file migration on a small, representative set in staging, such as one course with images, PDFs, video and a large file. The set should cover the file types and sizes your sites hold most. They compare file counts and sizes between the local filedir and the bucket or container, plus checksums where your tooling exposes them. The step is done when every test file matches on count, size and checksum and still opens for a learner from the course page and an assignment submission.

  7. Verify reads and writes from web and cron servers

    The administrator tests from every server that runs Moodle code: the web nodes that serve users and the cron nodes that run scheduled tasks. From each node, they confirm the site can read an existing file, write a new upload and delete a file, as cleanup tasks expect. They review Moodle, web server and cron logs for access or timeout errors and check outbound network rules from each node to the storage endpoint. The step is done when each node passes the checks and a full cron cycle completes with no permission or timeout errors.

  8. Schedule and run the production cutover

    The project owner agrees a change window with the business owners, announces it to users and plans a final sync that moves files written since the test migration. The rollback plan keeps the local filedir intact until the cutover is verified and names who decides to roll back. After migration, the team repeats the sample downloads and cron checks on production and reviews the logs over a period set in the plan. The step is done when production passes the same checks as staging and the business owner signs off.

Which Moodle settings map to buckets, containers and identities

This table maps each objectfs setting to the bucket, container, region, identity and path it corresponds to in Amazon S3 and Azure Blob Storage, with the team that usually owns each value. Read the last column before copying a production configuration into staging, because the bucket or container, identity and prefix should normally differ between the two environments. Confirm exact field labels on the plugin's settings page for your Moodle version.

Objectfs settingAmazon S3Azure Blob StorageOwner and staging note
Storage typeAmazon S3 selected as the external file systemAzure Blob Storage selected as the external file systemPlatform team. Same value in staging and production.
Bucket or container nameS3 bucket that holds Moodle file contentBlob container that holds Moodle file contentCloud team. Use separate buckets or containers for staging and production.
Region or accountAWS region where the bucket is createdStorage account that contains the containerCloud team. Changes only if staging sits in another region or account.
Access identity and permissionsIAM role or user limited to object read, write and delete on the bucketManaged identity or access key limited to the containerSecurity. Each environment gets its own identity with the smallest permissions that work.
Path or prefix for Moodle contentKey prefix that separates this site's objects in a shared bucketDirectory path inside the container for this site's objectsPlatform team. Differs per site if several Moodle instances share storage.
Credential storage and rotationAccess keys or role settings held in a secrets store, not in source controlAccount key, SAS token or identity settings held in a secrets storeSecurity. Confirm rotation schedule and where the plugin reads each credential for your version.

Protecting file access and credentials in object storage

Once Moodle file storage moves to S3 or Azure Blob Storage, the bucket or container becomes a central store for course files and user uploads. The controls below cover who can reach that store, how the Moodle site authenticates to it, and how activity and key changes are recorded.

Workload identity over static keys

Where the cloud account allows it, give the Moodle web and cron servers an attached role or managed identity instead of long-lived access keys. Where static keys are unavoidable, keep them out of the web root and version control, and confirm with your provider which secrets store fits your hosting. Ask your DeployOpen team to document which identity each Moodle node uses, so an audit can trace every storage call to a named principal.

Least privilege on the Moodle bucket

Grant the Moodle identity read, write and delete rights only on the Moodle bucket or container, and nothing on other buckets in the account. Objectfs needs to create, read and remove files, so test the policy against a staging copy before production. Avoid account-wide administrative roles for the storage plugin, and review the policy whenever the plugin or Moodle version changes.

Private access with no public listing

Keep the bucket or container private, with public access blocks enabled at the account level where the provider offers them. Moodle serves files through its own permission checks, so object URLs should not be shared openly and directory listing should be disabled. Confirm the public access settings in your account, and check them again after any change to bucket policies or CDN configuration.

Encryption at rest and in transit

Require HTTPS between the Moodle servers and the storage endpoint, and enable server-side encryption on the bucket or container. Choose between provider-managed keys and customer-managed keys based on your key custody rules, since customer-managed keys add key policy work and a dependency on key availability. Confirm which encryption options your cloud account provides and which one your compliance team accepts.

Separate staging and production buckets

Give staging and production their own buckets or containers and their own storage identities, so a test refresh cannot overwrite live course files. Environment refreshes are one of the reasons sites adopt objectfs, so define in advance how staging receives data, whether files are copied or referenced, and which identity performs the copy. Confirm the naming and tagging scheme with your team before the first migration run.

Storage access logging and rotation

Enable access logging on the bucket or container and send the logs to a location with its own retention and restricted access. Confirm which log types your provider offers, such as object-level data events, since they may carry extra cost and must be switched on deliberately. Set a rotation schedule for any static credentials and rehearse a revocation, so a leaked key can be replaced without a Moodle outage.

Migrating existing files and testing before cutover

Moving existing files is a separate piece of work from installing the plugin, and it should be planned as its own step. Moodle's local file store keeps each file under its content hash in the data directory, and the Object storage file system plugin (tool_objectfs) has to copy those files to the bucket or container and record that they now live in object storage. Confirm in the plugin documentation for your exact version which admin page, CLI command or scheduled task starts that copy, how it batches and resumes after an interruption, and whether the local copies are kept or removed afterward. Measure the total file count and size on your real data directory before you set a window, since transfer time depends on both and on the network path between your Moodle servers and the storage service.

A staging refresh should come first. Copy the production database and data directory into a staging environment running the same Moodle and plugin versions, and point staging at a separate bucket or container prefix so that no production object can be changed. Run the migration there, time it, and record every failed copy, missing object and size or checksum mismatch. Those findings are what you need before any production change. Also test the refresh process itself, because shared storage is one reason sites adopt this plugin. Check in the documentation how a refresh should handle the database pointers and the bucket, so that a refreshed staging site reads its own files and does not write into production storage.

Verification should cover what users and administrators actually touch. Download files from several courses, including large files, images embedded in pages, files attached to forum posts and files in assignment submissions. Open the file pickers in resources, assignments and the course files area, and test upload, selection and any repository plugins you have enabled. Take a course backup and restore it into a new course and into a separate test instance, confirming the files come back intact. Run the scheduled tasks and watch for errors, including the plugin's own tasks that move or delete objects and any clean-up task that removes unreferenced files. Confirm that deletion cannot run ahead of references. Keep a dated test log that someone other than the implementer signs.

Rollback needs a decision before cutover, not during an outage. Define what counts as failure, such as storage authentication errors, a broken private endpoint, DNS or firewall changes, or a rise in failed downloads, and name the person who can order a switch back. Confirm whether your plugin version can fall back to the local file store during an outage or only after a configuration change, because that determines how quickly users recover. In most designs the local data directory stays intact until cutover is accepted and the agreed retention period ends, and rollback means restoring the storage configuration and confirming the local copy is complete. Rehearse that rollback in staging, and document the network path, IAM permissions and key handling in the same runbook.

Why files stop loading after the switch

This table lists the failures that most often stop Moodle files from loading after objectfs is enabled, with the likely cause and the first fix or check for each. Read each row from the symptom outward: confirm the Moodle and plugin versions, then the web root, credentials, network path, migration state, bucket names and scheduled tasks. The main takeaway is that most failures trace to version, path or configuration mismatches rather than to the storage service itself.

FailureLikely causeFix and checks
Moodle version outside plugin supportThe plugin directory listing shows support only up to Moodle 4.5, so newer branches need confirmationCheck the plugin listing and release notes for your exact Moodle version before upgrading or switching.
Web root still on main Moodle folderFrom Moodle 5.1, the web server document root must point to the /public directoryRepoint the document root to /public, reload the web server, then confirm the site loads without listings or errors.
Credentials lack read or write accessThe access key or role cannot read, write or delete objects in the bucket or containerTest read, write and delete with the credentials Moodle uses. Compare the errors in the web server and Moodle logs.
Blocked network path to storageA firewall, proxy or security group blocks outbound HTTPS to the storage endpointTest HTTPS reachability from the Moodle web and cron hosts. Review egress rules and any proxy settings.
Files not migratedExisting files may still sit in the local file directory, so there are no objects to serveConfirm the migration task finished and compare file counts with the source. Keep local copies until verified.
Bucket or container names differStaging and production settings use different names, or a copied config keeps the staging nameCompare the bucket or container setting in each environment. Look for not-found errors that name the wrong bucket.
Cron tasks not running offloadScheduled tasks that move or clean up files do not run, so new files stay local or failConfirm Moodle cron runs on schedule. Check the task logs for the objectfs tasks and any recorded failures.

Questions buyers ask before moving Moodle files to object storage

How much does moving Moodle files to S3 or Azure Blob cost?

The total is DeployOpen's fee for the agreed scope plus the cloud charges you pay directly. DeployOpen's fee follows from the written scope and is not a list price. The fee is mostly one-time and depends on the number of Moodle instances, the total file volume, the cloud provider and account structure, how many environments need testing, and whether a retainer covers later upgrades. Cloud charges recur and are yours: storage capacity, requests, data transfer and any backup copies. How often files are read, and how large they are, drives the ongoing amount. Ask every quote to state the Moodle version, file volume per instance, number of instances, target provider, and which line items are one-time and which recur.

How long does an objectfs migration take for a Moodle site?

Duration depends on file volume, the number of instances, and how many environments must be tested before production. Your written scope should give the timeline for your site. Work usually starts with a staging copy, then a trial file move, then validation of course content and file access, and finally a maintenance window for cutover. Large file sets lengthen the copy and verification steps, and sharing storage across several instances adds coordination between them. Ask the proposal to list each phase, the approvals that depend on your cloud account, and the length of the maintenance window your team must allow.

What must our internal team provide before the work starts?

Provide a cloud account or subscription where the bucket or container will live, with permission for DeployOpen's engineers to create storage, identity roles or access keys, and logging under your governance rules. The Moodle web and cron servers must reach the storage endpoint, and staging must reach it too. You also need a staging site copied from production, a named owner who approves cutover, and a maintenance window long enough for the final file sync and a rollback check. Confirm data residency and encryption requirements in writing before the account is created, since they shape the storage configuration.

Can a Moodle administrator move files to object storage alone?

Possibly, if the administrator has Linux, PHP and cloud storage experience and the site is a single instance with a modest file set. Most sites need more than plugin settings. The work touches the web server, PHP, cron, storage credentials, file permissions, backups and the upgrade path, and one mistake can leave course files unreachable. Confirm compatibility first, because the plugin's directory listing shows support for Moodle 2.7 to 4.5. A fixed-scope engagement lets your administrator keep ownership of the result while an engineer handles the steps that need specialist judgment. Ask the partner to name the steps your team will carry out itself.

Will students and teachers notice a change after the migration?

Users should notice little in the normal course flow, because course content, enrolments and grades stay in the Moodle database and the interface stays the same. What may change is how files are delivered, such as downloads passing through Moodle or links pointing to the storage service. The exact behavior depends on the plugin configuration and version, so confirm it in the plugin documentation before planning. Send staff a short note about any change to file links, and test large downloads, embedded video, and file access from the mobile app during staging before cutover.

What happens to Moodle files if the storage account becomes unavailable?

Files held only in object storage cannot be served while the account or endpoint is unreachable, so the outcome depends on how the design handles that failure. Confirm with the plugin documentation how the site behaves when the store cannot be reached, and whether any local cache or fallback exists. Your design should set the storage redundancy, the location of backup copies, the restore procedure, and the person who responds to an outage. DeployOpen cannot control your cloud provider's availability. Ask for these failure modes and recovery steps to be written into the scope, and test a restore in staging before cutover.

Which Moodle versions does the objectfs plugin support before we start?

Check version support before planning. The Object storage file system plugin's directory listing shows support for Moodle 2.7 to 4.5, so a site on a later release needs compatibility confirmed against the plugin's current documentation before work begins. Moodle 5.1 requires 64-bit PHP 8.2 or later and a web server document root that points to the new public directory. Moodle 5.3 requires PHP 8.3 or later and PostgreSQL 17, among other items. If your site is on an older release, a version upgrade may need to happen first, so ask the quote to show the upgrade sequence alongside the storage work.

How DeployOpen scopes, delivers and supports Moodle object storage

DeployOpen plans, builds and documents Moodle file storage on Amazon S3 or Azure Blob Storage using the Object storage file system plugin, inside infrastructure you control. Most engagements are fixed-scope and start with a written scope that confirms your Moodle version against the plugin's listed support.

How we scope

  • The written scope names the storage backend, Amazon S3 or Azure Blob Storage, and the buckets or containers involved.
  • Plugin support for your Moodle version is confirmed first, since the directory lists support up to 4.5.
  • Fixed-scope agreements cover deliverables and timelines in writing, and ongoing support is available as a retainer.

How we build

  • Configure the plugin settings and credentials for the chosen bucket or container, with least-privilege access.
  • Test large-file offload, content deduplication and file serving from the object store on a staging copy first.
  • Document plugin upgrade steps, including the /public web root change required from Moodle 5.1.

How we hand over

  • Handover includes a configuration record listing buckets, credential owners, cron tasks and the rollback path.
  • Runbooks cover moving files back to local storage and checking object references after restores.
  • Your team receives documented test results for uploads, downloads, deletions and environment refresh steps.

How we support

  • Retainers can cover plugin updates, Moodle minor releases and checks against each new Moodle version.
  • Ask for the support matrix in writing, since plugin version listings change as new Moodle releases ship.
  • Set up monitoring for object errors and cron health after go-live, feeding alerts into your own stack.

Sources and further reading

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.