Skip to content

Commit af3756b

Browse files
authored
Merge pull request #441 from cgwalters/more-docs
filesystem: Explain more about /etc and /var
2 parents 11093ee + 54b4fd6 commit af3756b

File tree

2 files changed

+57
-5
lines changed

2 files changed

+57
-5
lines changed

docs/src/building/guidance.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,32 @@ make in the container image to e.g. `/etc/postgresql.conf`
8888
will be applied on update, assuming it is not modified
8989
locally.
9090

91+
### Prefer using drop-in directories
92+
93+
These "locally modified" files can be a source of state drift. The best
94+
pattern to use is "drop-in" directories that are merged dynamically by
95+
the relevant software. systemd supports this comprehensively; see
96+
[drop-ins](https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html)
97+
for example in units.
98+
99+
And instead of modifying `/etc/sudoers.conf`, it's best practice to add
100+
a file into `/etc/sudoers.d` for example.
101+
102+
Not all software supports this, however; and this is why there
103+
is generic support for `/etc`.
104+
105+
### Configuration in /usr vs /etc
106+
107+
Some software supports generic configuration both `/usr` and `/etc` - systemd,
108+
among others. Because bootc supports *derivation* (the way OCI
109+
containers work) - it is supported and encourged to put configuration
110+
files in `/usr` (instead of `/etc`) where possible, because then
111+
the state is consistently immutable.
112+
113+
One pattern is to replace a configuration file like
114+
`/etc/postgresql.conf` with a symlink to e.g. `/usr/postgres/etc/postgresql.conf`
115+
for example, although this can run afoul of SELinux labeling.
116+
91117
### Secrets
92118

93119
There is a dedicated document for [secrets](secrets.md),

docs/src/filesystem.md

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,48 @@ The overall recommendation is to keep all operating system content in `/usr`. S
2222

2323
## `/etc`
2424

25-
The `/etc` directory contains persistent state by default; however,
25+
The `/etc` directory contains mutable persistent state by default; however,
2626
it is suppported to enable the [`etc.transient` config option](https://ostreedev.github.io/ostree/man/ostree-prepare-root.html).
2727

2828
When in persistent mode, it inherits the OSTree semantics of [performing a 3-way merge](https://ostreedev.github.io/ostree/atomic-upgrades/#assembling-a-new-deployment-directory)
29-
across upgrades.
29+
across upgrades. In a nutshell:
30+
31+
- The *new default* `/etc` is used as a base
32+
- The diff between current and previous `/etc` is applied to the new `/etc`
33+
- Locally modified files in `/etc` different from the default `/usr/etc` (of the same deployment) will be retained
34+
35+
The implmentation of this defaults to being executed by `ostree-finalize-staged.service`
36+
at shutdown time, before the new bootloader entry is created.
37+
38+
The rationale for this design is that in practice today, many components of a Linux system end up shipping
39+
default configuration files in `/etc`. And even if the default package doesn't, often the software
40+
only looks for config files there by default.
41+
42+
Some other image-based update systems do not have distinct "versions" of `/etc` and
43+
it may be populated only set up at a install time, and untouched thereafter. But
44+
that creates "hysteresis" where the state of the system's `/etc` is strongly
45+
influenced by the initial image version. This can lead to problems
46+
where e.g. a change to `/etc/sudoers.conf` (to give on simple example)
47+
would require external intervention to apply.
48+
49+
For more on configuration file best practices, see [Building](building/guidance.md).
3050

3151
## `/var`
3252

3353
Content in `/var` persists by default; it is however supported to make it or subdirectories
34-
mount points (whether network or `tmpfs`)
54+
mount points (whether network or `tmpfs`). There is exactly one `/var`. If it is
55+
not a distinct partition, then "physically" currently it is a bind mount into
56+
`/ostree/deploy/$stateroot/var` and shared across "deployments" (bootloader entries).
3557

3658
As of OSTree v2024.3, by default [content in /var acts like a Docker VOLUME /var](https://github.com/ostreedev/ostree/pull/3166/commits/f81b9fa1666c62a024d5ca0bbe876321f72529c7).
3759

3860
This means that the content from the container image is copied at initial installation time, and *not updated thereafter*.
3961

40-
The rationale for this is to keep operating system upgrades from touching machine-local data by default.
62+
Note this is very different from the handling of `/etc`. The rationale for this is
63+
that `/etc` should generally only hold small text files, but `/var` should hold arbitrarily
64+
large data (system logs, databases, etc.). Creating multiple copies of it would have
65+
66+
to keep operating system upgrades from touching machine-local data by default.
4167
If the system is rolled back to a previous bootloader entry, the `/var` content remains. This also
4268
makes it possible to "stage" new operating system updates in an alternative root without affecting `/var` content.
4369

@@ -65,7 +91,7 @@ cases, there are several options (containerizing the app, running it in a system
6591
However, some use cases may find it easier to enable a fully transient writable rootfs by default.
6692
To do this, set the
6793

68-
```
94+
```toml
6995
[root]
7096
transient = true
7197
```

0 commit comments

Comments
 (0)