Take the File Garbage Collector Live
The file garbage collector reclaims storage held by files that no directory links to any more, such as the homes of deleted users. It works in two passes: a sweep marks unreferenced files by moving their records to a trash collection, and a purge later removes their keys, chunks and records. It was rebuilt in Backend 3.14.1, and it ships disabled and in dry-run. Its settings are described in Garbage Collector.
This page is the procedure for turning it on. Follow it in order: the purge is permanent.
The purge removes keys, chunks, and records. There is no undo and no backup is taken first. Work through every step below, and do not shorten the dry-run period to save time.
Before you enable anything
Verify your storage path
This is the one check that matters most, and it is not optional.
ticrypt.filemanager.storage.path defaults to /tmp/ticrypt-storage, and the shipped file-manager configuration template does not mention the setting at all, so a deployment set up from the template is using the default.
If that path is wrong or not mounted, chunk deletion fails silently. A chunk that does not exist is treated as successfully deleted, so the purge reports complete success, removes the trash record, and leaves the chunk files on disk permanently, with nothing in any log to say so. The storage is never reclaimed and you have lost the record that would let you find it.
Confirm before you start:
grep -r "storage" /etc/ticrypt/ticrypt-file-manager.conf
df -h /your/storage/path # is it mounted?
sudo -u ticrypt test -w /your/storage/path && echo writable
The file manager and the REST service must share this filesystem.
Expect the first live sweep to be large
Because the sweep has been returning nothing, every directory-less, unshared file older than your retention period is still on disk. The first live pass marks all of them, in batches of 100, and the first purge reclaims them a grace period later. Plan the first cycle for a window where you can watch it.
Know what this does not reclaim
Files deleted between December 2025 and 3.14.1 had their keys and records removed but their chunks left on disk. Those chunks appear in neither file_infos nor deleted_file_infos, so neither pass will ever find them. Reclaiming that backlog needs a separate reconciliation pass; contact support before attempting it.
Step 1: Run it in dry-run
Enable the collector while leaving dry-run on. Nothing is marked and nothing is purged; both passes write what they would have done to a log.
ticrypt.maintenance {
garbage-collector {
enabled = true
dry-run = true
retention-period = 60d
deleted-grace-period = 3d
frequency = 4h
purge-frequency = 24h
amount-grouped = 100
scan-timeout = 30m
purge-timeout = 30m
log-directory = "/var/log/ticrypt/file-gc"
}
}
Restart ticrypt-maintenance and let it run for at least one full frequency cycle.
Step 2: Read the logs
The service journal
journalctl -u ticrypt-maintenance -f | grep -i "garbage\|purge"
Lines worth knowing:
| Line | Meaning |
|---|---|
FileGarbageCollector starting up (dryRun=true, ...) | Confirms the mode it came up in. Check this after every config change |
Finished file garbage collection pass (dry run): would mark N files for deletion | The sweep ran. N is your candidate count |
Finished deleted-file purge pass (dry run): would purge N files past their grace period | The purge ran |
No directory entries found while N deletion candidates exist; skipping this garbage collection pass | A safety guard firing. The directory scan came back empty while candidates existed, so the pass refused to mark anything rather than mark everything. Investigate before continuing |
Deleted-file purge slow or failed: ... | The purge exceeded purge-timeout. It keeps running; only the summary line is lost |
The dry-run files
Both land in log-directory, timestamped in epoch milliseconds:
/var/log/ticrypt/file-gc/
├── file-garbage-collector-<timestamp>.log # sweep candidates
└── file-garbage-collector-cleanup-<timestamp>.log # purge candidates
The sweep log lists every file it would mark:
Removed 1284 files with no links to directories:
* 6f1a2c94-...
* 8b03df21-...
The cleanup log separates what would be destroyed from what would be saved:
Would purge 903 deleted files (14472 chunks) past their grace period:
* 6f1a2c94-... (16 chunks)
Would restore 4 deleted files still referenced by a directory:
* 2c77ba10-...
The first line of the sweep log reads Removed N files... even when nothing was touched. Confirm the mode from the journal line, not from this wording.
Step 3: Spot-check the candidates
Do not skip this. Take ten file IDs from the sweep log and satisfy yourself that each one really is unreachable: no directory entry anywhere links to it, and no key belongs to another user. If any candidate turns out to be a live file, stop and open a support case. Do not go live.
Read the counts, too. If the sweep proposes to mark a number that surprises you for the size of your deployment, find out why before going further.
One clean dry run is not enough. Enable the collector in dry-run and let it complete several
full frequency cycles, reading file-garbage-collector-<ts>.log after each one, before you ever
set dry-run = false.
The reason is that the candidate set is not static. A file becomes a candidate the moment nothing links to it, so a single pass only shows you what was orphaned at that instant. Running repeatedly tells you two things one pass cannot:
- Is the list stable? The same IDs should keep appearing. A candidate set that changes substantially between passes means something is still moving files or directories, and marking them now risks catching live data.
- Is the volume what you expect? Compare counts across passes. A number that grows sharply, or that never matched your sense of the deployment's size, is a signal to stop and investigate rather than proceed.
Spot-check file IDs from each run, not only the first. Once dry-run = false, the sweep begins
marking files for permanent deletion, and after deleted-grace-period elapses the purge removes
their keys, chunks and records. That step cannot be undone.
Step 4: Go live
One flag governs both passes:
dry-run = false
Your settings stop being hypothetical
While dry-run = true, the parameters only decide what gets written to a log. The moment it is
false, every one of them becomes an instruction the collector carries out. Read your own values
before flipping the flag and be sure you agree with what each one now means.
With the shipped defaults:
enabled = true
dry-run = false
retention-period = 60d
deleted-grace-period = 3d
frequency = 4h
purge-frequency = 24h
amount-grouped = 100
that configuration means, in plain terms:
| Setting | What it did in dry-run | What it does now |
|---|---|---|
retention-period = 60d | Listed files older than 60 days with no directory links | Marks every such file for deletion |
frequency = 4h | Wrote a candidate log every 4 hours | Marks a fresh batch every 4 hours, around the clock |
amount-grouped = 100 | Nothing | Marks in batches of 100 per pass |
deleted-grace-period = 3d | Nothing | A marked file is destroyed 3 days after it is marked |
purge-frequency = 24h | Logged what it would purge | Permanently removes keys, chunks and records once daily |
So on a default configuration, a file that lost its last directory link 60 days ago is marked within 4 hours and is gone 3 days after that, with the purge running every 24 hours in between.
Worked examples of changing one value:
retention-period = 7dreclaims space far sooner, and also catches files orphaned a week ago that a user may still be expecting to recover. A short retention on a first live run is the fastest way to delete something you wanted.deleted-grace-period = 14dis the setting to widen for a first live cycle. It does not change what gets marked, only how long you have to notice. Two weeks of marked-but-intact files is cheap insurance; three days is not much of a window if the first purge lands over a weekend.frequency = 24hslows the sweep to once a day, which makes the first live period far easier to watch than a pass every four hours.enabled = falsestops everything. Files already marked stay indeleted_file_infosuntouched and are restored if a directory links to them again.
A conservative first live configuration is therefore not the default one:
enabled = true
dry-run = false
retention-period = 90d # only long-orphaned files
deleted-grace-period = 14d # two weeks to catch a mistake
frequency = 24h # one sweep a day, easier to watch
purge-frequency = 24h
amount-grouped = 100
dry-run controls the sweep and the purge together. Turning it off starts both.
What protects you is deleted-grace-period: for three days after the sweep marks a file, nothing is permanently removed, and any file that gets relinked is restored on the next purge pass. For the first live cycle, widen that window: set deleted-grace-period = 14d and you have two weeks to notice a mistake before anything is destroyed.
Restart, confirm dryRun=false in the journal, and watch deleted_file_infos fill as the sweep marks files. Nothing leaves disk yet.
Step 5: Through the first purge
Once the grace period elapses, the purge begins removing files permanently. Confirm:
Finished deleted-file purge pass: purged N files past their grace periodin the journaldeleted_file_infosdraining rather than growing without bound- Reclaimed space on the storage filesystem
If anything looks wrong before the grace period ends, set enabled = false and restart. Files already marked stay in deleted_file_infos untouched.
Reading the audit log
Bulk directory entry deletion writes its own audit row, BulkDirectoryEntryRemove (BDER), recording the parent directory, the entries removed, whether the parent itself was deleted, and the outcome.
An internal delete event is written when a file is trashed, and restores are not logged at all. An audit reader can therefore see a deletion for a file that the purge later restored because a directory still linked to it. Read deleted_file_infos alongside the audit trail when investigating a specific file.
Summary
| Stage | Setting | What is at risk |
|---|---|---|
| Upgrade | enabled = false | Nothing |
| Observe | enabled = true, dry-run = true | Nothing. Logs only |
| Live sweep | dry-run = false | Nothing for deleted-grace-period |
| First purge | after the grace period | Files are permanently removed |
Verify your storage path first, run in dry-run for a full cycle, spot-check the candidates, and widen the grace period for the first live cycle. The collector is deliberately slow to destroy anything, and every stage before the purge is reversible.