DEV Community

iatxako
iatxako

Posted on

Your NAS Is Loud Because of Docker and Syncthing (and How to Fix It)

You buy a NAS for silent, always-on storage. It sits in a corner, humming quietly, doing its thing. Then you install Docker. Then Syncthing. Then a few containers.

Suddenly the HDDs never stop. Seeking, spinning, clicking. Not occasionally - constantly. At 2am you can hear it from the next room.

This is what happened, why it happens, and how to make it stop.

What's Actually Causing the Noise

Mechanical HDDs make noise when the read/write head moves. The more random the I/O - small reads and writes scattered across the disk - the more seeking, the more noise. Sequential writes to a single file are quiet. Random I/O across thousands of small files is loud.

Docker and Syncthing are both pathological for HDDs in different ways.

Docker overlay2

Docker's default storage driver is overlay2. Every container runs on top of layered filesystems - the image layers are stacked, and a thin writable layer sits on top for each running container.

Every file operation inside a container that touches a file from a lower layer triggers a copy-on-write: the entire file gets copied up to the writable layer before the write happens. On an SSD this is fast and silent. On spinning HDDs with mechanical heads, every copy-on-write is a seek, a read, and a write - often scattered across the disk.

And it's not just copy-on-write. Docker's overlay2 metadata lives in small files across a deep directory tree. Container startup reads dozens of these. Log rotation writes to them. Health checks touch them. Any container doing anything at all generates constant scattered I/O.

Syncthing's 60-Second Heartbeat

Syncthing uses BoltDB as its internal database - it stores file indexes, sync state, and peer information there. BoltDB flushes to disk every 60 seconds regardless of whether anything changed.

On a busy sync folder with thousands of files, this flush isn't a single sequential write. It rewrites pages across the B-tree structure, which means multiple seeks across the database file. Quiet when it's an SSD. Audible on HDDs - a short burst of activity every minute, on the minute, forever.

Once you know this, you'll recognize the pattern. Every 60 seconds: click-click-seek. Every 60 seconds.

Everything Else Piling On

Beyond Docker and Syncthing, a typical homelab NAS has:

  • System monitoring tools running on cron (every 5-10 minutes, writing stats to disk)
  • systemd journal flushing logs
  • The NAS OS itself doing housekeeping

None of these alone would be noticeable. All of them together, on top of Docker and Syncthing, means the HDDs are never idle long enough to spin down.

Diagnosing Which Process Is the Problem

Before moving anything, confirm what's actually hitting the disk:

# Real-time I/O per process (needs sysstat)
sudo iotop -o

# Disk utilization over time
iostat -x 2 10

# Which files are being written most
sudo fatrace | grep -E 'W|O'
Enter fullscreen mode Exit fullscreen mode

iotop -o shows only processes with active I/O. On a typical Docker + Syncthing setup you'll see the Docker daemon and the Syncthing process trading places at the top, with periodic spikes from cron jobs.

The Fix: Move the Noisy Workloads Off the HDDs

The HDDs are loud because they're doing work they shouldn't be doing. The solution is to give that work to something that doesn't make noise.

An external SSD connected via USB is cheap, silent, and fast enough for everything Docker and Syncthing need. USB 3.0 to a SATA SSD delivers 400+ MB/s - far more than any container workload requires.

The goal: HDDs handle only the NAS OS and system logs. Everything else moves to the SSD.

What to Migrate

Docker data-root - the overlay2 layers, image cache, container writable layers. By default this lives in a path managed by the NAS OS. Moving it to the SSD means all container I/O hits flash storage.

# /etc/docker/daemon.json
{"data-root": "/mnt/external-ssd/@docker"}
Enter fullscreen mode Exit fullscreen mode

Bind-mount volumes - the persistent data your containers read and write (databases, config files, sync folders). If these live on the HDD, container writes hit the HDD. Move them to the SSD.

For bind mounts, a symlink keeps things transparent - containers keep using the same paths, no reconfiguration needed:

# Original path stays the same from Docker's perspective
ln -s /mnt/external-ssd/volumes /original/volumes/path
Enter fullscreen mode Exit fullscreen mode

Syncthing database - if you can point Syncthing's home directory to the SSD, the 60-second BoltDB flush hits flash instead of spinning metal.

What Stays on the HDDs

  • The NAS operating system
  • System logs
  • Your actual data files (documents, media, backups) - these have sequential I/O patterns that HDDs handle well and that don't cause the constant seeking noise

A Note on Copying Files (UGOS Pro Caveat)

If your NAS runs UGOS Pro (UGREEN's Debian-based OS), there's a critical gotcha: rsync will silently corrupt permissions when copying from the NAS filesystem to an external drive. This is caused by proprietary kernel-level xattr hooks in UGOS Pro.

I ran into this the hard way. Both rsync -aHX and rsync -aH --no-xattrs result in all files getting reset to 600 permissions - containers fail to start, nothing works.

The fix and the full technical explanation are in a separate post: Why rsync Destroys Permissions on UGOS Pro - and the Only Fix That Works

Short version: use tar --xattrs-exclude='ug.*' instead of rsync for any file copy on UGOS Pro.

Mount the SSD Correctly

# /etc/fstab
UUID=<your-uuid> /mnt/external-ssd ext4 defaults,noatime,nofail 0 2
Enter fullscreen mode Exit fullscreen mode

Two flags matter:

  • noatime - disables access time updates on every file read. Eliminates a whole class of unnecessary writes.
  • nofail - if the SSD disconnects and the NAS reboots, it boots normally instead of hanging at the fstab error. Containers won't start, but the NAS stays accessible.

The Result

After migration: the HDDs are nearly silent. You can hear them spin up occasionally - system logs flushing, a cron job writing stats - but the constant background noise is gone. The 60-second Syncthing heartbeat is inaudible. Container I/O is invisible.

The NAS is back to being the quiet box in the corner it was always supposed to be.


If your NAS runs UGOS Pro, read the companion post before attempting the migration - the rsync issue will cost you time if you hit it blind: Why rsync Destroys Permissions on UGOS Pro

Top comments (0)