Moving Home Assistant Logs

Stop eating my SD card

“Read only file system” “No disk available” Most of us have been there at some time or another. Impatience or ignorance of knowing not shutting down a Raspberry Pi properly can chew up a SD card. Another lesser known issue is that SD cards have a limited lifespan; they only get a certain number of write cycles before they stop working. It’s like that Eddie Murphy movie where he’s only got a limited number of words he can say and they’re counted by leaves on a tree.

Because of this write-intensive stuff like logs and databases a card can get worn out far before it should due to excessive writes. There’s hope! You can use a USB drive and redirect all of this write-heavy activity there and your SD card will be safe.

First you need to figure out where Linux thinks the USB drive lives; in my case it was /dev/sda. Plug your drive into your Pi and then run the following command: (Thanks to Tinkerer for the better than ‘figure it out’ solution)

sudo dmesg|tail -n 20|grep sd

You’ll get output that will look something like:

[ 3.773637] sd 0:0:0:0: [sda] 62333952 512-byte logical blocks: (31.9 GB/29.7 GiB) 
[ 3.783125] sd 0:0:0:0: [sda] Write Protect is off 
[ 3.791694] sd 0:0:0:0: [sda] Mode Sense: 0b 00 00 08 
[ 3.792618] sd 0:0:0:0: [sda] No Caching mode page found 
[ 3.801020] sd 0:0:0:0: [sda] Assuming drive cache: write through 
[ 3.817186] sda: sda1 sda2  

Next you’ll create a mount point somewhere on the file system that you’ll use to mount the USB disk.

sudo mkdir /mnt/usb-disk

Now you’ll use the mount commad to mount the usb disk to the directory

sudo mount /dev/sda /mnt/usb-disk

We’ll want to make this permanent so we’ll have to add an fstab entry for it. First we’ll need to figure out what filesystem type to use. We’ll use fdisk to list out our disks

sudo fdisk -l

Find the part where your drive is and it should look something like this:

Disk /dev/sda: 7.5 GiB, 8053063680 bytes, 15728640 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x6f20736b

If the Disklabel type: says dos it’s FAT32. Otherwise it should spell out what the type is.

sudo vim /etc/fstab

You’ll add a new line in the file replacing my example values with your actual values:

/dev/sda /mnt/usb-disk fat32 auto

The goal here is to move the commonly written stuff to the USB drive to reduce writes to the SD card we’ll move the home-assistant.log and the database to the drive. Shut down home assistant before doing this stuff.

mv /home/homeassistant/.homeassistant/home-assistant.log /mnt/usb-disk/ 
mv /home/homeassistant/.homeassistant/home-assistant_v2.db /mnt/usb-disk

The files are now on the drive but we have to make sure that home assistant can write to them. We’ll create a symbolic link from the Home Assistant config directory to the USB disk

ln -s /home/homeassistant/.homeassistant/home-assistant.log /mnt/usb-disk/home-assistant.log 
ln -s /home/homeassistant/.homeassistant/home-assistant_v2.db /mnt/usb-disk/home-assistant_v2.db

Restart home assistant and make sure everything’s working appropriately. If not, check your permissions on the files on your USB drive. They should be owned by the user that you run Home Assistant as.

sudo systemctl restart home-assistant.service

The logging is a bit trickier. We’ll need to modify the systemd unit for home assistant and add a new configuration file for journalctl. The venv install method already makes sure that the log messages from home assistant are tagged with the identifier ‘hass’. You can check your syslog by editing /var/log/syslog and look for home assistant messages. If they’re already tagged at the beginning with something that looks like Oct 20 06:25:28 ubuntu hass[21411]: you can skip modifying the system unit. To modify the system unit you just need to edit the file:

sudo vim /etc/systemd/system/home-assistant.service

and add (or modify) the following

StandardOutput=syslog 
SyslogIdentifier=hass

This tells it to redirect standard output to the syslog file and to tag the messages with hass.

Make sure to reload the system unit.

sudo systemctl daemon-reload

Now we need to configure journalctl to split those messages out to a different log location. Create a hass config for journalctl:

sudo vim /etc/rsyslog.d/hass.conf

enter the following and save the file

if $programname == 'hass' then /mnt/usb-disk/hass-syslog.log

restart rsyslog

sudo systemctl restart rsyslog

check to make sure it’s logging appropriately

tail -f /mnt/usb-disk/hass-syslog.log

Everything should be logging and using files on your external drive which should greatly prolong the life of your SD card. Happy automating!