[OpenBSD]

[FAQ Index] [To Section 9 - Migrating to OpenBSD] [To Section 11 - The X Window System]

10 - System Management


Table of Contents


10.1 - Why does it say that I'm in the wrong group when I try to su root?

On OpenBSD, users who are in the wheel group are allowed to use su(1) to become root. Otherwise, the user will receive an error.

If you are creating new users with adduser(8), you can add them to the wheel group by answering "wheel" at the "Invite user into other groups:" prompt. Existing users must be added to the wheel group by hand. Here is an example of a /etc/group entry which has had the user ericj added to the wheel group:

wheel:*:0:root,ericj

If you want to give access to superuser privileges without adding users to the wheel group, use sudo(8).

10.2 - How do I duplicate a filesystem?

To duplicate your filesystem use dump(8) and restore(8). For example, to duplicate everything under directory SRC to directory DST, do a:

# cd /SRC; dump 0f - . | (cd /DST; restore -rf - )

dump is designed to give you plenty of backup capabilities, and it may be an overkill if you just want to duplicate a part of a (or an entire) filesystem. The command tar(1) may be faster for this operation. The format looks very similar:

# cd /SRC; tar cf -  . | (cd /DST; tar xpf - )

10.3 - How do I start daemons with the system? (Overview of rc(8))

OpenBSD itself uses an rc(8) style startup. This uses a few key files for startup.

How does rc(8) work?

The main files a system administrator should concentrate on are /etc/rc.conf (for guidance), /etc/rc.conf.local (for changes), /etc/rc.local and /etc/rc.shutdown. To get a look of how the rc(8) procedure works, here is the flow:

After the kernel is booted, /etc/rc is started:

Starting Daemons and Services that come with OpenBSD

Most daemons and services that come with OpenBSD are controlled on boot by variables defined in the /etc/rc.conf configuration file. Take a look at the /etc/rc.conf file. You'll see lines similar to this:

ftpd_flags=NO           # for non-inetd use: ftpd_flags=""

A line like this shows that ftpd(8) is not to start up with the system (at least not as a daemon via rc(8); ftpd is often run out of inetd(8), see Anonymous FTP FAQ to read more about this). Each line has a comment showing you the flags for common usage of that daemon or service. This doesn't mean that you must run that daemon or service with those flags. Read the relevant manual page to see how you can have that daemon or service start up in any way you like.

We strongly suggest you do not alter /etc/rc.conf itself. Instead, create or edit the file /etc/rc.conf.local, copy just the lines you need to change from /etc/rc.conf and adjust them as you like. This makes future upgrades easier -- all the changes are in the one file that isn't touched during upgrade.

For example, here is the default line pertaining to ntpd(8).

ntpd_flags=NO          # for normal use: ""

Here you can see that starting up ntpd normally requires no flags, so a line like ntpd_flags="" added to /etc/rc.conf.local will do the job. But to start ntpd with options, such as -s to immediately update the system clock at boot you would need a line like ntpd_flags="-s" instead.

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, I've installed a daemon which lies at /usr/local/sbin/daemonx. I want it to start at boot time. I could 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 a "&" 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, a normal boot with no errors would show a line like this:

Starting daemonx

The /etc/rc.d/ directory

OpenBSD's system daemons ("services") are started, stopped and controlled by /etc/rc.d. All system daemons are handled by these scripts, and most add-in 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 add-in 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/ntpd does not start ntpd(8) unless /etc/rc.conf or /etc/rc.conf.local contains a line defining the "ntpd_flags" variable. To help make sure your system will come up as expected on the next boot, the rc.d scripts will not run their daemon if the appropriate variable is not defined. You can, of course, manually invoke /usr/sbin/ntpd directly with whatever options you wish, if you wish to run the program manually.

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 a very few variables, and invoking the rc.subr 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.

rc.shutdown

/etc/rc.shutdown is a script that is run at shutdown. Anything you want done before the system shuts down should be added to this file. If you have apm, you can also set "powerdown=YES", which will give you the equivalent of "shutdown -p".

