OpenBSD FAQ - System Management [FAQ Index]



Duplicating filesystems

To duplicate everything under directory /SRC to directory /DST with dump(8) and restore(8), do:
# cd /SRC && dump 0f - . | (cd /DST && restore -rf - )
or use tar(1):
# cd /SRC && tar cf - . | (cd /DST && tar xpf - )

The rc system startup script

OpenBSD uses the rc(8) startup system. Its man page contains a good overview and explains the various scripts and files involved. If you wish to enable or disable daemons, use rcctl(8) to manage your rc.conf.local(8) file, as described below.

Starting daemons and services that come with OpenBSD

Most daemons and services that come with OpenBSD are controlled on boot by variables defined in /etc/rc.conf. You'll see lines similar to this:
httpd_flags=NO
This shows that httpd(8) is not to be started from rc(8) at boot time. Each line has a comment showing you the flags for common usage of that daemon or service.

Do not alter rc.conf(8) directly. Instead, use the rcctl(8) utility to maintain the /etc/rc.conf.local file. This makes future upgrades easier -- all the changes are in the one file that isn't touched during upgrade.

For example, to start the apmd(8) daemon for CPU scaling, you might do:

# rcctl enable apmd
# rcctl set apmd flags -A
# rcctl start apmd

Starting up local daemons and configuration

For other daemons which you might install on the system via packages or other ways, you could use the /etc/rc.local file. For example, say you installed a daemon located at /usr/local/sbin/daemonx. If you want it to start at boot time, put an entry into /etc/rc.local like this:
if [ -x /usr/local/sbin/daemonx ]; then
	echo 'Starting daemonx' && /usr/local/sbin/daemonx
fi
If the daemon does not automatically detach on startup, remember to add "&" at the end of the command-line.

From now on, this daemon will be started at boot. You will be able to see any errors on boot.

The /etc/rc.d directory

OpenBSD's system daemons ("services") are started, stopped and controlled by rc.d(8). All system daemons are handled by these scripts, and most add-on packages are as well.

These scripts, one per daemon, are invoked by rc. The order for system daemons is coded into rc, and the order for packages is managed by the pkg_scripts environment variable, which would be set in /etc/rc.conf.local. Note that simply placing a script in this directory does not cause it to be run on boot; the name of the script must be specified in the pkg_scripts variable to start on boot.

The starting of system scripts is determined by entries in the /etc/rc.conf.local file. For example, /etc/rc.d/httpd does not start httpd(8) unless /etc/rc.conf or /etc/rc.conf.local contains a line defining the httpd_flags variable.

Note that rather than having each script in rc.d managing the entire startup, shutdown, reload, restart, and check operations, most rc.d scripts can be reduced to specifying very few variables, and invoking the rc.subr(8) script, which manages most of the standard way of doing these tasks.

For example, our above daemonx application could be started with a /etc/rc.d/daemonx file consisting of:

#!/bin/sh

daemon="/usr/local/sbin/daemonx"

. /etc/rc.d/rc.subr

rc_cmd $1
and adding the daemon name to the pkg_scripts variable in /etc/rc.conf.local.

OpenBSD's sudo replacement, doas

doas(1) allows a user to run commands as another user. For example, if appropriately configured,
$ doas crontab -l -u root
will display root's crontab(5) file.

One common challenge system administrators face is the contradictory requirement of multiple people managing machines using logins that shouldn't be shared. doas(1) solves this problem by permitting a certain subset of your users to run predetermined commands as another user. Now, these users can run administrative commands, only needing to authenticate as themselves. They do not need to know the root password.

All activity is logged to /var/log/secure.

A very basic doas.conf(5) might look like this:

permit keepenv { PKG_PATH ENV PS1 SSH_AUTH_SOCK } :wheel as root
This file gives users in the wheel group root-level access to all commands, with the environment variables PKG_PATH, ENV, PS1 and SSH_AUTH_SOCK passed through to the program they are invoking. The user will be asked to verify their password before the command is run.

