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 OpenBSD requires an explicit tun device name via the 'tun.dev' config key. If the value is empty, the constructor refuses to proceed because OpenBSD tun devices must be opened by path (/dev/tunN), unlike Linux which can clone /dev/net/tun. This error signals the mandatory config key is missing.
Source
Thrown at overlay/tun_openbsd.go:73
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 openbsd")
}
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
- Set 'tun.dev: /dev/tun0' (or the appropriate /dev/tunN) in the config file
- Verify with `ls /dev/tun*` which tun devices exist and pick a free one
- Create the device if missing: `cd /dev && sh MAKEDEV tun0`
Example fix
# before tun: enabled: true # after tun: enabled: true dev: /dev/tun0
Defensive patterns
Strategy: validation
Validate before calling
dev := cfg.GetString("tun.dev", "")
if dev == "" {
return fmt.Errorf("tun.dev must be set on OpenBSD, e.g. /dev/tun0")
}
if _, err := os.Stat("/dev/" + strings.TrimPrefix(dev, "/dev/")); err != nil {
return fmt.Errorf("tun device %s not found", dev)
} Prevention
- Always set tun.dev in OpenBSD configs
- Check for /dev/tun* device nodes at startup
- Document platform-specific tun keys in config templates
When it happens
Trigger: Starting nebula with tun.enabled and no 'tun.dev' set in the config file (c.GetString("tun.dev", "") returns "").
Common situations: Copying a Linux-oriented config to an OpenBSD host; forgetting platform-specific tun settings; generating configs from templates that omit tun.dev.
Related errors
- no inside interface (tun)
- a device name in the format of /dev/tunN must be specified
- newTunFromFd not supported in openbsd
- error closing tun file: %w
- unable to determine IP version from packet
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/70e76c243d40b754.
Report an issue: GitHub.