What is the same, what is different and what is simply missing, on a real NetBSD 11.1 machine: services, packages, privileges, disks and network, with a Linux-to-NetBSD table to keep.
▶Prefer to watch? This short video runs this page's main commands on a real NetBSD 11.1 machine, with on-screen captions and a synthetic voiceover (an AI voice trained on the author's own recording). Click to play, or watch it on YouTube.
echo 'httpd=YES' >> /etc/rc.conf # start at boot
/etc/rc.d/httpd start # start it now
pkgin -y install figlet # install a package
If you know Linux you already know most of NetBSD: a Unix shell, the same everyday commands, files in the same places. This page covers the parts that are different, in the order you meet them: the manual, services without systemd, packages from pkgsrc, su instead of sudo, disks, the network and sysctl, with a Linux-to-NetBSD table at the end.
Every example ran for real on NetBSD 11.1 (amd64) in a virtual machine, as an ordinary user, with root commands marked #. The output you see is the output the machine gave.
What NetBSD is, and the lab
NetBSD is a complete Unix-like operating system, built to run on as many kinds of hardware as possible: PCs, servers, ARM boards, old workstations and more, all from one source tree. The kernel, the C library, the shell, the network tools and the manual pages are developed together, and a release has one version number for all of it. Software from outside the project comes from pkgsrc, a package collection that also works on Linux and macOS.
Every example below ran for real on NetBSD 11.1 (amd64) in a virtual machine, as an ordinary user called bsd. Where a command needs root it starts with # and is run as root, because NetBSD has no sudo by default. If you know Linux, most of this will feel familiar, with a few surprises.
$ uname -srm
NetBSD 11.1 amd64
$ echo $SHELL
/bin/sh
$ id
uid=1000(bsd) gid=100(users) groups=100(users),0(wheel)
$ sysctl kern.version | head -n 1
kern.version = NetBSD 11.1 (GENERIC) #0: Mon Nov 2 16:34:32 UTC 2026
The login shell is /bin/sh, the NetBSD Bourne shell, which is small and strict. It is a proper Almquist shell, not bash, so write scripts to POSIX rules. The user bsd is in the group wheel, which is what allows su to root.
The manual is part of the system
NetBSD documents itself well, and the pages are written with the code. Section 7 holds the overviews, which is where to start:
$ man -k hier | head -n 3
hier (7) layout of file systems
hier
$ man hier 2>/dev/null | col -b | sed -n 1,10p
HIER(7) Miscellaneous Information Manual HIER(7)
NAME
hier - layout of file systems
DESCRIPTION
An outline of the file system hierarchy.
Naming is very important. The UNIX System relies on filename conventions
for much of its power as a system. The following file system layout
$ man -w afterboot
/usr/share/man/man8/afterboot.8
$ man -k pkgsrc | head -n 2
pkgsrc (7) NetBSD packages collection (framework for third-party software)
...to perform various administrative tasks for the package system. pkg_add(1) , pkg_delete(1) , pkg_info(1) Alistair Crooks Hubert Feyrer The pkgsrc developers The pkgsrc guide, Documentation on the NetBSD packages system https://www.NetBSD.org/docs/pkgsrc/
hier(7) describes the file system layout, and afterboot(8) is the checklist for a new install. A manual page for each subsystem, and for each daemon, is the norm. man -k searches by keyword, the same as apropos.
The base system, and pkgsrc beside it
NetBSD keeps the system and the extra software strictly apart. The base system lives in /bin, /sbin, /usr/bin and /usr/sbin and is updated as a whole with the release. Everything you add from pkgsrc goes under /usr/pkg, with its own bin, etc and man directories.
$ ls /usr/pkg
bin
etc
include
lib
man
pkgdb
pkgdb.refcount
sbin
share
$ echo $PATH
/usr/bin:/bin:/sbin:/usr/sbin:/usr/pkg/bin:/usr/pkg/sbin:/usr/local/bin
$ ls /usr/pkg/etc | head -n 5
pkgin
$ ls /etc/rc.d | wc -l
132
The rule is easy to remember: if it came with the release, it is in /usr or /; if you installed it, it is in /usr/pkg and its configuration is in /usr/pkg/etc. Linux distributions mix the two. Here, removing all of pkgsrc never touches the base system.
Services: rc.d and rc.conf
NetBSD has no systemd. Services are shell scripts in /etc/rc.d, and one file, /etc/rc.conf, decides which ones run at boot. A fresh install is small:
$ cat /etc/rc.conf | grep -v '^#' | grep .
if [ -r /etc/defaults/rc.conf ]; then
. /etc/defaults/rc.conf
fi
rc_configured=YES
sshd=YES
hostname=nbsd
dhcpcd=YES
dhcpcd_flags="-qM -4 vioif0"
wscons=YES
$ grep -E '^(sshd|httpd|ntpd)=' /etc/defaults/rc.conf
ntpd=NO ntpd_flags="" # see below for ntpd_chrootdir
sshd=NO sshd_flags=""
httpd=NO httpd_flags=""
$ /etc/rc.d/sshd status
sshd is running as pid 834.
$ netstat -an -f inet | grep LISTEN
tcp 0 0 *.22 *.* LISTEN
/etc/defaults/rc.conf lists every setting and its default, and you override only what you need in /etc/rc.conf. The listing above shows sshd running and listening on port 22, and nothing else. Now start a web server. bozohttpd is a small web server in the base system, and its rc.d script is called httpd. Give it a page, switch it on in rc.conf, then start it:
# echo "hello from NetBSD" > /var/www/index.html
# echo 'httpd=YES' >> /etc/rc.conf
# /etc/rc.d/httpd start
Starting httpd.
$ /etc/rc.d/httpd status
httpd is running as pid 1315.
The value in rc.conf makes it start at every boot, and the script starts it now. Check it from the machine itself:
$ ftp -o - http://127.0.0.1/ 2>&1
hello from NetBSD
$ netstat -an -f inet | grep LISTEN
tcp 0 0 *.80 *.* LISTEN
tcp 0 0 *.22 *.* LISTEN
ftp is also the NetBSD download tool, and it speaks http. Stop it again:
# /etc/rc.d/httpd stop
Stopping httpd.
# sed -i.bak '/^httpd=YES/d' /etc/rc.conf
$ /etc/rc.d/httpd status; echo "exit status $?"
$httpd is not enabled - see rc.conf(5).
Use the following if you wish to perform the operation:
/etc/rc.d/httpd onestatus
exit status 1
With the line gone from rc.conf, the script refuses to run: the message is NetBSD's own and shows the name of the setting. onestatus ignores rc.conf. Every script takes start, stop, restart and status. Run it without arguments to see the list.
Packages: pkgin and pkg_add
The package tools come from pkgsrc. pkgin works like apt or dnf: it knows what exists, picks the dependencies and installs binary packages. Under it, pkg_add, pkg_info and pkg_delete do the work and are part of the system.
# pkgin -y install figlet
calculating dependencies...done.
1 package to install:
figlet-2.2.5nb2
0 to remove, 0 to refresh, 0 to upgrade, 1 to install
92K to download, 661K of additional disk space will be used
[1/1] downloading figlet-2.2.5nb2.tgz done.
[1/1] installing figlet-2.2.5nb2...
pkg_install warnings: 0, errors: 0
reading local summary...
processing local summary...
$ pkg_info | head -n 4
pkg_install-20260227 Package management and administration tools for pkgsrc
sqlite3-3.53.4 SQL Database Engine in a C Library
pkgin-26.4.0 Apt / yum like tool for managing pkgsrc binary packages
tree-1.8.0 Print a text or HTML tree diagram of a directory structure
$ pkgin search figlet
figlet-2.2.5nb2 = Print text banners in fancy ASCII art characters
figlet-fonts-20021023nb1 Additional fonts for figlet
toilet-0.3 Free replacement for the FIGlet utility
=: package is installed and up-to-date
<: package is installed but newer version is available
>: installed package has a greater version than available package
$ figlet NetBSD
_ _ _ ____ ____ ____
| \ | | ___| |_| __ ) ___|| _ \
| \| |/ _ \ __| _ \___ \| | | |
| |\ | __/ |_| |_) |__) | |_| |
|_| \_|\___|\__|____/____/|____/
$ pkg_info -FI /usr/pkg/bin/figlet
figlet-2.2.5nb2 Print text banners in fancy ASCII art characters
pkgin -y answers yes to its question. pkg_info lists what is installed, and -F with -I and a file name tells you which package owns it, much like dpkg -S. Packages install under /usr/pkg and never overwrite base files.
# pkgin -y remove figlet
1 packages to delete:
figlet-2.2.5nb2
[1/1] removing figlet-2.2.5nb2...
pkg_install warnings: 0, errors: 0
reading local summary...
processing local summary...
$ pkg_info | grep -c figlet
0
(exit status 1)
The mirror comes from /usr/pkg/etc/pkgin/repositories.conf, which holds one line. Source packages are also available: pkgsrc is a tree of build recipes that you fetch with CVS or git and compile with make, which is how the binary packages are made.
su, wheel and no sudo
A new NetBSD install has no sudo and no doas. Administration is done as root, and you become root with su. Only members of the group wheel may do that, and the user created during the install is already in it:
$ id
uid=1000(bsd) gid=100(users) groups=100(users),0(wheel)
$ grep '^wheel' /etc/group
wheel:*:0:root,bsd
$ which sudo doas; echo "exit status $?"
exit status 3
$ man su 2>/dev/null | col -b | sed -n 20,30p
is provided) is requested, and su switches to that user and group ID
after obtaining a Kerberos ticket granting ticket. A shell is then
executed, and any additional shell arguments after the login name are
passed to the shell. su will resort to the local password file to find
the password for login if there is a Kerberos error. If su is executed
by root, no password is requested and a shell with the appropriate user
ID is executed; no additional Kerberos tickets are obtained.
Alternatively, if the user enters the password "s/key", authentication
will use the S/Key one-time password system as described in skey(1).
S/Key is a Trademark of Bellcore.
su - starts a login shell as root, and prompts for the root password. On a machine with several administrators, install sudo or doas from pkgsrc with pkgin. Both are one line away, and they keep their configuration in /usr/pkg/etc.
Disks and file systems
NetBSD names disks by driver, like ld0 for a virtual disk, wd0 for SATA and sd0 for SCSI or USB. The disk is divided by a disklabel, and the root file system is the partition a:
$ df -h | head -n 3
Filesystem Size Used Avail %Cap Mounted on
/dev/ld0a 17G 1.3G 15G 8% /
tmpfs 512M 4.0K 512M 1% /tmp
# disklabel ld0 | tail -n 6
4 partitions:
# size offset fstype [fsize bsize cpg/sgs]
a: 37748672 64 4.2BSD 0 0 0 # (Cyl. 0*- 37449*)
b: 4194304 37748736 swap # (Cyl. 37449*- 41610*)
c: 41942976 64 unused 0 0 # (Cyl. 0*- 41610*)
d: 41943040 0 unused 0 0 # (Cyl. 0 - 41610*)
$ grep -v '^#' /etc/fstab | head -n 3
/dev/ld0a / ffs rw 1 1
/dev/ld0b none swap sw,dp 0 0
tmpfs /tmp tmpfs rw,-m1777,-sram%25
The default install uses just two partitions: a for / and b for swap. The disk label says FFS for the file system, which is the BSD fast file system. Note that /etc/fstab names devices, not UUIDs. If you move a disk to another controller its name changes and the machine will not boot until you edit that file. Many people use wedge names (NAME=) or dk devices to avoid the problem.
Network configuration
There is no network manager. The installer started dhcpcd, the DHCP client, and the rc.conf line that follows tells it which interface to manage. A fixed address is a line in /etc/ifconfig.vioif0 instead.
$ grep dhcpcd /etc/rc.conf
dhcpcd=YES
dhcpcd_flags="-qM -4 vioif0"
$ ifconfig vioif0 | grep -E 'status|inet '
status: active
inet 10.0.2.15/24 broadcast 10.0.2.255 flags 0
$ route -n show -inet | head -n 5
Routing tables
Internet:
Destination Gateway Flags Refs Use Mtu Interface
default 10.0.2.2 UG - - - vioif0
$ cat /etc/resolv.conf
# Generated by resolvconf
nameserver 10.0.2.3
$ cat /etc/ifconfig.vioif0
up
The name of the interface shows the driver: vioif is the virtio network card here, and a PC would show something like re0 or wm0. /etc/resolv.conf is written by resolvconf, so do not edit it by hand.
sysctl, securelevel and kernel modules
The kernel settings are read and written with sysctl, and /etc/sysctl.conf is applied at boot:
$ sysctl hw.ncpu hw.physmem
hw.ncpu = 2
hw.physmem = 2146942976
$ sysctl kern.securelevel
kern.securelevel = -1
$ grep -v '^#' /etc/sysctl.conf | grep .
ddb.onpanic?=0
net.inet6.ip6.accept_rtadv=0
$ modstat | head -n 4
NAME CLASS SOURCE FLAG REFS SIZE REQUIRES
aac driver builtin - 1 - pci
accf_dataready misc builtin - 0 - -
accf_httpready misc builtin - 0 - -
kern.securelevel is -1, the permanently insecure mode, which is the default. On OpenBSD the same value is 1 after boot. NetBSD lets you raise the level in /etc/rc.conf with the setting securelevel, but does not do it for you. modstat lists the kernel modules, and modload and modunload add and remove them while the system runs.
Linux to NetBSD side by side
Most commands you know have a close cousin here:
- systemctl enable and start: put name=YES in /etc/rc.conf, then /etc/rc.d/name start.
- journalctl: the logs are plain text files in /var/log, written by syslogd.
- apt or dnf: pkgin for binary packages, pkgsrc for building from source.
- dpkg -S: pkg_info -F file.
- sudo: su for root, or install sudo or doas from pkgsrc.
- NetworkManager: dhcpcd plus /etc/ifconfig.<interface>.
- /etc/fstab with UUIDs: /etc/fstab with device names.
- lsblk: disklabel and dmesg.
- ip addr: ifconfig. ip route: route.
- /proc: it exists, and so does /kern.
- bash: sh, and bash from pkgsrc if you want it.
Config files are in /etc for the system and /usr/pkg/etc for packages. When in doubt, man hier explains where a file belongs.
When something goes wrong
The first errors you will meet are about permissions and about a search that finds nothing:
$ pkgin -y install figlet
pkgin: You don't have enough rights for this operation.
(exit status 1)
$ pkgin search nosuchpackage-xyz; echo "exit status $?"
No results found for nosuchpackage-xyz
exit status 1
$ nosuchcommand
sh: nosuchcommand: not found
(exit status 127)
$ /etc/rc.d/nosuchservice start
sh: /etc/rc.d/nosuchservice: not found
(exit status 127)
pkgin refuses to install without root, and says so plainly. A search that finds nothing prints a message and a non-zero exit status, which scripts can test. A command that is not installed is not found, and a service script that does not exist is simply an error about the file. When a daemon fails to start, the reason is usually in /var/log/messages, and dmesg shows the kernel messages.