The doas.conf(5) manual contains more examples.

doas(1) is designed to be a minimalistic and simple replacement of sudo(8) and might not cover all your needs. An up-to-date version of sudo(8) is available as a package.

Managing users and groups

OpenBSD offers several tools for managing users and groups on your system:

Editing the password file

The main password file is /etc/master.passwd, which is only readable by root. The pwd_mkdb(8) utility generates the publicly readable /etc/passwd file and the password databases /etc/pwd.db and /etc/spwd.db from /etc/master.passwd. The file format is described in passwd(5).

Always use vipw(8) to edit your /etc/master.passwd file. vipw(8) will invoke your $EDITOR to edit a copy of /etc/master.passwd. After you are done editing, vipw(8) will first sanity check your changes, then it will re-create /etc/passwd and the password databases, and finally it will install the copy in place of the original /etc/master.passwd file. vipw(8) also takes care of locking these files, so that only one user can make changes at a time.

Setting up user disk quotas

Quotas are used to place limits on the amount of disk space available to certain users and groups.

Use the keywords userquota and groupquota to mark each filesystem in fstab(5) on which you want to enforce quotas. By default, the files quota.user and quota.group will be created at the root of those filesystems. Here is an example /etc/fstab line:

0123456789abcdef.k /home ffs rw,nodev,nosuid,userquota 1 1
To set the users' quotas, use edquota(8). For example, issue
# edquota ericj
and edit the soft and hard limits:
Quotas for user ericj:
/home: KBytes in use: 62, limits (soft = 1000000, hard = 1500000)
        inodes in use: 25, limits (soft = 0, hard = 0)
In this example, the soft limit is set to 1000000k, and the hard limit is set to 1500000k. No limits on the number of inodes will be enforced, since the corresponding soft and hard limits are set to 0. Users who exceed their soft limit are warned and are given a grace period to get their disk usage below their limits. Grace periods can be set by using the -t option on edquota(8). After the grace period is over, the soft limit is handled as a hard limit. This usually results in an allocation failure.

Use quotaon(8) to enable quotas:

# quotaon -a
This will scan through fstab(5) and enable quotas on the filesystems with quota options. View quota statistics with quota(1).

Using S/Key

S/Key is a "one-time password" authentication system. It generates a sequence of one-time (single use) passwords from a user's secret passphrase along with a challenge received from the server, by means of a hash function: md5, sha1 or rmd160.
WARNING: One-time password systems only protect authentication information. They do not prevent network eavesdroppers from gaining access to private information. Furthermore, if you are accessing a secure system A, it is recommended that you do this from another trusted system B, to ensure nobody is gaining access to system A by logging your keystrokes or by capturing and/or forging input and output on your terminal devices.

Setting up S/Key

To start off, the directory /etc/skey must exist. If this directory doesn't exist, have the superuser create it by doing:
# skeyinit -E
Then use skeyinit(1) to initialize your S/Key. You will first be prompted for your login password, then you will be asked for your S/Key secret passphrase, which must be at least 10 characters long:
$ skeyinit
Reminder - Only use this method if you are directly connected
           or have an encrypted channel.  If you are using telnet,
           exit with no password and use skeyinit -s.
Password:
[Adding ericj with md5]
Enter new secret passphrase:
Again secret passphrase:

ID ericj skey is otp-md5 100 oshi45820
Next login password: HAUL BUS JAKE DING HOT HOG
Notice the information in the last two lines. The program used to create your S/Key password is otp-md5(1), the sequence number is 100 and the secret key is oshi45820. The six small words HAUL BUS JAKE DING HOT HOG constitute the S/Key password with sequence number 100.

Generating S/Key passwords

