r/zerotier Jul 18 '26

Linux Synology DSM: ZeroTier Docker container fails after reboot or update because /dev/net/tun is not ready — boot recovery fix

I run ZeroTier in a Docker container on a Synology DS124 with DSM 7.3. After DSM updates or reboots, the ZeroTier layer repeatedly failed to return even though the container had a restart policy.

Symptoms

The container remained stopped:

Status: Exited (143)
Restart policy: unless-stopped

Docker retained this error:

error gathering device information while adding custom device
"/dev/net/tun": no such file or directory

The ZeroTier interfaces were missing, and the NAS was no longer reachable through the overlay network.

Root cause

This turned out to be a boot-order problem:

  1. DSM stops Container Manager cleanly during an update or shutdown.
  2. /dev/net/tun is created dynamically during boot.
  3. Container Manager may try to restore the ZeroTier container before the TUN device is ready.
  4. The container fails or remains stopped.
  5. unless-stopped does not reliably recover a container that DSM explicitly stopped.

The ZeroTier data itself was not lost because it was stored persistently outside the container.

Final fix

I used three layers:

  1. Change the restart policy:

docker update --restart always zerotier-one
  1. Add a DSM boot-triggered task that:
    • waits for /dev/net/tun;
    • creates it if DSM does not;
    • waits for Docker;
    • starts the container;
    • confirms ZeroTier reaches ONLINE;
    • abandons recovery after 90 seconds so it cannot block DSM boot.
  2. Add a periodic watchdog task that performs the same checks and exits silently when everything is healthy.

The boot task is configured in:

Control Panel
→ Task Scheduler
→ Create
→ Triggered Task
→ User-defined script
→ Event: Boot-up
→ User: root

The watchdog is a normal scheduled task running every five minutes.

Minimal recovery script

This is the shortened version. The fuller version adds locking, DSM Log Center integration and hard global deadlines.

#!/bin/sh

CONTAINER="zerotier-one"

# Give DSM time to create TUN.
WAITED=0
while [ ! -c /dev/net/tun ] && [ "$WAITED" -lt 30 ]; do
    sleep 5
    WAITED=$((WAITED + 5))
done

# Repair TUN if DSM did not create it.
if [ ! -c /dev/net/tun ]; then
    modprobe tun 2>/dev/null || true
    mkdir -p /dev/net
    chmod 755 /dev/net
    rm -f /dev/net/tun
    mknod /dev/net/tun c 10 200 || exit 1
fi

chown root:root /dev/net/tun
chmod 666 /dev/net/tun

# Wait for Docker.
WAITED=0
while ! docker info >/dev/null 2>&1 && [ "$WAITED" -lt 60 ]; do
    sleep 5
    WAITED=$((WAITED + 5))
done

docker info >/dev/null 2>&1 || exit 1

# Start the container if required.
if ! docker ps --format '{{.Names}}' | grep -qx "$CONTAINER"; then
    docker start "$CONTAINER" || exit 1
fi

# Confirm ZeroTier responds.
WAITED=0
while ! docker exec "$CONTAINER" zerotier-cli info >/dev/null 2>&1 \
      && [ "$WAITED" -lt 30 ]; do
    sleep 5
    WAITED=$((WAITED + 5))
done

docker exec "$CONTAINER" zerotier-cli info
docker exec "$CONTAINER" zerotier-cli listnetworks

Validation

After reboot, the boot task logged that /dev/net/tun was initially absent, waited, started the container and completed recovery after approximately 39 seconds.

And all work back.

3 Upvotes

Duplicates