When setting up my RaspberryPi for some actual ‘production’ work (as a low-volume NAS server and VPN endpoint to live at my parent’s house), I wanted to keep writes to the SD card as low as possible. To this end, I thought I’d keep things like /var/log and swap on a compressed RAM disk.
Unfortunately I’ve got one of the first RPi’s, so I only have 256MB to play with. I’ve set the RPi to allocate the minimum amount of memory to the GPU (16MB), leaving me with 232MB for the system. I have a 512MB swap partition on the SD card already. I need to set up a 32MB compressed RAMdisk for /var/log, and a 64MB one for swap.
Since I want to make sure the compressed swap area is used before writing to flash, I need to explicitly set the priority of the existing flash swap area to a low priority. This can be done by adding
pri=1 to the fstab line:
UUID=432...324 none swap sw,pri=1 0 0
On boot, I want all of this configured for me. The usual way of doing this would be to write an init script to take care of the setup and teardown. I’m too lazy for that! I don’t care about keeping the data either, so there is no need for a shutdown script to take care of writing the contents back to flash.
/etc/rc.local here I come.
echo "Setting up compressed RAMdisk..."
# Insert the zram module into the running kernel and ask
# it to configure 2 devices.
modprobe zram num_devices=2
# Set the size of the first zram device to 32MB.
echo 33554432 > /sys/block/zram0/disksize
# Make an ext2 filesystem on the device. ext2 eliminates
# the minor overhead of a journal. I'm using a RAMdisk for
# my logs, do I really need a better filesystem?
mkfs.ext2 /dev/zram0 > /dev/null 2>&1
# Stop the syslog service since we'll be moving the logs
# about. If you're running the default Raspbian
# installation this should be changed to 'rsyslog' instead
# of 'inetutils-syslogd'. I swapped them out to save
service inetutils-syslogd stop
# The next 5 lines move the existing logs out of the way
# (such as those logged during boot), mounts the zram
# device at /var/log, then copies the logs back into
# place, removing the temporary directory.
mv /var/log/* /tmp/logs
mount -o noatime /dev/zram0 /var/log > /dev/null 2>&1
mv /tmp/logs/* /var/log
rm -rf /tmp/logs
# Restart the syslog service now we have everything in
service inetutils-syslogd start
# Now we need to set up the compressed swap space, so set
# the size of the second zram device to 64MB.
echo 67108864 > /sys/block/zram1/disksize
# Make the swap area.
mkswap /dev/zram1 > /dev/null 2>&1
# Enable the swap space with a higher priority than the
# flash swap.
swapon -p10 /dev/zram1
So far, so good! The RAM allocated to the zram devices doesn’t count towards total memory usage unless it’s being used, either. After booting, memory usage on the RPi is a mere 16MB even with the zram disks configured!