FreeBSD 10.1 Guide

metadata

FreeBSD LogoThis is an installation and configuration guide for FreeBSD. I now use FreeBSD for my server which acts both as a NAS for all of my data and as a media server for my TV. I have managed to add some pretty neat features such as a Time Capsule for my MacBook and a PVR for BBC iPlayer. This guide describes the FreeBSD installation, ZFS configuration and user-land software installation and configuration. I include all of my configuration files so that you can see how I have set it all up.

  1. Installation Notes
  2. Configuration Notes
    1. General Setup
    2. Adding Users
    3. Installing Software
    4. Configuring Cron
    5. Configuring Software
      1. Time Machine
      2. Web Server
      3. Media Servers
      4. Samba
      5. SSH
      6. SMART Daemon
  3. Workarounds
  4. Usage Notes
  5. References
  6. Word Of Warning

§1 Installation Notes

I used a bootable USB image to install FreeBSD, you can grab one from the FreeBSD download page. During the first section of the installer I disabled “games” and “ports”. The automatic partitioner decided to go with:

DeviceSizeTypeMount Point
ada0149GB
ada0p164KBfreebsd-boot
ada0p2117GBfreebsd-ufs/
ada0p332GBfreebsd-swapnone

Further on in the process I decided to disable IPv6 and “dumpdev”. Once the process finished I decided to not immediately reboot into the new system, instead I opened a shell and typed gpart set -a active ada0 to set the drive as active before the first boot (which was needed to side-step a nasty bug which meant that you couldn’t boot into your nice new system).

§2 Configuration Notes

Now you should have a working fresh installation of FreeBSD. The majority of this tutorial covers the configuration of this fresh clean system. Firstly I talk about how I configured FreeBSD itself, then I add users, then I install user-land software, and finally I configure that user-land software.

§2.1 General Setup

Firstly, I tweaked the start-up configuration file, “/boot/loader.conf”, so that some additional kernel modules would be loaded during start-up. These modules allow the CPU temperature to be obtained (for my Intel CPUs), enable ACPI (for my ASUS motherboard) and finally enable disk encryption to be used (if the user wants). I did this with the following commands (as root) - the changes do not take effect until the system is rebooted, hence the final command.

1
2
3
4
5

#!/bin/sh
echo 'coretemp_load="YES"' >> /boot/loader.conf
echo 'acpi_asus_load="YES"' >> /boot/loader.conf
echo 'geom_eli_load="YES"' >> /boot/loader.conf
reboot

              
You may also download “freebsd-10p1-cmds1.sh” directly or view “freebsd-10p1-cmds1.sh” on GitHub Gist (you may need to manually checkout the “main” branch).

Next, I added some lines to the other start-up configuration file so that some additional software would be loaded during start-up. The “/etc/rc.conf” file is very important in FreeBSD as it contains most of the custom configuration for my system. The commands (as root) I used are below - likewise, the changes do not take effect until the system is rebooted, however, I do not reboot immediately as some further tweaking can be performed during this boot.

The first command enables ZFS to be used (if the user wants); the second sets the default encryption settings for GELI; the third enables the inet daemon (which is often called the ‘super server’); the fourth clears “/tmp” during boot; the fifth enables the daemon to automatically mount removeable storage (such as USB drives); and the final command enables memory disks (a.k.a. RAM disks).

1
2
3
4
5
6
7

#!/bin/sh
echo 'zfs_enable="YES"' >> /etc/rc.conf
echo 'geli_default_flags="-a HMAC/SHA256 -l 256 -s 4096"' >> /etc/rc.conf
echo 'inetd_enable="YES"' >> /etc/rc.conf
echo 'clear_tmp_enable="YES"' >> /etc/rc.conf
echo 'autofs_enable="YES"' >> /etc/rc.conf
echo 'md_enable="YES"' >> /etc/rc.conf

              
You may also download “freebsd-10p1-cmds2.sh” directly or view “freebsd-10p1-cmds2.sh” on GitHub Gist (you may need to manually checkout the “main” branch).

Next I configured the system to automatically mount removeable storage (such as USB drives). The instructions for this can be found in the section on USB disks in the FreeBSD handbook. Run vi /etc/auto_master and un-comment /media -media -nosuid. My only comment is that you don’t have to add all the lines to “/etc/devd.conf” as they are already there, just move the */ line further up the file and then they will not be commented out anymore. Run vi /etc/devd.conf and un-comment:

1
2
3
4
5

notify 100 {
    match "system" "GEOM";
    match "subsystem" "DEV";
    action "/usr/sbin/automount -c";
};

              
You may also download “freebsd-10p1-devd.conf” directly or view “freebsd-10p1-devd.conf” on GitHub Gist (you may need to manually checkout the “main” branch).

