slackhq/nebula · error
failed to bring the tun device up: %s
Error message
failed to bring the tun device up: %s
What it means
Raised in tun.Activate when the SIOCSIFFLAGS ioctl that sets IFF_UP on the tun interface fails. The device exists and its flags were read successfully, but the kernel refused to bring the interface administratively up.
Source
Thrown at overlay/tun_linux.go:490
ifrq := ifreqQLEN{Name: devName, Value: int32(t.TXQueueLen)}
if err = ioctl(t.ioctlFd, unix.SIOCSIFTXQLEN, uintptr(unsafe.Pointer(&ifrq))); err != nil {
// If we can't set the queue length nebula will still work but it may lead to packet loss
t.l.Error("Failed to set tun tx queue length", "error", err)
}
const modeNone = 1
if err = netlink.LinkSetIP6AddrGenMode(link, modeNone); err != nil {
t.l.Warn("Failed to disable link local address generation", "error", err)
}
if err = t.addIPs(link); err != nil {
return err
}
// Bring up the interface
ifrf.Flags = ifrf.Flags | unix.IFF_UP
if err = ioctl(t.ioctlFd, unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil {
return fmt.Errorf("failed to bring the tun device up: %s", err)
}
//set route MTU
for i := range t.vpnNetworks {
if err = t.setDefaultRoute(t.vpnNetworks[i]); err != nil {
return fmt.Errorf("failed to set default route MTU: %w", err)
}
}
// Set the routes
if err = t.addRoutes(false); err != nil {
return err
}
// Run the interface
ifrf.Flags = ifrf.Flags | unix.IFF_UP | unix.IFF_RUNNING
if err = ioctl(t.ioctlFd, unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil {
return fmt.Errorf("failed to run tun device: %s", err)View on GitHub (pinned to dd8f660c0a)
Solutions
- Run with sufficient privileges (root or CAP_NET_ADMIN) so interface flags can be changed.
- Check the %s errno: EPERM = permissions, ENODEV = interface gone.
- Ensure the device isn't being torn down concurrently (unmanaged in NetworkManager/systemd-networkd).
- Manually verify with `ip link set <dev> up` to confirm it's a privilege vs device issue.
Example fix
// before $ ./nebula -config config.yml # EPERM // after $ sudo setcap cap_net_admin=ep ./nebula $ ./nebula -config config.yml
Defensive patterns
Strategy: validation
Validate before calling
// require privileges before attempting to bring the interface up
if os.Geteuid() != 0 && !hasCapNetAdmin() {
return errors.New("bringing tun up requires root or CAP_NET_ADMIN")
} Try / catch
if err := t.Activate(netstack); err != nil {
if strings.Contains(err.Error(), "failed to bring the tun device up") {
if errors.Is(err, os.ErrPermission) || strings.Contains(err.Error(), "operation not permitted") {
log.Error("grant CAP_NET_ADMIN: setcap cap_net_admin=ep <binary>")
}
}
} Prevention
- Deploy with setcap cap_net_admin=ep or run under a privileged service
- Test `ip link set <dev> up` manually to separate privileges from device issues
- Keep network managers from resetting interface flags during startup
When it happens
Trigger: Activate() calls ioctl(t.ioctlFd, SIOCSIFFLAGS, ...) with Flags|IFF_UP and the kernel returns an error — typically EPERM from missing privileges or ENODEV if the link vanished.
Common situations: Running nebula without root/CAP_NET_ADMIN; interface removed concurrently by a network manager; containers where SIOCSIFFLAGS on the host-owned device is denied.
Related errors
- /dev/net/tun doesn't exist, failed to mkdir -p /dev/net: %w
- failed to create /dev/net/tun: %w
- created /dev/net/tun, but still failed: %w
- failed to enable offload on multiqueue tun fd: %w
- failed to get tun address list: %s
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/dfb26e48fe7c2092.
Report an issue: GitHub.