10.8 - I edited /etc/passwd, but the changes didn't seem to take place. Why?

If you edit /etc/passwd directly, your changes will be lost. OpenBSD generates /etc/passwd dynamically with pwd_mkdb(8). The main password file in OpenBSD is /etc/master.passwd. According to pwd_mkdb(8),

FILES
     /etc/master.passwd  current password file
     /etc/passwd         a 6th Edition-style password file
     /etc/pwd.db         insecure password database file
     /etc/pwd.db.tmp     temporary file
     /etc/spwd.db        secure password database file
     /etc/spwd.db.tmp    temporary file

In a traditional Unix password file, such as /etc/passwd, everything including the user's encrypted password is available to anyone on the system (and is a prime target for programs such as Crack). 4.4BSD introduced the master.passwd file, which has an extended format (with additional options beyond those provided by /etc/passwd) and is only readable by root. For faster access to data, the library calls which access this data normally read /etc/pwd.db and /etc/spwd.db.

OpenBSD does come with a tool with which you should edit your password file. It is called vipw(8). Vipw will use vi (or your favourite editor defined per $EDITOR) to edit /etc/master.passwd. After you are done editing, it will re-create /etc/passwd, /etc/pwd.db, and /etc/spwd.db as per your changes. Vipw also takes care of locking these files, so that if anyone else attempts to change them at the same time, they will be denied access.

10.9 - What is the best way to add and delete users?

OpenBSD provides two commands for easily adding users to the system:

You can also add users by hand, using vipw(8), but this is more difficult for most operations.

The easiest way to add a user in OpenBSD is to use the adduser(8) script. You can configure adduser(8) by editing /etc/adduser.conf. adduser(8) allows for consistency checks on /etc/passwd, /etc/group, and shell databases. It will create the entries and $HOME directories for you. It can even send a message to the user welcoming them. Here is an example user, testuser, being added to a system. He/she will be given the $HOME directory /home/testuser, made a member of the group guest, and given the shell /bin/ksh.

# adduser
Use option ``-silent'' if you don't want to see all warnings and questions.

Reading /etc/shells
Check /etc/master.passwd
Check /etc/group

Ok, let's go.
Don't worry about mistakes. There will be a chance later to correct any input.
Enter username []: testuser
Enter full name []: Test FAQ User
Enter shell csh ksh nologin sh [ksh]: ksh
Uid [1002]: Enter
Login group testuser [testuser]: guest
Login group is ``guest''. Invite testuser into other groups: guest no 
[no]: no
Login class authpf daemon default staff [default]: Enter
Enter password []: Type password, then Enter
Enter password again []: Type password, then Enter

Name:        testuser
Password:    ****
Fullname:    Test FAQ User
Uid:         1002
Gid:         31 (guest)
Groups:      guest
Login Class: default
HOME:        /home/testuser
Shell:       /bin/ksh
OK? (y/n) [y]: y
Added user ``testuser''
Copy files from /etc/skel to /home/testuser
Add another user? (y/n) [y]: n
Goodbye!

To delete users you should use the rmuser(8) utility. This will remove all existence of a user. It will remove any crontab(1) entries, their $HOME dir (if it is owned by the user), and their mail. Of course it will also remove their /etc/passwd and /etc/group entries. Next is an example of removing the user that was added above. Notice you are prompted for the name, and whether or not to remove the user's home directory.

# rmuser
Enter login name for user to remove: testuser
Matching password entry:

testuser:$2a$07$ZWnBOsbqMJ.ducQBfsTKUe3PL97Ve1AHWJ0A4uLamniLNXLeYrEie:1002
:31::0:0:Test FAQ User:/home/testuser:/bin/ksh

Is this the entry you wish to remove? y
Remove user's home directory (/home/testuser)? y
Updating password file, updating databases, done.
Updating group file: done.
Removing user's home directory (/home/testuser): done.

Adding users via user(8)

