I use FreeBSD. I’ve used it since 1998. For me, it does good stuff, reliably, and predictably. The community is very supportive and helpful. That goes a long way when choosing your open source operating system.
Included within FreeBSD, since FreeBSD 4.0 in March 2000, is a great tool for separating out services and to provide a virtualization strategy: jails. Some will argue that jails are not virtualization. I contend that it’s a perfectly acceptable method of virtualization.
I can create 28 jails on a single host system and use them for teaching purposes. Each student can ssh in, use FreeBSD and learn the basics and then move on to advanced topics. All on a single machine. The cost of creating one host with N jails is considerably less than purchasing and running N pieces of hardware.
Bacula
This post is about getting Bacula running in a jail, but the same strategy can be applied to any jail which needs to access hardware which is, by default, not accessible within a jail. I’ve been using Bacula since 2004, and it really is the best backup system I’ve ever used. In the past, I’ve always run Bacula on the host sytem, and never in a jail. I recently moved both the Director and the Storage Daemon into a jail. That move happened about two weeks ago. Now I want that Storage Daemon to use a tape library. In my case, I want one jail, and only that jail, to have access to the tape library; specifically, the autochanger and the tape drive.
How do you give permission to a jail?
Early on, I didn’t know how to grant permissions for a jail to access hardware. That restriction is one of the key points of a jail. By default, you cannot directly access most devices. It was about ten days ago that I first asked this question in the FreeBSD Forums. The answer was devfs.rules(5).
Last night, I started reading that man page. It made a bit of sense, but I didn’t see how it related to jails. Then I looked at /etc/defaults/devfs.rules and at the end, I found this:
# Devices usually found in a jail. # [devfsrules_jail=4] add include $devfsrules_hide_all add include $devfsrules_unhide_basic add include $devfsrules_unhide_login add path zfs unhide
Ahh, so there’s something..
I started reading jail(8) and I found this:
devfs_ruleset The number of the devfs ruleset that is enforced for mounting devfs in this jail. A value of zero (default) means no ruleset is enforced. Descendant jails inherit the parent jail's devfs ruleset enforcement. Mounting devfs inside a jail is possible only if the allow.mount and allow.mount.devfs permissions are effective and enforce_statfs is set to a value lower than 2. Devfs rules and rulesets cannot be viewed or modified from inside a jail.
Ahh, this is just what I need. Each jail can have its own set of rules! This is exactly what I need.
The devices
These are the devices which I need to access from within the jail:
ch0 at sym0 bus 0 scbus7 target 6 lun 0 ch0: <OVERLAND LXB 0524> Removable Changer SCSI-2 device ch0: 20.000MB/s transfers (10.000MHz, offset 15, 16bit) ch0: 15 slots, 1 drive, 1 picker, 0 portals sa0 at sym0 bus 0 scbus7 target 4 lun 0 sa0: <QUANTUM DLT8000 0250> Removable Sequential Access SCSI-2 device sa0: 20.000MB/s transfers (10.000MHz, offset 15, 16bit)
Or, as output by camcontrol devlist:
<QUANTUM DLT8000 0250> at scbus7 target 4 lun 0 (sa0,pass10) <OVERLAND LXB 0524> at scbus7 target 6 lun 0 (pass11,ch0)
To summarize, I may need access to four devices:
- sa0
- pass10
- pass11
- ch0
For now, I will start with sa0 and ch0.
What’s in the jail now?
Let’s see what the jail has now. This is before I made any changes to the system:
$ ls -l /dev total 1 dr-xr-xr-x 2 root wheel 512 Aug 5 21:55 fd lrwxr-xr-x 1 root wheel 14 Aug 6 14:54 log -> ../var/run/log crw-rw-rw- 1 root wheel 0, 19 Aug 6 14:54 null crw-rw-rw- 1 root wheel 0, 22 Aug 5 21:55 ptmx dr-xr-xr-x 2 root wheel 512 Aug 6 14:54 pts crw-rw-rw- 1 root wheel 0, 23 Aug 5 21:56 random lrwxr-xr-x 1 root wheel 4 Aug 6 14:54 stderr -> fd/2 lrwxr-xr-x 1 root wheel 4 Aug 6 14:54 stdin -> fd/0 lrwxr-xr-x 1 root wheel 4 Aug 6 14:54 stdout -> fd/1 lrwxr-xr-x 1 root wheel 6 Aug 6 14:54 urandom -> random crw-rw-rw- 1 root wheel 0, 20 Aug 5 21:55 zero crw-rw-rw- 1 root operator 0, 72 Aug 5 21:55 zfs $
Now, let’s make some changes.
The rules
Let’s look at the devices in the host system. Although the tape device is sa0, most backup software will use the non-automatic-rewinding version of the device. So, we need to include nsa0 as well.
$ ls -l /dev/pass11 /dev/ch0 /dev/pass10 /dev/sa0 /dev/nsa0 crw------- 1 root operator 0, 98 Aug 5 21:55 /dev/ch0 lrwxr-xr-x 1 root wheel 6 Aug 5 21:55 /dev/nsa0 -> nsa0.0 crw------- 1 root operator 0, 109 Aug 5 21:55 /dev/pass10 crw-rw---- 1 root operator 0, 110 Aug 5 21:55 /dev/pass11 lrwxr-xr-x 1 root wheel 5 Aug 5 21:55 /dev/sa0 -> sa0.0
We need to also include nsa0.0 and sa0.0 as shown in the symlinks above. I will be running Bacula as a member of the operator group. Which means pass11 needs to be writable by the group.
Let’s try theses rules in /etc/devfs.rules on the host system:
[devfsrules_jail_unhide_tapes=5] add path nsa0 unhide add path nsa0.0 unhide add path sa0 unhide add path sa0.0 unhide add path pass10 unhide add path pass11 unhide mode 0660 add path ch0 unhide [devfsrules_jail_bacula=6] add include $devfsrules_hide_all add include $devfsrules_unhide_basic add include $devfsrules_unhide_login add path zfs unhide add include $devfsrules_jail_unhide_tapes
For this, I got help from Installing Asterisk In A FreeBSD Jail. The examples there were just what I needed.
In the above, line 1 defines a new rule set. Lines 2-7 will unhide the devices I want. Line 6 also sets the permissions on that device.
Lines 11-14 duplicate the efforts from /etc/defaults/devfs.rules (as shown in a previous section) and then invokes the first ruleset I created just above.
Specifying the ruleset for the jail
I am using ezjail. Each jail has its own configuration file in /usr/local/etc/ezjail. Without ezjail, these parameters go in /etc/rc.conf (I think). This is the line I changed in bacula_example_org (the jail in question):
export jail_crey_unixathome_org_devfs_ruleset="devfsrules_jail_bacula"
Restarting
Now let’s restart devfs and the jail:
# /etc/rc.d/devfs restart # ezjail-admin restart bacula.example.org Stopping jails: bacula.example.org. Configuring jails:. Starting jails: bacula.example.org. #
After ssh‘ing into the jail, I found this:
$ ls -l /dev total 1 crw------- 1 root operator 0, 98 Aug 5 21:55 ch0 dr-xr-xr-x 2 root wheel 512 Aug 5 21:55 fd lrwxr-xr-x 1 root wheel 14 Aug 6 19:21 log -> ../var/run/log lrwxr-xr-x 1 root wheel 6 Aug 6 19:21 nsa0 -> nsa0.0 crw-rw---- 1 root operator 0, 113 Aug 5 21:55 nsa0.0 crw-rw-rw- 1 root wheel 0, 19 Aug 6 19:27 null crw------- 1 root operator 0, 109 Aug 5 21:55 pass10 crw-rw---- 1 root operator 0, 110 Aug 5 21:55 pass11 crw-rw-rw- 1 root wheel 0, 22 Aug 5 21:55 ptmx dr-xr-xr-x 2 root wheel 512 Aug 6 19:21 pts crw-rw-rw- 1 root wheel 0, 23 Aug 5 21:56 random lrwxr-xr-x 1 root wheel 5 Aug 6 19:21 sa0 -> sa0.0 crw-rw---- 1 root operator 0, 112 Aug 5 21:55 sa0.0 lrwxr-xr-x 1 root wheel 4 Aug 6 19:21 stderr -> fd/2 lrwxr-xr-x 1 root wheel 4 Aug 6 19:21 stdin -> fd/0 lrwxr-xr-x 1 root wheel 4 Aug 6 19:21 stdout -> fd/1 lrwxr-xr-x 1 root wheel 6 Aug 6 19:21 urandom -> random crw-rw-rw- 1 root wheel 0, 20 Aug 5 21:55 zero crw-rw-rw- 1 root operator 0, 72 Aug 5 21:55 zfs $
You will note that the jail has access to both sa0 and nsa0 and the device to which they are symlinked, sa0.0. Similarly, the jail also has access to pass11, which is what mtx will use to access ch0.
OK, but can you work the tape library?
Yes, I sure can. Look at this:
[root@crey ~]# /usr/local/sbin/mtx-changer /dev/pass11 slots 15 [root@crey ~]# /usr/local/sbin/mtx-changer /dev/pass11 list 1:ETU002 2:ETU004 3:ETU008 4:ETU016 5:ETU025 6:ETU026 7:ETU028 8:ETU030 9:ETU043 10:ETU045 11:ETU049 12:ETU054 13:ETU095 14:ETU171 15:ETU233 [root@crey ~]#
Success!