File System Management
AppJail uses its own way to use the fstab(5)
file if you don't use mount.fstab
as you can see in Templates
.
The main motivation is to allow mounting devices with strange characters, like a space in a directory. Especially in shared environments when users have no control over how they can name their files and directories. fstab(5)
allows you to mount such devices, but it is not automated, so appjail-fstab(1)
does it for you.
Another reason to get a specific order of the fields used by a jail and a useful description that allows you or another sysadmin to remember them very easily.
appjail-fstab(1)
has some useful commands. For example, you can list the current entries using appjail-fstab(1)
jail
<jail name>
list
.
# appjail fstab jail debian list
NRO ENABLED NAME DEVICE MOUNTPOINT TYPE OPTIONS DUMP PASS
0 1 - devfs /dev devfs rw,ruleset=0 0 0
1 1 - tmpfs /dev/shm tmpfs rw,size=1g,mode=1777 0 0
2 1 - fdescfs /dev/fd fdescfs rw,linrdlnk 0 0
3 1 - linprocfs /proc linprocfs rw 0 0
4 1 - linsysfs /sys linsysfs rw 0 0
It shows us their fields and their meanings are:
NRO
: NRO is an arbitrary number representing the entry and order in whichappjail-fstab(1)
jail
<jail name>
compile
writes to the resultingfstab(5)
. AppJail generates the NRO using the last NRO plus 1 when the-n
parameter is not used inappjail-fstab(1)
jail
<jail name>
set
or0
is used when there is no entry.ENABLED
: Indicates whether this entry will be written to the resultingfstab(5)
file.DEVICE
,MOUNTPOINT
,TYPE
,OPTIONS
,DUMP
,PASS
: Represents the entries in thefstab(5)
file.
We can add more entries using the appjail-fstab(1)
jail
<jail name>
set
command. For example, to run x11 applications we need to mount /tmp/.X11-unix
.
# appjail cmd local debian mkdir -p tmp/.X11-unix
# appjail fstab jail debian set -d /tmp/.X11-unix -m /tmp/.X11-unix
# appjail fstab jail debian list
NRO ENABLED NAME DEVICE MOUNTPOINT TYPE OPTIONS DUMP PASS
0 1 - devfs /dev devfs rw,ruleset=0 0 0
1 1 - tmpfs /dev/shm tmpfs rw,size=1g,mode=1777 0 0
2 1 - fdescfs /dev/fd fdescfs rw,linrdlnk 0 0
3 1 - linprocfs /proc linprocfs rw 0 0
4 1 - linsysfs /sys linsysfs rw 0 0
5 1 - /tmp/.X11-unix /tmp/.X11-unix nullfs rw 0 0
If you want to change a field of an existing entry, just specify the NRO and the corresponding parameter. -d
and -m
are not required when defined. For example, to change the mount(8)
options in NRO 0
:
appjail fstab jail debian set -n 0 -o rw,ruleset=11
To mount those device we can either restart the jail or use appjail-fstab(1)
jail
<jail name>
compile
and appjail-fstab(1)
jail
<jail name>
mount
-a
.
appjail restart debian
# or
appjail fstab jail debian compile
appjail fstab jail debian mount -a
appjail fstab
can also see the mounted devices for the given jail. For example, I want to see the mounted devices for my jail named movies
:
# appjail fstab jail movies set -d /dev/da0s1 -m /mnt/07181 -t msdosfs
# appjail fstab jail movies list
NRO ENABLED NAME DEVICE MOUNTPOINT TYPE OPTIONS DUMP PASS
0 1 - /dev/da0s1 /mnt/07181 msdosfs rw 0 0
# appjail fstab jail movies mounted
/usr/local/appjail/releases/amd64/13.1-RELEASE/default/release -> /usr/local/appjail/jails/movies/jail/.appjail
/dev/da0s1 -> /usr/local/appjail/jails/movies/jail/mnt/07181
devfs -> /usr/local/appjail/jails/movies/jail/dev
That device is not very descriptive. I want to give it a name that represents its contents.
# appjail fstab jail movies set -n 0 -N 'The Godfather Trilogy'
# appjail fstab jail movies list -n 0
NRO ENABLED NAME DEVICE MOUNTPOINT TYPE OPTIONS DUMP PASS
0 1 The Godfather Trilogy /dev/da0s1 /mnt/07181 msdosfs rw 0 0
Since it is a USB, the jail cannot be gracefully stopped or it will not boot because the device is gone. To solve this I will run the following commands:
# appjail fstab jail movies umount mnt/07181
# appjail fstab jail movies set -n 0 -E
# appjail fstab jail movies compile
# appjail fstab jail movies list -n 0
NRO ENABLED NAME DEVICE MOUNTPOINT TYPE OPTIONS DUMP PASS
0 0 The Godfather Trilogy /dev/da0s1 /mnt/07181 msdosfs rw 0 0
The jail can now be stopped without any problems.
appjail fstab
has the fstab
option to mount devices in the jail. Let's create a jail to compile ports:
# appjail quick jcomp fstab="/usr/ports /usr/ports" virtualnet=":<random> default" nat start
...
# appjail fstab jail jcomp list
NRO ENABLED NAME DEVICE MOUNTPOINT TYPE OPTIONS DUMP PASS
0 1 - /usr/ports /usr/ports nullfs rw 0 0
PseudoFS
An interesting and useful feature of appjail-fstab(1)
is when you set type
to <pseudofs>
. It is actually a pseudo-filesystem as the name implies, in other words, this does not exist on your system.
The purpose of this handy feature is to allow you to easily separate the data that should persist when removing the jail. For example, imagine you import an image and it comes with /usr/local/www/apache24/data/wp-content
indicating a WordPress installation. Such files and subdirectories will be removed with the jail data and other things it contains. For this data to persist, you must move them to the host and mount them using mount_nullfs(8)
. You will probably need to stop the jail before moving the files as some applications may not be able to run correctly.
This pseudo-filesystem does this. It moves the data from the jail to the host when you run appjail-fstab(1)
jail
<jail name>
compile
and mounts that file or directory using mount_nullfs(8)
, so that when you remove the jail, your data is safe.
As a side note, PASS
and DUMP
will be ignored.
Using <pseudofs>
is no different than using another file system.
# mkdir -p /tmp/var_tmp
# ls /tmp/var_tmp
# appjail fstab jail jtest set -d /tmp/var_tmp -m /var/tmp -t '<pseudofs>'
# appjail fstab jail jtest
NRO ENABLED NAME DEVICE MOUNTPOINT TYPE OPTIONS DUMP PASS
0 1 - /tmp/var_tmp /var/tmp <pseudofs> rw 0 0
# appjail restart jtest
...
[00:00:10] [ debug ] [jtest] Moving /usr/local/appjail/jails/jtest/jail//var/tmp/vi.recover -> /tmp/var_tmp/vi.recover ...
...
# appjail fstab jail jtest mounted
/usr/local/appjail/releases/amd64/13.2-RELEASE/default/release -> /usr/local/appjail/jails/jtest/jail/.appjail
/tmp/var_tmp -> /usr/local/appjail/jails/jtest/jail/var/tmp
devfs -> /usr/local/appjail/jails/jtest/jail/dev
# ls /tmp/var_tmp
vi.recover/
It is preferable and advisable to reboot, since as mentioned above, an application may have problems when moving files and directories here and there while running.
VolumeFS
VolumeFS is another pseudo-file system supported by AppJail. Again, this implies that it does not exist on your system. This pseudo-filesystem does the same thing as nullfs
and <pseudofs>
plus abstracts more things specifically related to owner, group, permissions and mount point.
To get a better idea of what this pseudo file system solves, let's create a new jail with some volumes.
Makejail:
OPTION start
OPTION overwrite=force
OPTION volume=db perm:750 owner:10001
OPTION volume=logs perm:750 owner:10001
CMD pw useradd -n app -d /app -u 10001
CMD mkdir -p /app
CMD chown app:app /app
# appjail makejail -j jtest
...
[00:00:14] [ debug ] [jtest] Configuring volumes ...
[00:00:14] [ debug ] [jtest] volume (db): "group:" "mountpoint:" "owner:10001" "perm:" "type:"
[00:00:14] [ debug ] [jtest] volume (logs): "group:" "mountpoint:" "owner:10001" "perm:" "type:"
...
# appjail volume list jtest
NAME MOUNTPOINT TYPE UID GID PERM
db /volumes/db <pseudofs> 10001 - 750
logs /volumes/logs <pseudofs> 10001 - 750
By default, when the mount point is not specified, {VOLUMESDIR}/{volume_name}
is used. <pseudofs>
is used by default, but you can use nullfs
, however only these values are allowed. UID
, GID
and PERM
are optional.
As you can see above, two volumes were created with some parameters. AppJail does nothing at this point until you create a new fstab entry for the specified jail.
# mkdir -p /tmp/volumes/db
# mkdir -p /tmp/volumes/logs
# appjail fstab jail jtest set -d /tmp/db -m db -t '<volumefs>'
# appjail fstab jail jtest set -d /tmp/logs -m logs -t '<volumefs>'
# appjail fstab jail jtest
NRO ENABLED NAME DEVICE MOUNTPOINT TYPE OPTIONS DUMP PASS
0 1 - /tmp/db db <volumefs> rw 0 0
1 1 - /tmp/logs logs <volumefs> rw 0 0
At this point, you can restart the jail.
appjail restart jail
Our volumes should be mounted with the parameters specified above.
# appjail fstab jail jtest mounted
/usr/local/appjail/releases/amd64/14.0-RELEASE/default/release -> /usr/local/appjail/jails/jtest/jail/.appjail
/tmp/db -> /usr/local/appjail/jails/jtest/jail/volumes/db
/tmp/logs -> /usr/local/appjail/jails/jtest/jail/volumes/logs
devfs -> /usr/local/appjail/jails/jtest/jail/dev
# appjail cmd jexec jtest sh -c 'ls -ld /volumes/*'
drwxr-x--- 2 app wheel 512 Dec 13 21:30 /volumes/db
drwxr-x--- 2 app wheel 512 Dec 13 22:57 /volumes/logs
Volume parameters persist in an image. This is very useful when a developer creates a Makejail that deploys an application that requires specified directories with specified parameters (as described above). Since the developer knows his application better than the user who just wants to use the application, it is preferable to use what he specified. As you can see, the volumes are just a suggestion for the end user, they are not mandatory.
# appjail makejail -j jtest
...
# appjail stop jtest
...
# appjail image export jtest
...
# tar tf /usr/local/appjail/cache/images/jtest/latest-amd64-image.appjail './conf/volumes/'
./conf/volumes/
./conf/volumes/db/
./conf/volumes/logs/
./conf/volumes/logs/mountpoint
./conf/volumes/logs/uid
./conf/volumes/logs/perm
./conf/volumes/logs/type
./conf/volumes/db/mountpoint
./conf/volumes/db/uid
./conf/volumes/db/perm
./conf/volumes/db/type
# appjail image jail -i jtest jother
...
# appjail volume list jother
NAME MOUNTPOINT TYPE UID GID PERM
db /volumes/db <pseudofs> 10001 - 750
logs /volumes/logs <pseudofs> 10001 - 750
Notes
appjail-fstab(1)
jail
<jail name>
compile
will do some things for you. If the file system type isnullfs
it will create the file or directory inside the jail specified byMOUNTPOINT
depending on whetherDEVICE
is a file or directory, or an error is displayed when the file's type is not a file or directory. If the file system type is<pseudofs>
it will perform the same things asnullfs
plus other things described inPseudoFS
. If none of these file system types match andMOUNTPOINT
does not exist inside the jail, a directory pointing to that path will be created.- You can reverse the mount order of a device by using the
:reverse
suffix, although it is only valid fornullfs
and<pseudofs>
. This implies that themountpoint
is mounted ondevice
.
See also: