Citadel documentation system

This commit is contained in:
Bruce Leidl 2020-12-07 17:24:22 -05:00
parent 5b8c330cb7
commit 7faf0ce39e
29 changed files with 2054 additions and 248 deletions

1
docs/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
pages/

25
docs/Makefile Normal file
View File

@ -0,0 +1,25 @@
DUCKFILES= $(notdir $(wildcard duck/*.duck))
PAGES= $(addprefix pages/, $(DUCKFILES:.duck=.page))
OUTDIR= pages
RECIPE_PAGES_DIR= ../meta-citadel/recipes-citadel/citadel-documentation/files/pages
.PHONY: directories clean
all: directories $(PAGES)
install: directories $(PAGES)
rm -f ${RECIPE_PAGES_DIR}/*.page
cp $(PAGES) ${RECIPE_PAGES_DIR}
clean:
rm $(PAGES)
directories: ${OUTDIR}
${OUTDIR}:
mkdir -p ${OUTDIR}
pages/%.page: duck/%.duck
ducktype -o $@ $<

26
docs/README.md Normal file
View File

@ -0,0 +1,26 @@
## Writing documentation
http://projectmallard.org/ducktype/1.0/index.html
## Building documentation
Building the documentation requires the 'ducktype' utility. The makefile will use this
command to generate a directory of .page files from the .duck files in the /duck directory.
$ sudo apt install ducktype
$ make
## Reading documentation
After generating the documentation it can be previewed by running yelp on the /pages directory:
$ yelp pages
## Installing documentation
After making changes to the documentation, run 'make install' to update the set
of .page files in the citadel-documentation recipe.
$ make install

84
docs/duck/boot.duck Normal file
View File

@ -0,0 +1,84 @@
= Booting Citadel
[topic]
@link[guide >index#internals]
== Disk Layout
When Citadel is installed two disk partitions are created on the target disk.
[screen]
sda 8:0 0 477G 0 disk
├─sda1 8:1 0 511M 0 part
└─sda2 8:2 0 476.5G 0 part
The first partition is an EFI boot partition and the second partition is LUKS encrypted
and contains multiple LVM volumes when decrypted.
[screen]
[[[
/dev/sda1 /dev/sda2
[EFI ESP Boot partition] [ LUKS encrypted partition filling remainder of disk ]
. .
. .
. | .
. | .
. V .
. .
[ rootfsA ] [ rootfsB ] [ citadel-storage ]
]]]
There are three logical volumes. Two root filesystem partitions so that one partition
can be updated while the other one is in use, and the remaining space is contained
in a volume called 'storage'.
[screen sh]
# lvs
LV VG Attr LSize
rootfsA citadel -wi-a----- 2.00g
rootfsB citadel -wi-ao---- 2.00g
storage citadel -wi-ao---- 472.43g
=== Bootloader
==== LUKS
The kernel initramfs has an /etc/crypttab file which guides the discovery of the LUKS partition.
The UUID of the LUKS partition is hardcoded to the value listed below. If citadel is installed
on more than one device on the system, the intended LUKS partition may not be chosen correctly.
This problem can be addressed by changing the UUID of other citadel LUKS partitions and passing
the UUID on kernel commandline to override /etc/crypttab. See systemd-cryptsetup-generator(8).
[screen sh]
# cat /etc/crypttab
luks UUID=683a17fc-4457-42cc-a946-cde67195a101 - discard
==== Mounting rootfs
The initramfs boot stage is orchestrated by various systemd unit files which can be found
in the citadel source tree at:
[screen]
citadel/meta-citadel/recipes-initrd/citadel-initramfs
The same kernel and initramfs is used for the installer image. One task of these unit files
is to set up a live mode boot when a certain kernel command line option is set. For a regular
boot, a pair of unit files will attempt to mount the root filesystem partition when it becomes
available:
[screen]
citadel-rootfs-mount.path
citadel-rootfs-mount.service
The .path unit triggers every time /dev/mapper changes and the corresponding .service unit is
activated only when all of the LVM volumes inside
[screen]
ConditionPathExists=/dev/mapper/citadel-rootfsA
ConditionPathExists=/dev/mapper/citadel-rootfsB
ConditionPathExists=/dev/mapper/citadel-storage

61
docs/duck/citadel.duck Normal file
View File

@ -0,0 +1,61 @@
= Subgraph Citadel
[topic]
@link[guide >index]
@desc Introduction to Subgraph Citadel
== What is Citadel?
Citadel is the core operating system of the new version of Subgraph OS.
Citadel includes the GNOME desktop session and a few basic system services and
nothing else. It is built and distributed as a single static disk image
rather than as a collection of software packages like a traditional Linux
distribution such as Ubuntu or Fedora. Citadel disk images are built entirely
from the source code of the individual software components. This gives us
complete control over what is included and how each component is configured.
[note .advanced]
Citadel is a modern desktop operating system based on the GNOME desktop, but if you
prefer we also include an tiling window manager called Sway as an alternative.
Since the Citadel root filesystem is immutable it is not possible to install
applications such as a web browser or text editor directly into Citadel.
Instead applications are run in a separate isolated environment called a Realm.
When Citadel is first installed a single primary Realm is created and while running
a single realm the system resembles and behaves similar to any other desktop Linux
system. The separation between Citadel and the realm in which user applications are
launched is mostly transparent to the user. However, a user may create as many new
realms as they like and each new realm behaves like a freshly installed Debian Linux
environment where the user may install packages and store files.
Realms are implemented in Subgraph OS as either containers or as virtual machines
running in a custom KVM hypervisor. Both approaches have advantages so the user is
free to choose either option for each realm they create.
[note .advanced]
Hypervisor isolation is stronger and more secure, but container isolation uses
less system resources and makes it possible to access hardware devices and other
system features directly. A Citadel user can decide which configuration makes
more sense for each Realm they create.
=== Stateless Foundation
In the architecture of Citadel the building blocks of the system are
immutable filesystem images rather than packages. These images are mounted
read-only and this property is enforced with a Linux kernel feature (dm-verity)
which efficiently guarantees each block loaded from disk has a valid
cryptographic checksum. This means that Citadel always loads exactly the
operating system software prepared by Subgraph and rebooting the system will
always brings the computer into a known consistent state.
When Citadel is updated an entirely new image is loaded rather than applying
a set of changes on top of an existing filesystem. By atomically updating the
entire system from one version to the next there is only ever a single software
configuration to consider and the system can never end up in an inconsistent state.
System upgrades cannot break your computer in mysterious ways and even if an
upgrade fails to boot for some reason, the system simply reverts to the
previously working version.

26
docs/duck/developer.duck Normal file
View File

@ -0,0 +1,26 @@
= Developer Guide
[topic]
@link[guide >index#internals]
== Make Root Filesystem Writable
Sometimes it can be useful to make changes directly to the citadel root filesystem to
experiment with changes or to debug a problem.
First $code(citadel.noverity) must be added to the kernel commandline. After booting with
this command line option verify that dm-verity has been disabled with the $code(dmsetup)
command.
[screen]
# dmsetup status rootfs
0 4194304 linear
If the output displays $code(verity) instead of $code(linear) then dm-verity is enabled
and the disk cannot be safely written to.
Next remount the root filesystem with read-write flag.
[screen]
# mount -oremount,rw,noatime /
== Debugging GNOME startup

198
docs/duck/disk-layout.duck Normal file
View File

@ -0,0 +1,198 @@
= Disk Layout
[topic]
@link[guide >index#internals]
@desc A Hands-on guide the Citadel Disk and Filesystem Layout
== Partitions
During installation, two partitions are created on the disk chosen as
the target of the install.
For example, if the installation disk is $code(/dev/sda):
[terms]
- $code(/dev/sda1)
* 512MB EFI System Partition
- $code(/dev/sda2)
* Remainder of the disk
The partition layout of a running system can be viewed by running the $code(lsblk) command.
[screen]
citadel:~ # lsblk /dev/sda
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 477G 0 disk
├─sda1 8:1 0 511M 0 part
└─sda2 8:2 0 476.5G 0 part
└─luks 252:0 0 476.4G 0 crypt
├─citadel-rootfsA 252:1 0 2G 0 lvm
│ └─rootfs 252:4 0 354M 1 crypt /
├─citadel-rootfsB 252:2 0 2G 0 lvm
└─citadel-storage 252:3 0 472.4G 0 lvm /storage
Several further block devices are created during boot when the main disk partition
is decrypted.
[screen]
sda
├─sda1 (a) /boot partition
└─sda2 (b) LUKS encrypted partition
└─citadel (c) LVM volume group
├─citadel-rootfsA (d1) rootfs partition A (Read Only)
│ └─rootfs (e) The dm-verity device created for rootfsA
├─citadel-rootfsB (d2) rootfs partition B (Read Only)
└─citadel-storage (f) mounted as /storage (Read/Write)
[terms]
- $code((a) /boot partition)
* EFI boot partition
- $code((b) LUKS encrypted partition)
* Remainder of disk is an encrypted volume
- $code((c) LVM volume group)
* Main partition contains several LVM volumes
- $code((d) citadel-rootfs(A/B))
* Two root partitions so one can be updated while other is in use.
- $code((e) /dev/mapper/rootfs)
* verity mapper device for mounted root partion
- $code((f) /dev/mapper/citadel-storage)
* The writable filesystem
== Citadel Filesystem Layout
[code]
/
├─ /run/citadel/images/
│ │
│ ├─ modules.mountpoint/ (modules image mounted here)
│ └─ extra.mountpoint/ (extra image mounted here)
└─ /storage
├─ resources/dev (resource images for channel 'dev')
│ │
│ ├─base-realmfs.img
│ └─main-realmfs.img
├─ /realms (/realms is a bind mount of /storage/realms)
│ ├─skel/
│ └─config
├─ /realms/realmfs-images
│ │
│ ├─citadel-kernel-5.7-dev-001.img
│ └─citadel-extra-dev-001.img
└─ /realms/realm-main
├─ home
└─ config
== Resource Image Mounts
Resource images are mounted into the system by creating loop devices. These devices can be
viewed by running the 'losetup' command inside Citadel.
[screen]
citadel:~ # losetup -ONAME,OFFSET,RO,BACK-FILE
NAME OFFSET RO BACK-FILE
/dev/loop1 4096 1 /storage/resources/dev/citadel-extra-dev-001.img
/dev/loop2 4096 1 /storage/realms/realmfs-images/main-realmfs.img
/dev/loop0 4096 1 /storage/resources/dev/citadel-kernel-5.0.6-dev-000.img
Resource image files are protected against accidental changes or malicious tampering by
using dm-verity so that the kernel verifies a cryptographic checksum of each block loaded
from the image.
You can view the verity device mapper node associated with each loop device with
the $code(lsblk) command.
[screen]
citadel:~ # lsblk /dev/loop0 /dev/loop1 /dev/loop4
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 116.9M 1 loop
└─verity-kernel 252:5 0 116M 1 crypt /run/citadel/images/kernel.mountpoint
loop1 7:1 0 938.9M 1 loop
└─verity-extra 252:6 0 931.5M 1 crypt /run/citadel/images/extra.mountpoint
loop2 7:2 0 4G 1 loop
└─verity-realmfs-main-11922f31 252:9 0 4G 1 crypt /run/citadel/realmfs/realmfs-main-11922f31.mountpoint
Parameters of each dm-verity instance can be viewed with the veritysetup command.
[screen]
citadel:~ # veritysetup status verity-kernel
/dev/mapper/verity-kernel is active and is in use.
type: VERITY
status: verified
hash type: 1
data block: 4096
hash block: 4096
hash name: sha256
salt: fa430cb7887de60dca6fd1974868036ea39cf5017eb55f02e3a76f82a12a0431
data device: /dev/loop0
data loop: /storage/resources/dev/citadel-kernel-5.0.6-dev-000.img
size: 237536 sectors
mode: readonly
hash device: /dev/loop0
hash loop: /storage/resources/dev/citadel-kernel-5.0.6-dev-000.img
hash offset: 237544 sectors
When a resource image file is mounted, a file in the root directory called 'manifest' lists
bind mounts to perform to integrate the image into the Citadel root filesystem.
Each line of this file is a directory to bind mount from the mounted image to the root
filesystem. If a directory should be mounted to a location which is different than
the source directory the source and target directories are both listed on a single
line and separated by the ':' character. In the 'extra' image below, the directory
/usr/share from the resource image is mounted to /opt/share on the Citadel filesystem.
[screen]
citadel:~ # cat /run/citadel/images/kernel.mountpoint/manifest
/usr/lib/modules
citadel:~ # cat /run/citadel/images/extra.mountpoint/manifest
/usr/lib/firmware
/usr/share:/opt/share
The citadel-image utility can be used to view the metainfo variables stored in the header
section of a resource image file.
[screen]
citadel:~ # citadel-image metainfo /storage/resources/dev/citadel-extra-dev-001.img
image-type = "extra"
channel = "dev"
version = 1
timestamp = "20190331172025"
nblocks = 195924
shasum = "04e6f58afa6f608aff2d6cbb47cbe704f8ab0995f4dfe8e1c03655dc9bb6635a"
verity-salt = "7bf3eec3c51ffd2e82329a9fc6fe42915743874d7c5af43589e589c037ae81e5"
verity-root = "b94eb3431c4fb95e5b9bd62b4505d089414ae660d75eee0fce54b8483d3f9571"
citadel:~ # citadel-image metainfo /storage/resources/dev/citadel-kernel-5.0.6-dev-000.img
image-type = "kernel"
kernel-version = "5.0.6"
kernel-id = "36b7a960dcd51d1649f83a7361f9eb5c2af5741ce6cc53689b411347aa1298b6"
channel = "dev"
version = 1
timestamp = "20190407002748"
nblocks = 29692
shasum = "c988bd7d468c409eb6cd3af8fa9e17b0a75a72d6ad765ad1749d15628a9096be"
verity-salt = "fa430cb7887de60dca6fd1974868036ea39cf5017eb55f02e3a76f82a12a0431"
verity-root = "f4c4fbaebb59d348bd44cfb1cdef54a813728aabc5acc439c2e739b63c1b8370"
RealmFS images also have a resource image header with a slightly different set of
metainfo variables.
[screen]
citadel:~ # citadel-image metainfo /storage/realms/realmfs-images/main-realmfs.img
image-type = "realmfs"
realmfs-name = "main"
nblocks = 1048575
channel = "realmfs-user"
verity-salt = "ad254e6dd385c0392ed8a6a41b849cfd4ef98ec3643e186feb011d5aa4f1d194"
verity-root = "11922f311b5a9141d65b7ef82e1c9159d75e413d1b420a7e3302ec8ec0ad8593"

11
docs/duck/index.duck Normal file
View File

@ -0,0 +1,11 @@
= Citadel Help
[guide]
== User Guide
[#user .2column]
== Citadel Internals
[#internals .2column]

View File

@ -0,0 +1,13 @@
= Kernel Command Line Options
[topic]
@link[guide >index#internals]
* citadel.noverity
* citadel.nosignatures
* citadel.install
* citadel.overlay
* citadel.channel
* citadel.verbose
* citadel.debug
* citadel.sway

View File

@ -0,0 +1,88 @@
= Configuring Realms
[topic]
@link[guide >index#user]
@desc Realm configuration file reference
Realms are usually configured with the tools for managing realms, but the configuration
is stored in a TOML file in the realm directory and can also be edited by hand.
== Options
[terms]
- $code(use-wayland)
* If 'true' access to Wayland display will be permitted in realm by
adding wayland socket /run/user/1000/wayland-0
- $code(use-x11)
* If 'true' access to X11 server will be added to realm by bind mounting directory
/tmp/.X11-unix
- $code(use-sound)
* If 'true' allows the use of sound inside realm. The following items will
be added to realm:
* /dev/snd
* /dev/shm
* /run/user/1000/pulse
- $code(use-kvm)
* If enabled, /dev/kvm will be added to the realm.
This option is only available for nspawn realms.
- $code(use-shared-dir)
* If enabled the directory /realms/Shared will be bind mounted into the home directory of the realm.
This directory is shared between all running realms that have this option enabled as a
convenient way to move files between realms.
- $code(use-ephemeral-home)
* If 'true' the home directory of this realm will be set up in ephemeral mode.
The ephemeral home directory is set up with the following steps
[steps]
* Home directory is mounted as tmpfs
* Any files in /realms/skel are copied into home directory
* Any files in /realms/realm-${name}/skel are copied into home directory
* Any directories listed in $code(ephemeral-persistent-dirs) are bind mounted
from /realms/realm-${name}/home into ephemeral home directory.
- $code(ephemeral-persistent-dirs) default: ["Documents"]
* A list of subdirectories of /realms/realm-${name}/home to bind mount into realm
home directory when $code(ephemeral-home) is enabled.
- $code(use-network)
* network
- $code(network-zone) default: "clear"
* network zone
- $code(use-gpu)
* Enables hardware graphics acceleration in relam.
if 'true' render node device /dev/dri/renderD128 will be added to realm.
- $code(use-gpu-card0)
* If 'true' and $code(use-gpu) is also enabled, privileged device /dev/dri/card0
will be added to realm.
- $code(realmfs) default: "base"
* name of realmfs image
- $code(overlay) default: "storage"
* type of overlay to use
- $code(terminal-scheme)
* terminal color scheme
- $code(extra-bindmounts)
* bind mounts
- $code(extra-bindmounts-ro)
* read-only bind mounts
- $code(system-realm) default: false
* system realm
- $code(autostart) default: false
* autostart realm

139
docs/duck/realmfs.duck Normal file
View File

@ -0,0 +1,139 @@
= RealmFS Images
[topic]
@link[guide >index#user]
@desc Realm root filesystem images
A RealmFS image contains a root filesystem for one or more realm instances.
Similar to resource images, RealmFS images are signed and mounted with dm-verity
to prevent tampering with the data on the root filesystem such as the
installation of malware or backdoors. The keys used to sign RealmFS images are
controlled by the user which makes it possible to upgrade software and install
new packages on the image.
RealmFS images are always mounted as read-only and this property is enforced
with dm-verity. Since RealmFS images are immutable a single image can be shared
between multiple running realm instances. By default, when a realm is launched a
temporary overlay is added to the root filesystem so that changes can be
performed that will last only until the realm is stopped or restarted. This
allows experimenting with the system configuration or installing new software
temporarily. The root filesystem can then be reverted to the original state by
simply restarting the realm.
== Updates
Since the root filesystem of realms are stored on read-only disk images,
packages cannot be permanently installed or upgraded in the usual way. Changes
to the root filesystem will succeed inside a realm, but these changes will be
lost as soon as the realm is stopped or restarted.
To make persistent changes to a RealmFS image, the image is first copied, then
changes are applied to the copy. After applying changes a new dm-verity hash
tree is generated for the image and the RealmFS image header is updated and
signed.
[note .advanced]
The process of generating a signature and a dm-verity hash tree for a RealmFS image
after applying some changes such as updating packages is called $em[.strong](Sealing)
the image.
=== Apt-Cacher NG Realm
Upon booting a system utility realm is started which runs an Apt-Cacher NG
instance. Each realm is configured to use this realm as a proxy for package
installation.
[code]
/etc/apt/apt.conf.d/000apt-cacher-ng-proxy
Acquire::http::Proxy "http://172.17.0.213:3142/";
The apt source lines use the special Apt-Cacher NG syntax.
[code]
/etc/apt/sources.list
deb http://HTTPS///deb.debian.org/debian buster main contrib non-free
Using a package cache avoids downloading and storing packages multiple times
when updating multiple RealmFS images. It also makes it possible to download and
cache packages while connected to a network before booting the system into a
safe mode without enabling the network to perform upgrades of realm packages.
=== Updates (Container method)
First the RealmFS image is copied to a temporary file. On a filesystem such as
btrfs, the image file will be cloned as a reflink rather than copying the file.
The copy of the RealmFS will then be mounted as writable so that changes can be
made. A systemd-nspawn container is launched and a root shell opened so that the
user can update packages, install new software, or perform any other
modifications to the root filesystem.
Once the shell is exited a prompt asks the user if they would like to save the
current changes or discard them. If the user chooses to save the changes, the
copied image is then sealed by generating a dm-verity hash tree and the header
of the image is signed with the user RealmFS sealing key.
=== Updates with pH Hypervisor
When a realm is launched with pH, the overlay is managed by the emulated disk
device of the hypervisor which tracks changes to blocks of the disk and stores
the changed blocks in memory. Since the hypervisor is tracking all of the
changes to the disk, it can also transparently apply the changes and generate a
new sealed RealmFS image and then discard the changed blocks and start directly
using the new image.
This process is initiated by the user when they decide they would like to commit
any changes they have made to the root filesystem in the running realm
permanently to the underlying RealmFS image.
[steps]
* The user makes changes to the root filesystem of the realm and pH tracks the blocks that have changed.
* A user request is made to pH to apply the changes to the RealmFS image.
* pH opens a prompt on the desktop to ask the user to confirm that they really did make this request.
* A copy (or reflink) of the current RealmFS is made, and pH applies the changed blocks to this copy.
* The copy is then sealed with the RealmFS key of the user.
* Now pH can quietly swap in the new version of the RealmFS image and discard all of the tracked block changes.
== Signing RealmFS Images
A secret key for signing RealmFS images is generated during installation and
stored on disk in an encrypted file called the User Keyring. During boot
when the user enters a passphrase to decrypt the disk, this passphrase is also
used to decrypt the keyring file and the public and secret key pair is
loaded into the kernel key storage.
The risk exists that an attacker who is able to compromise the kernel may
recover this secret key. This would allow the attacker to modify sealed RealmFS
images and install backdoors or other malware into realm root filesystems. Even
without obtaining the signing key an attacker who has compromised Citadel could
wait for the user to perform an update and make malicious changes at the same
time which the user will then sign.
For these reasons, it is also possible to configure the system so that only
the public key is retained in the kernel upon boot and the user must boot
into a special mode so that the private key is available to perform updates.
=== Safe Mode
If upgrades are performed in normal operating mode, an attacker who has
compromised citadel can persistently backdoor the upgraded realmfs images.
Safe mode is a way to boot citadel without starting any realms or enabling the
network device. Since the integrity of the Citadel root filesystem is enforced
by dm-verity and no realms are running, even if the system had become compromised
at some point in the past it is assumed to now be in a safe state for performing
updates and signing them with the user sealing keys.
Since the network is not available in safe mode, the packages to be installed or
upgraded must be stored somewhere. By either performing the packge updates with
the $code(--download-only) flag or installing them to the temporary overlay of a realm
the user will cause them to be stored on the Apt-Cache NG service realm so that
they are available for install in safe mode.
== Base RealmFS image
Citadel ships with a RealmFS image called $code(base-realmfs.img). There is nothing
special about this image other than that it is initially signed by Subgraph until
the user modifies or updates it. During installation, a copy of this RealmFS is
created with the name $code(main-realmfs.img) and sealed with the newly generated
user keys.

56
docs/duck/realms.duck Normal file
View File

@ -0,0 +1,56 @@
= Citadel Realms
[topic]
@link[guide >index#user]
Citadel contains only the base operating system and the GNOME desktop, it does not
include any applications. To be able to install and run applications Citadel can
create spaces which are called Realms.
A Realm is a container similar to a Docker or LXC container in which any Linux
distribution could be installed. We use a Debian based image but it would not be
difficult to create an image for another Linux distribution.
The realm containers are launched with systemd-nspawn but this is a detail of
how they are implemented and not something it is necessary to learn about in
order to use them.
== The $em(current) realm
Multiple realms may be launched at once but the GNOME Desktop is only associated with
one of the running realms. This realm is called the `current` realm.
When displaying applications available to launch from the desktop, GNOME will only
be aware of applications that are installed in the realm which is set as `current`
and any application launched from the desktop will run inside this current realm.
Setting another realm as current does not affect any applications that are already running.
Changing the current realm only means that any further applications which are launched
will now run in the newly chosen realm.
== Realm directory layout
The realms base directory is stored on the storage partition at `/storage/realms` and is bind mounted to `/realms` on the root filesystem for convenience.
[screen]
/realms
config
/Shared
/skel
/default.realm -> realm-main
/realm-main
/realm-project
/realm-testing
=== /realms/config
This is the global realm configuration file. Options set in this file apply to every realm
unless the same option has been overridden with a different value in the config file for
a realm.
=== /realms/Shared
This directory is bind mounted to `/home/user/Shared` of each running realm that has
the option `use-shared-dir` enabled. It's a convenient way to move files between
different realms and between citadel and realms.

View File

@ -0,0 +1,242 @@
= Citadel Resource Images
[topic]
@link[guide >index#internals]
Resource images are disk image files that are mounted read-only to create
the citadel filesystem. The first block (4096 bytes) of the image file
contains a header and immediately following the header is the raw disk
image contents.
The header contains information about the image including parameters for
configuring dm-verity to enforce the immutability of the image. The header
also contains a public key signature over the image information so that
the authenticity of the header information can be verified.
The root filesystem of citadel is also distributed as a resource image, and
this image will be installed to a disk partition for normal operation.
Resource images other than the root filesystem are mounted by creating loop
devices on the image file. Prior to mounting the image dm-verity is configured
on the loop device or the rootfs partition.
== Resource Image Types
Currently the following image types are defined for use in Citadel:
=== 1) Base Root Filesystem ("rootfs")
The base rootfs image is the only image type which is installed to a
partition. It is mounted as the root of the Citadel filesystem. When an
image is installed on a partition the 4906 byte header block is stored in
the last block (8 sectors) of the partition.
Citadel uses two partitions (A & B) for the root filesystem. This allows
updating one partition while the other one is being used. Then the system
can be rebooted into the updated rootfs partition. If the system fails to
boot after updating it will be reverted to use the working partition.
=== 2) Kernel Image ("kernel")
The kernel modules for the running kernel are stored in a resource image
so that the root filesystem is independent from the running kernel.
During boot, this image is mounted and the kernel modules and a bind mount
is created over /usr/lib/modules on the Citadel root filesystem.
=== 3) Extra Resource Image ("extra")
This image type contains additional directories of files which are mounted
during boot on the Citadel root filesystem. It contains files such as
firmware files and desktop icons which occupy substantial space but do not
need to be updated frequently.
By placing these files into a separate image the size of the root filesystem
image is reduced. This makes the more frequently updated rootfs image
smaller.
=== 4) Realm Filesystem Image ("realmfs")
This type of image contains the entire root filesystem for running a realm
container or VM. Unlike the other types of resource images, these images can
be modified and then signed with keys controlled by the user. This allows
updates and installation of software while still preserving the read-only
property.
=== Image Layout
Each resource image file reserves an initial 4096 byte block where a header is
stored. This is the maximum length of the header, which is generally much
smaller than this size.
Following the header is a raw disk filesystem image which may optionally be
compressed with xz compression algorithm. The disk image filesystem is ext4,
but this is an implementation detail which may change in the future. A header
flag (FLAG_DATA_COMPRESSED) indicates if an image is compressed and if so the
image must be decompressed before being used. Image updates are distributed in
compressed form and are decompressed once during installation.
When dm-verity is used a hash tree must be generated for the image. When an
image is installed it is first decompressed and then the dm-verity hash data
is generated. This hash data is stored in the image file immediately following
the image data and the flag FLAG_HASH_TREE is set to indicate this data is
present.
Image file:
[code]
[[[
[ Header ][ Ext4 Disk Image ][ dm-verity hash data ]
]]]
Partition:
[code]
[[[
[ Ext4 Disk Image ][ dm-verity hash data ][ unused space ][ Header ]
]]]
== Image Header
The image header contains the following fields.
[table]
[tr]
- Field
- Size
- Content
[tr]
* MAGIC
* 4 bytes
* ('S', 'G', 'O', 'S')
[tr]
* status
* 1 byte
* Used by images installed to partition
[tr]
* flags
* 1 byte
* Various flag values
[tr]
* metainfo-len
* 2 bytes
* 16 bit big-endian length
[tr]
* metainfo
* (metainfo-len) bytes
* TOML document containing key-value pairs
[tr]
* signature
* 64 bytes
* ed25519 signature over metainfo field
=== Header Fields
==== MAGIC
The initial 4 bytes are always set to the ascii bytes 'SGOS' so that a
valid image file can easily be identified.
==== status
The `status` field is used only on base rootfs image installed on a partition.
It must be set to 0 for all other images. The field is used to make decisions
about which parition to attempt to boot.
The status value is stored in the low nibble (4 bits) of this field and the
high nibble is reserved for counting boot attempts in `STATUS_TRY_BOOT` state.
The defined status values are:
[table]
[tr]
- status
- value
- description
[tr]
* STATUS_INVALID
* 0
* Partition does not contain a valid image
[tr]
* STATUS_NEW
* 1
* Newly written partition which has not yet been booted
[tr]
* STATUS_TRY_BOOT
* 2
* Set when booting a partition for the first time
[tr]
* STATUS_GOOD
* 3
* Partition has been successfully booted at least once
[tr]
* STATUS_FAILED
* 4
* Partition has failed to boot
[tr]
* STATUS_BAD_SIG
* 5
* Signature verification on metainfo failed
[tr]
* STATUS_BAD_META
* 6
* Parsing metainfo field failed
==== flags
[table]
[tr]
- flag
- value
- description
[tr]
* FLAG_PREFERRED_BOOT
* 0x01
* Override boot choice to boot from this partition
[tr]
* FLAG_HASH_TREE
* 0x02
* Image contains an appended dm-verity hash tree
[tr]
* FLAG_DATA_COMPRESSED
* 0x04
* Image is compressed with xz
==== metainfo-len
Length in bytes of the `metainfo` field.
Since header page has a fixed size of one block (4096 bytes), and all other
header fields have fixed sizes the maximum length of the `metainfo` field is
4096 - (4 + 2 + 2 + 64) = 4024 bytes
==== metainfo
==== signature
When the rootfs partition is chosen to mount, an attempt will be made to verify
the signature before configuring dm-verity. If this signature verification
fails, the partition status will be changed to `STATUS_BAD_SIG`
=== Booting
During boot of Citadel, the initramfs sets up the Citadel root filesystem. The
filesystem is built by locating and mounting three components:
* Base root filesystem
* Kernel modules
* Extra resources
The base root filesystem is stored on a partition unless running in certain
special modes such as installer and live disk. During installation the same
base root filesystem image is mounted from a loop mounted image file. This same
file will eventually be written to a partition during installation.
Kernel modules and extra resources are stored in file images which are
loop mounted during boot.
An additional type of resource image called a sealed application image exists
for the creation of immutable application image filesystems.
Resource images can optionally have dm-verity enabled when mounted.

View File

@ -1,247 +0,0 @@
Citadel Realms
--------------
Citadel contains only the base operating system and the Gnome desktop, it does not
include any applications. To be able to install and run applications Citadel can
create spaces which are called Realms.
A Realm is a container similar to a Docker or LXC container in which any Linux
distribution could be installed. We use a Debian based image but it would not be
difficult to create an image for another Linux distribution.
The realm containers are launched with systemd-nspawn but this is a detail of
how they are implemented and not something it is necessary to learn about in order to use them.
Citadel provides a command-line tool `realms` for creating, managing, and launching Realm instances.
### The `default` realm
One realm is always selected to be the `default` realm. This realm
starts automatically when the system boots. The `realms` utility can be used
to change which realm is the default realm. Switching the default realm changes
the symlink `/realm/default.realm` to point to a different realm instance directory.
citadel:~# realms default
Default Realm: main
citadel:~# realms default project
[+] default realm changed from 'main' to 'project'
citadel:~# realms default
Default Realm: project
### The `current` realm
Multiple realms may be launched at once but the Gnome Desktop is only associated with
one of the running realms. This realm is called the `current` realm.
When displaying applications available to launch from the desktop, Gnome will only
be aware of applications that are installed in the realm which is set as `current`
and any application launched from the desktop will run inside this current realm.
Setting another realm as current does not affect any applications that are already running.
Changing the current realm only means that any further applications which are launched
will now run in the newly chosen realm.
Changing or querying the current realm is done with the `realms current` command, and
if you choose a realm which is not currently running it will be automatically started.
citadel:~# realms current
Current Realm: main
citadel:~ # realms current project
[+]: Started realm 'project'
[+]: Realm 'project' set as current realm
citadel:~ # realms current
Current Realm: project
Underneath the hood, this command just changes the symlink `/run/realms/current.realm` to
point to a new realm. This directory is monitored for changes with `inotify` and when
the symlink changes a new set of `.desktop` files is swapped into a temporary directory
where Gnome will look for metadata about which applications are installed.
### Creating a new realm
New realms are created with the command `realms new <realm name>`
When a new realm is created a btrfs snapshot of some application image is created at
`/realms/realm-$name/rootfs`. By default it is the base image (`base.appimg`) which
is cloned as a snapshot. Application images are described in detail in a later section.
citadel:~ # realms new project
[+]: Populating realm home directory with files from /realms/skel
Create a snapshot of '/storage/appimg/base.appimg' in '/realms/realm-project/rootfs'
A new empty home directory is also created for the realm instance. Any file which are placed
into the `/realm/skel` directory will be copied into any newly created realm home directory.
### Realms configuration file
All of the curretly supported configuration options are listed below with their default values assigned.
use-shared-dir = true
use-sound = true
use-x11 = true
use-wayland = true
use-gpu = false
use-kvm = false
use-network = true
network-zone = "clear"
If you wish to change any of these options to something other than what is listed above add the
corresponding line to the file `/realms/realm-$name/config`
citadel:~ # echo "use-gpu = true" > /realms/realm-main/config
#### Option `use-shared-dir`
Set to `false` to disable mounting the shared directory `/realms/Shared` into this realm at
`/home/user/Shared`.
#### Option `use-sound`
Set to `false` to prevent mounting pulse audio socket and sound device into this realm.
#### Option `use-x11`
Set to `false` to prevent mounting `/tmp/.X11-unix` into the realm. This is the socket for communicating
with the `XWayland` X11 compatibility daemon.
#### Option `use-wayland`
Set to `false` to prevent mounting the wayland display server socket `/run/user/1000/wayland-0`
into the realm.
#### Option `use-gpu`
Set to `true` to mount the device `/dev/dri/renderD128` into the realm. Adding this
device will make hardware graphics acceleration available to applications running
in the realm.
#### Option `use-kvm`
Set to `true` to mount the device `/dev/kvm` into the realm. This will make it
possible to run Qemu and other KVM based tools with hardware virtualization
inside the realm.
#### Option `use-network`
Set to `false` to disable configuring the realm with access to the internet. The
realm instance will only have a localhost network interface.
#### Option `network-zone`
Setting a name here will create bridge device in citadel with the name vz-$name if
it doesn't already exist and attach this realm instance to that bridge.
### Realms base directory layout
The realms base directory is stored on the storage partition at `/storage/realms` and is bind mounted to `/realms` on the root filesystem for convenience.
/realms
config
/Shared
/skel
/default.realm -> realm-main
/realm-main
/realm-project
/realm-testing
#### File `/realms/config`
This file is a template of the configuration file for individual realms. When a new
realm is created this file in copied into the new realm instance directory. By
modifying this file, the default configuration for new realm instances can be changed.
#### Directory `/realms/Shared`
This directory is bind mounted to `/home/user/Shared` of each running realm that has
the option `use-shared-dir` enabled. It's a convenient way to move files between
different realms and between citadel and realms.
#### Directory `/realms/skel`
Files which are added to this directory will be copied into the home directory of
any newly created realm. The directory is copied as a tree of files and may contain
subdirectories.
#### Symlink `/realms/default.realm`
A symlink which points to a realm instance directory of the default realm. The
default realm is the realm which starts when the system is booted.
#### Directory `/realms/realm-$name`
This is a realm instance directory, for a realm with $name as the realm name.
/realm-main
config
/home
/rootfs
##### `config`
Configuration file for the realm instance copied from `/realms/config` or
created by the user.
##### `/home`
Home directory for this realm. It will be mounted to `/home/user` in
the realm instance.
##### `/rootfs`
The root filesystem of this realm. It is cloned from (a btrfs subvolume snapshot of)
some application image.
### Application Images
(Not to be confused with the [AppImage](https://appimage.org) packaging system)
The root filesystem for realms are called Application Images but we often use
the shorter name *appimg*.
We have created [a framework](https://github.com/subgraph/citadel/tree/master/appimg-builder)
for building a Debian based images and we use this to build the default appimg that we ship.
We also encourage users to experiment with building their own custom images.
**Tree Application Images** are the only type of application image which are currently implemented for realms.
The rootfs is a tree of files on the filesystem, and it is also a btrfs subvolume
which is cloned at zero cost (internally with `btrfs subvolume snapshot`) to use
as the root filesystem of newly created realms.
#### Block Application Images (and also Sealed Application Images)
In the future we will add another type of application image called a **Block
Application Image**. This type of image will be stored as a disk volume image file
and will be mounted with a loop device rather than existing as a tree of files on the
filesystem.
This will make it possible to enforce [dm-verity](https://www.kernel.org/doc/Documentation/device-mapper/verity.txt)
verification over the image and ensure that no malicous or unintended modifications
can be made to any of the the files on the root filesystem. Signature verification
over the dm-verity root hash is done from the citadel rootfs image which is also
secured with dm-verity. When enforcement of boot integrity is also implemented this
will create a chain of cryptographic assurances that no component of the system has
been tampered with.
Block images with signatures and dm-verify verification enabled are called **Sealed Application Images**
### Updating an Application Image
To modify or update an application image run the `realms update-appimg` command.
A container will be created for updating the image and a root shell session will
open. From this session regular package management commands can be run. Any changes
made will only affect future realms created from this appimg.
citadel:~ # realms update-appimg
[+]: Entering root shell on base appimg
root@base-appimg-update:/# apt update
[...]

View File

@ -0,0 +1,20 @@
DESCRIPTION = "Citadel Yelp Documentation"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
inherit allarch
SRC_URI = "\
file://pages \
file://citadel-documentation.desktop \
"
do_install() {
install -m 0755 -d ${D}${datadir}/citadel-documentation
install -m 0755 -d ${D}${datadir}/applications
install -m 0644 ${WORKDIR}/pages/*.page ${D}${datadir}/citadel-documentation
install -m 0644 ${WORKDIR}/citadel-documentation.desktop ${D}${datadir}/applications
}
FILES_${PN} = "/"

View File

@ -0,0 +1,9 @@
[Desktop Entry]
Name=Citadel Documentation
Keywords=documentation;information;manual;help;
Categories=Core;Documentation;
Icon=help-browser
Exec=/usr/libexec/citadel-run yelp /opt/share/citadel-documentation
Type=Application
Terminal=false
StartupNotify=true

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" type="topic" id="boot">
<info>
<link type="guide" xref="index#internals"/>
</info>
<title>Booting Citadel </title>
<section>
<title>Disk Layout</title>
<p>When Citadel is installed two disk partitions are created on the target disk.</p>
<screen>sda 8:0 0 477G 0 disk
├─sda1 8:1 0 511M 0 part
└─sda2 8:2 0 476.5G 0 part</screen>
<p>The first partition is an EFI boot partition and the second partition is LUKS encrypted
and contains multiple LVM volumes when decrypted.</p>
<screen>
/dev/sda1 /dev/sda2
[EFI ESP Boot partition] [ LUKS encrypted partition filling remainder of disk ]
. .
. .
. | .
. | .
. V .
. .
[ rootfsA ] [ rootfsB ] [ citadel-storage ]
</screen>
<p>There are three logical volumes. Two root filesystem partitions so that one partition
can be updated while the other one is in use, and the remaining space is contained
in a volume called 'storage'.</p>
<screen type="sh"># lvs
LV VG Attr LSize
rootfsA citadel -wi-a----- 2.00g
rootfsB citadel -wi-ao---- 2.00g
storage citadel -wi-ao---- 472.43g</screen>
<section>
<title>Bootloader</title>
<section>
<title>LUKS</title>
<p>The kernel initramfs has an /etc/crypttab file which guides the discovery of the LUKS partition.
The UUID of the LUKS partition is hardcoded to the value listed below. If citadel is installed
on more than one device on the system, the intended LUKS partition may not be chosen correctly.
This problem can be addressed by changing the UUID of other citadel LUKS partitions and passing
the UUID on kernel commandline to override /etc/crypttab. See systemd-cryptsetup-generator(8).</p>
<screen type="sh"># cat /etc/crypttab
luks UUID=683a17fc-4457-42cc-a946-cde67195a101 - discard</screen>
</section>
<section>
<title>Mounting rootfs</title>
<p>The initramfs boot stage is orchestrated by various systemd unit files which can be found
in the citadel source tree at:</p>
<screen>citadel/meta-citadel/recipes-initrd/citadel-initramfs</screen>
<p>The same kernel and initramfs is used for the installer image. One task of these unit files
is to set up a live mode boot when a certain kernel command line option is set. For a regular
boot, a pair of unit files will attempt to mount the root filesystem partition when it becomes
available:</p>
<screen>citadel-rootfs-mount.path
citadel-rootfs-mount.service</screen>
<p>The .path unit triggers every time /dev/mapper changes and the corresponding .service unit is
activated only when all of the LVM volumes inside</p>
<screen>ConditionPathExists=/dev/mapper/citadel-rootfsA
ConditionPathExists=/dev/mapper/citadel-rootfsB
ConditionPathExists=/dev/mapper/citadel-storage</screen>
</section>
</section>
</section>
</page>

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" type="topic" id="citadel">
<info>
<link type="guide" xref="index"/>
<desc>Introduction to Subgraph Citadel</desc>
</info>
<title>Subgraph Citadel</title>
<section>
<title>What is Citadel?</title>
<p>Citadel is the base operating system of the new version of Subgraph OS.</p>
<p>Citadel runs the GNOME desktop session and a few basic system services and
nothing else. It is built and distributed as a single static disk image
rather than as a collection of software packages like a traditional Linux
distribution such as Ubuntu or Fedora. Citadel disk images are built entirely
from the source code of the individual software components. This gives us
complete control over what is included and how each component is configured.</p>
<note style="advanced">
<p>Citadel is a modern desktop operating system based on the GNOME desktop, but if you
prefer we also include an tiling window manager called Sway as an alternative.</p>
</note>
<p>Since the Citadel root filesystem is immutable it is not possible to install
applications such as a web browser or text editor directly into Citadel.
Instead applications are run in a separate isolated environment called a Realm.</p>
<p>When Citadel is first installed a single primary Realm is created and while running
a single realm the system resembles and behaves similar to any other desktop Linux
system. The separation between Citadel and the realm in which user applications are
launched is mostly transparent to the user. However, a user may create as many new
realms as they like and each new realm behaves like a freshly installed Debian Linux
environment where the user may install packages and store files.</p>
<p>Realms are implemented in Subgraph OS as either containers or as virtual machines
running in a custom KVM hypervisor. Both approaches have advantages so the user is
free to choose either option for each realm they create.</p>
<note style="advanced">
<p>Hypervisor isolation is stronger and more secure, but container isolation uses
less system resources and makes it possible to access hardware devices and other
system features directly. A Citadel user can decide which configuration makes
more sense for each Realm they create.</p>
</note>
<section>
<title>Stateless Foundation</title>
<p>In the architecture of Citadel the building blocks of the system are
immutable filesystem images rather than packages. These images are mounted
read-only and this property is enforced with a Linux kernel feature (dm-verity)
which efficiently guarantees each block loaded from disk has a valid
cryptographic checksum. This means that Citadel always loads exactly the
operating system software prepared by Subgraph and rebooting the system will
always brings the computer into a known consistent state.</p>
<p>When Citadel is updated an entirely new image is loaded rather than applying
a set of changes on top of an existing filesystem. By atomically updating the
entire system from one version to the next there is only ever a single software
configuration to consider and the system can never end up in an inconsistent state.
System upgrades cannot break your computer in mysterious ways and even if an
upgrade fails to boot for some reason, the system simply reverts to the
previously working version.</p>
</section>
</section>
</page>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" type="topic" id="developer">
<info>
<link type="guide" xref="index#internals"/>
</info>
<title>Developer Guide</title>
<section>
<title>Make Root Filesystem Writable</title>
<p>Sometimes it can be useful to make changes directly to the citadel root filesystem to
experiment with changes or to debug a problem.</p>
<p>First <code>citadel.noverity</code> must be added to the kernel commandline. After booting with
this command line option verify that dm-verity has been disabled with the <code>dmsetup</code>
command.</p>
<screen># dmsetup status rootfs
0 4194304 linear</screen>
<p>If the output displays <code>verity</code> instead of <code>linear</code> then dm-verity is enabled
and the disk cannot be safely written to.</p>
<p>Next remount the root filesystem with read-write flag.</p>
<screen># mount -oremount,rw,noatime /</screen>
</section>
<section>
<title>Debugging GNOME startup</title>
</section>
</page>

View File

@ -0,0 +1,184 @@
<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" type="topic" id="disk-layout">
<info>
<link type="guide" xref="index#internals"/>
<desc>A Hands-on guide the Citadel Disk and Filesystem Layout</desc>
</info>
<title>Disk Layout</title>
<section>
<title>Partitions</title>
<p>During installation, two partitions are created on the disk chosen as
the target of the install.</p>
<p>For example, if the installation disk is <code>/dev/sda</code>:</p>
<terms>
<item>
<title><code>/dev/sda1</code></title>
<p>512MB EFI System Partition</p>
</item>
<item>
<title><code>/dev/sda2</code></title>
<p>Remainder of the disk</p>
</item>
</terms>
<p>The partition layout of a running system can be viewed by running the <code>lsblk</code> command.</p>
<screen>citadel:~ # lsblk /dev/sda
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 477G 0 disk
├─sda1 8:1 0 511M 0 part
└─sda2 8:2 0 476.5G 0 part
└─luks 252:0 0 476.4G 0 crypt
├─citadel-rootfsA 252:1 0 2G 0 lvm
│ └─rootfs 252:4 0 354M 1 crypt /
├─citadel-rootfsB 252:2 0 2G 0 lvm
└─citadel-storage 252:3 0 472.4G 0 lvm /storage</screen>
<p>Several further block devices are created during boot when the main disk partition
is decrypted.</p>
<screen>sda
├─sda1 (a) /boot partition
└─sda2 (b) LUKS encrypted partition
└─citadel (c) LVM volume group
├─citadel-rootfsA (d1) rootfs partition A (Read Only)
│ └─rootfs (e) The dm-verity device created for rootfsA
├─citadel-rootfsB (d2) rootfs partition B (Read Only)
└─citadel-storage (f) mounted as /storage (Read/Write)</screen>
<terms>
<item>
<title><code>(a) /boot partition</code></title>
<p>EFI boot partition</p>
</item>
<item>
<title><code>(b) LUKS encrypted partition</code></title>
<p>Remainder of disk is an encrypted volume</p>
</item>
<item>
<title><code>(c) LVM volume group</code></title>
<p>Main partition contains several LVM volumes</p>
</item>
<item>
<title><code>(d) citadel-rootfs(A/B)</code></title>
<p>Two root partitions so one can be updated while other is in use.</p>
</item>
<item>
<title><code>(e) /dev/mapper/rootfs</code></title>
<p>verity mapper device for mounted root partion</p>
</item>
<item>
<title><code>(f) /dev/mapper/citadel-storage</code></title>
<p>The writable filesystem</p>
</item>
</terms>
</section>
<section>
<title>Citadel Filesystem Layout</title>
<code>/
├─ /run/citadel/images/
│ │
│ ├─ modules.mountpoint/ (modules image mounted here)
│ └─ extra.mountpoint/ (extra image mounted here)
└─ /storage
├─ resources/dev (resource images for channel 'dev')
│ │
│ ├─base-realmfs.img
│ └─main-realmfs.img
├─ /realms (/realms is a bind mount of /storage/realms)
│ ├─skel/
│ └─config
├─ /realms/realmfs-images
│ │
│ ├─citadel-kernel-5.7-dev-001.img
│ └─citadel-extra-dev-001.img
└─ /realms/realm-main
├─ home
└─ config</code>
</section>
<section>
<title>Resource Image Mounts</title>
<p>Resource images are mounted into the system by creating loop devices. These devices can be
viewed by running the 'losetup' command inside Citadel.</p>
<screen>citadel:~ # losetup -ONAME,OFFSET,RO,BACK-FILE
NAME OFFSET RO BACK-FILE
/dev/loop1 4096 1 /storage/resources/dev/citadel-extra-dev-001.img
/dev/loop2 4096 1 /storage/realms/realmfs-images/main-realmfs.img
/dev/loop0 4096 1 /storage/resources/dev/citadel-kernel-5.0.6-dev-000.img</screen>
<p>Resource image files are protected against accidental changes or malicious tampering by
using dm-verity so that the kernel verifies a cryptographic checksum of each block loaded
from the image.</p>
<p>You can view the verity device mapper node associated with each loop device with
the <code>lsblk</code> command.</p>
<screen>citadel:~ # lsblk /dev/loop0 /dev/loop1 /dev/loop4
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 116.9M 1 loop
└─verity-kernel 252:5 0 116M 1 crypt /run/citadel/images/kernel.mountpoint
loop1 7:1 0 938.9M 1 loop
└─verity-extra 252:6 0 931.5M 1 crypt /run/citadel/images/extra.mountpoint
loop2 7:2 0 4G 1 loop
└─verity-realmfs-main-11922f31 252:9 0 4G 1 crypt /run/citadel/realmfs/realmfs-main-11922f31.mountpoint</screen>
<p>Parameters of each dm-verity instance can be viewed with the veritysetup command.</p>
<screen>citadel:~ # veritysetup status verity-kernel
/dev/mapper/verity-kernel is active and is in use.
type: VERITY
status: verified
hash type: 1
data block: 4096
hash block: 4096
hash name: sha256
salt: fa430cb7887de60dca6fd1974868036ea39cf5017eb55f02e3a76f82a12a0431
data device: /dev/loop0
data loop: /storage/resources/dev/citadel-kernel-5.0.6-dev-000.img
size: 237536 sectors
mode: readonly
hash device: /dev/loop0
hash loop: /storage/resources/dev/citadel-kernel-5.0.6-dev-000.img
hash offset: 237544 sectors</screen>
<p>When a resource image file is mounted, a file in the root directory called 'manifest' lists
bind mounts to perform to integrate the image into the Citadel root filesystem.</p>
<p>Each line of this file is a directory to bind mount from the mounted image to the root
filesystem. If a directory should be mounted to a location which is different than
the source directory the source and target directories are both listed on a single
line and separated by the ':' character. In the 'extra' image below, the directory
/usr/share from the resource image is mounted to /opt/share on the Citadel filesystem.</p>
<screen>citadel:~ # cat /run/citadel/images/kernel.mountpoint/manifest
/usr/lib/modules
citadel:~ # cat /run/citadel/images/extra.mountpoint/manifest
/usr/lib/firmware
/usr/share:/opt/share</screen>
<p>The citadel-image utility can be used to view the metainfo variables stored in the header
section of a resource image file.</p>
<screen>citadel:~ # citadel-image metainfo /storage/resources/dev/citadel-extra-dev-001.img
image-type = "extra"
channel = "dev"
version = 1
timestamp = "20190331172025"
nblocks = 195924
shasum = "04e6f58afa6f608aff2d6cbb47cbe704f8ab0995f4dfe8e1c03655dc9bb6635a"
verity-salt = "7bf3eec3c51ffd2e82329a9fc6fe42915743874d7c5af43589e589c037ae81e5"
verity-root = "b94eb3431c4fb95e5b9bd62b4505d089414ae660d75eee0fce54b8483d3f9571"
citadel:~ # citadel-image metainfo /storage/resources/dev/citadel-kernel-5.0.6-dev-000.img
image-type = "kernel"
kernel-version = "5.0.6"
kernel-id = "36b7a960dcd51d1649f83a7361f9eb5c2af5741ce6cc53689b411347aa1298b6"
channel = "dev"
version = 1
timestamp = "20190407002748"
nblocks = 29692
shasum = "c988bd7d468c409eb6cd3af8fa9e17b0a75a72d6ad765ad1749d15628a9096be"
verity-salt = "fa430cb7887de60dca6fd1974868036ea39cf5017eb55f02e3a76f82a12a0431"
verity-root = "f4c4fbaebb59d348bd44cfb1cdef54a813728aabc5acc439c2e739b63c1b8370"</screen>
<p>RealmFS images also have a resource image header with a slightly different set of
metainfo variables.</p>
<screen>citadel:~ # citadel-image metainfo /storage/realms/realmfs-images/main-realmfs.img
image-type = "realmfs"
realmfs-name = "main"
nblocks = 1048575
channel = "realmfs-user"
verity-salt = "ad254e6dd385c0392ed8a6a41b849cfd4ef98ec3643e186feb011d5aa4f1d194"
verity-root = "11922f311b5a9141d65b7ef82e1c9159d75e413d1b420a7e3302ec8ec0ad8593"</screen>
</section>
</page>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" type="guide" id="index">
<title>Citadel Help</title>
<section id="user" style="2column">
<title>User Guide</title>
</section>
<section id="internals" style="2column">
<title>Citadel Internals</title>
</section>
</page>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" type="topic" id="kernel-cmdline">
<info>
<link type="guide" xref="index#internals"/>
</info>
<title>Kernel Command Line Options</title>
<list>
<item>
<p>citadel.noverity</p>
</item>
<item>
<p>citadel.nosignatures</p>
</item>
<item>
<p>citadel.install</p>
</item>
<item>
<p>citadel.overlay</p>
</item>
<item>
<p>citadel.channel</p>
</item>
<item>
<p>citadel.verbose</p>
</item>
<item>
<p>citadel.debug</p>
</item>
<item>
<p>citadel.sway</p>
</item>
</list>
</page>

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" type="topic" id="realm-config">
<info>
<link type="guide" xref="index#user"/>
<desc>Realm configuration file reference</desc>
</info>
<title>Configuring Realms</title>
<p>Realms are usually configured with the tools for managing realms, but the configuration
is stored in a TOML file in the realm directory and can also be edited by hand.</p>
<section>
<title>Options</title>
<terms>
<item>
<title><code>use-wayland</code></title>
<p>If 'true' access to Wayland display will be permitted in realm by
adding wayland socket /run/user/1000/wayland-0</p>
</item>
<item>
<title><code>use-x11</code></title>
<p>If 'true' access to X11 server will be added to realm by bind mounting directory
/tmp/.X11-unix</p>
</item>
<item>
<title><code>use-sound</code></title>
<p>If 'true' allows the use of sound inside realm. The following items will
be added to realm:</p>
<list>
<item>
<p>/dev/snd</p>
</item>
<item>
<p>/dev/shm</p>
</item>
<item>
<p>/run/user/1000/pulse</p>
</item>
</list>
</item>
<item>
<title><code>use-kvm</code></title>
<p>If enabled, /dev/kvm will be added to the realm.
This option is only available for nspawn realms.</p>
</item>
<item>
<title><code>use-shared-dir</code></title>
<p>If enabled the directory /realms/Shared will be bind mounted into the home directory of the realm.
This directory is shared between all running realms that have this option enabled as a
convenient way to move files between realms.</p>
</item>
<item>
<title><code>use-ephemeral-home</code></title>
<p>If 'true' the home directory of this realm will be set up in ephemeral mode.
The ephemeral home directory is set up with the following steps</p>
<steps>
<item>
<p>Home directory is mounted as tmpfs</p>
</item>
<item>
<p>Any files in /realms/skel are copied into home directory</p>
</item>
<item>
<p>Any files in /realms/realm-${name}/skel are copied into home directory</p>
</item>
<item>
<p>Any directories listed in <code>ephemeral-persistent-dirs</code> are bind mounted
from /realms/realm-${name}/home into ephemeral home directory.</p>
</item>
</steps>
</item>
<item>
<title><code>ephemeral-persistent-dirs</code> default: ["Documents"]</title>
<p>A list of subdirectories of /realms/realm-${name}/home to bind mount into realm
home directory when <code>ephemeral-home</code> is enabled.</p>
</item>
<item>
<title><code>use-network</code></title>
<p>network</p>
</item>
<item>
<title><code>network-zone</code> default: "clear"</title>
<p>network zone</p>
</item>
<item>
<title><code>use-gpu</code></title>
<p>Enables hardware graphics acceleration in relam.
if 'true' render node device /dev/dri/renderD128 will be added to realm.</p>
</item>
<item>
<title><code>use-gpu-card0</code></title>
<p>If 'true' and <code>use-gpu</code> is also enabled, privileged device /dev/dri/card0
will be added to realm.</p>
</item>
<item>
<title><code>realmfs</code> default: "base"</title>
<p>name of realmfs image</p>
</item>
<item>
<title><code>overlay</code> default: "storage"</title>
<p>type of overlay to use</p>
</item>
<item>
<title><code>terminal-scheme</code></title>
<p>terminal color scheme</p>
</item>
<item>
<title><code>extra-bindmounts</code></title>
<p>bind mounts</p>
</item>
<item>
<title><code>extra-bindmounts-ro</code></title>
<p>read-only bind mounts</p>
</item>
<item>
<title><code>system-realm</code> default: false</title>
<p>system realm</p>
</item>
<item>
<title><code>autostart</code> default: false</title>
<p>autostart realm</p>
</item>
</terms>
</section>
</page>

View File

@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" type="topic" id="realmfs">
<info>
<link type="guide" xref="index#user"/>
<desc>Realm root filesystem images</desc>
</info>
<title>RealmFS Images</title>
<p>A RealmFS image contains a root filesystem for one or more realm instances.
Similar to resource images, RealmFS images are signed and mounted with dm-verity
to prevent tampering with the data on the root filesystem such as the
installation of malware or backdoors. The keys used to sign RealmFS images are
controlled by the user which makes it possible to upgrade software and install
new packages on the image.</p>
<p>RealmFS images are always mounted as read-only and this property is enforced
with dm-verity. Since RealmFS images are immutable a single image can be shared
between multiple running realm instances. By default, when a realm is launched a
temporary overlay is added to the root filesystem so that changes can be
performed that will last only until the realm is stopped or restarted. This
allows experimenting with the system configuration or installing new software
temporarily. The root filesystem can then be reverted to the original state by
simply restarting the realm.</p>
<section>
<title>Updates</title>
<p>Since the root filesystem of realms are stored on read-only disk images,
packages cannot be permanently installed or upgraded in the usual way. Changes
to the root filesystem will succeed inside a realm, but these changes will be
lost as soon as the realm is stopped or restarted.</p>
<p>To make persistent changes to a RealmFS image, the image is first copied, then
changes are applied to the copy. After applying changes a new dm-verity hash
tree is generated for the image and the RealmFS image header is updated and
signed.</p>
<note style="advanced">
<p>The process of generating a signature and a dm-verity hash tree for a RealmFS image
after applying some changes such as updating packages is called <em style="strong">Sealing</em>
the image.</p>
</note>
<section>
<title>Apt-Cacher NG Realm</title>
<p>Upon booting a system utility realm is started which runs an Apt-Cacher NG
instance. Each realm is configured to use this realm as a proxy for package
installation.</p>
<code>/etc/apt/apt.conf.d/000apt-cacher-ng-proxy
Acquire::http::Proxy "http://172.17.0.213:3142/";</code>
<p>The apt source lines use the special Apt-Cacher NG syntax.</p>
<code>/etc/apt/sources.list
deb http://HTTPS///deb.debian.org/debian buster main contrib non-free</code>
<p>Using a package cache avoids downloading and storing packages multiple times
when updating multiple RealmFS images. It also makes it possible to download and
cache packages while connected to a network before booting the system into a
safe mode without enabling the network to perform upgrades of realm packages.</p>
</section>
<section>
<title>Updates (Container method)</title>
<p>First the RealmFS image is copied to a temporary file. On a filesystem such as
btrfs, the image file will be cloned as a reflink rather than copying the file.
The copy of the RealmFS will then be mounted as writable so that changes can be
made. A systemd-nspawn container is launched and a root shell opened so that the
user can update packages, install new software, or perform any other
modifications to the root filesystem.</p>
<p>Once the shell is exited a prompt asks the user if they would like to save the
current changes or discard them. If the user chooses to save the changes, the
copied image is then sealed by generating a dm-verity hash tree and the header
of the image is signed with the user RealmFS sealing key.</p>
</section>
<section>
<title>Updates with pH Hypervisor</title>
<p>When a realm is launched with pH, the overlay is managed by the emulated disk
device of the hypervisor which tracks changes to blocks of the disk and stores
the changed blocks in memory. Since the hypervisor is tracking all of the
changes to the disk, it can also transparently apply the changes and generate a
new sealed RealmFS image and then discard the changed blocks and start directly
using the new image.</p>
<p>This process is initiated by the user when they decide they would like to commit
any changes they have made to the root filesystem in the running realm
permanently to the underlying RealmFS image.</p>
<steps>
<item>
<p>The user makes changes to the root filesystem of the realm and pH tracks the blocks that have changed.</p>
</item>
<item>
<p>A user request is made to pH to apply the changes to the RealmFS image.</p>
</item>
<item>
<p>pH opens a prompt on the desktop to ask the user to confirm that they really did make this request.</p>
</item>
<item>
<p>A copy (or reflink) of the current RealmFS is made, and pH applies the changed blocks to this copy.</p>
</item>
<item>
<p>The copy is then sealed with the RealmFS key of the user.</p>
</item>
<item>
<p>Now pH can quietly swap in the new version of the RealmFS image and discard all of the tracked block changes.</p>
</item>
</steps>
</section>
</section>
<section>
<title>Signing RealmFS Images</title>
<p>A secret key for signing RealmFS images is generated during installation and
stored on disk in an encrypted file called the User Keyring. During boot
when the user enters a passphrase to decrypt the disk, this passphrase is also
used to decrypt the keyring file and the public and secret key pair is
loaded into the kernel key storage.</p>
<p>The risk exists that an attacker who is able to compromise the kernel may
recover this secret key. This would allow the attacker to modify sealed RealmFS
images and install backdoors or other malware into realm root filesystems. Even
without obtaining the signing key an attacker who has compromised Citadel could
wait for the user to perform an update and make malicious changes at the same
time which the user will then sign.</p>
<p>For these reasons, it is also possible to configure the system so that only
the public key is retained in the kernel upon boot and the user must boot
into a special mode so that the private key is available to perform updates.</p>
<section>
<title>Safe Mode</title>
<p>If upgrades are performed in normal operating mode, an attacker who has
compromised citadel can persistently backdoor the upgraded realmfs images.
Safe mode is a way to boot citadel without starting any realms or enabling the
network device. Since the integrity of the Citadel root filesystem is enforced
by dm-verity and no realms are running, even if the system had become compromised
at some point in the past it is assumed to now be in a safe state for performing
updates and signing them with the user sealing keys.</p>
<p>Since the network is not available in safe mode, the packages to be installed or
upgraded must be stored somewhere. By either performing the packge updates with
the <code>--download-only</code> flag or installing them to the temporary overlay of a realm
the user will cause them to be stored on the Apt-Cache NG service realm so that
they are available for install in safe mode.</p>
</section>
</section>
<section>
<title>Base RealmFS image</title>
<p>Citadel ships with a RealmFS image called <code>base-realmfs.img</code>. There is nothing
special about this image other than that it is initially signed by Subgraph until
the user modifies or updates it. During installation, a copy of this RealmFS is
created with the name <code>main-realmfs.img</code> and sealed with the newly generated
user keys.</p>
</section>
</page>

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" type="topic" id="realms">
<info>
<link type="guide" xref="index#user"/>
</info>
<title>Citadel Realms</title>
<p>Citadel contains only the base operating system and the Gnome desktop, it does not
include any applications. To be able to install and run applications Citadel can
create spaces which are called Realms.</p>
<p>A Realm is a container similar to a Docker or LXC container in which any Linux
distribution could be installed. We use a Debian based image but it would not be
difficult to create an image for another Linux distribution.</p>
<p>The realm containers are launched with systemd-nspawn but this is a detail of
how they are implemented and not something it is necessary to learn about in
order to use them.</p>
<section>
<title>The <em>current</em> realm</title>
<p>Multiple realms may be launched at once but the Gnome Desktop is only associated with
one of the running realms. This realm is called the `current` realm.</p>
<p>When displaying applications available to launch from the desktop, Gnome will only
be aware of applications that are installed in the realm which is set as `current`
and any application launched from the desktop will run inside this current realm.</p>
<p>Setting another realm as current does not affect any applications that are already running.
Changing the current realm only means that any further applications which are launched
will now run in the newly chosen realm.</p>
</section>
<section>
<title>Realm directory layout</title>
<p>The realms base directory is stored on the storage partition at `/storage/realms` and is bind mounted to `/realms` on the root filesystem for convenience.</p>
<screen>/realms
config
/Shared
/skel
/default.realm -> realm-main
/realm-main
/realm-project
/realm-testing</screen>
<section>
<title>/realms/config</title>
<p>This is the global realm configuration file. Options set in this file apply to every realm
unless the same option has been overridden with a different value in the config file for
a realm.</p>
</section>
<section>
<title>/realms/Shared</title>
<p>This directory is bind mounted to `/home/user/Shared` of each running realm that has
the option `use-shared-dir` enabled. It's a convenient way to move files between
different realms and between citadel and realms.</p>
</section>
</section>
</page>

View File

@ -0,0 +1,361 @@
<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" type="topic" id="resource-image">
<info>
<link type="guide" xref="index#internals"/>
</info>
<title>Citadel Resource Images</title>
<p>Resource images are disk image files that are mounted read-only to create
the citadel filesystem. The first block (4096 bytes) of the image file
contains a header and immediately following the header is the raw disk
image contents.</p>
<p>The header contains information about the image including parameters for
configuring dm-verity to enforce the immutability of the image. The header
also contains a public key signature over the image information so that
the authenticity of the header information can be verified.</p>
<p>The root filesystem of citadel is also distributed as a resource image, and
this image will be installed to a disk partition for normal operation.</p>
<p>Resource images other than the root filesystem are mounted by creating loop
devices on the image file. Prior to mounting the image dm-verity is configured
on the loop device or the rootfs partition.</p>
<section>
<title>Resource Image Types</title>
<p>Currently the following image types are defined for use in Citadel:</p>
<section>
<title>1) Base Root Filesystem ("rootfs")</title>
<p>The base rootfs image is the only image type which is installed to a
partition. It is mounted as the root of the Citadel filesystem. When an
image is installed on a partition the 4906 byte header block is stored in
the last block (8 sectors) of the partition.</p>
<p>Citadel uses two partitions (A &amp; B) for the root filesystem. This allows
updating one partition while the other one is being used. Then the system
can be rebooted into the updated rootfs partition. If the system fails to
boot after updating it will be reverted to use the working partition.</p>
</section>
<section>
<title>2) Kernel Image ("kernel")</title>
<p>The kernel modules for the running kernel are stored in a resource image
so that the root filesystem is independent from the running kernel.</p>
<p>During boot, this image is mounted and the kernel modules and a bind mount
is created over /usr/lib/modules on the Citadel root filesystem.</p>
</section>
<section>
<title>3) Extra Resource Image ("extra")</title>
<p>This image type contains additional directories of files which are mounted
during boot on the Citadel root filesystem. It contains files such as
firmware files and desktop icons which occupy substantial space but do not
need to be updated frequently.</p>
<p>By placing these files into a separate image the size of the root filesystem
image is reduced. This makes the more frequently updated rootfs image
smaller.</p>
</section>
<section>
<title>4) Realm Filesystem Image ("realmfs")</title>
<p>This type of image contains the entire root filesystem for running a realm
container or VM. Unlike the other types of resource images, these images can
be modified and then signed with keys controlled by the user. This allows
updates and installation of software while still preserving the read-only
property.</p>
</section>
<section>
<title>Image Layout</title>
<p>Each resource image file reserves an initial 4096 byte block where a header is
stored. This is the maximum length of the header, which is generally much
smaller than this size.</p>
<p>Following the header is a raw disk filesystem image which may optionally be
compressed with xz compression algorithm. The disk image filesystem is ext4,
but this is an implementation detail which may change in the future. A header
flag (FLAG_DATA_COMPRESSED) indicates if an image is compressed and if so the
image must be decompressed before being used. Image updates are distributed in
compressed form and are decompressed once during installation.</p>
<p>When dm-verity is used a hash tree must be generated for the image. When an
image is installed it is first decompressed and then the dm-verity hash data
is generated. This hash data is stored in the image file immediately following
the image data and the flag FLAG_HASH_TREE is set to indicate this data is
present.</p>
<p>Image file:</p>
<code> [ Header ][ Ext4 Disk Image ][ dm-verity hash data ]</code>
<p>Partition:</p>
<code> [ Ext4 Disk Image ][ dm-verity hash data ][ unused space ][ Header ]</code>
</section>
</section>
<section>
<title>Image Header</title>
<p>The image header contains the following fields.</p>
<table>
<tr>
<th>
<p>Field</p>
</th>
<th>
<p>Size</p>
</th>
<th>
<p>Content</p>
</th>
</tr>
<tr>
<td>
<p>MAGIC</p>
</td>
<td>
<p>4 bytes</p>
</td>
<td>
<p>('S', 'G', 'O', 'S')</p>
</td>
</tr>
<tr>
<td>
<p>status</p>
</td>
<td>
<p>1 byte</p>
</td>
<td>
<p>Used by images installed to partition</p>
</td>
</tr>
<tr>
<td>
<p>flags</p>
</td>
<td>
<p>1 byte</p>
</td>
<td>
<p>Various flag values</p>
</td>
</tr>
<tr>
<td>
<p>metainfo-len</p>
</td>
<td>
<p>2 bytes</p>
</td>
<td>
<p>16 bit big-endian length</p>
</td>
</tr>
<tr>
<td>
<p>metainfo</p>
</td>
<td>
<p>(metainfo-len) bytes</p>
</td>
<td>
<p>TOML document containing key-value pairs</p>
</td>
</tr>
<tr>
<td>
<p>signature</p>
</td>
<td>
<p>64 bytes</p>
</td>
<td>
<p>ed25519 signature over metainfo field</p>
</td>
</tr>
</table>
<section>
<title>Header Fields</title>
<section>
<title>MAGIC</title>
<p>The initial 4 bytes are always set to the ascii bytes 'SGOS' so that a
valid image file can easily be identified.</p>
</section>
<section>
<title>status</title>
<p>The `status` field is used only on base rootfs image installed on a partition.
It must be set to 0 for all other images. The field is used to make decisions
about which parition to attempt to boot.</p>
<p>The status value is stored in the low nibble (4 bits) of this field and the
high nibble is reserved for counting boot attempts in `STATUS_TRY_BOOT` state.</p>
<p>The defined status values are:</p>
<table>
<tr>
<th>
<p>status</p>
</th>
<th>
<p>value</p>
</th>
<th>
<p>description</p>
</th>
</tr>
<tr>
<td>
<p>STATUS_INVALID</p>
</td>
<td>
<p>0</p>
</td>
<td>
<p>Partition does not contain a valid image</p>
</td>
</tr>
<tr>
<td>
<p>STATUS_NEW</p>
</td>
<td>
<p>1</p>
</td>
<td>
<p>Newly written partition which has not yet been booted</p>
</td>
</tr>
<tr>
<td>
<p>STATUS_TRY_BOOT</p>
</td>
<td>
<p>2</p>
</td>
<td>
<p>Set when booting a partition for the first time</p>
</td>
</tr>
<tr>
<td>
<p>STATUS_GOOD</p>
</td>
<td>
<p>3</p>
</td>
<td>
<p>Partition has been successfully booted at least once</p>
</td>
</tr>
<tr>
<td>
<p>STATUS_FAILED</p>
</td>
<td>
<p>4</p>
</td>
<td>
<p>Partition has failed to boot</p>
</td>
</tr>
<tr>
<td>
<p>STATUS_BAD_SIG</p>
</td>
<td>
<p>5</p>
</td>
<td>
<p>Signature verification on metainfo failed</p>
</td>
</tr>
<tr>
<td>
<p>STATUS_BAD_META</p>
</td>
<td>
<p>6</p>
</td>
<td>
<p>Parsing metainfo field failed</p>
</td>
</tr>
</table>
</section>
<section>
<title>flags</title>
<table>
<tr>
<th>
<p>flag</p>
</th>
<th>
<p>value</p>
</th>
<th>
<p>description</p>
</th>
</tr>
<tr>
<td>
<p>FLAG_PREFERRED_BOOT</p>
</td>
<td>
<p>0x01</p>
</td>
<td>
<p>Override boot choice to boot from this partition</p>
</td>
</tr>
<tr>
<td>
<p>FLAG_HASH_TREE</p>
</td>
<td>
<p>0x02</p>
</td>
<td>
<p>Image contains an appended dm-verity hash tree</p>
</td>
</tr>
<tr>
<td>
<p>FLAG_DATA_COMPRESSED</p>
</td>
<td>
<p>0x04</p>
</td>
<td>
<p>Image is compressed with xz</p>
</td>
</tr>
</table>
</section>
<section>
<title>metainfo-len</title>
<p>Length in bytes of the `metainfo` field.</p>
<p>Since header page has a fixed size of one block (4096 bytes), and all other
header fields have fixed sizes the maximum length of the `metainfo` field is
4096 - (4 + 2 + 2 + 64) = 4024 bytes</p>
</section>
<section>
<title>metainfo</title>
</section>
<section>
<title>signature</title>
<p>When the rootfs partition is chosen to mount, an attempt will be made to verify
the signature before configuring dm-verity. If this signature verification
fails, the partition status will be changed to `STATUS_BAD_SIG`</p>
</section>
</section>
<section>
<title>Booting</title>
<p>During boot of Citadel, the initramfs sets up the Citadel root filesystem. The
filesystem is built by locating and mounting three components:</p>
<list>
<item>
<p>Base root filesystem</p>
</item>
<item>
<p>Kernel modules</p>
</item>
<item>
<p>Extra resources</p>
</item>
</list>
<p>The base root filesystem is stored on a partition unless running in certain
special modes such as installer and live disk. During installation the same
base root filesystem image is mounted from a loop mounted image file. This same
file will eventually be written to a partition during installation.</p>
<p>Kernel modules and extra resources are stored in file images which are
loop mounted during boot.</p>
<p>An additional type of resource image called a sealed application image exists
for the creation of immutable application image filesystems.</p>
<p>Resource images can optionally have dm-verity enabled when mounted.</p>
</section>
</section>
</page>

View File

@ -14,6 +14,7 @@ PACKAGE_INSTALL = "\
adwaita-icon-theme-symbolic \
adwaita-icon-theme-symbolic-hires \
"
CITADEL_IMAGE_VERSION = "${CITADEL_IMAGE_VERSION_extra}"
CITADEL_IMAGE_TYPE = "extra"
@ -23,8 +24,11 @@ inherit citadel-image
ROOTFS_POSTPROCESS_COMMAND += "write_manifest_file; "
write_manifest_file() {
install -m 0755 -d ${IMAGE_ROOTFS}/usr/share/citadel-documentation
cat > ${IMAGE_ROOTFS}/manifest << EOF
/usr/lib/firmware
/usr/share:/opt/share
/sysroot/usr/share/citadel-documentation:/opt/share/citadel-documentation
EOF
}

View File

@ -10,4 +10,5 @@ RDEPENDS_${PN} = "\
citadel-tools \
citadel-tools-realms \
citadel-tools-boot \
citadel-documentation \
"

View File

@ -1 +1 @@
PACKAGES="man manpages vim-nox iputils-ping tmux vifm gnome-terminal firefox nautilus eog evince unzip x264"
PACKAGES="man manpages vim-nox iputils-ping tmux vifm gnome-terminal firefox nautilus eog evince unzip x264 yelp"