A FreeBSD 10 Desktop How-to

FreeBSD is a fast, secure, modern Unix-like operating system with a fantastic community, great documentation, and powerful technologies like ZFS and LLVM. It’s my operating system of choice for everything from my beefy i7-2600k desktop to my home router to my ARM plug computer jukebox. Though famed for its uptime in the datacenter the same OS is just as suited to desktop or laptop computing with a little work.

Why use FreeBSD? Maybe I’m just getting old, but it’s nice to use an operating system that didn’t spawn a billion-dollar anti-malware industry through frequent security failings, where you can choose the interface you like and reasonably expect it to stay that way instead of being forced into the design fad du jour, where you don’t have to argue about the init system being replaced two times in the same decade, and whose key organizations don’t collectively kowtow to Microsoft when convenient. I’ve used many operating systems and have yet to find one more consistent and cohesive yet as well-supported as the BSD family, and FreeBSD is the one with the biggest community and most available drivers for things like graphics cards. “FreeBSD on the server, Linux on the desktop” is an oft-seen sentiment among some FreeBSD enthusiasts, and it’s sort of understandable considering the conservative out-of-the-box FreeBSD installation. Despite that, FreeBSD is just a few settings away from being an easy, powerful Desktop OS rivaling Linux, complete with the same software ecosystem available through the Ports collection.

Unlike Linux where everything including the kernel is a package, FreeBSD is developed in a single source tree and released on a set schedule – twice a year – as a complete operating system on top of which you can install third-party software. The Release Engineering page tracks the release history and schedule. Two major branches see releases in parallel, and major branches tend to live for two years (four minor versions) after their x.0 release. FreeBSD 10.x is currently the newest release branch with 9.x in maintenance mode and major development happening on 11.x.

This guide attempts to show users with various hardware configurations the best way to configure a usable modern workstation running FreeBSD based on my own experience with Emi, my FreeBSD workstation. There are projects such as PC-BSD and GhostBSD that can give you a good out-of-the-box desktop FreeBSD experience, but I find them disconnected from the underlying operating systems because they dump you into KDE or XFCE and attempt to hide as much of FreeBSD as possible behind graphical configuration. That’s not a bad thing, and I’m glad those projects exist, but this guide gets there in the other direction. You will install FreeBSD, learn how it works, and configure it into a great desktop. Compare this guide to something like Linux From Scratch or a Gentoo installation and you’ll see what a breeze this really is. Let’s do it!

New Installations

The Getting FreeBSD page has links to ISOs for the six tier 1 architectures. This guide focuses on amd64/i386 PCs though is broadly applicable to them all. The ISOs are available in bootonly, CD, DVD, and memstick. I usually grab the nearest >1GB USB drive and dd the newest memstick image to it. The larger DVD images are available complete with Ports distribution files for those doing fully-offline installations.

Starting with 10.1 you also have the choice of uefi images, that being the first release to ship with the EFI version of the loader. Give it a shot if you have a computer with UEFI instead of an old-school BIOS, but be warned it is new and still sensitive to UEFI implementations that are incomplete or deviate from the standard. Booting it on my Macbook, for example, leaves me with a useless black screen console despite everything running correctly in the background (Bug 193745), but Apple are well-known for their shoddy UEFI implementation.

Boot the chosen installation media via whatever means your computer can (EFI boot menu, BIOS setting, fallback) and get ready to install. FreeBSD will boot to bsdinstall and offer to Install, load an interactive rescue shell, or just boot normally off the installation disk. Choose Install, choose the keyboard mapping appropriate for your computer, and enter a hostname for your machine.

When asked to choose system components I recommend selecting all of them. doc is useful to have locally if your Internet connection isn’t working, and system src is needed for some Ports to build and install.


On the next screen, Partitioning, select either the Auto (ZFS) option or the Auto (UFS) option. UFS is the traditional Unix file system and is usable on any machine. It is fragile in the case of power loss or crashes unless journaled. ZFS, on the other hand, is both a volume (pool) manager and a great filesystem. I strongly recommend ZFS for modern computers due to its resilience and rich feature set that makes it very practical for desktop use. It checksums your data constantly to ensure integrity and prevent silent corruption on-disk, and its copy-on-write model never overwrites blocks, eliminating the RAID-5 write hole. It supports snapshots, allowing you to snapshot a filesystem at an arbitrary point in time and roll back to it at will, like Apple’s Time Machine, and snapshots can be sent seamlessly across a network for incremental backups. It supports SSD cache devices to speed up reads and writes of pools backed by magnetic hard drives. It can deduplicate files, reducing the on-disk space for files that are significantly identical at the cost of lots of RAM. Achieving these features makes ZFS very memory-hungry. Plan to have 1GiB of physical memory for every 1TB of space in a zpool and much more if deduplication is used. ZFS can be tuned for tighter memory limitations, but very limited systems should use UFS instead. Most modern machines should not need to tune ZFS at all. It will use the memory available to it but also respond to memory pressure when other processes need RAM.

Assuming you choose ZFS, set up your zpool. The pool can be a single disk (still called stripe but just striped with itself), a mirror, or any combination of disks in RAID-Z. Name the pool something. I usually name boot pools after the hostname of the machine and then data pools by function.

The other ZFS options are dictated by your hardware.

ZFS Pool configuration screen in FreeBSD installer.

If you have an Advanced Format hard disk (any made in the last few years) or an SSD you should force 4k sectors.

If your computer has a recent Intel or AMD CPU supporting AES instruction set there is very little downside to encrypting your pool. I recommend it for any pool that doesn’t need to automatically mount at boot, i.e. I use encryption on my workstation but not on my FreeBSD router. Encrypting multiple physical devices with the same key will only require the passphrase once. You will be prompted for the passphrase while the kernel has loaded and is detecting hardware. On my system the passphrase prompt usually gets buried under my USB devices as the kernel enumerates them, so if you find yourself stuck there at boot hit a few keys and Enter to make the passphrase prompt reappear.

Use GUID Partition Table (GPT) if your computer uses EFI. PCs with BIOS most likely need to use a legacy MBR. GPT is a requirement to use disks over 2TB in size because MBR can address a maximum of 232 x 512 bytes, just larger than 2TB.

The amount of swap space you use if any is dictated by the amount of memory in your computer and the loads you plan to place on it. Conventional wisdom says to use a swap size double the amount of physical memory in the machine, but I find that to apply less and less when you get up into double-digit gigabytes of RAM. My computer has 16GiB or physical memory and 8GiB of swap space defined. On some systems I don’t touch swap at all, but I recommend having at least some. You can enlarge it later.


Once your disks are set up the installer will copy files and prompt you for the base configuration of things such root password, time zone, and network options. It will ask you to add at least one non-root user. When creating your personal user account be sure to invite it to the wheel and operator user groups. wheel membership is necessary to gain root privileges for administration tasks, and you will assign operator device permissions later in this guide. When prompted you can remove the install disk and reboot into your new system!


Are you running a previous version already? The upgrade process is covered in full in Chapter 24 of the Handbook, but assuming you are running the stock GENERIC kernel the process is very simple using freebsd-update. Check my upgrade notes section for specific version instructions.

First, fetch the new system using freebsd-update install by specifying the -r argument. Without -r it will just fetch security and errata updates for your current minor version. You can upgrade to a new minor version in your current major or to a new major version entirely. If you’re upgrading to a new major version, go to the .0 release first. Don’t upgrade from, say, 8.4-RELEASE to 9.3-RELEASE, but to 9.0-RELEASE first and then to 9.3.

  1. freebsd-update upgrade -r 10.1-RELEASE

upgrade is interactive and will ask you to confirm the system components it thinks you have installed. Once it fetches the updated system files you can begin the installation process.

  1. freebsd-update install

This will install the new kernel but not any non-kernel OS components like userland executables. Reboot via shutdown -r now, reboot, or a swift kick to the power switch. When the system comes up, log in as root and install the new userland by re-running the install command.

  1. freebsd-update install

At this point your OS itself is ready to go but your Ports need to be updated to run on the new major version via your preferred method, such as pkg update && pkg upgrade, portupgrade, or portmaster. It is alternatively possible to maintain ABI compatibility with an older major version of FreeBSD by installing a compatibility library package such as misc/compat9x, but you shouldn’t unless you need it for a particular binary that isn’t available as source to build for the new version.

Once that’s done you can run freebsd-update install one last time to chean out the shared libraries from the previous version. Reboot once more to your final updated system.

