Cloud storage
Cloud storage
🔒 Pro feature — requires the Pro plugin.
With Pro, you can store students’ evidence files in Bunny Storage (bunny.net) or a Google Shared Drive instead of on your own server. This guide covers choosing a backend, setting up each provider, keeping credentials out of the database, moving existing files between providers, and cleaning up files that no longer belong to an entry.
Before you start
- Who can use it: administrators only. Every setting and action on the Cloud Storage tab requires the ability to manage site options.
- Where to find it: Clinical Training Logbook → Plugin Settings → Cloud Storage.
- Cloud storage is optional. Without it, evidence is kept in the plugin’s private on-server store described in Evidence storage and privacy.
- Files always pass through your server. The student’s browser uploads to your WordPress site, and your server sends the file to the provider. Students never connect to Bunny or Google directly, so your server’s PHP upload limits (
upload_max_filesizeandpost_max_size) still apply. - Files are never public. Cloud files are not given public links. When a student, administrator or trainer opens a file, your server fetches it from the provider and passes it through the same secure, permission-checked link used for on-server files.
- Each section saves separately. The tab has its own save button for each section: Save Storage Preference, Save Bunny Settings and Save Google Drive Settings.
Choosing a storage backend
The General Storage section controls where new uploads go. It does not move files that are already stored — for that, see Migrating existing evidence.
| Active storage option | What happens to new uploads |
|---|---|
| Auto — use highest-priority configured provider (default) | Bunny Storage if it is configured, otherwise Google Drive if it is configured, otherwise the on-server store |
| Bunny CDN | Bunny Storage. Shown as Bunny CDN (not configured) and unavailable until all Bunny settings are saved |
| Google Drive | Google Drive. Shown as Google Drive (not configured) and unavailable until the service account and folder are saved |
| WordPress media library | The plugin’s private on-server evidence store. Despite the name, files are not added to the public Media Library — they go to the protected dclb-evidence folder |
Below the menu, Auto currently resolves to: names the backend that new uploads will actually use. Check this line after every change — it is the quickest way to confirm your setup is working.
- Configure Bunny Storage or Google Drive (sections below).
- Choose an Active storage option.
- Click Save Storage Preference.
- Confirm the Auto currently resolves to: line, then upload a test file from the entry form and open it again from the student overview.
If a selected provider stops working (for example, a credential is revoked), uploads to it fail and the student sees the error on the entry form. They are not quietly sent somewhere else.
Bunny Storage
Bunny Storage keeps files in a storage zone you create at bunny.net.
Setting up
- In the Bunny dashboard, create a Storage Zone and note its name and region.
- Open the zone’s FTP & API Access page and copy the password (the storage API key).
- Create a Pull Zone connected to the storage zone, turn on Token Authentication in its security settings, and copy the token authentication key.
- On the Cloud Storage tab, fill in the Bunny Storage section and click Save Bunny Settings.
Settings
| Setting | What to enter | Default |
|---|---|---|
| Storage zone name | The name of your Bunny Storage Zone | Empty |
| Storage region | Falkenstein (de), New York (ny), Los Angeles (la), Singapore (sg), Sydney (syd) or London (uk). Leave as — Select region — to use Bunny’s main storage endpoint | Not selected |
| Storage API key | The Storage Zone password (FTP & API Access Key). Stored encrypted. Once saved, the field shows Saved — leave blank to keep | Empty |
| Pull zone hostname | Your pull zone’s CDN hostname, without https:// — for example yourzone.b-cdn.net |
Empty |
| Pull zone token key | The pull zone’s token authentication key. Stored encrypted | Empty |
| Max upload size (MB) | Largest evidence file accepted for Bunny uploads, from 1 to 500 | 50 |
Bunny counts as configured only when the storage zone name, storage API key, pull zone hostname and pull zone token key are all saved.
The screen shows your server’s own upload limit beside Max upload size (MB). If your value is higher, a warning appears: files above the server limit are rejected before they reach the plugin. Raise upload_max_filesize and post_max_size in your PHP configuration, or lower the setting. The limit that applies is whichever is smaller.
How Bunny files are organised
Each file is stored under cohort/<cohort number>/student/<user ID>/<year>/<month>/<day>/ with a random file name. The cohort number comes from the student’s active allocation; students without a cohort use 0.
Google Drive
Google Drive storage uses a service account — a Google identity for your website — to upload into a folder on a Shared Drive. Service accounts cannot upload to a personal “My Drive” folder.
Setting up
- In the Google Cloud Console, create (or choose) a project and enable the Google Drive API.
- Create a service account, then add a key of type JSON and download the key file. Keep it safe — it grants access to your Drive.
- In Google Drive, create a Shared Drive (or use an existing one) and create a folder for evidence.
- Open the Shared Drive’s Manage members and add the service account’s email address (the
client_emailvalue in the JSON file):- Content manager is the minimum. It can upload, read and move files to Trash.
- Manager is needed if erased files must be permanently deleted (see Trash or permanent deletion).
- Open the evidence folder and copy its ID from the address bar:
drive.google.com/drive/folders/THIS_PART. - On the Cloud Storage tab, in Google Drive Storage:
- paste the folder ID into Drive folder ID, and
- open the JSON key file in a plain-text editor and paste its entire contents into Service account JSON. Do not reformat it — the
nsequences inside the private key must stay as they are.
- Click Save Google Drive Settings, then click Test Connection.
The key is encrypted before it is stored, and the plugin never shows it again. Once saved, the screen shows ✓ A service account key is currently stored. To replace it, paste a new key. Leave the box empty to keep the current one. If the pasted text is not a valid service-account key (it must contain private_key and client_email), the key is not saved. Use Test Connection to confirm.
Test Connection
Test Connection signs in to Google with the saved key and checks what the service account may do in your folder. Possible results:
- “Google Drive connection successful. Service account authenticated.” followed by either:
- “Permanent deletion is available — data erasure will permanently remove evidence.”, or
- “Note: this service account can only move evidence to Trash, not permanently delete it…”
- “Google Drive is not fully configured. Save a service account JSON and a folder ID first.” — save both fields, then test again.
- “Invalid Google Drive service account JSON.” or “Failed to parse the Google Drive service account private key.” — paste the key file again, unmodified.
- “Failed to obtain a Google Drive access token.” — check that the Drive API is enabled and the key has not been deleted in Google Cloud.
How Drive files are organised
Inside your folder, the plugin creates one subfolder per student, named Display name (username), and uploads that student’s files into it. Files are kept private to the Shared Drive’s members.
Trash or permanent deletion
When evidence must be removed from Drive — after an entry is deleted, a student’s data is erased, or you delete files in Unlinked Files Cleanup — the plugin first tries to delete the file permanently. If the service account is only a Content manager, Google refuses, and the plugin moves the file to the Shared Drive’s Trash instead. Google empties Trash automatically after about 30 days, and until then a Shared Drive manager can restore the file.
Under Test Connection, an erasure permanence panel shows the last result:
- ✓ Erasure permanently deletes evidence from Google Drive.
- Erasure will move files to Trash — not permanently delete them. — with steps to fix: in Google Drive, open the Shared Drive → Manage members → set the service account to Manager, then click Test Connection again.
- not yet checked — click Test Connection.
If files have been moved to Trash rather than deleted, administrators also see a yellow banner on admin pages: “…%d Google Drive evidence file(s) could only be moved to Trash during data erasure — not permanently deleted…”. The banner links to the Cloud Storage settings and has a Dismiss link. Dismissing hides it for you until the next time a file is trashed. A successful Test Connection with permanent deletion available clears it for everyone.
If keeping the 30-day recovery window is what your organisation wants, no action is needed.
Keeping credentials out of the database
You can define cloud credentials in wp-config.php instead of saving them on the settings screen. This keeps them out of database backups and exports.
| Constant | Replaces |
|---|---|
DCLB_BUNNY_STORAGE_ZONE |
Storage zone name |
DCLB_BUNNY_REGION |
Storage region (for example syd) |
DCLB_BUNNY_API_KEY |
Storage API key |
DCLB_BUNNY_PULL_ZONE |
Pull zone hostname |
DCLB_BUNNY_PULL_TOKEN |
Pull zone token key (DCLB_BUNNY_TOKEN_KEY is also accepted) |
DCLB_BUNNY_MAX_SIZE |
Max upload size (MB), 1–500 |
DCLB_GDRIVE_SERVICE_ACCOUNT_JSON |
Service account JSON |
Example (replace each value with your own):
define( 'DCLB_BUNNY_STORAGE_ZONE', 'your-storage-zone' );
define( 'DCLB_BUNNY_REGION', 'syd' );
define( 'DCLB_BUNNY_API_KEY', 'your-storage-zone-password' );
define( 'DCLB_BUNNY_PULL_ZONE', 'yourzone.b-cdn.net' );
define( 'DCLB_BUNNY_PULL_TOKEN', 'your-token-authentication-key' );
define( 'DCLB_GDRIVE_SERVICE_ACCOUNT_JSON', '{...raw json...}' );
For the Google key, copy the raw contents of the JSON file between single quotes, without reformatting it.
What changes on screen:
- Bunny: when any Bunny constant is defined, all Bunny fields are hidden and the section shows “✓ Bunny credentials are defined in wp-config.php constants…”. Define all of the Bunny values you need as constants. If values were saved earlier, a Clear stored Bunny credentials from the database (keep using the wp-config values). checkbox lets you remove them — tick it and click Save Bunny Settings.
- Google Drive: the key box is replaced with “✓ Service account key is defined in wp-config.php (DCLB_GDRIVE_SERVICE_ACCOUNT_JSON)…”. The Drive folder ID is still entered on screen. If a key was saved earlier, tick Remove stored key from the database (wp-config value will still be used at runtime). and save.
The encryption key
Credentials saved on the settings screen are encrypted. By default the encryption key is generated automatically and stored in the database. For stronger protection, define your own key in wp-config.php so a database copy on its own cannot be decrypted:
define( 'DCLB_SECRET_KEY', 'paste-a-base64-encoded-32-byte-key-here' );
Generate a suitable value with openssl rand -base64 32 (it must decode to exactly 32 bytes). Until you add it, the Google Drive section shows a reminder suggesting it.
If the key changes, saved credentials stop working. This happens if you add or change DCLB_SECRET_KEY after credentials were saved, restore a database without its matching key, or copy the site without copying the constant. The plugin does not use WordPress’s security salts, so changing those has no effect. When a stored credential cannot be decrypted, uploads and downloads for that provider fail and administrators see:
Clinical Training Logbook Pro: a stored cloud-storage credential could not be decrypted, so evidence uploads/downloads to that backend are failing. … Re-enter the affected credential to fix it.
Re-enter the Bunny API key and token key, or paste the Google key again, and save. The notice clears when settings are saved. If the credential still cannot be read, it reappears on the next upload or download.
Migrating existing evidence
Storage Migration moves existing evidence files between Bunny Storage and Google Drive, in either direction. It is for moving to a new provider after you change Active storage.
- Both providers must be configured before you run a migration in either direction.
- Only files already in Bunny or Google Drive can be moved. Files in the on-server store are not migrated and stay where they are.
- Migration does not change where new uploads go — set Active storage separately.
Running a migration
- Choose a direction: Bunny → Google Drive or Google Drive → Bunny.
- Click Check pending files. The result shows, for example, “12 file(s) ready to migrate (Bunny CDN → Google Drive).” or “No files to migrate (…)”.
- Click Run migration and confirm the prompt (“Migrate all evidence from Bunny CDN to Google Drive? Files are moved and their references updated.”).
- Keep the page open. Files are moved three at a time, and a progress bar shows “Migrating … N moved so far.”
- When it finishes, you see Migration complete (…): N file(s) moved. or Migration finished with errors (…): N moved, N failed. Each error, and each skipped file, is listed under the progress bar.
What happens to each file
- The file is downloaded from the source provider and uploaded to the destination.
- The entry is updated to point at the new copy, so students and trainers keep opening it normally.
- The original is deleted from the source provider, unless another entry still uses it. On Google Drive, “deleted” follows the trash rules above.
If the source file cannot be found, the file is skipped (“Skipped (not found in …): “file name”. Record marked as missing.”) and is not counted again. The final summary reports skipped files as “N already at the destination were skipped (…)” — in practice these are files that were missing at the source, so check the listed file names. You can run the migration again at any time — files already moved are no longer pending, so a re-run picks up only what is left, including anything that failed.
Cleaning up orphaned files
Over time, cloud storage can hold files that no longer belong to any entry, for example after entries are deleted. There are two ways they are removed.
Scheduled cleanup (automatic)
Twice a day (about every 12 hours), a scheduled task finds Google Drive files that the plugin has recorded as no longer linked to an entry — such as files from deleted entries, erasure requests and deleted accounts — and deletes them (or moves them to Trash, as above). This runs without a preview and is how cloud evidence is removed after an erasure request. It relies on WordPress’s scheduled tasks, so make sure they run on your site.
Unlinked Files Cleanup (manual)
- In Unlinked Files Cleanup, choose what to scan:
- Include WordPress media files created by Dantian Clinical Training Logbook — older evidence stored in the Media Library and marked as created by the plugin. (The current on-server private store is not scanned here.)
- Include Bunny attachment records not linked to current entries
- Include Google Drive files tracked in Dantian Clinical Training Logbook evidence index — only files the plugin has recorded as unlinked. Other files in your Drive folder are never touched.
- Click Preview unlinked files. A table lists each candidate with its Provider, File and Reference. All rows start ticked.
- Untick anything you want to keep.
- Tick I understand selected files will be permanently deleted and cannot be recovered.
- Click Delete selected files.
Notes:
- The scan options start from the Cleanup providers defaults on Plugin Settings → Evidence Defaults (WordPress media and Bunny on, Google Drive off by default). A provider that is ticked there is always included in the preview, even if you untick it here.
- A preview is kept for 15 minutes. If it expires, run Preview unlinked files again.
- Possible results: “Selected unlinked files were deleted.”, “Some selected files were deleted, but one or more deletions failed…”, “No selected files were deleted…”, “No files were selected for deletion.” and “Please confirm deletion before continuing.”
- Failed deletions are recorded in the log below.
Files the cleanup does not catch
- Replaced files: when a student replaces a cloud-stored file on an existing entry, the previous file is not removed from Bunny or Google Drive automatically.
- Bunny Storage: the Bunny scan reads attachment records that the current version of the plugin does not create, so it does not find files from deleted entries. Remove those from your storage zone in the Bunny dashboard (each student’s files are under
cohort/<cohort number>/student/<user ID>/).
Upload failure log
The log on this tab is headed Evidence Delete Failures (Admin). Despite where it sits, it records failed deletions, not failed uploads. When a manual cleanup or the scheduled cleanup cannot delete a file, a row is added with:
| Column | Meaning |
|---|---|
| Time (UTC) | When the failure happened, in UTC |
| Operation | What was being done (shown as manual-cleanup-delete for both manual and scheduled cleanup) |
| Provider | MEDIA, BUNNY or GDRIVE |
| Reference | The file’s identifier at the provider |
| HTTP / Error code / Message | The provider’s response, where available |
The 50 most recent failures are kept. When there are none, the section shows “No recent deletion failures recorded.” After resolving the cause (usually storage permissions — for example the Drive service account’s role, or a revoked Bunny key), click Clear failure log (“Evidence deletion failure log cleared.”). The log is also removed if you uninstall with data deletion turned on.
Upload failures are not logged here. They are shown to the student on the entry form when they save — for example “Bunny upload failed (HTTP 401).”, “Google Drive upload failed (HTTP 403).” or “File size exceeds the maximum allowed size of 50 MB.” — and the entry is not saved with a missing file.
Privacy and uninstall
- Third parties: with cloud storage enabled, evidence files are sent over HTTPS to Bunny (bunny.net) or Google. The plugin’s suggested privacy policy text (Settings → Privacy → Policy guide) says so. Review those providers’ terms for your organisation.
- Erasure requests: see Evidence storage and privacy › Personal data export and erasure.
- Uninstall: credentials are always removed when Pro or the free plugin is deleted. Cloud files are deleted only if you turned on data deletion before uninstalling Pro. See What happens on uninstall.
Worked example
Coastal Health Institute wants new evidence stored in its Google Workspace and previous Bunny files moved across.
- The IT officer creates a service account, adds it as Manager on the “Clinical Evidence” Shared Drive, and puts the key in
wp-config.phpasDCLB_GDRIVE_SERVICE_ACCOUNT_JSON, with aDCLB_SECRET_KEYalongside it. - On Cloud Storage, the administrator enters the Drive folder ID, clicks Save Google Drive Settings and Test Connection, and sees “Permanent deletion is available”.
- The administrator sets Active storage to Google Drive, saves, and uploads a test entry. It appears in a new “Priya Natarajan (pnatarajan)” subfolder and opens normally from the overview.
- Under Storage Migration, they choose Bunny → Google Drive, click Check pending files (“214 file(s) ready to migrate”), runs it, and finishes with “Migration complete (Bunny CDN → Google Drive): 214 file(s) moved.” The original Bunny copies are deleted as each file moves.
Troubleshooting
“Auto currently resolves to” still says “WordPress media library” after saving credentials. New uploads are going to the on-server store. A backend only counts as configured when every required value is present: Bunny needs all four of storage zone, API key, pull zone and token key; Google Drive needs both the service-account key and the folder ID. Re-open the tab, fill in whichever value is blank, save that section, and check the line again. If Active storage is set to a specific backend rather than Auto, make sure it is the backend you just configured.
Large files are rejected. Raise your server’s upload_max_filesize and post_max_size, and for Bunny also the Max upload size (MB) setting.
A Drive file opens with an error such as “File not found in Google Drive (HTTP 404).” The file was removed or the service account lost access to the Shared Drive. Check the account is still a member.
Erased Drive files are still visible in Trash. The service account is a Content manager. Make it a Manager and click Test Connection.
See also Troubleshooting and Settings reference.