These tools are less interactive than the adduser(8) command, which makes them easier to use in scripts.

The full set of tools is:

Actually adding users

The command /usr/sbin/user is just a frontend to the rest of the /usr/sbin/user* commands. Therefore, the following commands can be added by using user add or useradd, which form you chose doesn't change the results at all. Remember, since user(8) is not interactive, the easiest way to add users is with adduser(8).

useradd(8) is less daunting to use if you know the default settings beforehand. These settings are located in usermgmt.conf(5) and can be viewed by doing:

$ user add -D
group           users
base_dir        /home
skel_dir        /etc/skel
shell           /bin/csh
inactive        0
expire          Null (unset)
range           1000..60000

These defaults will be used unless you specify alternatives with the command line options. For example, we want the user to be added to the group guest, not users. One more little hurdle with adding users, is that passwords must be specified on the command line. Importantly, the passwords must be encrypted, so you need to use the encrypt(1) utility. For example: OpenBSD's passwords by default use the Blowfish algorithm for 6 rounds. Here is an example to create an encrypted password to give to useradd(8).

$ encrypt -p -b 6
Enter string:
$2a$06$YOdOZM3.4m6MObBXjeZtBOWArqC2.uRJZXUkOghbieIvSWXVJRzlq

Now that we have an encrypted password, we are ready to add the user. We will add the same user with the same specifications as the user we added above, via adduser(8).

# user add -p '$2a$06$YOdOZM3.4m6MObBXjeZtBOWArqC2.uRJZXUkOghbieIvSWXVJRzlq' -u 1002 \
-s /bin/ksh -c "Test FAQ User" -m -g guest testuser

Note: Make sure to use ' ' (single quotes) around the password string, not " " (double quotes) as the shell will interpret these before sending it to user(8). In addition to that, make sure you specify the -m option if you want the user's home directory created and the files from /etc/skel copied over.

To see that the user was created correctly, we can use many different utilities. Below are a few commands you can use to quickly check that everything was created correctly.

$ ls -la /home
total 14
drwxr-xr-x   5 root      wheel   512 May 12 14:29 .
drwxr-xr-x  15 root      wheel   512 Apr 25 20:52 ..
drwxr-xr-x  24 ericj     wheel  2560 May 12 13:38 ericj
drwxr-xr-x   2 testuser  guest   512 May 12 14:28 testuser
$ id testuser
uid=1002(testuser) gid=31(guest) groups=31(guest)
$ finger testuser
Login: testuser                         Name: Test FAQ User
Directory: /home/testuser               Shell: /bin/ksh
Last login Sat Apr 22 16:05 (EDT) on ttyC2
No Mail.
No Plan.

In addition to these commands, user(8) provides its own utility to show user characteristics, called userinfo(8).

$ userinfo testuser
login   testuser
passwd  *
uid     1002
groups  guest
change  Wed Dec 31 19:00:00 1969
class
gecos   Test FAQ User
dir     /home/testuser
shell   /bin/ksh
expire  Wed Dec 31 19:00:00 1969

Removing users

To remove users with the user(8) hierarchy of commands, you will use userdel(8). This is a very simple, yet usable command. To remove the user created in the last example, simply:

# userdel -r testuser

Notice the -r option, which must be specified if you want the users home directory to be deleted as well. Alternatively, you can specify -p and not -r and this will lock the user's account, but not remove any information.

10.10 - How do I create an ftp-only account (not anonymous FTP!)?

There are a few ways to do this, but a very common way to do such is to add "/usr/bin/false" into "/etc/shells". Then when you set a users shell to "/usr/bin/false", they will not be able log in interactively, but will be able to use ftp capabilities. You may also want to restrict access by Confining users to their home directory in ftpd.

10.11 - Setting up Quotas

Quotas are used to limit user's space that they have available to them on your disk drives. It can be very helpful in situations where you have limited resources. Quotas can be set by user and/or by group.