First Boot

Log in as root with the password you configured in the installer. Congratulations! You are now a FreeBSD user!

The FreeBSD base system is a fully-featured operating system but as you can see does not contain a graphical environment or any third-party software like your typical Linux distribution. Before installing any of that you should configure your new system to be a better desktop. FreeBSD’s roots are in academia and the datacenter, so its default configuration is very conservative. The desktop or laptop computer you are most likely using is vastly more powerful than some of the configurations that will run FreeBSD, so there is room to grow without being unreasonable.

You will need a text editor to edit configuration files. The base system ships with vi (not vim!) but for most users I would recommend ee. It’s part of the base system and is a simple but fully-featured editor like nano from the Linux world. If you aren’t happy with ee there are plenty of great editors you can install from Ports, like editors/vim, but let’s continue.

If you aren’t entirely comfortable with editing config files you can re-access the graphical configuration screen from the installer by running bsdconfig as root, but I don’t think you’d be reading this page if that’s the case :)


The LANG=xx_YY.ZZZZ environment variable sets the system locale to language code xx, country code YY, and character encoding ZZZZ. Language and country code affect default application language, number formatting, date and time formatting, string collation, currency settings, and more.

By enabling a locale using UTF-8 character encoding, the system can understand and display each of the 1112064 characters in the Unicode character set, instead of just US ASCII as is default with LANG=C.

Check locale -a | grep UTF-8 for a list of every available UTF-8 locale on your computer. As an American anglophone, I use en_US.UTF-8.

Edit the login class capability database in /etc/login.conf to add a default character set and locale. Login shells will inherit the environment variables defined here in the default class or in a narrower class if it matches one.

  1. --- login.conf.default 2012-01-02 17:08:05.804291477 -0500
  2. +++ login.conf 2012-01-02 17:08:16.996213774 -0500
  3. @@ -44,7 +44,9 @@
  4. \:pseudoterminals=unlimited:\
  5. \:priority=0:\
  6. \:ignoretime@:\
  7. - \:umask=022:
  8. + \:umask=022:\
  9. + \:charset=UTF-8:\
  10. + \:lang=en_US.UTF-8:

Rebuild the login database with cap_mkdb /etc/login.conf after making changes.

You may have to specify the new locale elsewhere (like /etc/profile) for non login shell uses such as GDM and other login managers.

  1. LANG=en_US.UTF-8; export LANG
  2. CHARSET=UTF-8; export CHARSET
  3. GDM_LANG=en_US.UTF-8; export GDM_LANG

You can read more in the Using Localization chapter of the Handbook. Check your work by running locale on your next login.

  1. LANG=en_US.UTF-8
  2. LC_CTYPE="en_US.UTF-8"
  3. LC_COLLATE="en_US.UTF-8"
  4. LC_TIME="en_US.UTF-8"
  5. LC_NUMERIC="en_US.UTF-8"
  6. LC_MONETARY="en_US.UTF-8"
  7. LC_MESSAGES="en_US.UTF-8"
  8. LC_ALL=en_US.UTF-8

Build Settings

Some third-party software options can only be set at compile time. Here are a few you should consider before getting started installing things.

The Qt toolkit has some options that can be set via any combination of the following knobs. If you change the QT4_OPTIONS after Qt is installed you will need to rebuild devel/qt4-corelib and x11-toolkits/qt4-gui.

  • QGtkStyle is a selectable theme engine that lets Qt applications integrate more closely with GTK+ environments and can be enabled with the QGTKSTYLE Qt4 option. You should enable this option if you plan to use a GTK+-based desktop environment like MATE or XFCE. Once built you can select the GTK+ visual style in qt4-qtconfig.
  • CUPS is the standard printing engine on Free Unix-like systems. Support for it in Qt can be enabled with the CUPS Qt4 option.
  • Network Audio System is a network transparent client/server audio transport system and can be enabled in Qt applications by setting the NAS Qt4 option.
  1. echo "QT4_OPTIONS= CUPS QGTKSTYLE NAS" >> /etc/make.conf

Tuning and drivers

Change a few sysctl variables to enhance the experience of FreeBSD on the desktop, including expanding the amount of shared memory, tuning the process scheduler for desktop use, and increasing the limit of simultaneously-open files to something sensible.

  1. # Enhance shared memory X11 interface
  2. kern.ipc.shmmax=67108864
  3. kern.ipc.shmall=32768
  4. # Enhance desktop responsiveness under high CPU use (200/224)
  5. kern.sched.preempt_thresh=224
  6. # Bump up maximum number of open files
  7. kern.maxfiles=200000
  8. # Disable PC Speaker
  9. hw.syscons.bell=0
  10. # Shared memory for Chromium
  11. kern.ipc.shm_allow_removed=1

Some knobs can only be set at boot by the loader by setting them in /boot/loader.conf. This is also where we define kernel modules to load at boot.

  1. # Use new graphical console driver
  2. kern.vty=vt
  3. # Devil worship in loader logo
  4. loader_logo="beastie"
  5. # Boot-time kernel tuning
  6. kern.ipc.shmseg=1024
  7. kern.ipc.shmmni=1024
  8. kern.maxproc=10000
  9. # Load MMC/SD card-reader support
  10. mmc_load="YES"
  11. mmcsd_load="YES"
  12. sdhci_load="YES"
  13. # Access ATAPI devices through the CAM subsystem
  14. atapicam_load="YES"
  15. # Filesystems in Userspace
  16. fuse_load="YES"
  17. # Intel Core thermal sensors
  18. coretemp_load="YES"
  19. # AMD K8, K10, K11 thermal sensors
  20. amdtemp_load="YES"
  21. # In-memory filesystems
  22. tmpfs_load="YES"
  23. # Asynchronous I/O
  24. aio_load="YES"
  25. # Handle Unicode on removable media
  26. libiconv_load="YES"
  27. libmchain_load="YES"
  28. cd9660_iconv_load="YES"
  29. msdosfs_iconv_load="YES"

Finally, enable everything else.

  1. moused_enable="YES"
  2. # powerd: hiadaptive speed while on AC power, adaptive while on battery power
  3. powerd_enable="YES"
  4. powerd_flags="-a hiadaptive -b adaptive"
  5. # Enable BlueTooth
  6. hcsecd_enable="YES"
  7. sdpd_enable="YES"
  8. # Synchronize system time
  9. ntpd_enable="YES"
  10. # Let ntpd make time jumps larger than 1000sec
  11. ntpd_flags="-g"

Enable remote access via SSH if you plan to use it. Otherwise, there’s no need to expose your system.

  1. # Remote logins
  2. sshd_enable="YES"


The procfs and fdescfs virtual filesystems are not a default part of BSD but are frequently required for compatibility with programs and environments written with Linux in mind, such as GNOME/MATE and KDE. The FreeBSD equivalent is sysctl, but you can mount /proc too if you plan to use software requiring it.

Some special filesystems like fdescfs must be mounted late on ZFS-rooted systems since the location of their mountpoint won’t exist until late in the boot process.

  1. proc /proc procfs rw 0 0
  2. fdesc /dev/fd fdescfs rw,auto,late 0 0

Toggle the sysctl that lets users mount disks.

  1. # Allow users to mount disks
  2. vfs.usermount=1

If you neglected to add your personal user account to the wheel and operator groups at creation, now is a good time to do so. wheel membership lets you use su to become root, and operator membership is required for device permissions in this configuration. In this example my user is nicole. Substitute it for yours.

  1. pw usermod nicole -G wheel
  2. pw usermod nicole -G operator

Device Permissions

Relax default permissions on the device filesystem to allow normal users access to a variety of disks and input/output devices.

Permissions for devices existing at boot time are set in devfs.conf. Each line defines a full device path and octal permission value.

  1. # Allow all users to access optical media
  2. perm /dev/acd0 0666
  3. perm /dev/acd1 0666
  4. perm /dev/cd0 0666
  5. perm /dev/cd1 0666
  6. # Allow all USB Devices to be mounted
  7. perm /dev/da0 0666
  8. perm /dev/da1 0666
  9. perm /dev/da2 0666
  10. perm /dev/da3 0666
  11. perm /dev/da4 0666
  12. perm /dev/da5 0666
  13. # Misc other devices
  14. perm /dev/pass0 0666
  15. perm /dev/xpt0 0666
  16. perm /dev/uscanner0 0666
  17. perm /dev/video0 0666
  18. perm /dev/tuner0 0666
  19. perm /dev/dvb/adapter0/demux0 0666
  20. perm /dev/dvb/adapter0/dvr 0666
  21. perm /dev/dvb/adapter0/frontend0 0666

For devices that may be connected post-boot, we add an entry to a devfs.rules ruleset. Rulesets must have a unique name and number, and their rules are composed of a path or quoted path glob and octal permission value.

  1. [devfsrules_common=7]
  2. add path 'ad[0-9]\*' mode 666
  3. add path 'ada[0-9]\*' mode 666
  4. add path 'da[0-9]\*' mode 666
  5. add path 'acd[0-9]\*' mode 666
  6. add path 'cd[0-9]\*' mode 666
  7. add path 'mmcsd[0-9]\*' mode 666
  8. add path 'pass[0-9]\*' mode 666
  9. add path 'xpt[0-9]\*' mode 666
  10. add path 'ugen[0-9]\*' mode 666
  11. add path 'usbctl' mode 666
  12. add path 'usb/\*' mode 666
  13. add path 'lpt[0-9]\*' mode 666
  14. add path 'ulpt[0-9]\*' mode 666
  15. add path 'unlpt[0-9]\*' mode 666
  16. add path 'fd[0-9]\*' mode 666
  17. add path 'uscan[0-9]\*' mode 666
  18. add path 'video[0-9]\*' mode 666
  19. add path 'tuner[0-9]*' mode 666
  20. add path 'dvb/\*' mode 666
  21. add path 'cx88*' mode 0660
  22. add path 'cx23885*' mode 0660 # CX23885-family stream configuration device
  23. add path 'iicdev*' mode 0660
  24. add path 'uvisor[0-9]*' mode 0660

Enable our new ruleset.

  1. devfs_system_ruleset="devfsrules_common"


Enable sound support at boot in loader.conf, and load it immediately with kldload snd_driver.

  1. echo 'snd_driver_load="YES"' >> /boot/loader.conf

Then, cat /dev/sndstat to see your available devices.

cat /dev/sndstat
  1. FreeBSD Audio Driver (newpcm: 64bit 2009061500/amd64)
  2. Installed devices:
  3. pcm0: <HDA NVidia (Unknown) PCM #0 DisplayPort> (play)
  4. pcm1: <HDA NVidia (Unknown) PCM #0 DisplayPort> (play)
  5. pcm2: <HDA NVidia (Unknown) PCM #0 DisplayPort> (play)
  6. pcm3: <HDA NVidia (Unknown) PCM #0 DisplayPort> (play)
  7. pcm4: <HDA Realtek ALC892 PCM #0 Analog> (play/rec)
  8. pcm5: <HDA Realtek ALC892 PCM #1 Analog> (play/rec)
  9. pcm6: <HDA Realtek ALC892 PCM #2 Digital> (play)
  10. pcm7: <HDA Realtek ALC892 PCM #3 Digital> (play)
  11. pcm8: <USB audio> (play) default
  12. pcm9: <USB audio> (rec)

The hw.snd.default_unit sysctl variable controls the default audio output. I want to use the S/PDIF output of my onboard Realtek audio, pcm6, so I set hw.snd.default_unit to 6.

Enabling the hw.snd.default_auto boolean will automatically assign hw.snd.default_unit to newly-attached devices.

  1. # S/PDIF out on my MSI board
  2. hw.snd.default_unit=6
  3. # Don't automatically use new sound devices
  4. hw.snd.default_auto=0


If you didn’t enable networking during the install process now is a good time to do so. Here as an example is my computer, emi, a desktop with a wired network. I have a Realtek interface, re0. The name of your interface may vary based on the driver it uses. Most drivers are built into the GENERIC kernel, so your interface should be visible by running ifconfig. Common drivers you may see include if_em for Intel PRO interfaces, if_re for Realtek interfaces, and if_en for Midway interfaces. Read more about network configuration in the Handbook to learn about other possible configurations.


You can use DHCP and SLAAC auto-discovery on most home networks:

  1. hostname="emi.aloe.cooltrainer.org"
  2. # Enable DHCP for re0 and don't let dhclient block
  3. background_dhclient="YES"
  4. ifconfig_re0="DHCP"
  5. ifconfig_re0_ipv6="inet6 accept_rtadv"

You can bring up the interface and get a DHCP address immediately by issuing ifconfig re0 up and dhclient re0, again substituting the name of your own interface.

Alternatively, you can supply static network addresses for your computer and default router:

  1. hostname="emi.aloe.cooltrainer.org"
  2. ifconfig_re0="inet netmask broadcast"
  3. defaultrouter=""
  4. ifconfig_re0_ipv6="inet6 2001:370:10f5:806::40 prefixlen 64"
  5. ipv6_defaultrouter="2001:370:10f5:806::1"


For WiFi configuration, see the wireless networking section of the Handbook. I sometimes tether my desktop to my Android phone using a run B/G USB interface. It’s as simple as defining a new virtual wlan interface on run0, configuring wpa_supplicant for the WPA pre-shared key, and specifying the SSID and encryption standard (WPA).

  1. wlans_run0="wlan0"
  2. ifconfig_wlan0="ssid Doubleshot WPA DHCP"
  1. network={
  2. ssid="Doubleshot"
  3. psk="pantsupantsu"
  4. }


My configuration examples cover both IPv4 and IPv6 because I have a dual-stacked network. Depending on your network you may prefer to enable and prefer IPv6 like me, enable it but prefer IPv4, or not enable it at all. This can be done in rc.conf:

  1. ipv6_activate_all_interfaces="YES"
  2. ip6addrctl_policy="ipv6_prefer"
  1. # Accept IPv6 router advertisements
  2. net.inet6.ip6.accept_rtadv=1


You should run a firewall. Windows, OS X, and many Linux distributions ship with a default firewall ruleset. FreeBSD does not, because there is no one-size-fits-all firewall configuration, but it does include one of the best software firewalls in the world, PF, courtesy of the OpenBSD project.

Configuring a firewall can be a very complex topic. There are entire books on the matter. Shown here is the ruleset from my computer. It has rules for a single network interface defined at the top of the file in the ext_if macro. Change it to the name of your computer’s interface as seen in ifconfig. The macros on the next few lines define the TCP and UDP ports on which this ruleset will allow incoming connections. My computer runs an SSH server on the default port, runs www/subsonic on port 443 (HTTPS), and has control ports for net/mosh in the 60000 range. You can open ports for additional services by defining them in those macros. The named services like ssh are defined in /etc/services.

  1. # The name of our network interface as seen in `ifconfig`
  2. ext_if="re0"
  3. # Macros to define the set of TCP and UDP ports to open.
  4. # Add additional ports or ranges separated by commas.
  5. # UDP 60000-60010 is mosh control http://mosh.mit.edu/
  6. tcp_services = "{ssh, https}"
  7. udp_services = "{60000:60010}"
  8. # If you block all ICMP requests you will break things like path MTU
  9. # discovery. These macros define allowed ICMP types. The additional
  10. # ICMPv6 types are for neighbor discovery (RFC 4861)
  11. icmp_types = "{echoreq, unreach}"
  12. icmp6_types="{echoreq, unreach, 133, 134, 135, 136, 137}"
  13. # Modulate the initial sequence number of TCP packets.
  14. # Broken operating systems sometimes don't randomize this number,
  15. # making it guessable.
  16. tcp_state="flags S/SA keep state"
  17. udp_state="keep state"
  18. # Don't send rejections. Just drop.
  19. set block-policy drop
  20. # Exempt the loopback interface to prevent services utilizing the
  21. # local loop from being blocked accidentally.
  22. set skip on lo0
  23. # all incoming traffic on external interface is normalized and fragmented
  24. # packets are reassembled.
  25. scrub in on $ext_if all fragment reassemble
  26. # set a default deny policy.
  27. block in log all
  28. # This is a desktop so be permissive in allowing outgoing connections.
  29. pass out quick modulate state
  30. # Enable antispoofing on the external interface
  31. antispoof for $ext_if inet
  32. antispoof for $ext_if inet6
  33. # block packets that fail a reverse path check. we look up the routing
  34. # table, check to make sure that the outbound is the same as the source
  35. # it came in on. if not, it is probably source address spoofed.
  36. block in from urpf-failed to any
  37. # drop broadcast requests quietly.
  38. block in quick on $ext_if from any to
  39. # Allow the services defined in the macros at the top of the file
  40. pass in on $ext_if inet proto tcp from any to any port $tcp_services $tcp_state
  41. pass in on $ext_if inet6 proto tcp from any to any port $tcp_services $tcp_state
  42. pass in on $ext_if inet proto udp from any to any port $udp_services $udp_state
  43. pass in on $ext_if inet6 proto udp from any to any port $udp_services $udp_state
  44. # Allow ICMP
  45. pass inet proto icmp all icmp-type $icmp_types keep state
  46. pass inet6 proto icmp6 all icmp6-type $icmp6_types keep state

Enable the firewall in rc.conf and start it now.

  1. echo 'pf_enable="YES"' >> /etc/rc.conf
  2. service pf start

After making changes to your ruleset you can check them for validity and load the new rules with pfctl. It will abort if your ruleset contains an error unlike service pf restart which will stop, fail to start due to the error, and leave you locked out of SSH. Ask me how I know this will happen.

  1. pfctl -f /etc/pf.conf

Installing Software

FreeBSD is historically famous for its Ports Collection, a directory skeleton of Makefiles and patches describing how to programmatically build packages of third-party software for your computer. Each port contains the metadata for that piece of software including the filename of the source archive, sha256 hash of the files, what other software dependencies it requires, what compile-time options are available, what files it installs, and any patches necessary to work around non-portable code or fix issues that can’t be upstreamed to the projects themselves. Every port has a maintainer whose job it is to keep the port up to date and respond to issues if they arise with newer versions of the operating system. For example, check out the ports I maintain! When you make a port in the Ports Collection it downloads the upstream source archive, patches it, configures it, builds a customized binary package, and uses FreeBSD’s underlying binary package manager to install it.

Third-party software installed through the package manager ends up in /usr/local where it mirrors the hierarchy of /usr. It might seem confusing to have them in two places, but it gives a fairly clean separation of the base system from the packages. For example, /usr/local/bin is where you will find firefox after installing www/firefox, but /usr/bin is where you will find ee or sed. As you have experienced, configuration for the operating system is done in /etc. Configuration files for your ports will usually be in /usr/local/etc. Check the hier manual for the full layout.

As of FreeBSD 10 there is a new binary package manager, known as pkgng or just pkg. It replaces the old suite of pkg_ tools such as pkg_add and pkg_delete and contains many advanced features that have been missing from FreeBSD for years. Compared to the old package manager, pkgng supports safe upgrades (meaning it saves a copy of the previous-version package to roll back in case of failure), multiple repositories, package staging before install, a more modern binary package format, a more robust sqlite-based package registration database, and most importantly remote binary package upgrades.

Thanks to pkgng it is now possible to add multiple remote binary package repositories and get updates from them without relying on building Ports at all. I still prefer building from Ports to using the binary packages because there are many useful non-default options on many useful ports and many ports unavailable as binary packages on the default repository. FreeBSD Ports’ options are as conservative as the base system, so options that pull in optional shared libraries or enable non-Free features will be off by default, and binary packages from the official package repository will reflect those defaults. Examples of non-default options you as a desktop user will probably want include support for most of the codecs in multimedia/mplayer and multimedia/vlc, PAM support in net/samba36, USB printer support in print/cups, and many others.

It is possible to mix and match binary packages and building certain packages from Ports using pkgng’s lock and unlock, but that gets more advanced and more annoying than is appropriate for this guide. I build my ports on one of my computers using poudriere then use that computer as a binary package repository for the other FreeBSD computers on my network. A new user with just one computer should stick with one or the other until they are more familiar with the OS. I use and recommend Ports for users in this guide for the customizability, but the names are equivalent. For example, when I say “Change directory to /usr/ports/www/firefox and make install” you can also use pkg install firefox to get the already-compiled package from the official default repo with default options.

No matter the route you choose, you should begin by updating your pkg repository or your Ports tree. pkg update will fetch an updated index from every PACKAGESITE defined in that environment variable or in /usr/local/etc/pkg.conf. For Ports, portsnap fetch extract will retrieve a new full ports tree. You should read pkg for the list of commands supported by pkg and read ports for the list of available make targets in Ports, but in general you will use pkg install <portname> or cd /usr/ports/<category>/<portname> && make install to install software.

The first things I usually install are sysutils/tmux and shells/zsh because I prefer it to the venerable default tcsh. You might be more comfortable with shells/bash. Once installed, changing your user’s default shell is as simple as chsh -s /usr/local/bin/zsh.

Staying Up To Date

Before updating your Ports tree or pkg catalogue I suggest checking out UPDATING. This file – also found at /usr/ports/UPDATING – tracks breaking changes in packages and the steps necessary to to fix them. It will tell you when configuration file syntax has changed, how to fix dependencies when ports split or merge, when default versions of packages change, and more.

You can update your already-extracted Ports tree to the newest revision with portsnap fetch update. There are two common tools for programmatically upgrading your ports, ports-mgmt/portupgrade and ports-mgmt/portmaster. I prefer portupgrade because portmaster stubbornly aborts the entire upgrade on any error, but you might like it. The common portmaster usage is portmaster -a to upgrade installed ports. I usually update with portupgrade -rac, with -r -a to recursively update all installed ports and -c to preemptively show new port options so they won’t interrupt the build.

If you are using binary packages you can update the package repository catalog with pkg update and upgrade your installed packages with pkg upgrade.

The Handbook has a more detailed chapter on using Ports that includes upgrading and other tasks.

Going Graphical

I’m sure you’re eager to get out of the text-only console. To do so you need to install the X.org distribution of the X Window System.

Change directory to /usr/ports/x11/xorg. Since Xorg is comprised of many modular Ports it takes a while to build and contains many port options (displayed to you as a blue dialog prompt.) Run make config-recursive in x11/xorg to set these port options in advance so they don’t continually interrupt the build. Read over the options as they are presented, but generally don’t toggle an option if you don’t know what it does. The defaults are default for a reason :)

Once you’ve chosen all the options, run make config-recursive again, since it’s likely for a dependency enabled the first time to have options of its own. When no further port options are displayed run make install to compile and install X.org.

X.org by default uses FreeBSD’s devd for hardware detection and D-Bus for interprocess communication. HAL used to be the default hardware detection mechanism but is in the process of deprecation, so you may not need it unless you plan to use a desktop environment that still depends on it. Check the dependencies for sysutils/hal for a list of software still requiring it.

  1. hald_enable="YES"
  2. dbus_enable="YES"

With Radeon, Intel, or otherwise

This section explains how you should configure X for systems using an AMD Radeon and the radeon driver, an Intel grahpics chip with the intel driver, virtualized graphics cards like emulators/virtualbox-ose-additions’s vboxvideo, or any other generic framebuffer device supported by the default vesa driver.

As root, run X -configure. It will spit out a new X.org configuration file in /root/xorg.conf.new based on your detected hardware. Copy this file to /etc/X11/xorg.conf, then pull it up in a text editor for a few modifications.

Add an “Extensions” section and enable the Composite extension.

  1. Section "Extensions"
  2. Option "Composite" "Enable"
  3. EndSection

Add one line to the ServerLayout section to enable AIGLX.

  1. Section "ServerLayout"
  2. Identifier "X.org Configured"
  3. Screen 0 "Screen0" 0 0
  4. InputDevice "Mouse0" "CorePointer"
  5. InputDevice "Keyboard0" "CoreKeyboard"
  6. Option "AIGLX" "true"
  7. EndSection

I usually enable the EXA AccelMethod and DRI by adding their respective lines to the Device section. If you have a Radeon card ensure your Driver is configured as radeon, not radeonhd! radeonhd is an older, Novell-sponsored, defunct driver for Radeon HD hardware, but -configure likes to pick it by default if it’s installed. You should use radeon instead. Otherwise X -configure should pick the best driver.

  1. Section "Device"
  2. Option "AccelMethod" "EXA"
  3. Option "DRI" "true"
  4. Identifier "Card0"
  5. Driver "radeon"
  6. VendorName "Advanced Micro Devices [AMD] nee ATI"
  7. BoardName "RV770 [Radeon HD 4850]"
  8. BusID "PCI:1:0:0"
  9. EndSection

Enable the freetype, bitmap, and type1 X font modules by adding them to the Module section. According to the manual, “[t]he extmod, dbe, dri, dri2, glx, and record extension modules are loaded automatically if they are present”, but I like to go for the explicit configuration and define them anyway.

  1. Section "Module"
  2. Load "dbe"
  3. Load "dri"
  4. Load "dri2"
  5. Load "extmod"
  6. Load "record"
  7. Load "freetype"
  8. Load "bitmap"
  9. Load "type1"
  10. Load "glx"
  11. EndSection


Skip this section if you don’t use an NVIDIA graphics card.

The binary x11/nvidia-driver is the only proprietary software on my system. As much as I’d prefer a free and open solution, I’ve found that neither Nouveau nor the free Radeon or Intel driver compare to the speed and feature support of Nvidia’s official driver.

Install the driver itself, x11/nvidia-settings, and x11/nvidia-xconfig.

To load the nvidia kernel module at boot, enable it in /boot/loader.conf.

  1. echo 'nvidia_load="YES"' >> /boot/loader.conf

Run nvidia-xconfig to get a base xorg.conf in /etc/X11/xorg.conf. Pull it up in your favourite text editor and add the Module section to enable the freetype2, glx, type1 extensions.

  1. Section "Module"
  2. Load "freetype"
  3. Load "bitmap"
  4. Load "type1"
  5. Load "glx"
  6. EndSection

Later on, once you’re booted into the graphical environment, you can use nvidia-settings to configure TwinView and any other settings.

Install fonts

X.org doesn’t include many attractive typefaces by default. Luckily, there are plenty available in Ports.

Here are a few I use, including many from non-Roman languages for better Unicode coverage.

x11-fonts/webfonts is a special case. It includes the Microsoft Core Fonts for the Web such as Andale and Verdana. If you own a valid Microsoft Windows license you can get Tahoma as well by adding to /etc/make.conf first.

  1. # Enable Tahoma in x11-fonts/webfonts if you have a Windows license
  2. # You show me yours and I'll show you mine ;)
  3. .if ${.CURDIR:M*/x11-fonts/webfonts}
  5. .endif

Now that those fonts are installed you need to tell Xorg about them using a FontPath in your /etc/X11/xorg.conf so they can be used. Unfortunately the font paths in Ports are not entirely standardized. Most of them end up in /usr/local/lib/X11/fonts, some end up in /usr/local/share/fonts/, and some in just /usr/local/share/. Here’s the relevant section from my xorg.conf. Yours should look similar.

  1. Section "Files"
  2. FontPath "/usr/local/lib/X11/fonts/100dpi/"
  3. FontPath "/usr/local/lib/X11/fonts/75dpi/"
  4. FontPath "/usr/local/lib/X11/fonts/Caladea/"
  5. FontPath "/usr/local/lib/X11/fonts/Carlito/"
  6. FontPath "/usr/local/lib/X11/fonts/CharisSIL/"
  7. FontPath "/usr/local/lib/X11/fonts/DoulosSIL/"
  8. FontPath "/usr/local/lib/X11/fonts/Droid/"
  9. FontPath "/usr/local/lib/X11/fonts/GentiumBasic/"
  10. FontPath "/usr/local/lib/X11/fonts/GentiumPlus/"
  11. FontPath "/usr/local/lib/X11/fonts/Hana/"
  12. FontPath "/usr/local/lib/X11/fonts/Khmer/"
  13. FontPath "/usr/local/lib/X11/fonts/Liberation/"
  14. FontPath "/usr/local/lib/X11/fonts/LinLibertineG/"
  15. FontPath "/usr/local/lib/X11/fonts/Myanmar/"
  16. FontPath "/usr/local/lib/X11/fonts/OTF/"
  17. FontPath "/usr/local/lib/X11/fonts/PataType/"
  18. FontPath "/usr/local/lib/X11/fonts/TTF/"
  19. FontPath "/usr/local/lib/X11/fonts/TrueType/"
  20. FontPath "/usr/local/lib/X11/fonts/Type1/"
  21. FontPath "/usr/local/lib/X11/fonts/alee-ttf/"
  22. FontPath "/usr/local/lib/X11/fonts/anonymous-pro/"
  23. FontPath "/usr/local/lib/X11/fonts/artwiz-aleczapka-en/"
  24. FontPath "/usr/local/lib/X11/fonts/bitstream-vera/"
  25. FontPath "/usr/local/lib/X11/fonts/cyrillic/"
  26. FontPath "/usr/local/lib/X11/fonts/dejavu/"
  27. FontPath "/usr/local/lib/X11/fonts/dockapp/"
  28. FontPath "/usr/local/lib/X11/fonts/ecofont/"
  29. FontPath "/usr/local/lib/X11/fonts/encodings/"
  30. FontPath "/usr/local/lib/X11/fonts/fonts-indic/"
  31. FontPath "/usr/local/lib/X11/fonts/fonts-te/"
  32. FontPath "/usr/local/lib/X11/fonts/hebrew/"
  33. FontPath "/usr/local/lib/X11/fonts/junicode/"
  34. FontPath "/usr/local/lib/X11/fonts/koi8-u-gemini/"
  35. FontPath "/usr/local/lib/X11/fonts/local/"
  36. FontPath "/usr/local/lib/X11/fonts/misc/"
  37. FontPath "/usr/local/lib/X11/fonts/misc/:unscaled"
  38. FontPath "/usr/local/lib/X11/fonts/profont/"
  39. FontPath "/usr/local/lib/X11/fonts/proggy_fonts-ttf/"
  40. FontPath "/usr/local/lib/X11/fonts/stix/"
  41. FontPath "/usr/local/lib/X11/fonts/stracke/"
  42. FontPath "/usr/local/lib/X11/fonts/terminus-font/"
  43. FontPath "/usr/local/lib/X11/fonts/ubuntu-font/"
  44. FontPath "/usr/local/lib/X11/fonts/unfonts-core/"
  45. FontPath "/usr/local/lib/X11/fonts/unfonts-extra/"
  46. FontPath "/usr/local/lib/X11/fonts/webfonts/"
  47. FontPath "/usr/local/share/fonts/OTF/"
  48. FontPath "/usr/local/share/fonts/TTF/"
  49. FontPath "/usr/local/share/fonts/TrueType/"
  50. FontPath "/usr/local/share/fonts/amsfonts/"
  51. FontPath "/usr/local/share/fonts/cantarell/"
  52. FontPath "/usr/local/share/fonts/cm-super/"
  53. FontPath "/usr/local/share/fonts/shinonome/"
  54. FontPath "/usr/local/share/fonts/std.ja_JP/"
  55. FontPath "/usr/local/share/fonts/std.zh_CN/"
  56. FontPath "/usr/local/share/font-ipa/"
  57. FontPath "/usr/local/share/font-ipa-uigothic/"
  58. FontPath "/usr/local/share/font-ipaex/"
  59. FontPath "/usr/local/share/font-kochi/"
  60. FontPath "/usr/local/share/font-migmix/"
  61. FontPath "/usr/local/share/font-migu/"
  62. FontPath "/usr/local/share/font-mona-ipa/"
  63. FontPath "/usr/local/share/font-motoya-al/"
  64. FontPath "/usr/local/share/font-sazanami/"
  65. FontPath "/usr/local/share/font-shinonome/"
  66. FontPath "/usr/local/share/font-takao/"
  67. FontPath "/usr/local/share/font-vlgothic/"
  68. EndSection

You can install other invididual fonts later as a user by copying them to ~/.fonts under your home directory.

You can re-scan the configured FontPaths by running fc-cache -vf and can list all installed fonts with fc-list to check that they all appear. For example, I have a fairly large local font repository in my ~/.fonts/ directory and have 2313 fonts available on my system as of this writing according to fc-list | wc -l.

Desktop Environments

The best part of the X Window System ecosystem is the variety of environments available. You might prefer the configurability of KDE, the sparse cleanliness of MATE, something minimal like Window Maker, or even tiling like i3. This isn’t xwinman, but I’ve included screenshots and descriptions for some of the most popular environments to give you an idea what’s out there.


KDE is the largest and most fully-featured Free Software desktop environment, based on the Qt toolkit. Its configuration options are dizzyingly numerous and it has excellent support for modern technologies like high-DPI displays. It has a modern compositing window manager, KWin, the web and file browser Konqueror that famously spawned the KHTML engine that became WebKit, and a family of other Qt applications like the excellent Clementine. The KDE4 meta-port is available at x11/kde4.

FreeBSD 10 KDE 4.12 desktop

