Lightweight, zero-dependency, self-configuration for FreeBSD droplets on DigitalOcean
- Allows you to run a FreeBSD droplet that auto-configures itself at boot time.
- No dependency on extra packages or ports -- it's just a simple shell script.
- Automatically sets up:
- IPv4 and IPv6 public and private network addressing and routing
- Floating IP anchor addresses
- Hostname and DNS servers
- freebsd user's authorized public keys
- Replaces networking configurations in /etc/rc.conf with just one
digitalocean_enable="YES"
setting. - Runs "user-data" as shell commands e.g. to install packages or run a chef/puppet/ansible/... worker
- Completely configurable.
WARNING: Any custom networking scripts you may have created in /etc/rc.conf.d will be replaced. Backup if needed.
Droplets built from DigitalOcean's base FreeBSD images have extra packages and scripts that will no longer be required for auto configuration. They should be disabled first to avoid conflicts. When you're confident your cleaned-up droplet is working properly with this solution, you can remove the preinstalled stuff you do not need:
Unnecessary packages:
- curl
- dmidecode
- e2fsprogs
- gettext-runtime
- gpart (is in base, no clue why DO installs it from pkg)
- indexinfo
- jq
- libffi
- libiconf
- libnghttp2
- oniguruma
- python27
- lots of py27-* packages
- readline
- rsync
- sudo (doas is much more elegant and safer)
Unnecessary users:
- freebsd
Settings in /etc/rc.conf that can/should be removed:
- hostname
- cloudinit_enable
- digitaloceanpre
- digitalocean
- all ifconfig and route-related lines
- basically everything from the comment
DigitalOcean Dynamic Configuration lines and the immediate line below it, are removed each boot.
until the end of the file
Extraneous files and directories:
- /usr/local/etc/rc.d/cloud* (cloudconfig, cloudfinal, cloudinit, cloudinitlocal)
- /usr/local/etc/rc.d/digitalocean (digitalocean, digitaloceanpre)
-
As root, run update.sh which essentially does this for you:
install -m 700 digitalocean /usr/local/etc/rc.d install -m 644 digitalocean.conf /usr/local/etc install -m 700 digitalocean.sh /usr/local/sbin
-
Add
digitalocean_enable="YES"
to /etc/rc.conf -
If needed, edit /usr/local/etc/digitalocean.conf (self-documenting)
-
Test it by entering
service digitalocean start
(Note: this builds configuration files but does not change any active network settings) -
Sanity-check the
hostname
,network
, androuting
files in /etc/rc.conf.d -
Optional: If you configured the
droplet_user
(typically freebsd), check its home directory for .ssh/authorized_keys -
If all looks good, you can restart the droplet
Hint: sshd is configured to allow root-login with ssh-keys; so no additional user is needed. However, it is highly recommended to add a normal user and disable ssh root login.
It is possible to reconfigure the FreeBSD instance while running without needing to reboot. To restart networking and routing, enter these commands:
service digitalocean restart
service netif restart && service routing restart
Setting the config option hosts_file
to point to a file (such as /etc/hosts) will cause special DO_*
entries found in that file to be updated with their corresponding IP addresses. Example:
0.0.0.0 public-ip # DO_PUB_IPV4
0.0.0.0 private-ip # DO_PVT_IPV4
0.0.0.0 anchor-ip # DO_ANCHOR_IPV4
0.0.0.0 floating-ip # DO_FLOATING_IPV4
0.0.0.0 gateway-ip # DO_GW_IPV4
The script searches for a line with a DO_*
entry, such as DO_PUB_IPV4
, and replaces the first column address with the corresponding metadata address value. This creates an alias for services that listen on an address by referring to its symbolic DO_
name. The DO_*
symbols are required exactly as shown for matching purposes. Optionally, any other symbolic names may be included on the line, such as the *-ip
examples above. In the case of the /etc/hosts file, this would allow a service to bind to the address associated with anchor-ip
, provided the service permits host names.
Your own scripts can also lookup these metadata addresses easily by using getent(1):
anchor_ip=`getent hosts anchor-ip | cut -f1 -d' '`
(Use _IPV6
suffixed symbols for IPv6 adddresses.)
I didn't want to use DigitalOcean's implementation for auto-configuration. Extra packages of networking support tools and the special freebsd user account increase attack surfaces. Those packages will require updates at some point. They take up disk space, create persistent processes in memory, and steal CPU cycles. This shell script-based solution does the trick.
I'd love to get some feedback from others running and testing this just to make sure it's solid and has all features working well. After that, I could see making this an actual FreeBSD package. That is, of course, if DigitalOcean doesn't adopt something equivalent in their upcoming base images.
- August 12, 2016: Added support for dynamically updated host file entries.
- August 3, 2016: DigitalOcean now offers FreeBSD base images with ZFS support! Removed references for performing your own standard memory-based FreeBSD installation in order to run bsdinstall so you can enable ZFS on the root filesystem.
- July 28, 2016: This project was mentioned on episode 152 of the BSD Now show.