The first step to setting up quotas is to make sure that "option QUOTA" is in your Kernel Configuration. This option is in the GENERIC kernel. After this, you need to mark in /etc/fstab the filesystems which will have quotas enabled. The keywords userquota and groupquota should be used to mark each filesystem that you will be using quotas on. By default, the files quota.user and quota.group will be created at the root of that filesystem to hold the quota information. This default can be overridden by specifying the file name with the quota option in /etc/fstab, such as "userquota=/var/quotas/quota.user". Here is an example /etc/fstab that has one filesystem with userquotas enabled, and the quota file in a non-standard location:

/dev/wd0a / ffs rw,userquota=/var/quotas/quota.user 1 1

Now it's time to set the user's quotas. To do so you use the utility edquota(8). A simple use is just "edquota <user>". edquota(8) will use vi(1) to edit the quotas unless the environmental variable EDITOR is set to a different editor. For example:

# edquota ericj

This will give you output similar to this:

Quotas for user ericj:
/: KBytes in use: 62, limits (soft = 0, hard = 0)
        inodes in use: 25, limits (soft = 0, hard = 0)

To add limits, edit it to give results like this:

Quotas for user ericj:
/: KBytes in use: 62, limits (soft = 1000, hard = 1050)
        inodes in use: 25, limits (soft = 0, hard = 0)

Note that the quota allocation is in 1k blocks. In this case, the softlimit is set to 1000k, and the hardlimit is set to 1050k. A softlimit is a limit where the user is just warned when they cross it and have until their grace period is up to get their disk usage below their limit. Grace periods can be set by using the -t option on edquota(8). After the grace period is over the softlimit is handled as a hardlimit. This usually results in an allocation failure.

Now that the quotas are set, you need to turn the quotas on. To do this use quotaon(8). For example:

# quotaon -a

This will go through /etc/fstab to turn on the filesystems with quota options. Now that quotas are up and running, you can view them using quota(1). Using a command of "quota <user>" will give that user's information. When called with no arguments, the quota(1) command will give your quota statistics. For example:

# quota ericj

Will result in output similar to this:

Disk quotas for user ericj (uid 1001): 
     Filesystem  blocks   quota   limit   grace   files   quota   limit   grace
              /      62    1000    1050              27       0       0        

By default quotas set in /etc/fstab will be started on boot. To turn them off use

# quotaoff -a

10.13 - Setting up Anonymous FTP Services

Anonymous FTP allows users without accounts to access files on your computer via the File Transfer Protocol. This will give an overview of setting up the anonymous FTP server, and its logging, etc.

Adding the FTP account

To start off, you need to have an ftp account on your system. This account should not have a usable password. Here we will set the login directory to /home/ftp, but you can put it wherever you want. When using anonymous ftp, the ftp daemon will chroot itself to the home directory of the ftp user. To read up more on that, read the ftpd(8) and chroot(2) man pages. Here is an example of adding the ftp user. I will do this using adduser(8). We also need to add /usr/bin/false to our /etc/shells, this is the "shell" that we will be giving to the ftp user. This won't allow them to login, even though we will give them an empty password. To do this you can simply do

# echo /usr/bin/false >> /etc/shells
After this, you are ready to add the ftp user:
# adduser
Use option ``-silent'' if you don't want to see all warnings and questions.

Reading /etc/shells
Check /etc/master.passwd
Check /etc/group

Ok, let's go.
Don't worry about mistakes. There will be a chance later to correct any input.
Enter username []: ftp
Enter full name []: anonymous ftp
Enter shell csh false ksh nologin sh [ksh]: false
Uid [1002]: Enter
Login group ftp [ftp]: Enter
Login group is ``ftp''. Invite ftp into other groups: guest no 
[no]: Enter
Login class authpf daemon default staff [default]: Enter
Enter password []: Enter
Set the password so that user cannot logon? (y/n) [n]: y

