惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
月光博客
月光博客
T
Tailwind CSS Blog
阮一峰的网络日志
阮一峰的网络日志
小众软件
小众软件
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Last Week in AI
Last Week in AI
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
罗磊的独立博客
Jina AI
Jina AI
酷 壳 – CoolShell
酷 壳 – CoolShell
宝玉的分享
宝玉的分享
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 三生石上(FineUI控件)
量子位
雷峰网
雷峰网
Apple Machine Learning Research
Apple Machine Learning Research
美团技术团队
博客园 - 聂微东
V
V2EX

IT Notes - hosting

IT Notes IT Notes IT Notes IT Notes IT Notes IT Notes IT Notes IT Notes IT Notes IT Notes IT Notes IT Notes IT Notes IT Notes IT Notes IT Notes IT Notes IT Notes IT Notes IT Notes
IT Notes
Stefano Marinelli · 2024-09-10 · via IT Notes - hosting

One detail that is often overlooked when dealing with embedded (or remote) devices is a key point of vulnerability: the file system.

For non-COW file systems (like ext4 on Linux, FFS, etc.), there are situations where a crash or a power outage could cause corruption, requiring manual intervention. This risk is especially present when using root on SD cards or similar storage media in embedded systems. Over time, these media are destined to fail due to numerous writes.

For certain use cases, it's advisable to set up a read-only root file system, which ensures better reliability in case of system issues. Think of scenarios like a router (critical for network access) or a caching reverse-proxy, such as the one described in my series "Make your own CDN".

While FreeBSD natively supports this configuration and some Linux distributions offer custom solutions (e.g., Alpine Linux), NetBSD stands out as an excellent choice for such devices. It supports nearly all embedded devices, is lightweight, and its stability minimizes the need for frequent updates.

The Key Idea

Although NetBSD doesn't provide native read-only support, it's flexible enough to allow for this configuration. Many years ago, I followed a howto to set up a read-only system, and the idea remains simple and effective: NetBSD writes primarily to specific locations, unlike some Linux distributions that attempt to write to various parts of the file system. On NetBSD, the main write targets are the /tmp directory and /var.

With this in mind, we can configure these directories to reside in memory file systems (mfs) and ensure that /var contains everything necessary for the system to function correctly.

1. Prepare the Environment

Start with a basic NetBSD installation (I'll skip the installation steps as there are many tutorials available, and it's straightforward).

As a first step, clean up the /var directory. After each reboot, its contents will be extracted into the mfs and occupy RAM.

Disable man.db generation and swap usage:

Edit the following configuration files:

# /etc/rc.conf
makemandb=NO
no_swap=YES
# /etc/daily.conf
run_makemandb=NO

Then, remove the current man.db file:

rm /var/db/man.db

Once this is done, create a compressed archive of the current /var contents to be replicated at every boot:

cd /
tar -cvzf var-image.tar.gz var

2. Create a Custom Startup Script

Next, create a file called /etc/rc.d/mount_mfs_fs with the following content:

#!/bin/sh
#
# mount_mfs_fs: mount memory file system for /var
# by roby, 23 jun 2003 - adapted by Stefano - 01 Sep 2024

# PROVIDE: mount_mfs_fs
# REQUIRE: root

. /etc/rc.subr

name="mount_mfs_fs"
start_cmd="mount_mfs_fs_start"
stop_cmd=":"

mount_mfs_fs_start()
{
    # Check if the /var entry is present and uncommented in /etc/fstab
    if grep -q '^tmpfs[[:space:]]\+/var[[:space:]]\+tmpfs[[:space:]]\+rw,-m1777,-sram%25' /etc/fstab; then
        echo "Mounting memory file system: /var"

        # Mount the file system for /var
        mount /var

        # Extract the contents of the tar file into /var
        tar -xvzpf /var-image.tar.gz -C /

        echo "Mounting memory file systems: Done."
    else
        echo "The tmpfs entry for /var is not present or is commented out in /etc/fstab. Skipping mount and extraction."
    fi
    sleep 5
}

load_rc_config $name
run_rc_command "$1"

Make the script executable:

chmod a+rx /etc/rc.d/mount_mfs_fs

3. Modify Boot Process

Now, modify the /etc/rc.d/mountcritlocal file to require this script to run before its execution:

#!/bin/sh
#
# $NetBSD: mountcritlocal,v 1.17 2022/02/20 14:42:07 alnsn Exp $
#

# PROVIDE: mountcritlocal
# REQUIRE: mount_mfs_fs

$_rc_subr_loaded . /etc/rc.subr

name="mountcritlocal"
start_cmd="mountcritlocal_start"
stop_cmd=":"

mountcritlocal_start()
{
    #       Mount critical file systems that are `local'
    #       (as specified in $critical_filesystems_local)
    #       This usually includes /var.
    #
    mount_critical_filesystems local || return $?
    if checkyesno zfs; then
        mount_critical_filesystems_zfs || return $?
    fi
    return 0
}

load_rc_config $name
load_rc_config_var zfs zfs
run_rc_command "$1"

4. Configure /etc/fstab

Edit the /etc/fstab file to mount /tmp and /var in memory:

tmpfs           /tmp        tmpfs   rw,-m1777,-sram%25
tmpfs           /var        tmpfs   rw,-m1777,-sram%25

5. Test the Configuration

You can now reboot the system and check if everything works correctly. Once logged in, the df command should show something like this:

Filesystem      1K-blocks         Used        Avail %Cap Mounted on
/dev/ld0a        18298254       393938     16989404   2% /
tmpfs              524192         4224       519968   0% /var
kernfs                  1            1            0 100% /kern
ptyfs                   1            1            0 100% /dev/pts
procfs                  4            4            0 100% /proc
tmpfs              524192            4       524188   0% /var/shm
tmpfs              524192            4       524188   0% /tmp

6. Set Root to Read-Only

Currently, the system is still running in read-write mode, but /var and /tmp are in memory disks. To switch the root file system to read-only, edit the /etc/fstab file like this:

/dev/ld0a               /       ffs     ro               1 1

On the next reboot, the system will be in pure read-only mode.

7. Perform Updates

To install packages, update the system, or make any changes, you'll need to temporarily switch back to read-write mode. Comment out /var in mfs, change the root file system back to read-write, and reboot:

mount -uw /
vi /etc/fstab
/dev/ld0a               /       ffs     rw               1 1
[...]
#tmpfs           /var    tmpfs   rw,-m1777,-sram%25
[...]

After making the necessary changes, regenerate the /var tarball as done in step 1.