1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
|
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Language" content="en" />
<title>s6-rc: the "repo" subset of commands: definitions and concepts</title>
<meta name="Description" content="s6-rc: an overview" />
<meta name="Keywords" content="s6-rc overview" />
<!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
</head>
<body>
<p>
<a href="index.html">s6-rc</a><br />
<a href="//skarnet.org/software/">Software</a><br />
<a href="//skarnet.org/">skarnet.org</a>
</p>
<h1> The <em>repo</em> subset of s6-rc commands: management of source definition directories </h1>
<p>
s6-rc commands such as
<a href="s6-rc.html">s6-rc</a>,
<a href="s6-rc-compile.html">s6-rc-compile</a>, or
<a href="s6-rc-db.html">s6-rc-db</a>, implement pure <em>mechanism</em>, and
leave all the burden of <em>policy</em>, i.e. how to organize source files,
when to compile a service database, etc., to the user. This is on purpose, but
does not make it easy to integrate s6-rc in a distribution, where service
files are provided by packages installed by a package manager, and where the
user wants to be able to easily define which services start at boot time and
which do not, etc.
</p>
<p>
The solution to this conundrum is the high-level user interface to s6-rc
(and more generally to the s6 ecosystem) named
<a href="//skarnet.org/software/s6-frontend/">s6-frontend</a> (currently
in development). But in order for
<a href="//skarnet.org/software/s6-frontend/">s6-frontend</a> to be a
<em>user interface</em> and not a whole engine in its own right, some
stepping stones are in order: intermediary-level helpers to manage s6-rc
source definition directories in a way that maps better to the way that
distributions work than just the raw <a href="s6-rc-compile.html">s6-rc-compile</a>.
</p>
<p>
These intermediary-level helpers made their appearance in version 0.6.0.0
of s6-rc, and they're collectively known as <em>repo</em> commands —
simply because they manage a <em>repository</em> of services.
</p>
<h2> Definitions </h2>
<h3 id="store"> Store </h3>
<p>
<em> Store: place where service definitions are stored </em>
</p>
<p>
A service <em>store</em> is a place in the filesystem where source
definition directories are written by the package manager or the
user, where you can find the real contents of the services (instead
of just symlinks), as in, source definition directories that are
processed by <a href="s6-rc-compile.html">s6-rc-compile</a>.
A <a href="#repository">repository</a> will typically link to several
stores: one provided by the package manager, and one — or more
— provided locally by the admin. No s6-rc command will ever
write to a store, but most repo commands read from all the stores.
</p>
<p>
The location of the stores is entirely determined by distribution
policy, and s6-rc hardcodes no default for them. A good place to
host service definition directories installed by a package manager
could be, for instance, <tt>/usr/share/s6-rc/sources</tt>. A good
place to host local service definition directories managed by
an administrator could be <tt>/etc/s6-rc/sources</tt>.
</p>
<h3 id="repository"> Repository </h3>
<p>
<em> Repository: place in the filesystem where the repo commands work,
write their data, maintain the dependency graph of all the services
in the stores, etc. </em>
</p>
<p>
The s6-rc <em>repository</em> is the central concept of the <em>repo</em>
commands: it's the place in the filesystem where these commands perform
their work and store their data. It is made of hierarchies of symlinks
(lots and lots of symlinks), that ultimately point to source definition
directories in the <a href="#store">stores</a>, as well as several
compiled databases: the <a href="#refdb">reference database</a>, and the
compiled databases made of the <a href="#set">sets</a> the user has
<a href="#commit">committed</a>, including the one the user will eventually
<a href="#install">install</a>.
</p>
<p>
The <em>repository</em> is where <strong>offline</strong> work on
services happens. It must be located on a read-write filesystem, but
that filesystem does not need to be accessible during the early boot.
By default, the repository is located in <tt>/var/lib/s6-rc/repository</tt>;
it is configurable at s6-rc build time.
</p>
<p>
The repository is generally unique for a system. However, it is possible
to create and use repositories in non-default locations; that is, for
instance, what non-root users would do in order to manage their own sets
of services.
</p>
<h3 id="refdb"> Reference database </h3>
<p>
<em>Reference database: the dependency graph between all the services
in all the stores used by the repository. </em>
</p>
<p>
When the repository is created or updated, the list of all services
defined in all the <a href="#store">stores</a> used by this repository
is analyzed, and all these services are automatically compiled into a
<em>reference database</em>, stored in the repository. The reference
database is never meant to be installed or go live in any way; its
purpose is mainly to give repo commands access to the full dependency
graph of all the services in the stores. Additionally, compiling this
reference database ensures that the whole set of services defined by
the unions of all the stores is consistent: if not, the initialization
fails, so the problem is reported as early as possible.
</p>
<h3 id="set"> Set </h3>
<p>
<em> Set: a set of services with all the states the user wants them
to be in at boot time: unavailable in the database, available but not
automatically started, started at boot time. </em>
</p>
<p>
Inside the repository, a <em>set</em> is the fundamental unit of operation,
and what users will interact the most with. A set contains all the
services defined in the <a href="#refdb">reference database</a>
(so, each service listed in all the <a href="#store">stores</a> used by the
repository) and associates, to each service, a given state that the user
wants this service to be in when the system boots. This target state is
called a <a href="#rx">prescription</a>, or rx for short.
</p>
<p>
The idea is that the user can work on a set, making modifications to
the target states as they see fit; the repo commands always ensure that
the set will be consistent, i.e. that dependencies will be respected and
target states are reachable. When satisfied with the states, the user
can <a href="#commit">commit</a> the set, then <a href="#install">install</a> it.
</p>
<h3 id="rx"> Prescriptions </h3>
<p>
<em> Prescription (or rx): the state the user wants a service to reach at boot time. </em>
</p>
<p>
A <em>prescription</em> is the target state for every service in a set. At all times,
each service is in one and only one rx. The list of rxs the service can be in
is the following:
</p>
<ul>
<li> <em>masked</em>: when the set is committed, masked services <em>will not</em>
be included in the compiled set database. They will be completely absent; if
the set database is installed, <a href="s6-rc.html">s6-rc</a> will not know them.
A service in another rx cannot depend on a masked service. Users typically mask
services that are included in a store but are superfluous to them, services they
just do not want to interact with. </li>
<li> <em>disabled</em>: these services will appear in the compiled set database,
and will be startable by <a href="s6-rc.html">s6-rc</a> if the database is installed.
However, they will not be included in the default bundle, i.e. they will not be
automatically started at boot time. Other names for <em>disabled</em> are:
<em>inactive</em>, <em>unmasked</em>, <em>latent</em>, <em>usable</em>. (Tooling
will likely report these services as <em>latent</em> or <em>usable</em>.) </li>
<li> <em>enabled</em>: these services will appear in the compiled set database,
<em>and</em> in the default bundle, which means they will be started at boot time.
Other names for <em>enabled</em> are: <em>active</em>. </li>
<li> <em>essential</em>, aka <em>always</em>: these services have been marked
as essential in their source definition directories, so they will always be
enabled. They cannot be disabled or masked. They cannot depend on non-essential
services. This rx is typically used by early boot services that should always
run. </li>
</ul>
<p>
Working on a set basically means moving services from one of these rxs to
another, mostly choosing what services to enable or disable, and sometimes
masking services the user does not want to see at all. Once the user is happy
with a set, they should commit it.
</p>
<h3 id="commit"> Commit </h3>
<p>
<em>Committing</em> a set means assembling a subset of all the source
definition directories in the set and compiling them into a
<em>set database</em>, replacing any previous database for the same
set. This set database can then be <em>installed</em>.
</p>
<h3 id="install"> Install </h3>
<p>
<em>Installing</em> a committed set means copying the compiled set
database to the place (defined by distribution policy) where it can be
used as a <em>live database</em>, i.e. booted on, and then switching
the live database to it. In other words: making the set database into
the new live database.
</p>
<h2> Workflow </h2>
<ul>
<li> <strong>At distribution installation time</strong>:
<ul>
<li> The installer creates a repository with
<a href="s6-rc-repo-init.html">s6-rc-repo-init</a>, linking to stores
according to distribution policy. </li>
<li> The installer also sets a default live service database up. </li>
</ul> </li>
<li> <strong>Whenever distribution policies change</strong>, for instance
when declaring an additional local store:
<ul>
<li> The admin updates the list of stores with
<a href="s6-rc-repo-init.html">s6-rc-repo-init -U</a>. </li>
</ul> </li>
<li> <strong>Whenever service files change</strong>, typically when the
package manager installs/updates/deletes packages that provide daemons,
or admins modify services in local stores:
<ul>
<li> The package manager, or the admin, invokes
<a href="s6-rc-repo-sync.html">s6-rc-repo-sync</a> to keep the sets in the
repository in sync with the stores. </li>
<li> It may also be necessary to commit the live set again with
<a href="s6-rc-set-commit.html">s6-rc-set-commit</a>, and to install it with
<a href="s6-rc-repo-set-install.html">s6-rc-repo-set-install</a>, so the live
database is also kept in sync with the machine state. (Failure to do so may
prevent the machine from booting next time.)
</ul> </li>
<li> <strong>Whenever the admin wants to modify the <em>current</em>, live,
machine state, by starting, stopping or restarting services</strong>:
<ul>
<li> They use the original <a href="s6-rc.html">s6-rc change</a> command,
which operates on the live database. No <em>repo</em> command is involved
here. </li>
</ul> </li>
<li> <strong>Whenever the admin wants to customize their startup process</strong>:
<ul>
<li> They can create new sets (with default prescriptions coming from policy that's
hardcoded in the stores) with <a href="s6-rc-set-new.html">s6-rc-set-new</a>,
make a copy of an existing set with <a href="s6-rc-set-copy.html">s6-rc-set-copy</a>,
or delete sets with <a href="s6-rc-set-delete.html">s6-rc-set-delete</a>. </li>
<li> They can list the existing sets with <a href="s6-rc-repo-list.html">s6-rc-repo-list</a>. </li>
<li> They can mask, unmask, enable or disable services in their favorite set with
<a href="s6-rc-set-change.html">s6-rc-set-change</a>. </li>
<li> They can check the list of services and their prescriptions with
<a href="s6-rc-set-status.html">s6-rc-set-status</a>. </li>
<li> They can check for inconsistencies and fix them with
<a href="s6-rc-set-fix.html">s6-rc-set-fix</a>. </li>
<li> They commit the set with <a href="s6-rc-set-commit.html">s6-rc-set-commit</a>. </li>
<li> They install the set with <a href="s6-rc-set-install.html">s6-rc-set-install</a>.
This action potentially modifies the current state of the machine! </li>
</ul> </li>
<li> <strong>At boot time</strong>:
<ul>
<li> The system boots on the installed live database. None of the <em>repo</em>
commands are involved. </li>
</ul> </li>
</ul>
<p>
All these steps can be done manually, but they are made easier by the higher-level
user interface provided by <a href="s6-frontend.html">s6-frontend</a>.
</p>
</body>
</html>
|