Edit: I've come across an issue with the previous script I had been using. I've edited this thread to explain the issue and the script has been modified.
Sorry for the bump, but this thread is still the top result on Google for "freebsd encrypted swap file" so I wanted to drop a line with my own solution, which is an improvement upon the post above.
Just like above I'm making use of
rc.local to set up my encrypted swap. If that files does not exist, create it with +x permissions. It will be automatically executed upon bootup. If it already exists, simply append to the end of it.
First off, you may need to load the geom_eli module upon boot. In
/boot/loader.conf:
If you have a CPU with AES-NI acceleration, you should also load the aesni driver upon boot, to get hardware accelerated AES -- this significantly improves the speed of the swap file we're creating.
/boot/loader.conf:
Next you'll have to create the swap file. Previously we were using a sparse file created in the script itself, but it has come to my attention that your swap file should never be a sparse file, for unspecified reasons.
Code:
dd if=/dev/zero of=/swap bs=1M count=6144 && sync
chmod 0600 /swap
Alter
count=6144
to the desired size of your swap file, in number of megabytes.
The contents of my
rc.local are as follows:
Code:
#!/bin/sh
# Create and mount one-time encrypted swap file
SWFILE="/swap";
if [ -f "$SWFILE" ]; then
chmod 0600 "$SWFILE" &&
SWMD=$(mdconfig -a -t vnode -f "$SWFILE");
if [ $? -eq 0 ] && [ -n "$SWMD" ] && [ -e "/dev/$SWMD" ]; then
chmod 0600 "/dev/$SWMD" &&
geli onetime -e AES-XTS -l 256 -d "/dev/$SWMD" &&
chmod 0600 "/dev/$SWMD.eli" &&
swapon "/dev/$SWMD.eli";
fi
fi
unset SWFILE;
unset SWMD;
Alter
SWFILE="/swap"
if you have placed the swap elsewhere.
The notable improvements are as follows:
- We make sure the permissions on the swap file are strict. World cannot read or write.
- Rather than depending on our swap file to exist at /dev/md0 we capture the actual ID of the file, ensure it exists, and then feed that to GELI. If any other scripts created an md device prior to this script, it won't break.
- Instead of using
geli init
and geli attach
, GELI provides a convenient onetime
function which initiates and attaches the device with a random passphrase. This way, the user never has to enter a password during boot.
- We use key length 256 because that's the longest key (currently) accelerated by AES-NI according to aesni(). The default is 128.
The above post was also using
mdconfig
incorrectly. We want a memory disk of type "vnode" (file backed, that is, a file on the hard drive) rather than "swap" (buffer backed, or, in other words, a RAM disk).
Reboot and check
swapinfo
to ensure everything functioned correctly. On my machine, everything appears good:
Code:
$ swapinfo
Device 1K-blocks Used Avail Capacity
/dev/md0.eli 6291456 0 6291456 0%
Edit: It has also come to my attention that, because of the level of indirection involved in handing 'swapon' an encrypted md, perhaps the kernel will not be aware of where the data eventually resides and may choose to buffer/cache the contents of the file, when we probably want it written directly to disk to act as an effective swap. I do not know if this will pose a problem, and if so, how to correct this.