You can start KDE with exec startkde in your .xinitrc, but KDE also includes its own graphical login manager, KDM which you can optionally enable in rc.conf and start as a service.

  1. echo 'kdm4_enable="YES"' >> /etc/rc.conf
  2. service kdm4 start


GNOME 2 was a venerable desktop environment made famous as the Ubuntu default around 2008, and MATE is the community fork of GNOME 2 after the GNOME team lost their collective minds.

GNOME 2 is still available in Ports at x11/gnome2 but I can’t recommend using it since version 2.32 in 2010 is the last of its lineage. If you have a major GNOME craving check out the MATE Desktop Environment instead. It’s a well-maintained fork of 2.32 by an awesome team who lack GNOME’s utter contempt for their users. The MATE meta-port is available at x11/mate.

MATE and GNOME users should configure PolicyKit to allow normal users to mount removable media automatically.

  1. <config version="0.1">
  2. <match action="org.freedesktop.hal.storage.mount-removable">
  3. <return result="yes"/>
  4. </match>
  5. <match action="org.freedesktop.hal.storage.mount-fixed">
  6. <return result="yes"/>
  7. </match>
  8. <match user="root">
  9. <return result="yes"/>
  10. </match>
  11. <define_admin_auth group="wheel"/>
  12. </config>

MATE doesn’t include a GDM alternative, so start it with exec mate-session in your .xinitrc.

Compiz is a popular alternative window manager with MATE and GNOME 2 users. It gives you those fancy wobbly windows, 3d cubes, and all kinds of flashy stuff. You can install Compiz-Fusion from x11-wm/compiz-fusion. Be sure to disable the obsolete and unmaintained window decorator Emerald, a leftover from the Beryl project, when prompted on the port configuration screen. With Emerald disabled, compiz will default to gtk-window-decorator and will take on your normal GTK theme appearance but with more transparency and garish animation.

A screenshot of my FreeBSD GNOME 2 desktop.

Once installed, open Settings > Preferences > CompizConfig Settings Manager. You’ll probably want to enable the following plugins at minimum:

  • General: Gnome Compatibility
  • Desktop: Desktop Cube, Rotate Cube
  • Effects: Animations, Window Decoration, Wobbly Windows
  • Window Management: Application Switcher, Move Window, Place Windows, Resize Window

Open the “Run” box with Alt+F2 and execute compiz-manager. compiz-manager is a script for detecting and using the proper compiz options for your video hardware. Your screen will flash while Compiz and gtk-window-decorator initialize and replace Marco, MATE’s default window manager.

If your windows are missing titlebars, double-check you’ve enabled “Window Decoration” in ccsm. If all seems well, add compiz-manager as a new startup application (in Settings > Preferences > Startup Applications), then change MATE’s window manager preference in DConf:

  1. gsettings set org.mate.session.required-components windowmanager compiz

To switch back, use the same command with the argument marco.

Window Maker

It isn’t as popular or well-known as the others here, but Window Maker is my favorite and longest-used window manager. It is based on the look and feel of the NEXTSTEP operating system, the OS that became Rhapsody and then Mac OS X and iOS. Unlike the extremely limited one-dimensional Mac OS X dock, Window Maker offers a main dock as well as a “clip” dock that is unique to each virtual desktop. Docks can hold normal launchers and “dockapps”, small self-contained dock accessories.

A screenshot of my FreeBSD Window Maker desktop.

You can install Window Maker from x11-wm/windowmaker and start it with exec wmaker in your .xinitrc. In addition, I also show x11-clocks/wmclock, sysutils/wmcpuload, net/wmnd, audio/wmix, x11/sakura, and x11-fm/rox-filer.

The first time you start Window Maker you should run wmaker.inst to install the starter configuration to your ~/GNUstep directory.


Enlightenment was the original eye-candy desktop before modern compositors were even a thing. Version 0.17 is the ambitious rewrite release that almost never came out until e17releasemanager got it out the door. It contains an eye-catching desktop built on the project’s own Enlightenment Foundation Libraries. E17 is shiny, bouncy, extendable, and very configurable. You can install it from x11-wm/enlightenment and run it with exec enlightenment_start in your .xinitrc.

FreeBSD 10 Enlightenment 0.17.5 desktop


XFCE descends, like KDE, from the design of the once-proprietary Common Desktop Environment. As of XFCE 4.0, however, the desktop has become more of a GNOME-lite, the “other” GTK+ desktop environment. I don’t have much to say about it, but it is a very functional and lightweight desktop with panels, a window manager, a great file manager (Thunar), and some other lightweight applications like a terminal.

FreeBSD 10 XFCE desktop

You can start XFCE with exec startxfce4 in your .xinitrc.


Cinnamon is a GTK 3 desktop environment from the Linux Mint project. It began as a fork of the GNOME 3 Shell into a more traditional panels and menus UI since many were dissatisfied with the drastic redesign of a beloved environment. It’s come into its own as a modern DE and offers everything you would expect from GNOME 2 or MATE with a cohesive feel and forks of several of the GNOME core apps.

The only reasons I strongly prefer MATE to Cinnamon are the dearth of great GTK+ 3.x themes and Cinnamon’s inability to have more than a single panel in a multiple-monitor setup, issue #130, but the latter looks to be getting some traction as of late 2014.

You can install Cinnamon from x11/cinnamon and start it with exec cinnamon-session in your .xinitrc. There is also a fallback software-rendering mode that can be started with exec cinnamon-session-cinnamon2d instead.

No screenshots of this one since it won’t run in VirtualBox with any combination I can find of 3D/cinnamon2d and vboxvideo/vesa. Shoot me an email if you know how to make it behave otherwise check out screenshots of Linux Mint Cinnamon Edition on their screenshots page.


GNOME 3, available on Linux since 3.0 in the spring of 2011, is finally available in the official FreeBSD tree as of November 2014. The three and a half year delay is thanks to the upstream GNOME project’s years-long fight against any operating system that doesn’t have a penguin for a mascot. It took several years and a vastly waning userbase, then suddenly they care about portability again. Sure, okay. Either way, it’s here and you can install it from x11/gnome3.

We weren’t missing much in the delay, since the GNOME team tossed out everything great about their once-ubiquitous DE and turned it into a shiny but unconfigurable iOS imitator where basic features and options are either not available at all, buried inside a settings registry more reminiscent of Windows 98 than BSD, or relegated to extensions that will break with every new minor version thanks to the lack of any stable extensions API and whose very existence are opposed by many of the main project contributors. Take a look at the GNOME Shell Extensions page with me and be amused that you need an extension to use a theme, categorize the Applications menu, remove the otherwise-omnipresent accessibility menu from the status bar, or even power off your computer without knowing about the magic Alt-button toggle.

GNOME Shell in GNOME 3.12 on FreeBSD.

If you want a great GTK-based desktop environment maintained by a team that doesn’t hate you, check out MATE, XFCE, or Cinnamon. All three are excellent. I guess I can thank the GNOME project’s self-destruction for getting me back into Window Maker.


Qt4 settings application on FreeBSD.

Finding Clearlooks too drab and blue? You can find a world of themes and icons for MATE over on GNOME-Look, for KDE at KDE-Look, for XFCE at XFCE-Look, for E17 at E17-Stuff, and for several lightweight window managers at Box-Look. There are several attractive and usable themes buried among the OS X Aqua clones, Vista Aero clones, and black-as-my-soul darkness-fests that are standard on any theming website.

You can change theme settings for Qt4 applications with qt4-qtconfig and for KDE Qt applications (like Clementine) in the KDE System Settings. GTK+ is selectable in many window managers’ appearance preferences, and you can also install x11-themes/lxappearance for a light GTK theme switcher.

Starting X

The shell script .xinitrc in your home directory is the script that is executed for the lifecycle of your X session. .xinitrc is used to run startup applications and then run your window manager. When you finally end your X session your window manager will exit, .xinitrc will return, and the X server will stop.

  1. xscreensaver -no-splash &
  2. xdg-user-dirs-update &
  3. redshift &
  4. compton &
  5. exec wmaker

In my example .xinitrc I use Window Maker and start x11/xscreensaver, xdg-user-dirs, accessibility/redshift, and the lightweight compositor x11-wm/compton. This example script takes an argument to allow a choice of window managers. You can start an X session with startx or xinit <windowmanager> to supply the argument to .xinitrc.