Name:        ftp
Password:    ****
Fullname:    anonymous ftp
Uid:         1002
Gid:         1002 (ftp)
Groups:      ftp
Login Class: default
HOME:        /home/ftp
Shell:       /usr/bin/false
OK? (y/n) [y]: Enter
Added user ``ftp''
Copy files from /etc/skel to /home/ftp
Add another user? (y/n) [y]: n
Goodbye!

Directory Setup

Along with the user, this created the directory /home/ftp (though you can use other locations as well, of course). There are some changes that we will have to make to get it ready for anonymous ftp. Again these changes are explained in the ftpd(8) man page.

You do not need to make a /home/ftp/usr or /home/ftp/bin directory.

Note that all these directories should be owned by ''root''. Here is a listing of what the directories should look like after their creation.

# pwd
/home
# ls -laR ftp
total 5
dr-xr-xr-x  5 root  ftp    512 Jul  6 11:33 .
drwxr-xr-x  7 root  wheel  512 Jul  6 10:58 ..
dr-x--x--x  2 root  ftp    512 Jul  6 11:34 etc
dr-xr-xr-x  2 root  ftp    512 Jul  6 11:33 pub

ftp/etc:
total 43
dr-x--x--x  2 root  ftp    512 Jul  6 11:34 .
dr-xr-xr-x  5 root  ftp    512 Jul  6 11:33 ..
-r--r--r--  1 root  ftp    316 Jul  6 11:34 group
-r--r--r--  1 root  ftp  40960 Jul  6 11:34 pwd.db

ftp/pub:
total 2
dr-xr-xr-x  2 root  ftp  512 Jul  6 11:33 .
dr-xr-xr-x  5 root  ftp  512 Jul  6 11:33 ..

Starting up the server and logging

You can choose to start ftpd either by inetd(8) or from the rc scripts. Generally, running ftpd as a daemon from the rc scripts is recommended and is what we will show here; a sample line for running it from inetd(8) is commented out in the default /etc/inetd.conf.

Here is an example line to add to /etc/rc.conf.local to start ftpd(8) at boot.

ftpd_flags="-llUSA"
The options used here are:

It is not necessary to give startup options to ftpd to allow anonymous connections; the preceding steps of creating the 'ftp' user is sufficient. However, to stop anonymous connections it isn't necessary to undo everything, just restart ftpd with the -n option included. Anonymous connections are then disabled.

Other relevant files

10.14 - Confining users to their home directories in ftpd(8)

By default, when logging in by ftp, users can change to any directory on the filesystem that they have access to. This may not be desirable in some cases. It is possible to restrict what users may see through ftp sessions by chrooting them to their home directory.

If you only wish to allow chrooted ftp logins, use the -A option to ftpd(8).

If you wish to apply them more finely, OpenBSD's login capability infrastructure and ftpd(8) together make this easy.

Users in a login class with the ftp-chroot variable set are automatically chrooted. Additionally, you can add a username to the file /etc/ftpchroot to chroot those usernames. A user only needs to be listed in one of these locations.

10.15 - Applying patches in OpenBSD

Even with OpenBSD, bugs happen. Some bugs may lead to reliability issues (i.e., something may cause the system to stop functioning as desired). Other bugs may lead to security vulnerabilities (which may allow others to "use" your computer in unintended and unauthorized ways). When a critical bug is found, the fix will be committed to the -current source tree, and patches will be released for the supported releases of OpenBSD. These patches appear on the errata web page, and are separated into "common" errata that impact all platforms, and errata that impact only one or more, but not all, platforms.

Note, however, that patches aren't released for new features or additional hardware support for OpenBSD, and are only published for important reliability fixes or security problems that should be addressed right away on impacted systems (which is often NOT all systems, depending on their purpose).

There are three ways to update your system with patched code:

Again, patching individual files is not always simple, so give serious thought to following the -stable (or "patch") branch of OpenBSD. Mixing and matching of patching solutions can be done if you understand how everything works, but new users should pick one method and stick with it.

How are "errata" patches different from what is in the CVS tree?