To generate the S/Key password for the next login, use skeyinfo(1) to find out what command to run:
$ skeyinfo -v
otp-md5 95 oshi45820
$ otp-md5 95 oshi45820
Reminder - Do not use this program while logged in via telnet.
Enter secret passphrase:
NOOK CHUB HOYT SAC DOLE FUME
In order to generate a list of S/Key passwords, do:
$ otp-md5 -n 5 95 oshi45820
Reminder - Do not use this program while logged in via telnet.
Enter secret passphrase:
91: SHIM SET LEST HANS SMUG BOOT
92: SUE ARTY YAW SEED KURD BAND
93: JOEY SOOT PHI KYLE CURT REEK
94: WIRE BOGY MESS JUDE RUNT ADD
95: NOOK CHUB HOYT SAC DOLE FUME

Using S/Key to log in

Here is an example session using S/Key to log in to an ftp server on localhost. To perform an S/Key login, you append :skey to your login name.
$ ftp localhost
Connected to localhost.
220 oshibana.shin.ms FTP server (Version 6.5/OpenBSD) ready.
Name (localhost:ericj): ericj:skey
331- otp-md5 93 oshi45820
331 S/Key Password: JOEY SOOT PHI KYLE CURT REEK
[...]
230 User ericj logged in.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> quit
221 Goodbye.
Similarly, for ssh(1) or telnet(1):
$ ssh -l ericj:skey localhost
otp-md5 91 oshi45821
S/Key Password: SHIM SET LEST HANS SMUG BOOT
Last login: Thu Apr  7 12:21:48 on ttyp1 from 156.63.248.77
$

Directory services

OpenBSD can be used for both servers and clients of databases containing user credentials, group information and other network-related data.

Which directory services are available?

Of course, you could use various directory services on OpenBSD. But YP is the only one that can be accessed directly using standard C-library functions like getpwent(3), getgrent(3), gethostbyname(3) and so on. Thus, if you keep your data in a YP database, you do not need to copy it to local configuration files like master.passwd(5) before you can use it, for example to authenticate system users.

YP is a directory service compatible with Sun Microsystems NIS (Network Information System). See yp(8) for an overview of the available manual pages. Be careful, some operating systems contain directory services bearing similar names but all the same being incompatible, for example NIS+.

To use other directory services except YP, you either need to populate local configuration files from the directory, or you need a YP frontend to the directory. For example, you can use the sysutils/login_ldap port when you choose the former, while the ypldap(8) daemon provides the latter.

For some applications, simply synchronizing a small number of configuration files among a group of machines using tools like cron(8), scp(1) or rsync (available from ports) constitutes an easy and robust alternative to a full-blown directory service.

YP security considerations

For compatibility reasons, all security features built into the OpenBSD implementation of YP are switched off by default. Even when they are all switched on, the NIS protocol is still inherently insecure for two reasons: All data, including sensitive data like password hashes, is transmitted unencrypted across the network, and neither the client nor the server can reliably verify each other's identity.

Thus, before setting up any YP server, you should consider whether these inherent security flaws are acceptable in your context. In particular, YP is inadequate if potential attackers have physical access to your network. Anybody gaining root access to any computer connected to your network segments carrying YP traffic can bind your YP domain and retrieve its data. In some cases, passing YP traffic through SSL or IPSec tunnels might be an option.

Setting up a YP server

  1. A YP server serves a group of clients called a "domain." You should first select a domain name; it can be an arbitrary string and need not be related in any way to DNS domain names. Choosing a random name like "Eepoo5vi" can marginally improve security, though the effect is mostly in security by obscurity. In case you need to maintain several distinct YP domains, it's probably better to choose descriptive names like "sales," "marketing" and "research" in order to forestall system administration errors caused by obscurity. Also note that some versions of SunOS require using the host's DNS domain name, so your choice might be restricted in a network including such hosts.

    Use the domainname(1) utility to set the domain name, and put it into the defaultdomain(5) file to have it automatically set at system startup time.

        # echo "puffynet" > /etc/defaultdomain
        # domainname `cat /etc/defaultdomain`
        
  2. Initialise the YP server using the interactive command
        # ypinit -m
        
    At this point, it is not necessary to specify slave servers yet. To add slave servers, you can rerun ypinit(8) later, using the -u option. Setting up at least one slave server for each domain is useful to avoid service interruptions. For example, should the master server ever go down or lose network connectivity, client processes trying to access YP maps block indefinitely until they receive the requested information. Thus, YP service interruptions typically render the client hosts completely unusable until YP is back to service.
  3. Decide where to store the source files to generate your YP maps from. Keeping the server configuration separate from the served configuration helps to control which information will be served and which won't, so the default /etc often isn't the best choice.

    The only inconvenience caused by changing the source directory is that you will not be able to add, remove and modify users and groups in the YP domain using utilities like user(8) and group(8). Instead, you will have to edit the configuration files with a text editor.

    To define the source directory, edit the file /var/yp/`domainname`/Makefile and change the DIR variable, e.g.

        DIR=/etc/yp/src/puffynet
        
  4. Consider customizing other variables in /var/yp/`domainname`/Makefile. See Makefile.yp(8) for details.

    For example, even in case you use the default source directory /etc, you do not usually need all accounts and groups existing on the server on all your client hosts. In particular, not serving the root account and thus keeping root's password hash confidential is often beneficial to security. Review the values of MINUID, MAXUID, MINGID and MAXGID and adjust them to you needs.

    If all your YP clients run OpenBSD or FreeBSD, exclude the encrypted passwords from the passwd maps by setting UNSECURE="" in /var/yp/`domainname`/Makefile.

    The former practice of editing the template file /var/yp/Makefile.yp is no longer recommended. Changes to that file affect all domains initialized after the change, but do not affect domains initialized before the change, so this is error-prone either way: You both risk that the intended changes do not take effect, and you risk to forget about them and have them affect other domains later which they were never intended for.

  5. Create the source directory and populate it with the configuration files you need. See Makefile.yp(8) to learn which YP maps require which source files. For the format of the individual configuration files, refer to passwd(5), group(5), hosts(5) and so on, and look at the examples in /etc.
  6. Create the initial version of your YP maps using the commands
        # cd /var/yp
        # make
        
    Do not worry about error messages from yppush(8) right now. The YP server is not yet running.
  7. YP uses rpc(3) (remote procedure calls) to communicate with clients, so it is necessary to enable portmap(8). To do so, use rcctl(8).
        # rcctl enable portmap
        # portmap
        
  8. Consider using either the securenet(5) or the ypserv.acl(5) security feature of the YP server daemon. But be aware that both of these only provide IP based access control. Thus, they only help as long as potential attackers have neither physical access to the hardware of the network segments carrying your YP traffic nor root access to any host connected to those network segments.
  9. Finally, start the YP server daemon:
        # ypserv
        
    It will automatically be restarted at boot time as long as the directory /var/yp/`domainname` continues to exist.
  10. To test the new server, consider making it its own client, following the instructions in the first part of the next section. In case you don't want the server to use its own maps, you can disable the client part after the test with the following commands:
        # pkill ypbind
        # rm -rf /var/yp/binding
        
  11. If you wish to allow users to change their passwords from client machines, then you must enable yppasswdd(8):
        # rcctl set yppasswdd flags -d /etc/yp/src/puffynet
        # rpc.yppasswdd
        
    If you left the source directory at the default /etc, just use rcctl enable yppasswdd.
  12. Remember that each time you change a file sourced by a YP map, you must regenerate your YP maps.
        # cd /var/yp
        # make
        
    This updates all database files in /var/yp/`domainname`, with one exception: The file ypservers.db, listing all YP master and slave servers associated with the domain, is created directly from ypinit -m and modified exclusively by ypinit -u. In case you accidentally delete it, run ypinit -u to recreate it from scratch.

Setting up a YP client

