I don't reach for FreeBSD for many projects, though for awhile it was in my tool kit when I needed to quickly stand up a ZFS-based test bed environment. At the time of writing the major VPS providers in my nebula that offer FreeBSD are Vultr and AWS Lightsail. Vultr offers a more up-to-date image, but updating is easy enough and the Lightsail image seems to be more barebones (which is my preference).
If you want to install FreeBSD on Vultr from scratch (e.g. to implement ZFS, as their image does not), it would seem that one should just upload a custom ISO and install it at-will. There is an issue with the console though, and ultimately you'll be left staring at the serial output with no way to interact with the installer. The workaround is to choose a new instance in your desired configuration and choose their FreeBSD image, let it boot up, then choose a Custom ISO from within that instance. From there, some settings must be in place that allow things to proceed as usual.
Unless you need to heavily customize any packages on FreeBSD, I recommend using pkg
to install binary packages rather than compiling things from the ports tree. For one, the binaries install much faster, and for two, the ports collection itself can be quite large with time. You can minimize the amount of space the ports collection takes up by removing it when not in-use, and by issuing a make clean
after installing anything (or after something fails to compile - do not forget to run make clean
!).
If you are intending to use ports, rather than trying to clone with git which sometimes fails on systems with fewer than 1-2G of RAM (for what it's worth, I can't replicate this issue on Linux), I recommend using portsnap fetch extract
. There are also tools such as portmaster to help manage ports, though I find they don't add a lot of value if you're only using ports in cases where you're trying to customize a package, and not to install every piece of software in your FreeBSD environment.
If you need to use the ports tree or the FreeBSD kernel source for anything, located at /usr/ports
and /usr/src
respectively, there is an option to save some space This is reliant on having installed FreeBSD on ZFS, but you can set the respective filesystems for these locations to use higher compression, such as gzip-9. Upon doing so, here is the size of my ports tree:
root@freebsd:/usr/local/etc/sssd # zfs list zroot/usr/ports
NAME USED AVAIL REFER MOUNTPOINT
zroot/usr/ports 737M 14.8G 737M /usr/ports
To enable gzip-9 on the ports filesystem, simply run zfs set compression=gzip-9 zroot/usr/ports
. Be mindful that when interacting with these locations you will use a lot more CPU as the data is heavily compressed. For comparison, though, here is the same data without compression:
root@freebsd:/usr/ports # zfs list zroot/usr/ports
NAME USED AVAIL REFER MOUNTPOINT
zroot/usr/ports 1.01G 14.5G 1.01G /usr/ports
Note: at the time of writing, lz4 is the default compression and does almost as well as gzip-9 on this particular dataset, so do your homework and figure out what is best for your use-case.
Most things go off without a hitch when using FreeBSD, though if you come from a primarily Linux background as I do, there are a few things that could be hangups. Keep in mind the following is based on my use-case, and you should be sure any config file changes aren't going to break your own system (especially when dealing with things like PAM!).
Installing WireGuard on FreeBSD can be done by issuing a pkg install wireguard
or by navigating to the appropriate place in the ports tree and compiling. The config is the same as on Linux (my home), and all of the options tested seem to work fine. To enable starting the service and to start on boot, add the following to /etc/rc.conf
:
wireguard_interfaces="wg0"
wireguard_enable="YES"
If you come from Linux, especially a RedHat environment, it's really easy to interface with SSSD to manage authorization and authentication to your system, and it has a variety of backends such as for LDAP, FreeIPA, etc. One of my goals recently using FreeBSD was to get their port of SSSD working so that I could use a common configuration file between all of my systems to minimize the amount of work required to bootstrap a new environment. I have a personal LDAP server that manages users, groups, SSH keys, and sudoers. Initially I was struggling to get SSSD working fully on FreeBSD, but upon doing some digging I learned that the default sudo package is not compiled with SSSD support. As such, it is necessary to compile your own sudo package if you intend to fetch sudoers using SSSD (from any backend - LDAP, IPA, etc.). On a new system, the following packages and configuration file changes are required (at minimum, and specific to my setup – change for your own needs!).
First install sssd using pkg or from the ports collection. Its defaults are sane and haven't proven to be an issue, so I recommend the binary unless you require further customization. Create an sssd.conf file at /usr/local/etc/sssd/sssd.conf and be sure to change the owner to root, and make sure the file is not world readable chown root /usr/local/etc/sssd/sssd.conf && chmod 600 /usr/local/etc/sssd/sssd.conf. There is a sample configuration file by default at /usr/local/etc/sssd/sssd.conf.sample. The following is my minimally viable config, properly redacted:
# sssd.conf
# Generated by 389 Directory Server - dsidm
#
# For more details see man sssd.conf and man sssd-ldap
# Be sure to review the content of this file to ensure it is secure and correct
# in your environment.
[domain/ldap]
# Uncomment this for more verbose logging.
#debug_level=9
#debug_level=0x2670
# Cache hashes of user authentication for offline auth.
cache_credentials = True
id_provider = ldap
auth_provider = ldap
access_provider = ldap
chpass_provider = ldap
ldap_schema = rfc2307bis
ldap_search_base = #CHANGEME
ldap_uri = #CHANGEME
# If you have DNS SRV records, you can use the following instead. This derives
# from your ldap_search_base.
# ldap_uri = _srv_
ldap_tls_reqcert = hard
# To use cacert dir, place *.crt files in this path then run:
# /usr/bin/openssl rehash /etc/openldap/certs
# or (for older versions of openssl)
# /usr/bin/c_rehash /etc/openldap/certs
#ldap_tls_cacertdir = /etc/openldap/certs
# Path to the cacert
# ldap_tls_cacert = /etc/openldap/certs/ca.crt
# Only users who match this filter can login and authorise to this machine. Note
# that users who do NOT match, will still have their uid/gid resolve, but they
# can't login.
ldap_access_filter = #CHANGME
enumerate = false
access_provider = ldap
ldap_user_member_of = memberof
ldap_user_gecos = cn
ldap_user_uuid = nsUniqueId
ldap_group_uuid = nsUniqueId
# This is really important as it allows SSSD to respect nsAccountLock
ldap_account_expire_policy = rhds
ldap_access_order = filter, expire
# Setup for ssh keys
# Inside /etc/ssh/sshd_config add the lines:
# AuthorizedKeysCommand /usr/bin/sss_ssh_authorizedkeys
# AuthorizedKeysCommandUser nobody
# You can test with the command: sss_ssh_authorizedkeys <username>
ldap_user_ssh_public_key = sshPublicKey
# This prevents an issue where the Directory is recursively walked on group
# and user look ups. It makes the client faster and more responsive in almost
# every scenario.
ignore_group_members = False
default_shell = /bin/bash
override_shell = /usr/local/bin/bash
override_homedir = /usr/home/%u
sudo_provider = ldap
ldap_sudo_search_base = #CHANGEME
[sssd]
services = nss, pam, sudo, ssh
config_file_version = 2
domains = ldap
[nss]
homedir_substring = /home
[ssh]
[sudo]
Ensure SSSD can be started and starts at boot by adding sssd_enable="YES"
to /etc/rc.conf. Start SSSD using service sssd start
. If you want to use SSSD to manage sudoers using an LDAP or other backend, compile sudo from the ports collection and be sure to include SSSD support when the dialog pops up, or specify it as an option at the command line when issuing make
.
cd /usr/ports/security/sudo
make install clean # when dialog promps for sssd compile options, be sure to include SSSD!
Update /etc/pam.d/system
to allow users to auth using sssd:
#
# $FreeBSD$
#
# System-wide defaults
#
# auth
auth sufficient /usr/local/lib/pam_sss.so
auth sufficient pam_opie.so no_warn no_fake_prompts
auth requisite pam_opieaccess.so no_warn allow_local
#auth sufficient pam_krb5.so no_warn try_first_pass
#auth sufficient pam_ssh.so no_warn try_first_pass
auth required pam_unix.so no_warn try_first_pass nullok
# account
#account required pam_krb5.so
account required pam_login_access.so
account required pam_unix.so
# session
#session optional pam_ssh.so want_agent
session required pam_lastlog.so no_fail
# password
#password sufficient pam_krb5.so no_warn try_first_pass
password required pam_unix.so no_warn try_first_pass
Update /etc/pam.d/sshd
to include the same changes:
#
# $FreeBSD$
#
# PAM configuration for the "sshd" service
#
# auth
auth sufficient /usr/local/lib/pam_sss.so
auth sufficient pam_opie.so no_warn no_fake_prompts
auth requisite pam_opieaccess.so no_warn allow_local
#auth sufficient pam_krb5.so no_warn try_first_pass
#auth sufficient pam_ssh.so no_warn try_first_pass
auth required pam_unix.so no_warn try_first_pass
# account
account required pam_nologin.so
#account required pam_krb5.so
account required pam_login_access.so
account required pam_unix.so
# session
#session optional pam_ssh.so want_agent
session required pam_permit.so
# password
#password sufficient pam_krb5.so no_warn try_first_pass
password required pam_unix.so no_warn try_first_pass
Create a new file if it doesn't already exist (it didn't in my case) for pam sudo rules - /etc/pam.d/sudo
:
auth sufficient /usr/local/lib/pam_sss.so
Modify /etc/nsswitch.conf to tell it to check sssd for mapping UIDs and GIDs to usernames, as well as sudoers:
#
# nsswitch.conf(5) - name service switch configuration file
# $FreeBSD$
#
group: files sss
group_compat: nis
hosts: files dns
netgroup: compat
networks: files
passwd: files sss
passwd_compat: nis
shells: files
services: compat
services_compat: nis
protocols: files
rpc: files
sudoers: files sss
After completing all of these steps, assuming sssd started correctly, you should be able to check if an LDAP user exists using getent passwd <username>
:
root@freebsd:/usr/local/etc/sssd # getent passwd jonathan
jonathan:*:1000:1000:Jonathan:/home/jonathan:/bin/bash
If you store SSH public keys in your LDAP server, there is a utility included with SSSD to grab them, installed at /usr/local/bin/sss_ssh_authorizedkeys
.
To utilize it, add the following lines to /etc/ssh/sshd_config
:
AuthorizedKeysCommand /usr/local/bin/sss_ssh_authorizedkeys
AuthorizedKeysCommandUser nobody
If you store a user's shell in your LDAP schema, which most do, then it can be a bit annoying on FreeBSD when bash
gets installed at /usr/local/bin/bash
. One way of dealing with this, albeit a bit hacky, is to create a symlink for bash at /bin/bash
and additionally add a line to /etc/shells
. If you do this, be sure not to ever use this “modified” shell for the root user!
pkg install bash # in case you haven't already installed it
ln -s /usr/local/bin/bash /bin/bash
echo "/bin/bash" >> /etc/shells
Another option for handling this is to override the shell and force a known good shell for all users. Modify your sssd.conf
to contain the following:
[domain/yourdomain]
...
override_shell = /usr/local/bin/bash
The default location for home directories in FreeBSD is /usr/local/home
. In your LDAP directory, it's likely if you use Linux that your users' home directories are /home/<user>
. To fix this, you can set the following directive in your sssd.conf
to override the default:
[domain/yourdomain]
...
override_homedir = /usr/home/%u
LDAP users also likely won't have a home directory. To rectify this, you can install pam_mkhomedir
and further modify /etc/pam.d/system
and /etc/pam.d/ssh
.
/etc/pam.d/system:
#
# $FreeBSD$
#
# System-wide defaults
#
# auth
auth sufficient /usr/local/lib/pam_sss.so
auth sufficient pam_opie.so no_warn no_fake_prompts
auth requisite pam_opieaccess.so no_warn allow_local
#auth sufficient pam_krb5.so no_warn try_first_pass
#auth sufficient pam_ssh.so no_warn try_first_pass
auth required pam_unix.so no_warn try_first_pass nullok
# account
#account required pam_krb5.so
account required pam_login_access.so
account required pam_unix.so
# session
#session optional pam_ssh.so want_agent
session required /usr/local/lib/pam_mkhomedir.so
session required pam_lastlog.so no_fail
# password
#password sufficient pam_krb5.so no_warn try_first_pass
password required pam_unix.so no_warn try_first_pass
/etc/pam.d/sshd:
#
# $FreeBSD$
#
# PAM configuration for the "sshd" service
#
# auth
auth sufficient /usr/local/lib/pam_sss.so
auth sufficient pam_opie.so no_warn no_fake_prompts
auth requisite pam_opieaccess.so no_warn allow_local
#auth sufficient pam_krb5.so no_warn try_first_pass
#auth sufficient pam_ssh.so no_warn try_first_pass
auth required pam_unix.so no_warn try_first_pass
# account
account required pam_nologin.so
#account required pam_krb5.so
account required pam_login_access.so
account required pam_unix.so
# session
#session optional pam_ssh.so want_agent
session required /usr/local/lib/pam_mkhomedir.so
session required pam_permit.so
# password
#password sufficient pam_krb5.so no_warn try_first_pass
password required pam_unix.so no_warn try_first_pass