Linux with / mounted read-only 2.0

(This is a new version of a previous post updated to work with Ubuntu 9.10 (karmic).)

I wondered why you usually mount / (the root file system) read-write in Linux and decided to do some experiments to find out if it is possible to have it mounted read-only.

So why do you want to do that? Perhaps you have the root file system on a read-only media, such as CD-ROM. Or on a writable media which can only handle a limited number of writes, such as a CD-RW or flash disk. It would also increase security since it will be more difficult (though not impossible) for some malware to infect your system.

I found out that it is possible to mount / read-only, but only after some tweaking. Here is how I did it in Ubuntu 9.10 (karmic) desktop.

The first obvious step is to change the mount options to “ro” for / in /etc/fstab and reboot. But the tweaking has to be done first, so don’t reboot yet!

There are some locations in the file system which has to be writeable, the solution is to mount them as tmpfs. After some experiments, I found out that I had to mount the following locations as tmpfs (assuming that /dev is already mounted in an appropriate way):

  • /tmp
  • /media
  • /var/run
  • /var/lock
  • /var/tmp
  • /var/crash
  • /var/log
  • /var/lib/xkb
  • /var/lib/gdm
  • /var/lib/dhcp3 (only if you use DHCP client)
  • /var/lib/nfs (only if you use NFS)
  • /var/spool/cups

Ubuntu mounts /var/run and /var/lock as tmpfs by default. This is done by the mountall tool.

Add this to /etc/fstab:

none /tmp             tmpfs mode=1777,nodev,exec,nosuid 0 0
none /media           tmpfs mode=0755,nodev,noexec,nosuid 0 0
none /var/tmp         tmpfs mode=1777,nodev,noexec,nosuid 0 0
none /var/crash       tmpfs mode=0755,nodev,noexec,nosuid 0 0
none /var/spool/cups  tmpfs mode=0710,nodev,noexec,nosuid,gid=lp 0 
none /var/log         tmpfs mode=0755,nodev,noexec,nosuid 0 0
none /var/lib/dhcp3   tmpfs mode=0755,nodev,noexec,nosuid 0 0
none /var/lib/xkb     tmpfs mode=0755,nodev,noexec,nosuid 0 0
none /var/lib/gdm     tmpfs mode=0775,nodev,noexec,nosuid,gid=gdm 0 0
none /var/lib/nfs     tmpfs mode=0755,nodev,noexec,nosuid 0 0

And add this to /etc/rc.local:

mkdir /var/log/apt

There are some files in /etc which have to be writeable:

  • /etc/mtab
  • /etc/resolv.conf (only if you use DHCP client and let it set DNS configuration)

I handle /etc/mtab by symlink it to /proc/mounts, that has some minor side-effects but I can live with it. I handle /etc/resolv.conf by symlinking it to /var/lib/dhcp3/resolv.conf. In order for this to work, you have to patch the DHCP client (dhcp3-client) accodring to this bug report (use the new version of the patch).

You also have to mount /home read-write somewhere, and I would not recommend using tmpfs. You can use a separate hard disk partition or NFS.

It is a bit tricky to get this to work with NFS. You have to set the NFS mount points in /etc/fstab as noauto and add these lines to /etc/init/statd.conf just before status portmap...

mkdir /var/lib/nfs/sm
mkdir /var/lib/nfs/sm.bak
mkdir /var/lib/nfs/rpc_pipefs

Then mount the NFS shares in /etc/gdm/PostLogin/Default. For some reason it did not work to do it from /etc/rc.local, perhaps due to delay in DHCP lookup.

Finally it might be a good idea to set a password for the root account, this enables you to switch to a virtual console (CtrlAltF1) and login as root if something goes wrong.

If you then do want to change anything, such as edit a file in /etc or install or upgrade a package, you can just remount / as read-write temporary (assuming that the media actually is writeable):
sudo mount -o rw,noatime,remount /

and revert to read-only when finished:
sudo mount -o ro,noatime,remount /

Note that this setup is for a desktop or laptop system, it’s probably not appropriate for a server.

If you have plenty of RAM (such as at least 1 GB), then you can also mount /var/cache/apt as tmpfs. That helps if you have limited free space on / and want to do a distribution upgrade.

Add this to /etc/fstab:

none /var/cache/apt   tmpfs mode=0755,nodev,noexec,nosuid 0 0

And add this to /etc/rc.local:

mkdir -p /var/cache/apt/archives/partial
This entry was posted in Linux. Bookmark the permalink.

12 Responses to Linux with / mounted read-only 2.0

  1. does doing this make it then impossible to do updates? nothing on the disk can be written? home?

  2. nick,

    If you read more carefully, you will discover that you need to temporary remount read-write in order to do updates. And that you should mount /home somewhere read-write.

  3. David Bugess says:


    Thanks for keeping this up to date. I’ve been using your guides since 8.10.


  4. johnd16 says:

    For 10.04 with a .32-server kernel, my experience is that the following lines in /etc/fstab will stop the boot process:

    #none /var/crash tmpfs mode=0755,noatime,nodev,noexec,nosuid, 0 0
    #none /var/spool/cups tmpfs mode=0710,noatime,nodev,noexec,nosuid,gid=lp 0

    Or should these mounts not have got the noatime property?

  5. johnd16 says:

    Easy cause?

    $ sudo ls /var/crash
    ls: cannot access /var/crash: No such file or directory
    $ sudo ls /var/spool/cups
    ls: cannot access /var/spool/cups: No such file or directory

  6. (I haven’t tried this with 10.04 yet.)

    I see no reason for using noatime with tmpfs. noatime is a performance optimization to avoid unnecessary writes to the underlaying device. It is not relevant for tmpfs since there is no underlaying device (that’s the point with tmpfs).

    Try to remove noatime from all tmpfs mounts. And make sure that you actually have a group “lp”. And make sure that you don’t have any trailing comma after nosuid on the /var/crash line.

    And the mount point directories needs to exist.

  7. johnd16 says:

    Thanks for the trailing comma. I didn’t spot that error myself.

    What could be the unwanted side effects from setting option “noatime” on tmpfs mounts for /media, /var/log, /var/lib/dhcp3 mount points?

    My idea is to not waste any cycles on not really necessary tasks.
    I know this might be an ultra tiny (0.0000001%) saving.

  8. johnd16 says:

    BTW: Why is this setup probably not advisable for a server?

  9. I don’t know about any side effects of noatime here. However, I am quite sure that you won’t get any performance improvement at all from noatime on tmpfs.

  10. On a server, you probably store data somewhere in /var which you want to have persistent.

    But if you mount /var somehow persistent read-write (just like /home), something like this setup should work on a server as well. In that case you should probably not bother to mount all the subdirectories of /var as tmpfs.

    On a server, only these should be tmpfs:

    (in addition to /dev, /dev/shm, /lib/init/rw and other stuff which the distribution mounts as tmpfs by default).

  11. Pingback: Mount your home directory with SSHFS in Linux | Mikael Ståldal’s technical blog

  12. Pingback: How to roll your own bootable Linux CD-ROM | Mikael Ståldal’s technical blog

Comments are closed.