Starting your graphical session after logging in on a TTY is the traditional way, but I like to use a graphical login manager, x11/slim. It is like KDM or GDM but with no dependency on a particular desktop environment. After installing it you can configure the sessiondir directive in the SLiM configuration file to define the path to desktop entries installed by your ports, usually /usr/local/share/xsessions. Use exec $1 instead of a particular executable name in your .xinitrc to run the command from SLiM passed in as an argument. You can switch session with the F1 key on the login screen.

  1. sessiondir /usr/local/share/xsessions/
  1. echo 'slim_enable="YES"' >> /etc/rc.conf
  2. service slim start

FreeBSD 10 running the SLiM login manager.

The X session will use one of the virtual ttys. Once started, you can switch to a different virtual TTY with CTRL-ATL-F#. You can switch back to the graphical TTY with CTRL-ATL-F9. You may need to create a desktop entry for your window manager of choice if the port maintainer doesn’t ship one. Here’s an example.

  1. [Desktop Entry]
  2. Encoding=UTF-8
  3. Name=Window Maker
  4. Exec=/usr/local/bin/wmaker
  5. Comment=This session logs you into Window Maker
  6. Type=Application

Extras and Miscellany


CUPS is the standard for printing on Free Unix-like systems and can be installed from Ports along with any needed filters. Install the CUPS meta-port at print/cups. Install HPLIP in print/hplip for HP printer drivers (and my Brother HL-2170W, for some reason). Install the Foomatic filter collection in print/foomatic-filters and its database and engine in print/foomatic-db and print/foomatic-db-engine, respectively. I find the CUPS-PDF virtual printer in print/cups-pdf very useful as well.

Enable CUPS once installed:

  1. # Disable line printer daemon since we have CUPS
  2. lpd_enable="NO"
  3. # Enable CUPS
  4. cupsd_enable="YES"

Add local users to the cups group if you want them to be able to print.

  1. pw usermod root -G cups
  2. pw usermod nicole -G cups

Start the CUPS service with service cupsd start and you should be able to access its web configuration UI at http://localhost:631/ in your web browser. It may prompt you for your root password to write the config files in /usr/local/etc/cups. Most full desktop environments include a GUI to control CUPS and add printers, but the web interface is available in any of them.

A screenshot of the CUPS web interface showing my Brother HL-2170W printer configuration.

The web interfaces’ built-in documentation can help you configure different models of printer, specifically the Network Protocols Supported by CUPS and Common Network Printer URIs sections.


sysutils/smartmontools installs smartd and smartctl, a daemon and utility for checking the S.M.A.R.T. status of your local disks.

Enable the sample smartd.conf. It contains one directive, DEVICESCAN, that causes smartd to scan all attached drives.

  1. cp /usr/local/etc/smartd.conf.sample /usr/local/etc/smartd.conf
  2. echo 'smartd_enable="YES"' >> /etc/rc.conf
  3. service smartd start

You can check the S.M.A.R.T. status of a drive directly with smartctl as root. The -H flag will show basic pass or fail health status, and the -a flag will show everything.

smartctl -H /dev/ada0
  1. smartctl 6.2 2014-02-18 r3874 [FreeBSD 10.0-RELEASE-p2 amd64] (local build)
  2. Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org
  4. SMART overall-health self-assessment test result: PASSED


FreeBSD has several available Java providers, including OpenJDK and Sun's Oracle’s JDK. I recommend the newest OpenJDK for most people. It’s far easier to install than the binary Oracle JRE which requires logging in to a web page, agreeing to the license, and manually downloading the distfile for Ports. At the time of this writing the newest OpenJDK is java/openjdk8. OpenJDK 6 and 7 are available as well if you have software that doesn’t run on Java 8.

If you need a Java browser plugin you can build and install java/icedtea-web once a Java provider is available.

Webcams and DVB

Most USB webcams and many DVB tuners are supported by multimedia/webcamd, and webcamd depends on the userland character device driver in multimedia/cuse4bsd-kmod. Install them, then enable them in rc.conf and loader.conf.

  1. # Webcam daemon
  2. webcamd_enable="YES"
  1. # Userland character device driver for webcams
  2. cuse4bsd_load="YES"

You can use your camera device with pwcview available in multimedia/pwcview or with Cheese in multimedia/cheese. Cheese provides a nice interface similar to Apple’s Photobooth on OS X, but it has a heavy GNOME library dependency some may not want on their systems.


IBus is a modern IME for Unix-like systems, allowing one to input CJK languages. Install the main IME from textproc/ibus as well as QT application support from textproc/ibus-qt.

You’ll need one or more input methods once the IME itself is installed. Ports of interest:

Heavyweight desktop environments like GNOME or KDE will let you configure the input method graphically. In GNOME 2 and MATE, for example, you can open the IBus preferences from the Settings > Preferences menu. KDE/Qt users can enable it as the default IME in qtconfig-qt4.

Lightweight window manager users like me can start it in .xinitrc:

  1. export XMODIFIERS="@im=ibus"
  2. export GTK_IM_MODULE="ibus"
  3. export QT_IM_MODULE="ibus"
  4. exec ibus-daemon -d -x &

Now run any GTK or QT application, press your keyboard shortcut to switch input methods, and test it out.

IBus preferences window showing available input methods. GVim testing IBus input with Japanese.


FreeBSD’s Linuxulator allows it to run Linux application binaries using system call translation. Desktop users will find it useful for running the handful of proprietary but necessary programs that are available for Linux but not for FreeBSD, such as Adobe Flash Player.

Install the Linux base distribution from Ports. As I write this the default base distribution is emulators/linux_base-c6, based on CentOS 6, replacing the old Fedora 10 based emulators/linux_base-f10. Unless you need to use a particular f10-only application (like Skype) you should prefer the modern base, overriding the default in make.conf and switching to the necessary kernel version in sysctl.conf before doing the installation:

  1. echo 'compat.linux.osrelease=2.6.18' >> /etc/sysctl.conf
  2. sysctl -f /etc/sysctl.conf

Once your chosen linux_base installed, tell your system to load the linux kernel module at boot.

  1. echo 'linux_load="YES"' >> /boot/loader.conf

Mount the linprocfs virtual filesystems for compatibility with GNOME and other programs requiring them.

  1. linproc /compat/linux/proc linprocfs,auto,late rw 0 0

A screenshot of the Loki Software port of Simcity 3000 Unlimited running on FreeBSD via the Linuxulator.

Besides proprietary garbageware like Flash Player I also use Linuxulator along with the Loki compatibility library package to run Loki Software’s Linux ports of some of the best PC games ever made, like Simcity 3000 Unlimited.


Wine is a free implementation of the Win32 API capable of running real Windows applications on Unix-like systems. It’s available from emulators/wine or emulators/wine-devel, containing the latest stable and unstable versions respectively. The optional Gecko support is an mshtml.dll replacement that will allow Windows programs to embed web pages using the Mozilla engine. The optional Mono will let Wine run Windows programs written in versions 1.x or 2.0 of the .NET Framework without using the proprietary .NET runtime. You can also download winetricks, a script containing Wine installation recipes for popular software, and you may find a Wine GUI such as emulators/swine useful for maintaining separate Wine prefixes.

FreeBSD currently lacks the ability to install 32-bit ports on a 64-bit system, normally precluding an amd64 user from installing a 32-bit Wine capable of running 32-bit Windows applications. As a workaround, David Naylor maintains Wine32 packages for FreeBSD amd64. You can install them from emulators/i386-wine or emulators/i386-wine-devel.

If you plan to use Wine to run browser plugins, use the compholio-patched version of wine in emulators/wine-compholio or emulators/i386-wine-compholio instead.

FreeBSD 10 playing GalaxyTrail's Freedom Planet via Wine.

Wine is very impressively-compatible these days. I use it to run a lot of games from Humble Store and GOG so I don’t have to fire up a Windows computer or VM. Wine is so good it is used to create the Linux versions of many of these titles, such as Freedom Planet, and in that case it’s a lot easier to run the same executable in FreeBSD Wine than to try and get the Linux Wine binaries running via Linuxulator.

If every wine command fails with ELF interpreter /libexec/ld-elf.so.1 not found your 64-bit system is missing the 32-bit libraries necessary for Wine. You’ll need to install them. From the releases FTP, grab the lib32.txz matching your version of the OS and extract it either as root or with sudo to the root of your filesystem to install. The archive contains a full directory hierarchy so all the files will end up in the right place.

  1. fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/10.1-RELEASE/lib32.txz
  2. tar xfp lib32.txz -C /

