Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support for mounting additional devices (as /perm, or separately) #236

Open
stapelberg opened this issue Dec 18, 2023 · 3 comments
Open
Labels
enhancement good-for-stream https://www.twitch.tv/stapelberg

Comments

@stapelberg
Copy link
Contributor

There has been some interest in mounting external disks as /perm (permanent data partition) or on arbitrary mountpoints:

I’m not opposed to adding support for mounting disks, but we need to carefully think through which features we want to support and in which way.

For example, we don’t use udev, so we don’t have stable symlinks to the device nodes in /dev. Especially once you have more than one external disk, the order is not necessarily stable on boot, so I think it will be vital to have some sort of stable identifier to use. See also https://michael.stapelberg.ch/posts/2020-01-21-initramfs-from-scratch-golang/#3-block-device-identification

Here’s a strawman proposal for how the configuration could look like:

"MountDevices": [
 {
    "Device": "/dev/sdb",
    "Type": "ext4",
    "Mountpoint": "/perm/archival",
    "Options": "relatime,noexec"
  } 
]

(And aside from Device, one or more ways to specify a stable identifier should be supported.)

@FiloSottile
Copy link

I would also use this, definitely with a stable identifier and probably mounting to an otherwise read-only mount point, so that if mounting fails data is not written anyway somewhere it doesn't belong.

I assume the mounts would happen before applications are started, but what if the filesystem needs checking, which can take a long time? Maybe there should be gokrazy.WaitForFilesystem()?

Alternatively, if there was a way to specify a dependency order between applications, this could just be an application configured with an ExtraFile, which the applications that need disks wait for.

@stapelberg
Copy link
Contributor Author

I would also use this, definitely with a stable identifier and probably mounting to an otherwise read-only mount point, so that if mounting fails data is not written anyway somewhere it doesn't belong.

That’s a good point. We should probably introduce a /mnt directory on the (read-only) root file system that can be used for such mounts.

I assume the mounts would happen before applications are started, but what if the filesystem needs checking, which can take a long time? Maybe there should be gokrazy.WaitForFilesystem()?

Generally, applications have to declare what they are waiting for, gokrazy doesn’t sequence dependencies or delay application startup.

In the early days of gokrazy, this was only possible by modifying the source to call e.g. gokrazy.WaitForClock(), but then we introduced a configuration parameter: https://gokrazy.org/userguide/instance-config/#packagewaitforclock

I like your suggestion of gokrazy.WaitForFilesystem(path), which would wait for a file system to be mounted at path. We could have a corresponding configuration parameter for applications where modifying the source code is inconvenient.


In #235 (comment), @thirdeyenick links to the start of an implementation. I’m not sure if we need the diskfs dependency, as gokrazy already has its own code to deal with partition tables that might be good to extend for this purpose (to avoid any dependencies we don’t absolutely need). But aside from that detail, it looks like a good start :)

@stapelberg stapelberg added the good-for-stream https://www.twitch.tv/stapelberg label Apr 1, 2024
stapelberg added a commit to gokrazy/internal that referenced this issue May 10, 2024
stapelberg added a commit to gokrazy/internal that referenced this issue May 10, 2024
stapelberg added a commit to gokrazy/tools that referenced this issue May 10, 2024
stapelberg added a commit to gokrazy/tools that referenced this issue May 10, 2024
stapelberg added a commit that referenced this issue May 10, 2024
@stapelberg
Copy link
Contributor Author

stapelberg commented May 10, 2024

Alright, I implemented a first version of this feature (see the attached commits).

Here’s what I included in my instance configuration:

    "MountDevices": [
	{
	    "Source": "PARTUUID=c995c848-1d29-4f08-a34d-cd811e84a763",
	    "Type": "ext4",
	    "Target": "/mnt/logs",
	    "Options": ""
	}
    ]

This is what my Raspberry Pi printed on the serial console on boot (note how the first mount attempt failed before the USB memory stick was enumerated, but gokrazy keeps trying):

1970/01/01 01:00:04 mount.go:238: mounting PARTUUID=c995c848-1d29-4f08-a34d-cd811e84a763: PARTUUID=c995c848-1d29-4f08-a34d-cd811e84a763 not found
[    4.797156] scsi 0:0:0:0: Direct-Access     SanDisk  Extreme Pro      0    PQ: 0 ANSI: 6
[    4.807694] sd 0:0:0:0: [sda] 250085376 512-byte logical blocks: (128 GB/119 GiB)
[    4.816030] sd 0:0:0:0: [sda] Write Protect is off
[    4.821572] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[    4.843760]  sda: sda1 sda2 sda3 sda4
[    4.848368] sd 0:0:0:0: [sda] Attached SCSI removable disk
1970/01/01 01:00:05 mount.go:205: mounting /dev/sda4 on /mnt/logs

2024/05/10 19:01:00 gokrazy.go:359: starting shell /tmp/serial-busybox/ash upon input on serial console
/ # ls -l /mnt/logs
total 24
drwxr-xr-x    4 0        0             4096 May  8 18:01 install-logs-2024-05-08.0
drwxr-xr-x    4 0        0             4096 May  8 21:12 install-logs-2024-05-08.1
drwx------    2 0        0            16384 May  8 18:01 lost+found
/ # df -h /mnt/logs
Filesystem                Size      Used Available Use% Mounted on
/dev/sda4               111.2G      5.1M    105.5G   0% /mnt/logs
/ # mount
/dev/root on / type squashfs (ro,relatime,errors=continue)
devtmpfs on /dev type devtmpfs (rw,relatime,size=1892336k,nr_inodes=473084,mode=755)
tmpfs on /tmp type tmpfs (rw,nosuid,nodev,relatime)
devpts on /dev/pts type devpts (rw,relatime,mode=600,ptmxmode=000)
tmpfs on /dev/shm type tmpfs (rw,relatime)
tmpfs on /run type tmpfs (rw,relatime)
proc on /proc type proc (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
/dev/mmcblk1p4 on /perm type ext4 (rw,relatime)
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,relatime)
tmpfs on /etc/cni/net.d type tmpfs (rw,relatime)
/dev/sda4 on /mnt/logs type ext4 (rw,relatime)
/ # cat /etc/gokrazy/mountdevices.json 
[{"Source":"PARTUUID=c995c848-1d29-4f08-a34d-cd811e84a763","Type":"ext4","Target":"/mnt/logs","Options":""}]/ # 
/ # 

Let me know if you have any feedback / if it works for you!

Next steps:

  • adding documentation
  • include extra mounts in the “storage” section in the gokrazy web interface
  • perhaps more supported source devices (currently only PARTUUID= and full device paths).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement good-for-stream https://www.twitch.tv/stapelberg
Projects
None yet
Development

No branches or pull requests

2 participants