All patches posted to the errata web page are patches directly against the indicated release's source tree. Patches against the latest CVS tree might also include other changes that wouldn't be wanted on a release system. This is important: If you have installed a snapshot, checked out the source trees at the time you obtained that snapshot and attempt to patch it using a published patch, you may well find the patch doesn't apply, as that code may have changed.

Applying patches.

Patches for the OpenBSD Operating System are distributed as "Unified diffs", which are text files that hold differences to the original source code. They are NOT distributed in binary form. This means that to apply a patch you must have the source code from the RELEASE version of your system available. In general, it is advisable to acquire the entire source tree before applying a patch. If you are running a release from an official CDROM, the source trees are available as files on disk 3, these can also be downloaded from the FTP servers. We will assume you have the entire tree checked out.

For our example here, we will look at patch 001 for OpenBSD 3.6 dealing with the st(4) driver, which handles tape drives. Without this patch, recovering data from backups was quite difficult. People using a tape drive needed this patch, however those without a tape drive may have had no particular need to install it. Let's look at the patch:

# more 001_st.patch
Apply by doing:
        cd /usr/src
        patch -p0 < 001_st.patch

Rebuild your kernel.

Index: sys/scsi/st.c
===================================================================
RCS file: /cvs/src/sys/scsi/st.c,v
retrieving revision 1.41
retrieving revision 1.41.2.1
diff -u -p -r1.41 -r1.41.2.1
--- sys/scsi/st.c       1 Aug 2004 23:01:06 -0000       1.41
+++ sys/scsi/st.c       2 Nov 2004 01:05:50 -0000       1.41.2.1
@@ -1815,7 +1815,7 @@ st_interpret_sense(xs)
        u_int8_t skey = sense->flags & SSD_KEY;
        int32_t info;
 