Setting up a YP client involves two distinct parts. First, you must get the YP client daemon running, binding your client host to a YP server. Completing the following steps will allow you to retrieve data from the YP server, but that data will not yet be used by the system:
  1. Like on the server, you must set the domain name and enable the portmapper:
        # echo "puffynet" > /etc/defaultdomain
        # domainname `cat /etc/defaultdomain`
        # rcctl enable portmap
        # portmap
        
  2. It is recommended to provide a list of YP servers in the configuration file /etc/yp/`domainname`. Otherwise, the YP client daemon will use network broadcasts to find YP servers for its domain. Explicitly specifying the servers is both more robust and marginally less open to attack. If you have not set up any slave servers, just put the host name of the master server into /etc/yp/`domainname`.
  3. The YP client daemon is called ypbind(8). Starting it manually will create the directory /var/yp/binding, such that it will be automatically restarted at boot time.
        # ypbind
        
  4. If all went well you should be able to query the YP server using ypcat(1) and see your passwd map returned.
        # ypcat passwd
        bob:*:5001:5000:Bob Nuggets:/home/bob:/usr/local/bin/zsh
        ...
        
    Other useful tools for debugging your YP setup include ypmatch(1) and yptest(8).
The second part of configuring a YP client involves editing local configuration files such that certain YP maps get used by various system facilities. Not all servers serve all standard maps supported by the operating system, some servers serve additional non-standard maps, and you are by no means compelled to use all those maps. Which of the available maps shall or shall not be used, and for which purposes they shall be used, is fully at the discretion of the client host's system administrator.

For a list of standard YP maps and their standard usage, see Makefile.yp(8). The most common use cases include:

Keeping OpenBSD up to date

When a critical bug is found, the fix will be committed to the -current tree as soon as possible. From that point on, things are handled differently depending on whether the problem was in the OpenBSD base system or a third party package. This section details how to keep your system up to date with all the latest fixes.

For the OpenBSD base system, there are three options:

For third party software installed via packages, there are two options:

Applying errata patches

Patches for the OpenBSD base system are distributed as unified diffs, which are text files that hold differences to the original source code. This means that, to apply a patch, you must have the source code from the -release version of your system available.

Whether you download and untar the source trees or fetch them from CVS, it's best to avoid using root where possible. Installing the new binaries will be the only step that requires it.

For our example here, we will look at patch 011 for OpenBSD 5.6, dealing with pppoe(4) connections. Each patch is cryptographically signed with the signify(1) tool and contains instructions on how to apply it properly. We will assume you have put this patch into your current working directory.

$ signify -Vep /etc/signify/openbsd-56-base.pub -x 011_pppoe.patch.sig \
  -m - | (cd /usr/src && patch -p0)

Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|
|OpenBSD 5.6 errata 11, Dec 5, 2014:
|
|An incorrect memcpy call would result in corrupted MAC addresses when
|using PPPOE.
|
|Apply patch using:
|
|    signify -Vep /etc/signify/openbsd-56-base.pub -x 011_pppoe.patch.sig \
|        -m - | (cd /usr/src && patch -p0)
|
|Then build and install a new kernel.
|
|Index: sys/net/if_ethersubr.c
|===================================================================
|RCS file: /cvs/src/sys/net/if_ethersubr.c,v
|retrieving revision 1.174
|diff -u -p -r1.174 if_ethersubr.c
|--- sys/net/if_ethersubr.c     12 Jul 2014 18:44:22 -0000      1.174
|+++ sys/net/if_ethersubr.c     1 Dec 2014 17:48:55 -0000
--------------------------
Patching file sys/net/if_ethersubr.c using Plan A...
Hunk #1 succeeded at 673.              <-- Look for this message!
done
Note the "Hunk #1 succeeded" message above - this indicates the patch was applied successfully. Many patches are more complex than this and will involve multiple hunks and multiple files, in which case you should verify that all hunks succeeded on all the files. Patches are very sensitive to "white space" - copying and pasting from your browser will often change tab characters into spaces or otherwise alter the white space of a file, making it not apply.

At this point, you would build and install the new kernel and reboot the system.

Not all patches are for the kernel. In some cases, you will have to rebuild individual utilities. At other times, will require recompiling all utilities statically linked to a patched library.