The Problem
Running a rootless Podman container on a home‑lab server is great for isolation, but the logs it spits out can quietly eat up disk space. I once had a simple nginx container that, after a few days, filled a 20 GB SSD with log files. The container was running as my normal user, so I couldn’t just rm -rf /var/lib/containers/... without risking a permission error. The real issue was that Podman, by default, writes container stdout/stderr to files under /var/lib/containers/storage/overlay-containers/.../files/var/log/ and those files never rotate.
Rootless Podman and Log Storage
Rootless containers use the user‑namespace overlayfs layout. All container data lives in $XDG_RUNTIME_DIR/containers or $HOME/.local/share/containers. When a container writes to /var/log/nginx/access.log, Podman copies that into the overlay and keeps it there. Because the container runs as a non‑root user, the host’s systemd journal is not automatically used unless you explicitly tell Podman to forward logs. Without any rotation, a busy web server can generate gigabytes of log data in a week.
Strategies to Keep Disk in Check
Below are the tactics I use on my own machines. Pick the ones that fit your workflow; you can combine them for maximum safety.
1. Rely on Journald
The simplest way to avoid log files on disk is to let the container write to the host’s journal. Podman supports the journald log driver:
podman run --log-driver=journald \
--log-opt=label=container=myapp \
--log-opt=tag={{.ImageName}} \
-d nginx:alpine
All output goes into journalctl under the specified label. You can then prune old entries with:
journalctl --vacuum-size=500M
or keep only the last 7 days:
journalctl --vacuum-time=7d
Because journald stores logs in a compressed, rotating format, you won’t run out of space unless you keep the retention window too long.
2. Use Podman Log Options
Podman 4.0+ added max-size and max-file options for the json-file driver, mirroring Docker’s behaviour:
podman run --log-driver=json-file \
--log-opt=max-size=10m \
--log-opt=max-file=5 \
-d myapp
This keeps each log file under 10 MiB and keeps only five rotated files. The files live in the container’s overlay, so they’re still part of the rootless storage, but the size is capped.
3. Systemd User Units
When you run a container via a systemd user unit, you can set StandardOutput=journal and StandardError=journal so that systemd captures the logs. Example unit (~/.config/systemd/user/nginx.service):
[Unit]
Description=Rootless Nginx
After=network-online.target
[Service]
ExecStart=/usr/bin/podman run --rm -p 80:80 nginx:alpine
StandardOutput=journal
StandardError=journal
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=default.target
Enable and start it:
systemctl --user enable --now nginx.service
Now the logs are in the user’s journal, which you can prune with the same journalctl --vacuum-* commands.
4. Logrotate Outside the Container
If you prefer file‑based logs, set up a logrotate rule that points to the container’s log directory. Create /etc/logrotate.d/podman-nginx:
/home/youruser/.local/share/containers/storage/overlay-containers/*/files/var/log/nginx/*.log {
daily
rotate 7
compress
missingok
notifempty
create 0640 youruser youruser
}
logrotate will run daily and keep a week of compressed logs. Adjust the path if you use a different storage location.
5. tmpfs for /var/log in the Container
For containers that generate a lot of short‑lived logs, mount /var/log as a tmpfs. This keeps logs in RAM and they vanish when the container stops:
podman run -d \
--tmpfs /var/log:rw,size=100m \
nginx:alpine
The trade‑off is that logs are lost on reboot, but for stateless services it’s often acceptable.
Trade‑offs and Security
- Journald vs. Files: Journald compresses and rotates automatically, but you lose the ability to stream logs to external systems without extra tooling. File logs are portable but need explicit rotation.
- Podman Log Options: The
max-size/max-fileflags are easy but still keep logs on disk. If the container writes a burst of data, you might hit the size limit before rotation kicks in. - Systemd Units: Capturing logs in the user journal keeps them separate from root logs, which is good for isolation. However, the user’s journal can grow if you forget to vacuum.
- tmpfs: Fast and clean, but logs are lost on shutdown. Also, RAM usage can spike if the container writes a lot of data.
From a security standpoint, keeping logs in the journal avoids exposing raw log files to the host filesystem, reducing the attack surface. If you need to audit logs, the journal’s structured format is easier to parse with journalctl.
Practical Commands and Examples
# Start nginx with journald logging
podman run --name nginx \
--log-driver=journald \
-d nginx:alpine
# Check journal entries
journalctl -u nginx --since "1 hour ago"
# Prune old journal entries
journalctl --vacuum-time=30d
# Run container with log rotation
podman run --name myapp \
--log-driver=json-file \
--log-opt=max-size=5m
See also
- Recovering a single config file from a corrupted Borg backup without restoring the whole archive
- Preventing Rootless Podman from Filling Up My Home Directory with Container Logs
- Running My Home NAS Backups with `nice` and `ionice` So My Desktop Never Freezes
- Docker builds on a 32 GB Raspberry Pi: How I recovered from a full disk
- Using a systemd path unit to clean my home server’s cache when disk space hits 90%