The tunnel stops accepting connections, the service restarts twice, and then nothing appears in its log. That silence is the clue, because the log is what filled the disk and the daemon has nowhere to write the error you are waiting for. Any long-running service can reach that state, and deleting a directory called logs rarely fixes it. The durable fix is to know which store grew, who owns its retention, and whether the writer actually let go of the space.

Find the store that grew, and the rate it grew at

Start with two numbers that are easy to forget: free blocks and free inodes. A filesystem can report plenty of space and still refuse a write because it has no inodes left, which happens when a service creates one file per session. Ask for both readings on the same volume, because the answers can disagree on the same afternoon. Do it while the host is healthy, so the numbers describe normal operation rather than an outage.

df -h /var
df -i /var

Then attribute the growth to an owner. The journal's own usage figure covers only the journal, and it will never see a daemon writing to a path from its configuration file.

journalctl --disk-usage

Growth over time says more than any single reading. A debug level left on, a retry loop that logs every attempt, or a capture file nobody stopped can each look ordinary at one moment and alarming an hour later. Take one reading, wait through a busy period, take another, and divide by the interval. A rate you can state turns capacity into a decision instead of a fire.

What rotation does to an open file

A log file is a name pointing at an inode, and the space returns only when the last open handle closes. Rename the file and the writer keeps filling the same inode; remove it and the writer keeps filling an inode with no name at all. That state is why 'I deleted the file and the disk stayed full' describes file descriptors rather than a broken filesystem. Restarting the writer, or choosing a rotation mode that reopens the file, is what actually returns the blocks.

lsof +L1 | head

Policy belongs to the component that writes the file. The journal enforces its own storage limits from its configuration file, while a file-based service usually relies on logrotate with either a create rule plus a reopen signal or a truncate-in-place mode when the writer cannot reopen. Confirm the decision without changing anything first:

logrotate -d /etc/logrotate.conf

Where the limit belongs, and how big it should be

Put the cap where the writer is configured, not at the mount point. A quota on the whole volume protects the host but says nothing about which service fails first, and a global cleanup script tends to delete the evidence the next incident needs. A journal cap, a rotate count with a maximum size, and application retention each bound one producer. Together they bound the total; alone each is a guess.

Size that cap from the retention you can defend, not from the free space available. If a review needs a week of connection attempts, the journal has to hold a week at the busiest expected rate, and that rate is the number measured earlier.

Debug logging is a temporary mode with a recorded start time, not a storage plan. Keep the privacy question inside the same decision, because connection logs carry addresses and identifiers. Longer retention is also a data-handling choice, and it should be made by someone who knows both constraints.

Verify the cap after a restart

A retention change that lasts until the next reboot is not a change. Restart the writer, confirm the new limit applies, and check that rotation still runs afterwards. For the journal, one restart and one usage reading answer both questions:

systemctl restart systemd-journald
journalctl --disk-usage

For a file-based service, run the rotation job by hand once and confirm the file was replaced and the descriptor reopened. A writer that keeps the old handle passes a superficial check and fails the next time the volume fills. Watch free space during the test, because a file that shrank while the space did not return means the old inode is still held.

Compare the next reading with this one

Come back after a week and compare the growth rate with the recorded one. A matching rate means the cap holds and the workload is stable; a doubled rate means something changed, and the useful question is what. Read the log content for repeated failures first, since a retry loop is both a symptom and a cause of volume. Then check for anything newly enabled, including debug levels switched on during an incident and never switched off.

Keep backups off the same volume, or accept that one full disk takes the backup with it. A copy written to the host it protects is not a recovery plan, and its retention needs its own answer.

Write down what is retained, where, for how long, and who removes it. That sentence is the deliverable, and it is the only part of this work that survives the next restart.

Nuŋlɔɖi siwo ku ɖe eŋu