It’s pretty common to carve off some tmpfs space for /var/log, /var/tmp, and /tmp as tmpfs volumes. You give up some RAM to do this and of course those files disappear on reboot or loss of power. I do this routinely on my RPi devices that don’t do a whole lot or are remotely deployed so replacing the SD card is a relative hardship (e.g. the openHAB I have deployed at my dad’s house an hour’s drive away).
Here is my /etc/fstab of my remote OH RPi for the curious. I did a manual openHABian install on it and it is connected to my home network over an OpenVPN connection.
proc /proc proc defaults 0 0
PARTUUID=7ba75bb5-01 /boot vfat defaults 0 2
PARTUUID=7ba75bb5-02 / ext4 defaults,noatime 0 1
# a swapfile is not a swap partition, no line here
# use dphys-swapfile swap[on|off] for that
tmpfs /tmp tmpfs defaults,noatime,nosuid,size=100m 0 0
tmpfs /var/tmp tmpfs defaults,noatime,nosuid,size=30m 0 0
tmpfs /var/log tmpfs defaults,noatime,nosuid,mode=0755,size=100m 0 0
/usr/share/openhab2 /srv/openhab2-sys none bind 0 0
/etc/openhab2 /srv/openhab2-conf none bind 0 0
/var/lib/openhab2 /srv/openhab2-userdata none bind 0 0
/var/log/openhab2 /srv/openhab2-logs none bind 0 0
/usr/share/openhab2/addons /srv/openhab2-addons none bind 0 0
//fafnir.koshak.net/backups/ /mnt/backups cifs credentials=/etc/samba/.smbcredentials,uid=1000,gid=1000 0 0
Note that openHABian created the openhab2 folders. fafnir is my openMediaVault NAS and I have Amanda set up to backup this RPi there. The three tmpfs lines are creating and mounting RAM disks over the three folders where the most writes take place.
You can even go so far as to make / read only, though it’s a pain because there are some files that need to be written to periodically like /etc/fake-hwclock and such. I don’t run this way any longer but have done so in the past. It was a fun experiment but in the end is didn’t really add anything and made using the machine a major PITA.
For the curious, here is the Ansible playbook I wrote to setup my RPi readonly. It probably doesn’t work, it has been over a year since I last ran it and even then I only half ran it (i.e. did a bunch of steps manually).
---
#- name: Add aliases and fancy prompt to show status of FS
# blockinfile:
# state: present
# dest: /etc/bash.bashrc
# block: |
# # set variable identifying the filesystem you work in (used in the prompt below)
# set_bash_prompt(){
# fs_mode=$(mount | sed -n -e "s/^\/dev\/.* on \/ .*(\(r[w|o]\).*/\1/p")
# PS1='\[\033[01;32m\]\u@\h${fs_mode:+($fs_mode)}\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
# }
#
# alias ro='sudo mount -o remount,ro / ; sudo mount -o remount,ro /boot'
# alias rw='sudo mount -o remount,rw / ; sudo mount -o remount,rw /boot'
#
# # setup fancy prompt"
# PROMPT_COMMAND=set_bash_prompt
# become: yes
# when: "'readonly' in group_names"
#
#- name: Set permissions on /tmp
# file:
# mode: a+rwx
# path: /tmp
# state: directory
# become: yes
# when: "'readonly' in group_names"
#
#- name: Mount tempfs directories
# mount:
# path: "{{ item }}"
# src: tmpfs
# fstype: tmpfs
# opts: nosuid,nodev
# state: mounted
# become: true
# when: "'readonly' in group_names"
# with_items:
# - /tmp
# - /var/log
# - /var/tmp
#
#- name: Backup dhcp
# command: cp -r /var/lib/dhcp /tmp
# become: yes
# when: "'readonly' in group_names"
#
##- name: Remove contents of folders pending relinking to /tmp
## shell: /bin/rm -rf {{ item }}
## become: yes
## when: "'readonly' in group_names"
## with_items:
### - /var/lock/*
## - /var/spool/*
### - /var/run/*
## - /var/lib/dhcp/*
#
#- name: Create softlinks to /tmp
# file:
# src: "{{ item }}"
# dest: /tmp
# state: link
# become: yes
# when: "'readonly' in group_names"
# with_items:
# - /var/lock
# - /var/spool
# - /var/run
# - /var/lib/dhcp
#
#- name: Reboot
# include_role:
# name: reboot
# when: "'readonly' in group_names"
# Did all of the above manually
- name: Add cron job to reset permissions on /tmp on boot
cron:
name: "add write to /tmp"
special_time: reboot
job: "chmod a+w /tmp > /dev/null"
- name: Configure boot command line
replace:
dest: /boot/cmdline.txt
regexp: 'otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait'
replace: 'otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait fastboot noswap ro'
become: yes
when: "'readonly' in group_names"
- name: Move dhcpd lock file to temp
replace:
dest: /etc/systemd/system/dhcpcd5
regexp: '\=/run/dhcpcd.pid'
replace: '\=/var/run/dhcpcd.pid'
become: yes
when: "'readonly' in group_names"
- name: update fake-hwclock cron job to remount / rw and then mount it back
copy:
dest: /etc/cron.hourly/fake-hwclock
src: fake-hwclock
become: yes
when: "'readonly' in group_names"
- name: Check for presence of Tripwire cron job
stat: path=/etc/cron.daily/tripwire
register: tripwire_cron
when: "'readonly' in group_names"
- name: Update cron job to remount rw before running check
copy:
dest: /etc/cron.daily/tripwire
src: tripwire-cron
become: yes
when: ("'readonly' in group_names") and
(tripwire_cron.stat.exists == True)
- name: Update apt daily script to remount rw before running
copy:
dest: /etc/cron.daily/apt
src: apt
become: yes
when: "'readonly' in group_names"
- name: Update dpkg daily script to remount rw before running
copy:
dest: /etc/cron.daily/dpkg
src: dpkg
become: yes
when: "'readonly' in group_names"
- name: Update logrotate daily script to remount rw before running
copy:
dest: /etc/cron.daily/logrotate
src: logrotate
become: yes
when: "'readonly' in group_names"
- name: Update man-db daily script to remount rw before running
copy:
dest: /etc/cron.daily/man-db
src: man-db
become: yes
when: "'readonly' in group_names"
- name: Update man-db weekly script to remount rw before running
copy:
dest: /etc/cron.weekly/man-db
src: man-db
become: yes
when: "'readonly' in group_names"
- name: Update passwd daily script to remount rw before running
copy:
dest: /etc/cron.daily/passwd
src: passwd
become: yes
when: "'readonly' in group_names"
- name: Remove some start scripts
shell: /sbin/insserv -r bootlogs; /sbin/insserv -r console-setup
become: yes
when: "'readonly' in group_names"
- name: Set boot FS as readonly
replace:
dest: /etc/fstab
regexp: '/dev/mmcblk0p1 /boot vfat defaults 0 2'
replace: '/dev/mmcblk0p1 /boot vfat defaults,ro 0 2'
become: yes
when: "'readonly' in group_names"
- name: Set root as readonly
replace:
dest: /etc/fstab
regexp: '/dev/mmcblk0p2 / ext4 defaults,noatime 0 1'
replace: '/dev/mmcblk0p2 / ext4 defaults,noatime,ro 0 1'
become: yes
when: "'readonly' in group_names"
- name: Reboot
include_role:
name: reboot
when: "'readonly' in group_names"
Note that most of the copies at the end of the playbook are all the cron jobs that write to the file system that needed to be altered to remount the file system read/write so they could do their job.
I’m not sure why it would be significantly different in terms of performance. The overwhelming set of operations are still appends and as long as the file is kept open for writing (as it should be) the logger doesn’t have to seek around the file for the insertion point, it’s already there after the first write. Unless this appender works differently than I’m assuming.
Boot time/OH startup is where the most file reads are taking place so that could suffer some performance issues. I’ve seen some reports of 10 minutes to an hour for OH start times for some users on RPis (I was and still am shocked at that). This might exacerbate that problem. NOTE: we have discovered this is caused in part by explicitly using lots of primitives in Rules.
Except for logging and persistence OH doesn’t have too many writes in comparison so I wouldn’t expect too much of an impact. And since persistence is occurring in background threads I wouldn’t expect it to impact the overall performance of OH all that much. In very rare cases you may need to add short Thread::sleeps before you can make calls to the historicState methods on the Item and be guaranteed to get results that include the event that triggered the Rule. This should be a very rare occurrence if it is ever needed.
As for the logging, I don’t know if the log statements block on write or if the appenders cache the logging and write it out to disk in the background. If it is caching then it seems pretty unlikely that the responsiveness of OH would be that impacted at all. The primary impact would be on a crash not necessarily having the latest logs. It’s probably configurable.
It would be interesting to see some numbers showing what the impact of running OH off of a NAS really would be. Enough users set up their RPis this way to run OH that I don’t think the performance impact is enough to offset the potential benefits.