Browser Plugins

Adobe Flash Player is not released for FreeBSD but is usable on FreeBSD i386 and amd64 through your choice of two wrappers.

The 32-bit Linux version of the Flash plugin can be installed via www/linux-c6-flashplugin11 or www/linux-f10-flashplugin11, executed through Linuxulator, and adapted to 32-bit or 64-bit native browsers with www/nspluginwrapper, though it is important to note Adobe dropped support for the NPAPI Linux version of Flash with version 11.2 back in 2012. They left development up to Google who only release a PPAPI version as part of their proprietary Chrome browser bundle, something that isn’t even available for FreeBSD. Even Chromium will be unable to use NPAPI Flash after 2014 as Google deprecates and removes NPAPI support from Chromium and Chrome starting in version 32. For now you can still use it in Firefox and other NPAPI browsers, but I think it’s just time to say goodbye to this old version or to Flash in general if you can help it.

To use nspluginwrapper, make sure linprocfs is mounted and execute nspluginwrapper -v -a -i as your normal user to locate and enable the Linux Flash plugin. -a automatically finds available plugins and -i installs them. It’s important to remember it makes a copy of the Flash library in your home directory when you do this, so every time you update the version of Flash installed through Ports you need to remove your local cory with nspluginwrapper -v -a -r and install the new one with nspluginwrapper -v -a -i. Adobe promised security updates for the NPAPI Flash Player through 2017, and if history is any indication you’re going to need them.

A newer and arguably better solution is emulators/pipelight, a Wine-based wrapper for Windows browsers plugins. It supports the very newest version of Flash, freeing us from the limitations of 11.2, and also supports Shockwave, Silverlight, Unity, and more. It requires a special patched version of Wine, emulators/wine-compholio or emulators/i386-wine-compholio. Once installed, activate plugins as root.

  1. pipelight-plugin --create-mozilla-plugins
  2. pipelight-plugin --enable flash

Silverlight is available as well and can allow you to watch DRMed NetFlix content via your browser on FreeBSD. I have no experience using it since I don’t buy DRMed streaming media subscriptions, but it can be installed the same way.

  1. pipelight-plugin --enable silverlight5.1

Heed www/pipelight’s pkg-message warning about Silverlight DRM if you have a ZFS-based system:

For users running with ZFS on root, watching DRM protected content requires extensive xattr support. If you run into issues with DRM failing, you can use the “pipelight-mkufs” command to create a UFS formatted ZVOL mounted on your users ~/.wine-pipelight directory.

Other plugins are enabled the same way, and the list of available plugins can be seen in pipelight-plugin --help.


It’s pretty common to virtualize another operating system on your computer, possibly to run a proprietary program or access a proprietary office groupware system. Whatever the reason, it’s easy to accomplish on FreeBSD.

VirtualBox management application

FreeBSD 10 has a new built-in hypervisor known as bhyve capable of running FreeBSD natively and other operating systems via sysutils/grub2-bhyve. At the moment it only implements a serial console to access the guest systems which is fine for a server OS but probably not what you want.

Alternatively, VirtualBox open source edition is available at emulators/virtualbox-ose. Build it with Guest Additions enabled for the best experience virtualizing Windows and Linux.

Once it’s installed, configure loader.conf to load the VirtualBox kernel module and configure rc.conf to start VirtualBox bridged networking.

  1. vboxdrv_load="YES"
  1. vboxnet_enable="YES"
  1. # Allow VirtualBox network access
  2. own vboxnetctl root:vboxusers
  3. perm vboxnetctl 0660
  1. pw usermod nicole -G vboxusers


Skype is bad, proprietary software that doesn’t value your freedom. Use audio/mumble or net-im/ekiga instead if you can. If you still wish to use Skype, make sure you have Linuxulator enabled and install net-im/skype.

Version 2.1 of Skype’s Linux client dropped support for OSS, found in FreeBSD as the default sound API. Thanks to this, Skype 2.0 persisted for years as the version in Ports. With the introduction of an ALSA compatibility shim in FreeBSD 8.3 and 9.0 and audio/linux-f10-alsa-plugins-oss, we can use the newer ALSA-only Skype client.

There is a newer Skype client available as net-im/skype4 that supports the CentOS 6 linux_base, but that version is not usable on FreeBSD 10.x due to missing syscalls in that branch’s Linuxulator.

The ALSA client, unlike the old OSS client, requires some explicit configuration to use our sound devices. They must be defined manually in /compat/linux/etc/alsa/pcm/pcm-oss.conf, the configuration file of alsa-plugins-oss.

In this example, I enable pcm6/dsp6 for audio output, and pcm8/dsp8, a USB webcam, as a microphone source.

  1. pcm.oss8 {
  2. type oss
  3. device /dev/dsp8
  4. hint {
  5. description "Open Sound System - Webcam"
  6. }
  7. }
  8. ctl.oss8 {
  9. type oss
  10. device /dev/mixer8
  11. hint {
  12. description "Open Sound System - Webcam"
  13. }
  14. }
  15. pcm.oss6 {
  16. type oss
  17. device /dev/dsp6
  18. hint {
  19. description "Open Sound System - S/PDIF"
  20. }
  21. }
  22. ctl.oss6 {
  23. type oss
  24. device /dev/mixer6
  25. hint {
  26. description "Open Sound System - S/PDIF"
  27. }
  28. }

The microphone volume can be controlled by invoking the mixer of your chosen recording device. Let’s raise the microphone volume now from 0% to 75%.

  1. mixer -f /dev/mixer8 mic 75


This is personal preference, but I also set my LC_TIME environment variable to the en_DK faux-locale for ISO-8601 date formats instead of the ridiculous American standard.

Quick, what date is 6/5/12? Oh, it’s 2012-06-05, of course.

The locale isn’t included with the FreeBSD base system as it is in many Linux distributions, but it’s available from Ivan Voras’ blog.

  1. tar -C /usr/share/locale -zxf /path/to/your/en_DK.UTF-8.tgz

Enable it in the login database and /etc/profile.

  1. @@ -46,7 +46,8 @@
  2. \:ignoretime@:\
  3. \:umask=022:\
  4. \:charset=UTF-8:\
  5. - \:lang=en_US.UTF-8:
  6. + \:lang=en_US.UTF-8:\
  7. + \:setenv=LC_TIME=en_DK.UTF-8:
  1. cap_mkdb /etc/login.conf
  1. LC_TIME=en_DK.UTF-8; export LC_TIME

Upgrade Notes

This guide assumes you will track the newest STABLE branch, upgrading to new stable branches at the initial .0 release. That’s not a thing I would ever recommend with OS X, but I haven’t been burned by a new major FreeBSD version yet. This section notes things you need to know to keep your system in top shape when upgrading.

9.x to 10.0

If you are updating from 9.x to 10.0 or higher, run pkg2ng after rebooting into the new OS. This conversion script will convert the list of installed packages from the format used by the old pkg_ tools to the format used by pkgng, the new binary package manager. If you neglect this step the OS will think you have no packages installed and your life will become very confusing.

10.0 to 10.1

WITH_NEW_XORG is no longer a thing. The old version is gone.

vt is a new console driver designed to replace syscons. It offers Unicode and graphics support using kernel modesetting. This is necessary to support UEFI. A loader variable kern.vty can select between vt and sc.

  1. kern.vty=vt

It will default to graphics mode but can be configured to use a text mode instead if necessary.

  1. hw.vga.textmode=1



  • Whoops, I missed that GNOME 3 and Cinnamon finally made it to the official tree!
  • CentOS 6 is the default Linux base.
  • HAL is mostly deprecated throughout the Free desktop world. Now that X.org no longer uses it by default I stopped recommending its use.



  • SLiM wants sessiondir now, not enumerated sessions.
  • Update and expand Wine section
  • TeXLive is now the default TeX provider, so no need to specify it over teTeX.


  • Section re-organization
  • I stopped using or recommending GNOME
  • Cover firewalling
  • Add a whole desktop environments section.
  • Cover pkgng
  • Cover installation instead of linking to a ZFS installation guide now that bsdinstall supports it
  • Stop recommending blf in login.conf because the default is sha512 now instead of md5
  • KDE4_PREFIX is ${LOCALBASE} by default now
  • Use TeX Live
  • FUSE is built-in now
  • Add additional device paths for permissions
  • Add virtualization section
  • Wine packages are available in Ports now



  • Initial article