Nextcloud already includes the pieces needed to clean up deleted files automatically, so most administrators do not need a custom shell script. As of the current Nextcloud 35 administration documentation, the recommended approach is still to combine a defined trash-bin retention policy with reliable background-job execution. The important detail is that the default auto policy is not the same as “delete everything after exactly 30 days.” It keeps deleted items for at least 30 days, then makes them eligible for cleanup when space is needed.
If your goal is predictable cleanup, set an explicit maximum retention age and make sure Nextcloud background jobs run through system cron. The steps below use only behavior documented by Nextcloud and also explain when the occ trashbin:expire and trashbin:cleanup commands are appropriate.
What automatic trash-bin cleanup actually does
When the Deleted files app (files_trashbin) is enabled, files removed by users are moved to their trash bins instead of being deleted immediately. That gives users a recovery window, but those deleted items still consume storage. Nextcloud controls their lifetime with the trashbin_retention_obligation setting in config/config.php.
The current Nextcloud trash-bin configuration documentation defines these policy forms:
| Setting | Meaning | Good fit |
auto | Keep items for at least 30 days; after that, remove eligible items when space is needed. | Small installations that are comfortable with the default behavior. |
D, auto | Keep items for at least D days, then allow space-driven cleanup. | You need a minimum recovery window but no firm deletion deadline. |
auto, D | Guarantee deletion after D days, while still allowing earlier space-driven cleanup. | You want a maximum retention age but can tolerate earlier deletion when storage pressure occurs. |
D1, D2 | Keep items for at least D1 days and delete them when they exceed D2 days. | You need both a minimum recovery period and a firm maximum retention age. |
disabled | Disable automatic trash-bin expiration. | Only when indefinite retention is intentional and storage growth is managed another way. |
There is one more storage rule to keep in mind: if a user's quota is exceeded because of deleted files, Nextcloud may ignore the retention setting and clean up trash until quota requirements are met. That is why retention should not be treated as an immutable backup guarantee.
Step 1: Choose a retention policy before changing anything
Decide what the trash bin is for in your environment. If users commonly restore accidentally deleted files, give them a meaningful minimum window. If your priority is bounded storage or a documented data-retention policy, define a maximum as well.
For example, this setting allows space-based cleanup at any time but guarantees that files older than 30 days are removed:
'trashbin_retention_obligation' => 'auto, 30',
If you want deleted files preserved for at least 30 days and also removed after 30 days, use a bounded policy instead:
'trashbin_retention_obligation' => '30, 30',
Choose values that match your recovery requirements. A shorter period saves storage sooner but reduces the time users have to restore files. A longer period offers more recovery time but can increase disk usage.
Step 2: Set trashbin_retention_obligation in config.php
Open the Nextcloud configuration file, normally located at config/config.php under the installation directory. Add or change the setting inside the $CONFIG array. A typical example is:
<?php
$CONFIG = array (
// Other Nextcloud settings...
'trashbin_retention_obligation' => 'auto, 30',
);
Do not edit unrelated values, and take care not to expose the contents of config.php in tickets or screenshots because it may contain sensitive server configuration.
You can also inspect the effective configuration through Nextcloud's command-line tooling rather than copying the file contents into a troubleshooting message.
Step 3: Use system cron for reliable background jobs
The retention policy only helps if Nextcloud background jobs are actually running. Nextcloud's background-jobs documentation recommends operating-system cron for production instances. AJAX is the default mode, but it depends on page visits and is the least reliable option.
On a typical Linux installation using the www-data web-server account, edit that account's crontab:
crontab -u www-data -e
Then run Nextcloud's cron.php every five minutes:
*/5 * * * * php -f /var/www/nextcloud/cron.php
Replace /var/www/nextcloud with the real path to your installation. Some systems require the full PHP CLI path, such as /usr/bin/php.
You can also select cron mode explicitly with:
sudo -E -u www-data php /var/www/nextcloud/occ background:cron
Nextcloud documents the trash-bin expiration background job as running every 30 minutes. Calling cron.php every five minutes does not mean the trash bin is purged every five minutes; it means the scheduler gets frequent opportunities to run jobs that are due.
Step 4: Verify that the scheduler is working
After configuring cron, verify the operating-system entry first:
crontab -u www-data -l
Then check Nextcloud's Administration settings for the background-job status. The page should report that jobs have run recently. If the reported last-run time keeps getting older, fix cron before diagnosing the retention policy.
On Nextcloud 35, the documented occ commands also include background-job inspection commands such as background-job:list, background-job:running, and background-job:history. These can help when you need to verify that jobs are being processed rather than merely assuming cron is active.
Step 5: Use trashbin:expire for policy-based manual runs
If you configured a custom retention period, you can manually apply that policy with:
sudo -E -u www-data php /var/www/nextcloud/occ trashbin:expire
The current Nextcloud files and trashbin command reference notes an important limitation: trashbin:expire only performs a manual expiration when a custom retention period is configured. With the default auto policy, the command exits with an informational message and does nothing because automatic expiration is handled by the background job.
If you deliberately want a separate system cron entry for trashbin:expire, Nextcloud documents a way to disable the app's built-in trash-expiration background job first:
sudo -E -u www-data php /var/www/nextcloud/occ config:app:set --value=no files_trashbin background_job_expire_trash
You can then schedule occ trashbin:expire --quiet yourself. This is an advanced option. For most installations, leaving the built-in expiration job enabled and running Nextcloud's normal cron.php scheduler is simpler and easier to maintain.
Do not confuse trashbin:expire with trashbin:cleanup
The names are similar, but the commands have very different effects. trashbin:expire removes items that qualify under the configured retention policy. trashbin:cleanup permanently removes trash-bin contents for the users you specify.
For example:
sudo -E -u www-data php /var/www/nextcloud/occ trashbin:cleanup --all-users
is a destructive, all-user purge. It is useful when you intentionally need to empty every user's trash, but it is usually the wrong command for routine retention-based automation because it ignores the recovery window you designed. Do not put an all-user cleanup command into cron unless permanent, unconditional purging is truly your policy.
Step 6: Check and control trash-bin size on Nextcloud 35
The current Nextcloud 35 command documentation includes trashbin:size, which lets administrators inspect or set the target size of the trash bin globally or per user. To view the current global value:
sudo -E -u www-data php /var/www/nextcloud/occ trashbin:size
To view a specific user's effective target:
sudo -E -u www-data php /var/www/nextcloud/occ trashbin:size --user USER_ID
A configured size target can complement age-based retention when storage capacity is the main concern. Nextcloud notes that changing the global default size immediately triggers cleanup of existing trash bins, so treat size changes as an operational action, not just a harmless display setting.
How to tell whether automatic cleanup is working
- The background-job status shows recent runs.
- The operating-system crontab contains the expected
cron.php entry.
- Your configured
trashbin_retention_obligation matches the policy you intended.
- Old trash items eventually disappear according to the configured maximum age, if one exists.
trashbin:expire behaves as documented when a custom policy is configured.
- Disk or quota usage stops growing unexpectedly because stale deleted files are no longer retained indefinitely.
If old files remain longer than expected, first confirm that your policy actually contains a maximum value. The default auto setting does not promise deletion precisely at day 30. Next, verify background jobs. Only after those checks should you investigate permissions, storage back ends, or application logs.
A practical configuration for most self-hosted servers
For a typical self-hosted instance, a sensible starting point is to use system cron every five minutes and define an explicit maximum trash age. For example, 'auto, 30' gives users up to roughly a month in ordinary conditions while ensuring that items do not remain indefinitely. If users must always have the full recovery window regardless of storage pressure, use a bounded minimum-and-maximum policy such as '30, 30' instead.
Keep backups separate from the trash bin. The trash bin is a user-recovery feature with quota and retention behavior; it is not a substitute for an independent backup strategy.
Official Nextcloud references