slackhq/nebula · error

a device name in the format of /dev/tunN must be specified

Error message

a device name in the format of /dev/tunN must be specified

What it means

newTun on NetBSD requires the tun.dev config value to be a device name matching tunN (opened as /dev/tunN). This error is returned when tun.dev is empty, or when the value doesn't match the ^tun[0-9]+$ pattern. NetBSD has no automatic device naming, so an explicit valid name is mandatory.

Source

Thrown at overlay/tun_netbsd.go:82

	Routes      atomic.Pointer[[]Route]
	routeTree   atomic.Pointer[bart.Table[routing.Gateways]]
	l           *slog.Logger
	f           *os.File
	fd          int
}

var deviceNameRE = regexp.MustCompile(`^tun[0-9]+$`)

func newTunFromFd(_ *config.C, _ *slog.Logger, _ int, _ []netip.Prefix) (*tun, error) {
	return nil, fmt.Errorf("newTunFromFd not supported in NetBSD")
}

func newTun(c *config.C, l *slog.Logger, vpnNetworks []netip.Prefix, _ bool) (*tun, error) {
	// Try to open tun device
	var err error
	deviceName := c.GetString("tun.dev", "")
	if deviceName == "" {
		return nil, fmt.Errorf("a device name in the format of /dev/tunN must be specified")
	}
	if !deviceNameRE.MatchString(deviceName) {
		return nil, fmt.Errorf("a device name in the format of /dev/tunN must be specified")
	}

	fd, err := unix.Open("/dev/"+deviceName, os.O_RDWR, 0)
	if err != nil {
		return nil, err
	}

	err = unix.SetNonblock(fd, true)
	if err != nil {
		l.Warn("Failed to set the tun device as nonblocking", "error", err)
	}

	t := &tun{
		f:           os.NewFile(uintptr(fd), ""),
		fd:          fd,

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Set tun.dev in config to a bare device name like 'tun0' (no /dev/ prefix).
  2. Ensure the name matches tun[0-9]+ exactly — lowercase 'tun' followed only by digits.
  3. Verify the device node exists: ls /dev/tun* and create it if your NetBSD setup requires (ifconfig tun0 create).
  4. If migrating from Linux, remember tun.dev is required on NetBSD.

Example fix

// before (config)
tun:
  dev: /dev/tun0   # wrong: includes /dev/ prefix
// after
tun:
  dev: tun0
Defensive patterns

Strategy: validation

Validate before calling

var deviceNameRE = regexp.MustCompile(`^tun[0-9]+$`)
func validNetbsdTunDev(cfg string) bool {
    return deviceNameRE.MatchString(cfg) // 'tun0' ok; '/dev/tun0' and '' are not
}

Try / catch

if err := startOverlay(c); err != nil {
    if strings.Contains(err.Error(), "device name in the format of /dev/tunN must be specified") {
        log.Error("set tun.dev to a bare name like 'tun0' (no /dev/ prefix)")
    }
}

Prevention

When it happens

Trigger: Starting the overlay on NetBSD with tun.dev unset, or set to something like 'tun', 'tunX', '/dev/tun0', 'eth0', or 'tun10x' — anything not matching tun followed by digits.

Common situations: Copying a Linux config (where tun.dev is optional) to NetBSD; including the /dev/ prefix in tun.dev even though the message mentions /dev/tunN; typo in the device name.

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/38945c26d9558fe5. Report an issue: GitHub.