Before rebooting I edited “/etc/fstab” to create a RAM disk (to hold temporary copies of sensitive un-encrypted data) and to encrypt the swap partition. This final step ensures that any sensitive data that is written to swap (because the RAM is full) is unrecoverable if the machine is powered off (just like the data in RAM). Of course, the swap has no knowledge of which data it stores is sensitive and which isn’t: this method encrypts the whole partition. The downside to this is that your machine cannot be hibernated (which requires reading the swap during wake-up) or debugged completely (as memory dumps are sometimes written to swap). I believe that these two hindrances are acceptable.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14

#!/bin/sh

# Make mount target ...
mkdir /mnt/volatile

# Create both file-systems ...
echo "md    /mnt/volatile    mfs    rw,-s8M    0    0" >> /etc/fstab
vi /etc/fstab                           # add ".eli" to end of /dev/ada0p3

# Setup "vim" ...
echo "syntax on" > ~/.vimrc

# Reboot ...
reboot

              
You may also download “freebsd-10p1-cmds3.sh” directly or view “freebsd-10p1-cmds3.sh” on GitHub Gist (you may need to manually checkout the “main” branch).

Next I cleaned the beginning of all of my data disks that were going to be my ZFS array. WARNING: This will make any existing data on the drive inaccessible. I then created the pool and created some useful partitions on the pool. You’ll notice that I enabled LZ4 compression and set the flags for snapshots on all partitions except “timecapsule” (which has its own snapshots in Mac OS X). The “autoexpand=on” line is needed if in future I decide to replace the disks (one-by-one) with larger ones.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

#!/bin/sh

# Remove partition tables from the disks ...
gpart destroy -F /dev/ada1
gpart destroy -F /dev/ada2
gpart destroy -F /dev/ada3
gpart destroy -F /dev/ada4
gpart destroy -F /dev/ada5

# Clean the disks ...
dd if=/dev/zero of=/dev/ada1 bs=1m count=10
dd if=/dev/zero of=/dev/ada2 bs=1m count=10
dd if=/dev/zero of=/dev/ada3 bs=1m count=10
dd if=/dev/zero of=/dev/ada4 bs=1m count=10
dd if=/dev/zero of=/dev/ada5 bs=1m count=10

# Create the ZFS pool ...
zpool create pool1 raidz /dev/ada1 /dev/ada2 /dev/ada3 /dev/ada4 /dev/ada5

# Enable auto-expansion of the ZFS pool ...
zpool set autoexpand=on pool1

# Enable transparent compression ...
zfs set compression=lz4 pool1

# Create partitions ...
zfs create -p pool1/home
zfs create -p pool1/mnt/data
zfs create -p pool1/mnt/timecapsule
zfs create -p pool1/usr/local/share/doc
zfs create -p pool1/usr/local/www/thomasguymer.co.uk
zfs create -p pool1/usr/ports
zfs create -p pool1/usr/src
zfs create -p pool1/var/db
zfs create -p pool1/var/log
zfs create -p pool1/var/mail

# Mark them for snapshots ...
zfs set com.sun:auto-snapshot=true pool1/home
zfs set com.sun:auto-snapshot=true pool1/mnt/data
zfs set com.sun:auto-snapshot=true pool1/usr/local/share/doc
zfs set com.sun:auto-snapshot=true pool1/usr/local/www/thomasguymer.co.uk
zfs set com.sun:auto-snapshot=true pool1/usr/ports
zfs set com.sun:auto-snapshot=true pool1/usr/src
zfs set com.sun:auto-snapshot=true pool1/var/db
zfs set com.sun:auto-snapshot=true pool1/var/log
zfs set com.sun:auto-snapshot=true pool1/var/mail

              
You may also download “freebsd-10p1-cmds4.sh” directly or view “freebsd-10p1-cmds4.sh” on GitHub Gist (you may need to manually checkout the “main” branch).

Next I mounted the partitions so that they could be used straight away (whilst keeping copies of any data in the two targets that already existed).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

#!/bin/sh

# Move already existing versions ...
mv /usr/local/share/doc /usr/local/share/TEMPdoc
mv /var/log /var/TEMPlog

# Make mount targets ...
mkdir /home
mkdir /mnt/data
mkdir /mnt/timecapsule
mkdir /usr/local/share/doc
mkdir /usr/local/www/thomasguymer.co.uk
mkdir /usr/ports
mkdir /var/db
mkdir /var/log

# Mount the partitions ...
zfs set mountpoint=/home pool1/home
zfs set mountpoint=/mnt/data pool1/mnt/data
zfs set mountpoint=/mnt/timecapsule pool1/mnt/timecapsule
zfs set mountpoint=/usr/local/share/doc pool1/usr/local/share/doc
zfs set mountpoint=/usr/local/www/thomasguymer.co.uk pool1/usr/local/www/thomasguymer.co.uk
zfs set mountpoint=/usr/ports pool1/usr/ports
zfs set mountpoint=/usr/src pool1/usr/src
zfs set mountpoint=/var/db pool1/var/db
zfs set mountpoint=/var/log pool1/var/log
zfs set mountpoint=/var/mail pool1/var/mail

