freebsd Archive

Fixing a Monitor with an Identity Crisis

After today, I’m about ready for an old-man rant about the evils of modern technology. Instead I’ll write up the problem and solution I had today in case others come looking for it.

I happened to brush against my computer today and the static caused it to freeze up. Okay, that’s annoying, but not the end of the world. Reboot and start things back up. But monitor #2 came back up in a weird resolution. It’s normally 1680x1050, and it was 1280x1024 for some reason. Not just smaller, but stretched out horizontally.

Investigation found that the monitor, which is a Westinghouse LCM-22w3, started telling the video card it’s actually an Acer AL1714. It’s suddenly a trans-monitor. Next thing I know it’ll demand I call it Catelyn.

Back in the old days, you had to configure the X Window display for your monitor by hand, filling in modelines with horizontal and vertical sync values from the specs, which could be kind of a pain. Nowadays, monitors have something called EDID, which is a block of data held on a chip which is sent to the video card to tell it what the monitor is capable of. That’s very handy if it works. But suddenly mine’s EDID block says it’s an Acer with completely different specs. Other people online reported the same thing, so it must not be uncommon.

I figured there would be a database somewhere of correct EDID blocks for different monitors, the way we used to have databases of modelines. Couldn’t find one for it. So I couldn’t just override the monitor’s EDID block with a file. I tried tinkering with the Xorg config in various ways, none of which worked. Sometimes one monitor would work, sometimes the other, sometimes they’d both work and both have wrong resolutions.

One suggestion said to use xrandr to force the right mode, but that gave me a BadMatch error. It turned out that because the NVidia card was getting the bad EDID block, it thought the monitor couldn’t handle the mode I was trying to force. So the first part of the solution ended up being to add this line to the “Monitor” section for the Westinghouse in my xorg.conf (actually my /usr/local/etc/X11/xorg.conf.d/driver-nvidia.conf, but the location of yours may vary):

Option   "UseEDID"  "FALSE"

On starting X, both monitors were active (progress!) but with the wrong resolution, since the video card couldn’t use EDID to ask what it should be. So then I had to run these commands:

xrandr --newmode "1680x1050_60.00"  146.25  1680 1784 1960 2240  1050 1053 1059 1089 -hsync +vsync
xrandr --addmode DVI-D-0 1680x1050_60.00
xrandr --output VGA-0 --mode 1280x1024
xrandr --output DVI-D-0 --mode 1680x1050_60.00

My setup has a 1280x1024 Samsung connected via VGA on the left, and the 1680x1050 Westinghouse connected via DVI on the right. So the first line there adds the new mode the Westinghouse needs, using values I got from running cvt 1680 1050. The second line adds that new mode to the right-hand monitor, and the third and fourth lines set the correct resolution for each monitor. All is well now.

Now I’ll just add those four xrandr lines to my ~/.xinitrc, so they run each time I start up X with startx. Depending on how X starts on your system, you may need to put them somewhere else.

Spinning Up a New Digital Ocean Droplet (VPS)

I have a $5/month virtual server at Digital Ocean, which I use for some light work and for an extra location outside my usual networks from which to test connectivity. I noticed recently that they’d increased the RAM and disk space included for that price. It turns out I could have just clicked a button to expand it, but I decided to make a new droplet and move everything to it, since that’s really how you’re supposed to handle the cloud – lean toward spinning up new systems rather than getting attached to the ones you have.

So I recorded myself going through the process of starting and configuring the droplet, setting it up far enough to start installing packages. If you’re inspired to get a droplet for yourself, feel free to use my referral link, which I think gives me $5 when someone signs up with it. I’m also available if you need a sysadmin for your servers.

Getting bwn driver working on a Dell Latitude D520

I run FreeBSD on a Dell Latitude D520 laptop. One issue in installing it is that the wireless doesn’t work out of the box, so you have to install firmware for it. In this machine’s case, the needed firmware is in the net/bwn-firmware-kmod port. So you have to connect with the Ethernet port long enough to get that installed, or pull it in some other way, like a flash drive.

After installing the port, though, it still wasn’t working. It installs three files in /boot/modules:

  • bwn_v4_lp_ucode.ko
  • bwn_v4_n_ucode.ko
  • bwn_v4_ucode.ko

But looking at the dmesg errors, it was searching for a file called bwn_v4_ucode5.ko. So I had to do this to get it working:

cp /boot/modules/bwn_v4_ucode.ko /boot/modules/bwn_v4_ucode5.ko

I don’t know why the discrepancy, but this gets mine running, so I haven’t dug into it further. It seems like laptops vary greatly, even within the same model number sometimes, so you never know. I figured I’d put it on public record, in case anyone else gets the same error message and goes hunting for a solution.

Using Jails with ZFS on FreeBSD - Part 1

For FreeBSD administrators, ZFS and jails combine to make virtualization easy, fast, and secure. A FreeBSD jail is a virtual machine which can only access the resources assigned to it when it was created, so its processes have no access to the rest of the machine. ZFS is an advanced filesystem that makes it very easy to create and destroy filesystems whenever they are needed. Together, they make it a matter of moments to create a new virtual system for testing, walling off network services, or other projects.

This article, Part 1, will walk you through setting up a host FreeBSD system to be ready for jails. Part 2 will cover creating a jail to run a network service. In the terminology I’ll use here, the “host” system is the main OS, which can control and look inside its jails. The “jailed” or “guest” system can only see what resources the host has assigned to it, and cannot see outside itself.

Create a ZFS pool (if necessary)

If you already have a ZFS pool on your system and want to put your jails in it, you can skip this step. This sets up a ZFS pool named zf on one or more hard drives, in which you will then create your ZFS filesystems. Depending on how many free drives you have available, use one of these commands, substituting in the device names for your drives:

zpool create zf /dev/ada2                             # one drive, no redundancy
zpool create zf mirror /dev/ada2 /dev/ada3            # two drives, mirrored
zpool create zf raidz  /dev/ada2 /dev/ada3 /dev/ada4  # 3+ drives, striped

Create and mount a filesystem for your jails

We will create one filesystem called zf/jail, mount it on /usr/jail, and give it the options we want all our jails to have. Then those options will be inherited by all filesystems created beneath it:

zfs create zf/jail
zfs set mountpoint=/usr/jail zf/jail
zfs set compression=on zf/jail

You probably want to turn on compression, unless you know you’re going to be storing mostly already-compressed files in the jail. You can also turn that on and off per-jail later, so use whatever you want as the default here.

If your pool has a single drive, you may also want to use what I call “poor man’s RAID,” by telling ZFS to store two copies of every file. If the drive fails entirely, you will still lose everything, so it’s not as good as multiple drives or a replacement for regular backups. But if individual sectors fail or there are occasional bit errors, ZFS will be able to repair a file by making a new copy based on the other good sector, so you might be able to get by until you’re ready to replace it. To turn on two copies:

zfs set copies=2 zf/jail

Now create a filesystem in which to build a fresh FreeBSD install. Give it a dotfile name, because you won’t actually be using this one as a live system, so that’s an easy way to keep it separate from them in scripts:

zfs create zf/jail/.freebsd-10x64

Unpack FreeBSD into the new jail

Go to your favorite FreeBSD mirror site and fetch the distribution files matching your architecture and the release you want to use. You can get your architecture with uname -p, and see your release with uname -r (dropping any -pX patchlevel from the end). In my case, my architecture is amd64 and my release is 10.2-RELEASE, so I fetched from ftp://ftp5.us.freebsd.org/pub/FreeBSD/releases/amd64/10.2-RELEASE.

You don’t need the kernel, ports, or doc archives, so grab the other four. (You probably don’t need games either, but it’s small.) Download them into somewhere handy. I put them in /root.

Unpack them into your new jail:

cd /usr/jail/.freebsd-10x64
tar -xJvf /root/base.txz
tar -xJvf /root/lib32.txz
tar -xJvf /root/src.txz
tar -xJvf /root/games.txz

Setup the fresh install

You need to copy a few things into your new FreeBSD install and setup a few things to make it a bootable OS of its own:

cp /etc/resolv.conf /usr/jail/.freebsd-10x64/etc/  # so the jail can do DNS

Edit /root/.profile and add this line, if you aren’t already defining and exporting ENV. The reason for this will appear later:

ENV=$HOME/.shrc ; export ENV

Now we’ll chroot into the filesystem, so that the following commands will treat the jailed filesystem as if it is the root filesystem. These are setup details that would normally be handled by the installer. The last line updates the guest OS with any available updates.

chroot /usr/jail/.freebsd-10x64

passwd               # (set the password for root in the jail)
mkdir /usr/ports
mkdir /usr/home
ln -s /usr/home /home
cd /etc/mail
make aliases
freebsd-update fetch install

Now edit /root/.shrc (still chrooted into the jailed filesystem) and add the following line, plus any other environment variables or aliases that you want to set when you run a shell within the jail. This will put JAIL:{hostname} in your command prompt later whenever you enter a jail as root, so you won’t get confused about whether you’re in the host or the guest. You don’t want to do a rm -rf * at some point, thinking you’re in the jail, and then realize you already exited and are wiping something out on the host.

PS1='JAIL:{\h} \$ '

Edit /etc/rc.conf and add a few lines to keep the jail from running things it doesn’t need to:

sendmail_enable="NONE"
syslogd_flags="-ss"
rpcbind_enable="NO"

Edit /etc/make.conf and add these lines. The important thing here is that we’re going to have each jail mount /usr/ports read-only from the host system, so all your jails don’t have to download and maintain their own copies of the ports tree. But since they won’t be able to write in /usr/ports, they need to download distfiles, build ports, and store packages somewhere local. If you don’t want them in /var, choose somewhere else, just not under /usr/ports.

WITH_PKGNG=yes
WRKDIRPREFIX=/var/ports
DISTDIR=/var/ports/distfiles
PACKAGES=/var/ports/packages
INDEXDIR=/usr/ports

Now run pkg once to setup the pkg directories, and ignore the error it spits out.

If there’s anything else you can think of that you want all your jails to have, go ahead and put it in place now. For instance, if you want a particular user account in every jail, create it now. When you’re ready, exit to get out of chroot and back to the full host.

Create a snapshot of this prepared FreeBSD image

Now that you have this fresh install of FreeBSD configured to your satisfaction and have exited back to the host, take a ZFS snapshot of its filesystem. You will clone this snapshot later to create individual jails. I name it “ready” to show that it is ready for cloning:

zfs snapshot zf/jail/.freebsd-10x64@ready

Setup the host to support jails

First enable jails:

echo jail_enable="YES" >>/etc/rc.conf

Now create /etc/jail.conf and add the following lines.

# file: /etc/jail.conf
# Defaults
exec.prestart = "/sbin/mount -t nullfs -o ro /usr/ports/ /usr/jail/$name/usr/ports";
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.poststop = "/sbin/umount -f /usr/jail/$name/usr/ports";
exec.clean;
mount.devfs;
mount.fstab = "/etc/fstab.blank";
host.hostname = "$name.domain.com";   # replace 'domain.com' with your own
allow.nomount;
path = "/usr/jail/$name";

You’ll add a few lines here later when you create your first jail, but this sets up defaults for all your jails. To explain some of these lines: the jail commands replace $name in these settings with the name of a jail. The exec.prestart lines runs before the jail starts and mounts /usr/ports read-only so the jail can see it. The exec.poststop line likewise unmounts it when you stop the jail. It gives a blank fstab so the jailed OS won’t complain on boot. Set the hostname domain to whatever you like; the $name will match the jail name, which makes things easy.

Now create that empty fstab:

touch /etc/fstab.blank

Make jails!

Now your host system is ready to create all the jails you like! The first time you do all this, it may take a few hours, as you get things just the way you want them. With some experience, it can all be done in 30 minutes or so.

Coming up in Part 2: creating a jail to support a single network service.

(Hat-tip to Savagedlight, whose article on FreeBSD jails and ZFS clones was a major source of the procedure I’ve outlined here.)