-       if (((sense->flags & SDEV_OPEN) == 0) ||
+       if (((sc_link->flags & SDEV_OPEN) == 0) ||
            (serr != 0x70 && serr != 0x71))
                return (EJUSTRETURN); /* let the generic code handle it */
As you will note, the top of the patch includes brief instructions on applying it. We will assume you have put this patch into the /usr/src directory, in which case, the following steps are used:
# cd /usr/src
# patch -p0 < 001_st.patch
Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|Apply by doing:
|        cd /usr/src
|        patch -p0 < 001_st.patch
|
|Rebuild your kernel.
|
|Index: sys/scsi/st.c
|===================================================================
|RCS file: /cvs/src/sys/scsi/st.c,v
|retrieving revision 1.41
|retrieving revision 1.41.2.1
|diff -u -p -r1.41 -r1.41.2.1
|--- sys/scsi/st.c      1 Aug 2004 23:01:06 -0000       1.41
|+++ sys/scsi/st.c      2 Nov 2004 01:05:50 -0000       1.41.2.1
--------------------------
Patching file sys/scsi/st.c using Plan A...
Hunk #1 succeeded at 1815.              <-- 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 one, and will involve multiple hunks and multiple files, in which case, you should verify that all hunks succeeded on all files. If they did not, it normally means your source tree was different in some way from the release source tree the patch was created from, or you didn't follow instructions carefully, or your patch was mangled. 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 can build and install the new kernel, then reboot the system as normal.

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. Follow the guidance in the header of the patch, and if uncertain, rebuild the entire system.

Patches that are irrelevant to your particular system need not be applied -- usually. For example, if you did not have a tape drive on your system, you would not benefit from the above patch. However, patches are assumed to be applied "in order" -- it is possible that a later patch is dependent upon an earlier one. Be aware of this if you elect to "pick and choose" which patches you apply, and if in doubt, apply them all, in order.

10.17 - Can I change the root shell?

It is sometimes said that one should never change the root shell, though there is no reason not to in OpenBSD.

The default shell for root on OpenBSD is ksh.

A traditional Unix guideline is to only use statically compiled shells for root, because if your system comes up in single user mode, non-root partitions won't be mounted and dynamically linked shells won't be able to access libraries located in the /usr partition. This isn't actually a significant issue for OpenBSD, as the system will prompt you for a shell when it comes up in single user mode, and the default is sh. The three standard shells in OpenBSD (csh, sh and ksh) are all statically linked, and thus usable in single user mode.

10.18 - What else can I do with ksh?

In OpenBSD, ksh is pdksh, the Public Domain Korn Shell, and is the same binary as sh.

Users comfortable with bash, often used on Linux systems, will probably find ksh very familiar. Ksh(1) provides most of the commonly used features in bash, including tab completion, command line editing and history via the arrow keys, and CTRL-A/CTRL-E to jump to beginning/end of the command line. If other features of bash are desired, bash itself can be loaded via either packages or ports.

The command prompt of ksh can easily be changed to something providing more information than the default "$ " by setting the PS1 variable. For example, inserting the following line:

export PS1='$PWD $ '
in your /etc/profile produces the following command prompt:
/home/nick $
See the file /etc/ksh.kshrc, which includes many useful features and examples, and may be invoked in your user's .profile.

OpenBSD's ksh(1) has been enhanced with a number of "special characters" for the primary prompt string, PS1, similar to those used in bash. For example:

\e - Insert an ASCII escape character.
\h - The hostname, minus domain name.
\H - The full hostname, including domain name.
\n - Insert a newline character.
\t - The current time, in 24-hour HH:MM:SS format.
\u - The current user's username.
\w - The current working directory. $HOME is abbreviated as `~'.
\W - The basename of the current working directory.
\$ - Displays "#" for root users, "$" for non-root users.
(see the ksh(1) man page for more details, and many, many more special characters! Also note the "$" character has special meaning inside double quotes, so handle it carefully)

One could use the following command:

export PS1="\n\u@\H\n\w \\$ "
to give an overly verbose but somewhat useful prompt.

10.19 - Directory services

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

10.19.1 - 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.

10.19.2 - 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.

10.19.3 - 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 file defaultdomain(5) 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, should the master server ever go down or lose network connectivity, in particular since 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, edit rc.conf.local(8) and set portmap_flags="". This will start the portmapper on next boot. You can avoid rebooting by also starting it manually:

    echo 'portmap_flags=""' >> /etc/rc.conf.local
    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):

    echo 'yppasswdd_flags="-d /etc/yp/src/puffynet"' >> /etc/rc.conf.local
    rpc.yppasswdd
    
    In case you left the source directory at the default /etc, just use yppasswdd_flags="".
  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.

10.19.4 - 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`
    echo 'portmap_flags=""' >> /etc/rc.conf.local
    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:

10.20 - Character sets and localization

OpenBSD uses the ASCII character set by default. It also supports the Latin (ISO-8859-*), KOI-8, and Unicode (UTF-8) character sets.

10.20.1 - Configuring the active character set

To use one of the extended character sets, the LC_CTYPE environment variable must be set to the name of a supported locale. LC_CTYPE will only affect the character set available to applications. It will not change the language used for application messages.

The list of supported locales can be obtained by running the command:

locale -a
The LC_CTYPE environment variable can be set in one of the following ways:

Few utilities in the base system support UTF-8 at this time. Most will use ASCII in the UTF-8 locale. However, many programs from the ports collection do support UTF-8.

UTF-8 can also be used with specific applications only by starting those applications in uxterm(1). This works even if the login session uses a non-UTF-8 locale.

When logging into remote systems with ssh(1), the LC_CTYPE environment variable is not propagated and will need to be manually set to the same value used by the local terminal.

10.20.2 - Changing the language used in application messages

The language used for application messages can be changed by setting the LC_MESSAGES environment variable to the name of a supported locale. This can be done in the same way as described for LC_CTYPE above. Both LC_MESSAGES and LC_CTYPE should be set to the same value.

Few utilities in the base system support languages other than English at this time. However, many programs from the ports collection support localized messages in various languages. They will fall back to English if the desired language is not available.


[FAQ Index] [To Section 9 - Migrating to OpenBSD] [To Section 11 - The X Window System]