# Move already existing files into new versions ...
mv /usr/local/share/TEMPdoc/* /usr/local/share/doc/
mv /var/TEMPlog/* /var/log/

# Remove old versions ...
rmdir /usr/local/share/TEMPdoc
rmdir /var/TEMPlog

# Reboot ...
reboot

              
You may also download “freebsd-10p1-cmds5.sh” directly or view “freebsd-10p1-cmds5.sh” on GitHub Gist (you may need to manually checkout the “main” branch).

I like using BASH as my shell, which is not included in the default install of FreeBSD. I installed BASH using the port system, which means that I had to set up the port system first. The following command (as root) will download the port tree and extract it to the local directory: portsnap fetch extract.

Once that is done I created the “/etc/make.conf” file so that all ports were installed using the settings I wished. Use the Vi editor (by typing the command vi) to create the file and make it look like mine below.

1
2
3
4
5
6
7
8
9

# Set build options
BUILD_OPTIMIZED=yes
CPUTYPE=native
NO_INET6=yes
WITH_PKGNG=yes

# Set configure options
OPTIONS_SET=AVX AVX2 ICONV MANPAGES MMX OPENGL OPTIMIZATION OPTIMIZED_CFLAGS OPTIMIZED_FLAGS SIMD SSE SSE2 THREADS UNICODE X11
OPTIONS_UNSET=DEBUG DOCS EXAMPLES HTMLDOCS IPV6 PHP TEST

              
You may also download “freebsd-10p1-make.conf” directly or view “freebsd-10p1-make.conf” on GitHub Gist (you may need to manually checkout the “main” branch).

Finally, I installed BASH by typing make -C /usr/ports/shells/bash config-recursive first to configure it (deselect “implicitcd” when the first configuration screen appears) and then make -C /usr/ports/shells/bash install to actually install it. BASH will not work straight away as it needs two specific file-systems to exist. You can make them with appear at boot with the following two commands.

1
2
3

#!/bin/sh
echo "fdesc    /dev/fd    fdescfs    rw    0    0" >> /etc/fstab
echo "proc    /proc    procfs    rw    0    0" >> /etc/fstab

              
You may also download “freebsd-10p1-cmds6.sh” directly or view “freebsd-10p1-cmds6.sh” on GitHub Gist (you may need to manually checkout the “main” branch).

BASH should now be there ready for you to use - after you do a reboot.

§2.2 Adding Users

I created all of the infrastructure for users to use the ZFS file-system, have a data store and a Time Capsule. This resulted in quite a few ZFS commands, but hopefully they will all make sense (and most are duplicates).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

#!/bin/sh

# Create their home ...
zfs create pool1/home/user1
zfs create pool1/home/user2
zfs create pool1/home/user3
zfs create pool1/home/user4

# Limit their home ...
zfs set refquota=100G pool1/home/user1
zfs set refquota=100G pool1/home/user2
zfs set refquota=100G pool1/home/user3
zfs set refquota=100G pool1/home/user4

# Create their data store ...
zfs create pool1/data/user1
zfs create pool1/data/user2
zfs create pool1/data/user3
zfs create pool1/data/user4

# Create their time machine store ...
zfs create pool1/timecapsule/user1
zfs create pool1/timecapsule/user2
zfs create pool1/timecapsule/user3
zfs create pool1/timecapsule/user4

              
You may also download “freebsd-10p1-cmds7.sh” directly or view “freebsd-10p1-cmds7.sh” on GitHub Gist (you may need to manually checkout the “main” branch).

Note that there is no need to put quotas on the Time Capsules as they are handled in the configuration file later on and work quite well. Users are added using the aptly named adduser command. Once that is done I modified their groups and the permissions of their directories.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

#!/bin/sh

# Add all users to "staff" ...
pw groupmod staff -m user1,user2,user3,user4

# Add "user1" to "wheel" ...
pw groupmod wheel -m user1

# Add SFTP-only users to custom group ...
pw groupadd sftp_only -m user3,user4

# Forbid "user4" from logging in ...
pw usermod user4 -s /usr/sbin/nologin

# Set secure umasks ...
echo umask=0077 > /home/user1/.profile
echo umask=0077 > /home/user2/.profile
echo umask=0077 > /home/user3/.profile
echo umask=0077 > /home/user4/.profile

# Setup "vim" ...
echo "syntax on" > /home/user1/.vimrc
echo "syntax on" > /home/user2/.vimrc
echo "syntax on" > /home/user3/.vimrc
echo "syntax on" > /home/user4/.vimrc

# Make users own their folders ...
chown user1:staff /home/user1 /mnt/data/user1 /mnt/timecapsule/user1
chown user2:staff /home/user2 /mnt/data/user2 /mnt/timecapsule/user2
chown user3:staff /home/user3 /mnt/data/user3 /mnt/timecapsule/user3
chown user4:staff /home/user4 /mnt/data/user4 /mnt/timecapsule/user4

# Make private folders private ...
chmod 700 /home/user1 /home/user2 /home/user3 /home/user4
chmod 700 /mnt/timecapsule/user1 /mnt/timecapsule/user2 /mnt/timecapsule/user3 /mnt/timecapsule/user4

# Make shared (parent) folders group read-only ...
chmod 755 /mnt/data/user1 /mnt/data/user2 /mnt/data/user3 /mnt/data/user4

# Make sure that users can get to their folders ...
chgrp staff /home /mnt /mnt/data /tmp

              
You may also download “freebsd-10p1-cmds8.sh” directly or view “freebsd-10p1-cmds8.sh” on GitHub Gist (you may need to manually checkout the “main” branch).

§2.3 Installing Software

The first thing that I did at this stage is to download the source code for FreeBSD. If you are just going to use this machine as a server or some such then you don’t need to do this. However, if you intend on using it as a build platform for other FreeBSD machines (such as ARM boards) then you’ll need the source code. You can grab it with the command svnlite co https://svn0.us-west.freebsd.org/base/head /usr/src/.

Next, I installed Portmaster as it is a handy tool for installing software from the ports tree. To install it you’ll need to run the command make -C /usr/ports/ports-mgmt/portmaster install.

Now I start installing other software that I need, using Portmaster instead of Make. Below you’ll find a list of all of the software that I have installed. I do each one in turn using the command portmaster -y foo/bar (i.e., portmaster -y editors/vim). Next to some of them is a description of what configuration settings I changed from default, some of them are configuration options for [grand-]daughters.

That will take a long time to run/wait for. Once it is all done I like to create a link to Python using this command cd /usr/local/bin && ln -s python2.7 python. I then append some lines to the end of “/etc/rc.conf” so that some of the recently installed software starts automatically. You can do this with the following commands.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

#!/bin/sh

# Enable SMART monitoring of hard drives ...
echo 'smartd_enable="YES"' >> /etc/rc.conf

# Enable the Time Capsules ...
echo 'netatalk_enable="YES"' >> /etc/rc.conf
echo 'cnid_metad_enable="YES"' >> /etc/rc.conf
echo 'afpd_enable="YES"' >> /etc/rc.conf

# Enable UPnP/DNLA ...
echo 'mediatomb_enable="YES"' >> /etc/rc.conf
echo 'mediatomb_flags="-i 192.168.1.110 -p 49152"' >> /etc/rc.conf

# Enable SMB ...
echo 'samba_enable="YES"' >> /etc/rc.conf

# Configure NTP ...
echo 'ntpd_sync_on_start="YES"' >> /etc/rc.conf
echo 'ntpd_hosts="uk.pool.ntp.org"' >> /etc/rc.conf

# Enable mail ...
echo 'sendmail_enable="YES"' >> /etc/rc.conf

# Enable DAAP ...
echo 'firefly_enable="YES"' >> /etc/rc.conf

# Enable web server ...
echo 'nginx_enable="YES"' >> /etc/rc.conf

# Enable protection of SSH ...
echo 'sshguard_enable="YES"' >> /etc/rc.conf

# HACK: Bug 174018 from https://www.freshports.org/security/sshguard
echo 'sshguard_blacklist=""' >> /etc/rc.conf

              
You may also download “freebsd-10p1-cmds9.sh” directly or view “freebsd-10p1-cmds9.sh” on GitHub Gist (you may need to manually checkout the “main” branch).

At this point it is probably worth doing a reboot just to check that everything is working OK for you. A lot of the daemons that have just been installed will probably not run because we have not configured them yet, but the fact that they print an error message means that they are at least trying to start up - which is good.

§2.4 Configuring Cron

Here is a copy of my Cron file, I think that it is fairly self-explanatory. All it does is correct permissions of user’s private/shared folders, check for updates in both FreeBSD and the ports system; and finally it performs some maintenance of the ZFS pool.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# Define environment variables ...
LANG=en_GB.UTF-8
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/games:/usr/local/bin:/usr/local/sbin
SHELL=/usr/local/bin/bash

# Ensure user/group/permissions are correct for personal/shared folders ...
0 0 * * * /usr/bin/find /mnt/data/user2/ ! -user user2 -exec chown user2 {} \;
0 0 * * * /usr/bin/find /mnt/data/user2/ ! -group staff -exec chgrp staff {} \;
0 0 * * * /usr/bin/find /mnt/data/user2/ -type f ! -perm 600 -exec chmod 600 {} \;
0 0 * * * /usr/bin/find /mnt/data/user2/ -depth +0 -type d ! -perm 700 -exec chmod 700 {} \;
0 0 * * * /usr/bin/find /mnt/data/user3/ ! -user user3 -exec chown user3 {} \;
0 0 * * * /usr/bin/find /mnt/data/user3/ ! -group staff -exec chgrp staff {} \;
0 0 * * * /usr/bin/find /mnt/data/user3/ -type f ! -perm 600 -exec chmod 600 {} \;
0 0 * * * /usr/bin/find /mnt/data/user3/ -depth +0 -type d ! -perm 700 -exec chmod 700 {} \;
0 0 * * * /usr/bin/find /mnt/data/user4/ ! -user user4 -exec chown user4 {} \;
0 0 * * * /usr/bin/find /mnt/data/user4/ ! -group staff -exec chgrp staff {} \;
0 0 * * * /usr/bin/find /mnt/data/user4/ -type f ! -perm 644 -exec chmod 644 {} \;
0 0 * * * /usr/bin/find /mnt/data/user4/ -depth +0 -type d ! -perm 755 -exec chmod 755 {} \;

# Fetch updates for FreeBSD and Ports then clean the ports tree ...
0 0 * * * /usr/sbin/freebsd-update cron > /dev/null
0 0 * * * /usr/sbin/portsnap cron update > /dev/null
0 2 * * * /usr/local/sbin/portmaster -y --clean-distfiles > /dev/null
2 2 * * * /usr/local/sbin/portmaster -y --clean-packages > /dev/null
4 2 * * * /usr/local/sbin/portmaster --check-depends

# Provide ZFS usage statistics ...
0 0 * * * /sbin/zfs list -o name,used,avail,compressratio -r pool1/home > /home/USAGE.txt
0 0 * * * /sbin/zfs list -o name,used,avail,compressratio -r pool1/mnt/data > /mnt/data/USAGE.txt
0 0 * * * /sbin/zfs list -o name,used,avail,compressratio -r pool1/mnt/timecapsule > /mnt/timecapsule/USAGE.txt

# Scrub ZFS ...
0 0 * * 1 /sbin/zpool scrub pool1

# Create ZFS snapshots ...
0 0 * * 1-6 /usr/local/sbin/zfs-auto-snapshot daily  6
0 0 * *   0 /usr/local/sbin/zfs-auto-snapshot weekly 5

              
You may also download “freebsd-10p1-crontab” directly or view “freebsd-10p1-crontab” on GitHub Gist (you may need to manually checkout the “main” branch).

§2.5 Configuring Software

I have highlighted a few keys pieces of software (such as media servers and the like) to describe how I configured them for my needs.

§2.5.1 Time Machine

The settings for the Time Capsules are kept in “/usr/local/etc/AppleVolumes.default”. Use your favourite editor (I use Vim) to change the file so that the un-commented lines look like the ones below. Now Mac computers should be able to see, and use, your FreeBSD machine as a Time Capsule.

1
2
3
4
5
6

:DEFAULT: options:upriv,usedots

/mnt/timecapsule/user1 Time Capsule-user1 options:tm volsizelimit:500000 allow:user1
/mnt/timecapsule/user2 Time Capsule-user2 options:tm volsizelimit:500000 allow:user2
/mnt/timecapsule/user3 Time Capsule-user3 options:tm volsizelimit:500000 allow:user3
/mnt/timecapsule/user4 Time Capsule-user4 options:tm volsizelimit:500000 allow:user4

              
You may also download “freebsd-10p1-AppleVolumes.default” directly or view “freebsd-10p1-AppleVolumes.default” on GitHub Gist (you may need to manually checkout the “main” branch).
§2.5.2 Web Server

Above I installed Nginx so that I could have a very light weight webserver on my local network. The settings for Nginx are in “/usr/local/etc/nginx/nginx.conf”. Use your favourite editor (I use Vim) to change the file so that it looks like the one below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

# Basic settings
worker_processes            auto;

events {
    worker_connections          1024;
}

http {
    # Basic settings
    charset                     utf8;
    gzip_static                 on;
    server_tokens               off;
    sendfile                    off;
    tcp_nopush                  on;
    limit_conn_zone             $binary_remote_addr zone=addr:10m;

    # Buffers
    client_body_buffer_size     1k;
    client_header_buffer_size   1k;
    client_max_body_size        1k;
    large_client_header_buffers 2 1k;

    # Timeouts
    client_body_timeout         10;
    client_header_timeout       10;
    keepalive_timeout           5 5;
    send_timeout                10;

    # Define the default MIME types for files
    include                     mime.types;
    default_type                application/octet-stream;

    server {
        # Basic settings
        listen                      80;
        server_name                 www.thomasguymer.co.uk;
        if ($request_method !~ ^(GET|HEAD)$ ) {
            return                      444;
        }

        location / {
            root                        /usr/local/www/thomasguymer.co.uk/www;
            index                       index.html;
            limit_conn                  addr 5;
        }

        # List all available MIME types
        types {
            application/javascript      js;
            application/pdf             pdf;
            application/rss+xml         rss;
            application/xml             xml;
            application/zip             zip;
            image/x-icon                ico;
            image/jpeg                  jpg;
            image/png                   png;
            image/svg+xml               svg;
            text/css                    css;
            text/html                   html;
            text/plain                  log txt;
            text/x-suse-ymp             ymp;
        }
    }
}

              
You may also download “freebsd-10p1-nginx.conf” directly or view “freebsd-10p1-nginx.conf” on GitHub Gist (you may need to manually checkout the “main” branch).
§2.5.3 Media Servers

I have installed two separate media servers to serve my music and videos over different protocols: Firefly (a.k.a. mt-daapd) serves content over DAAP for Apple devices; and Mediatomb serves content over UPnP/DNLA for Android, Linux and Windows devices. The two configuration files for these pieces of software are “/usr/local/etc/firefly/mt-daapd.conf” and “/usr/local/etc/mediatomb/config.xml” respectively. Below I have included both configuration files - Firefly first and Mediatomb second.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22

[general]
web_root = /usr/local/share/mt-daapd/admin-root
port = 3689
admin_pw = PASSWORD
db_type = sqlite3
db_parms = /var/db/firefly
mp3_dir = /mnt/data/user1/Music
servername = HOST
runas = daapd
extensions = .mp3
logfile = /var/log/mt-daapd.log
debuglevel = 1
rescan_interval = 1800
scan_type = 2

[plugins]
plugin_dir = /usr/local/lib/mt-daapd/plugins

[scanning]
process_playlists = 0
process_itunes = 0
process_m3u = 0

              
You may also download “freebsd-10p1-mt-daapd.conf” directly or view “freebsd-10p1-mt-daapd.conf” on GitHub Gist (you may need to manually checkout the “main” branch).
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://mediatomb.cc/config/2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2" xsi:schemaLocation="http://mediatomb.cc/config/2 http://mediatomb.cc/config/2.xsd">
  <server>
    <ui enabled="yes" show-tooltips="yes">
      <accounts enabled="yes" session-timeout="30">
        <account user="mediatomb" password="PASSWORD"/>
      </accounts>
    </ui>
    <name>HOST</name>
    <udn>uuid:9dafbdf1-904a-4016-9af9-b0bc756c7537</udn>
    <home>/var/mediatomb</home>
    <webroot>/usr/local/share/mediatomb/web</webroot>
    <storage caching="yes">
      <sqlite3 enabled="yes">
        <database-file>mediatomb.db</database-file>
      </sqlite3>
      <mysql enabled="no">
        <host>localhost</host>
        <username>mediatomb</username>
        <database>mediatomb</database>
      </mysql>
    </storage>
    <protocolInfo extend="no"/>
    <custom-http-headers>
      <add header="transferMode.dlna.org: Streaming"/>
      <add header="contentFeatures.dlna.org: DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=017000 00000000000000000000000000"/>
    </custom-http-headers>
    <extended-runtime-options>
      <ffmpegthumbnailer enabled="yes">
        <thumbnail-size>128</thumbnail-size>
        <seek-percentage>5</seek-percentage>
        <filmstrip-overlay>no</filmstrip-overlay>
        <workaround-bugs>no</workaround-bugs>
        <image-quality>8</image-quality>
      </ffmpegthumbnailer>
      <mark-played-items enabled="no" suppress-cds-updates="yes"/>
    </extended-runtime-options>
  </server>
  <import hidden-files="no">
    <scripting script-charset="UTF-8">
      <common-script>/usr/local/share/mediatomb/js/common.js</common-script>
      <playlist-script>/usr/local/share/mediatomb/js/playlists.js</playlist-script>
      <virtual-layout type="builtin">
        <import-script>/usr/local/share/mediatomb/js/import.js</import-script>
      </virtual-layout>
    </scripting>
    <mappings>
      <extension-mimetype ignore-unknown="no">
        <map from="flac" to="audio/x-flac"/>
        <map from="flv" to="video/x-flv"/>
        <map from="m3u" to="audio/x-mpegurl"/>
        <map from="mp3" to="audio/mpeg"/>
        <map from="mp4" to="video/mp4"/>
        <map from="mpg" to="video/mpeg"/>
        <map from="pls" to="audio/x-scpls"/>
        <map from="wma" to="audio/x-ms-wma"/>
        <map from="wmv" to="video/x-ms-wmv"/>
      </extension-mimetype>
      <mimetype-upnpclass>
        <map from="audio/*" to="object.item.audioItem.musicTrack"/>
        <map from="image/*" to="object.item.imageItem"/>
        <map from="video/*" to="object.item.videoItem"/>
      </mimetype-upnpclass>
      <mimetype-contenttype>
        <treat mimetype="audio/mpeg" as="mp3"/>
        <treat mimetype="audio/x-flac" as="flac"/>
        <treat mimetype="audio/x-mpegurl" as="playlist"/>
        <treat mimetype="audio/x-scpls" as="playlist"/>
        <treat mimetype="audio/x-wav" as="pcm"/>
        <treat mimetype="image/jpeg" as="jpg"/>
        <treat mimetype="video/x-msvideo" as="avi"/>
      </mimetype-contenttype>
    </mappings>
  </import>
  <transcoding enabled="no"/>
</config>

              
You may also download “freebsd-10p1-config.xml” directly or view “freebsd-10p1-config.xml” on GitHub Gist (you may need to manually checkout the “main” branch).

For advice on mt-daapd then check out this excellent article. I feel like the Mediatomb one can still be trimmed out some more. It is derived from the one that is included in the package but I do feel that a lot of the MIME-type related lines are superfluous.

§2.5.4 Samba

I found Chapter 9 of the Samba documentation particularly useful for this part. The settings for Samba are kept in “/usr/local/etc/smb4.conf”. Use your favourite editor (I use Vim) to change the file so that the un-commented lines look like the ones below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

[global]
    netbios name = HOST
    encrypt passwords = yes
    server string = HOST Samba Folders
    workgroup = WORKGROUP
    hosts allow = 192.168.1.
    load printers = no
    log file = /var/log/samba4.log
    map to guest = bad user

[Music]
    comment = Music Share
    path = /mnt/data/user1/Music
    read only = yes
    guest ok = yes
    only guest = yes

[Videos]
    comment = Videos Share
    path = /mnt/data/user1/Videos
    read only = yes
    guest ok = yes
    only guest = yes

[Origin]
    comment = Origin Backup
    path = /mnt/data/user4
    read only = no
    create mask = 0644
    directory mask = 0755
    valid users = user4

              
You may also download “freebsd-10p1-smb4.conf” directly or view “freebsd-10p1-smb4.conf” on GitHub Gist (you may need to manually checkout the “main” branch).

Now you need to go ahead and actually create the Samba users (and their passwords), which are in addition to the FreeBSD users. To create the guest account run adduser like below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

Username: guest
Full name: guest
Uid (Leave empty for default):
Login group [guest]: staff
Login group is staff. Invite guest into other groups? []: sftp_only
Login class [default]:
Shell (sh csh tcsh bash rbash git-shell nologin) [sh]: nologin
Home directory [/home/guest]:
Home directory permissions (Leave empty for default):
Use password-based authentication? [yes]:
Use an empty password? (yes/no) [no]:
Use a random password? (yes/no) [no]:
Enter password:
Enter password again:
Lock out the account after creation? [no]:
Username   : guest
Password   : *****
Full Name  : guest
Uid        : 1011
Class      :
Groups     : staff sftp_only
Home       : /home/guest
Home Mode  :
Shell      : /usr/sbin/nologin
Locked     : no
OK? (yes/no): yes
adduser: INFO: Successfully added (guest) to the user database.
Add another user? (yes/no): no
Goodbye!

              
You may also download “freebsd-10p1-adduser” directly or view “freebsd-10p1-adduser” on GitHub Gist (you may need to manually checkout the “main” branch).

Now it is time to add the Samba users: this is done by using smbpasswd like below.

1
2
3
4
5
6
7
8
9

#!/bin/sh
smbpasswd -a user1
smbpasswd -a user2
smbpasswd -a user3
smbpasswd -a user4
smbpasswd -e user1
smbpasswd -e user2
smbpasswd -e user3
smbpasswd -e user4

              
You may also download “freebsd-10p1-cmds10.sh” directly or view “freebsd-10p1-cmds10.sh” on GitHub Gist (you may need to manually checkout the “main” branch).
§2.5.5 SSH

The settings for the SSH server are kept in “/etc/ssh/sshd_config”. Use your favourite editor (I use Vim) to change the file so that the un-commented lines look like the ones below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

# Accept environment variables LANG, LC_*, TIMEFORMAT and TZ ...
AcceptEnv LANG LC_* TIMEFORMAT TZ

# Show banner before logging in ...
Banner /etc/banner

# Make sure that users are still connected ...
ClientAliveInterval 5m

# Kill in-active login attempts ...
LoginGraceTime 5m

# Log all activity ...
LogLevel VERBOSE

# Number of password attempts ...
MaxAuthTries 4

# Number of hanging connections ...
MaxStartups 4

# Disable root login ...
PermitRootLogin no

# Enable port forwarding ...
PermitTunnel yes

# Maintain privacy ...
PrintLastLog no

# Use internal SFTP process with increased logging and file mode restrictions ...
Subsystem sftp internal-sftp -l VERBOSE -u 077

# Disable reverse lookup ...
UseDNS no

# Enable X11 forwarding ...
X11Forwarding yes

# Specific options for "sftp_only" group members ...
Match group sftp_only
    # Disallow agent forwarding ...
    AllowAgentForwarding no

    # Disallow TCP forwarding ...
    AllowTCPForwarding no

        # Chroot to the ZFS data partition ...
        ChrootDirectory /mnt/data

    # Force all connections to be SFTP ...
    ForceCommand internal-sftp -l VERBOSE -u 077

    # Disable port forwarding ...
    PermitTunnel no

    # Disable X11 forwarding ...
    X11Forwarding no

# Specific options for "user1" user ...
Match user user1
    # Hide banner ...
    Banner none

              
You may also download “freebsd-10p1-sshd_config” directly or view “freebsd-10p1-sshd_config” on GitHub Gist (you may need to manually checkout the “main” branch).

All the options are pretty self-explanatory I think but I would like to draw your attention to the line ForceCommand internal-sftp -l VERBOSE -u 077 under the section Match group sftp_only. These two lines mean that users who are members of the group “sftp_only” (“user3” and “user4” in this tutorial) cannot run commands over SSH on my server but do have the ability to use it’s storage over an SFTP connection. If one of those users tries to connect using ssh user3@HOST then it will always fail but they can still transfer files using an encrypted SFTP connection. In essence, my server is simply a data store for them and it will refuse all attempts to log in, run commands, forward ports or open GUIs.

§2.5.6 SMART Daemon

The settings for the SMART daemon are kept in “/usr/local/etc/smartd.conf”. Use your favourite editor (I use Vim) to change the file so that the un-commented lines look like the ones below. This will start a short self-test on all disks between 2AM and 3AM on Tuesday morning and any changes in their health will be emailed to you.

1
2
3
4
5
6
7

DEFAULT -m user@example.com
/dev/ada0 -s S/../../2/02
/dev/ada1 -s S/../../2/02
/dev/ada2 -s S/../../2/02
/dev/ada3 -s S/../../2/02
/dev/ada4 -s S/../../2/02
/dev/ada5 -s S/../../2/02

              
You may also download “freebsd-10p1-smartd.conf” directly or view “freebsd-10p1-smartd.conf” on GitHub Gist (you may need to manually checkout the “main” branch).

§3 Workarounds

For some reason the default installation of Python from the ports system does not load up the machine’s SSL certificates correctly. This means that Python scripts which connect to servers securely, such as youtube-dl, fail with “CERTIFICATE_VERIFY_FAILED” errors. After a fair amount of searching I found other people had similar issues. I was able to implement a workaround by typing the following command as root ln -s /usr/local/etc/ssl/cert.pem /etc/ssl/cert.pem.

§4 Usage Notes

To find a port in the port tree run whereis bar.

To perform an audit of all known security holes in the installed software run pkg audit. Before you update the software using portmaster foo/bar you should check UPDATING to see if there are any issues for updating any specific package.

To update the base of FreeBSD run freebsd-update fetch install.

To restart servers run one of the following commands:

To update the time after a long down period run (during which the clock may have drifted) ntpdate -v -b uk.pool.ntp.org.

To upgrade all installed ports in the correct order run portmaster -afy.

To list all ports that have upgrades available run portmaster -L | grep "New version available" | sort.

To upgrade from 10.0-RELEASE to 10.1-RELEASE (according to the Installation Notes) run the following commands (I have added the -m DISABLE_VULNERABILITIES=yes because sometimes updating FreeBSD to a secure version is more important than ensuring all installed packages are themselves secure):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11

#!/bin/sh
freebsd-update fetch install
reboot
freebsd-update upgrade -r 10.1-RELEASE
freebsd-update install
reboot
freebsd-update install
portmaster -B -f -m DISABLE_VULNERABILITIES=yes -a
# Run "portmaster -B -R -f -m DISABLE_VULNERABILITIES=yes -a" if you were interrupted and need to restart from where you left off
freebsd-update install
reboot

              
You may also download “freebsd-10p1-cmds11.sh” directly or view “freebsd-10p1-cmds11.sh” on GitHub Gist (you may need to manually checkout the “main” branch).

If you have changed the umask of the root account then some permissions will be more restrictive than intended. To correct port’s documentation installation (which assumes default umask) run the following commands:

1
2
3
4

#!/bin/sh
chmod="$(which chmod 2> /dev/null)"
find /usr/local/share/doc ! -perm 755 -type d -exec "${chmod}" 755 {} \;
find /usr/local/share/doc ! -perm 644 -type f -exec "${chmod}" 644 {} \;

              
You may also download “freebsd-10p1-cmds12.sh” directly or view “freebsd-10p1-cmds12.sh” on GitHub Gist (you may need to manually checkout the “main” branch).

If you have changed the umask of the root account then some permissions will be more restrictive than intended. To correct a PIP installation (which assumes default umask) run the following commands:

1
2
3
4

#!/bin/sh
chmod="$(which chmod 2> /dev/null)"
find /usr/local/lib/python2.7/site-packages ! -perm 755 -type d -exec "${chmod}" 755 {} \;
find /usr/local/lib/python2.7/site-packages ! -perm 644 -type f -exec "${chmod}" 644 {} \;

              
You may also download “freebsd-10p1-cmds13.sh” directly or view “freebsd-10p1-cmds13.sh” on GitHub Gist (you may need to manually checkout the “main” branch).

To update all PHP 5.6 packages, for example, run portmaster $(portmaster -l | egrep -o php56.+ | sed "s/-5.6.*//g;s/-1.0//g").

§5 References

For advice on which folders to copy on Windows to backup Origin downloads then check out this informative article (remembering to connect to the SMB share as “WORKGROUP\user4” from Windows).

§6 Word Of Warning

A xkcd comic about installing *BSD
© xkcd