Fossil SCM

Replaced Jan Nijtman's Dockerfile with a new one that does a 2-stage build. The first stage runs atop Alpine Linux instead of Fedora, reducing the initial build from ~635 MiB to about 16. Rather than stop there, I then made it multi-stage, copying two key static binaries — Fossil and Busybox — over from the first stage into a fresh-from-scratch container and set it up to run the former jailed away from the latter. The result is under 9 MiB, and it's as secure as one can hope, given that it starts up in "PUBLIC" mode. The new build doesn't have all the extra features turned on that the old one did, but it seems right to build the container with Fossil in its default configuration. If you want something else, copy the Dockerfile, hack it, and make it do what you want instead. Having done all this, I replaced the one-off Dockerfile inline in section 5.0 of the build doc with a reference to this new Dockerfile and rewrote the section in terms of the new capabilities. Finally, this lets us brag on how small the container can be, as compared to the Gitlab-CE container. Before, we were comparing a standalone binary to the container, which wan't entirely fair. (The desire to produce such a container was the spark that kicked this project off.)

wyoung 2022-08-06 04:24 trunk
Commit 77d603c6a194a8941a028a5d43f38122b86114ca6525a5dd2658f3483c99a7a8
+46 -26
--- Dockerfile
+++ Dockerfile
@@ -1,26 +1,46 @@
1
-###
2
-# Dockerfile for Fossil
3
-###
4
-FROM fedora:29
5
-
6
-### Now install some additional parts we will need for the build
7
-RUN dnf update -y && dnf install -y gcc make tcl tcl-devel zlib-devel openssl-devel tar && dnf clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil
8
-
9
-### If you want to build "trunk", change the next line accordingly.
10
-ENV FOSSIL_INSTALL_VERSION release
11
-
12
-RUN curl "https://fossil-scm.org/home/tarball/fossil-src.tar.gz?name=fossil-src&uuid=${FOSSIL_INSTALL_VERSION}" | tar zx
13
-RUN cd fossil-src && ./configure --disable-fusefs --json --with-th1-docs --with-th1-hooks --with-tcl=1 --with-tcl-stubs --with-tcl-private-stubs
14
-RUN cd fossil-src/src && mv main.c main.c.orig && sed s/\"now\"/0/ <main.c.orig >main.c
15
-RUN cd fossil-src && make && strip fossil && cp fossil /usr/bin && cd .. && rm -rf fossil-src && chmod a+rx /usr/bin/fossil && mkdir -p /opt/fossil && chown fossil:fossil /opt/fossil
16
-
17
-### Build is done, remove modules no longer needed
18
-RUN dnf remove -y gcc make zlib-devel tcl-devel openssl-devel tar && dnf clean all
19
-
20
-USER fossil
21
-
22
-ENV HOME /opt/fossil
23
-
24
-EXPOSE 8080
25
-
26
-CMD ["/usr/bin/fossil", "server", "--create", "--user", "admin", "/opt/fossil/repository.fossil"]
1
+# STAGE 1: Build a static Fossil binary atop Alpine Linux
2
+
3
+# Avoid the temptation to swap the wget call below out for an ADD URL
4
+# directive. The URL is fixed for a given release tag, which triggers
5
+# Docker's caching behavior, causing it to reuse that version as long
6
+# as it remains in the cache. We prefer to rely on the caching of the
7
+# server instance on fossil-scm.org, which will keep these trunk
8
+# tarballs around until the next trunk commit.
9
+
10
+FROM alpine:latest AS builder
11
+WORKDIR /tmp
12
+RUN apk update \
13
+ && apk upgrade --no-cache \
14
+ && apk add --no-cache \
15
+ busybox-static gcc make \
16
+ musl-dev \
17
+ openssl-dev openssl-libs-static \
18
+ zlib-dev zlib-static \
19
+ && wget https://fossil-scm.org/home/tarball/src.tar.gz \
20
+ && tar -xf src.tar.gz \
21
+ && cd src \
22
+ && ./configure --static CFLAGS='-Os -s' \
23
+ && make -j
24
+
25
+# STAGE 2: Pare that back to the bare essentials.
26
+
27
+FROM scratch
28
+ENV JAIL=/jail
29
+WORKDIR ${JAIL}
30
+COPY --from=builder /tmp/src/fossil ${JAIL}/bin/
31
+COPY --from=builder /bin/busybox.static /bin/busybox
32
+RUN [ "/bin/busybox", "--install", "/bin" ]
33
+RUN mkdir -m 700 dev \
34
+ && mknod -m 600 dev/null c 1 3 \
35
+ && mknod -m 600 dev/urandom c 1 9
36
+
37
+# Now we can run the stripped-down environment in a chroot jail, while
38
+# leaving open the option to debug it live via the Busybox shell.
39
+
40
+EXPOSE 8080/tcp
41
+CMD [ \
42
+ "bin/fossil", "server", \
43
+ "--create", \
44
+ "--jsmode", "bundled", \
45
+ "--user", "admin", \
46
+ "repo.fossil"]
2747
--- Dockerfile
+++ Dockerfile
@@ -1,26 +1,46 @@
1 ###
2 # Dockerfile for Fossil
3 ###
4 FROM fedora:29
5
6 ### Now install some additional parts we will need for the build
7 RUN dnf update -y && dnf install -y gcc make tcl tcl-devel zlib-devel openssl-devel tar && dnf clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil
8
9 ### If you want to build "trunk", change the next line accordingly.
10 ENV FOSSIL_INSTALL_VERSION release
11
12 RUN curl "https://fossil-scm.org/home/tarball/fossil-src.tar.gz?name=fossil-src&uuid=${FOSSIL_INSTALL_VERSION}" | tar zx
13 RUN cd fossil-src && ./configure --disable-fusefs --json --with-th1-docs --with-th1-hooks --with-tcl=1 --with-tcl-stubs --with-tcl-private-stubs
14 RUN cd fossil-src/src && mv main.c main.c.orig && sed s/\"now\"/0/ <main.c.orig >main.c
15 RUN cd fossil-src && make && strip fossil && cp fossil /usr/bin && cd .. && rm -rf fossil-src && chmod a+rx /usr/bin/fossil && mkdir -p /opt/fossil && chown fossil:fossil /opt/fossil
16
17 ### Build is done, remove modules no longer needed
18 RUN dnf remove -y gcc make zlib-devel tcl-devel openssl-devel tar && dnf clean all
19
20 USER fossil
21
22 ENV HOME /opt/fossil
23
24 EXPOSE 8080
25
26 CMD ["/usr/bin/fossil", "server", "--create", "--user", "admin", "/opt/fossil/repository.fossil"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
--- Dockerfile
+++ Dockerfile
@@ -1,26 +1,46 @@
1 # STAGE 1: Build a static Fossil binary atop Alpine Linux
2
3 # Avoid the temptation to swap the wget call below out for an ADD URL
4 # directive. The URL is fixed for a given release tag, which triggers
5 # Docker's caching behavior, causing it to reuse that version as long
6 # as it remains in the cache. We prefer to rely on the caching of the
7 # server instance on fossil-scm.org, which will keep these trunk
8 # tarballs around until the next trunk commit.
9
10 FROM alpine:latest AS builder
11 WORKDIR /tmp
12 RUN apk update \
13 && apk upgrade --no-cache \
14 && apk add --no-cache \
15 busybox-static gcc make \
16 musl-dev \
17 openssl-dev openssl-libs-static \
18 zlib-dev zlib-static \
19 && wget https://fossil-scm.org/home/tarball/src.tar.gz \
20 && tar -xf src.tar.gz \
21 && cd src \
22 && ./configure --static CFLAGS='-Os -s' \
23 && make -j
24
25 # STAGE 2: Pare that back to the bare essentials.
26
27 FROM scratch
28 ENV JAIL=/jail
29 WORKDIR ${JAIL}
30 COPY --from=builder /tmp/src/fossil ${JAIL}/bin/
31 COPY --from=builder /bin/busybox.static /bin/busybox
32 RUN [ "/bin/busybox", "--install", "/bin" ]
33 RUN mkdir -m 700 dev \
34 && mknod -m 600 dev/null c 1 3 \
35 && mknod -m 600 dev/urandom c 1 9
36
37 # Now we can run the stripped-down environment in a chroot jail, while
38 # leaving open the option to debug it live via the Busybox shell.
39
40 EXPOSE 8080/tcp
41 CMD [ \
42 "bin/fossil", "server", \
43 "--create", \
44 "--jsmode", "bundled", \
45 "--user", "admin", \
46 "repo.fossil"]
47
+74 -75
--- www/build.wiki
+++ www/build.wiki
@@ -248,85 +248,84 @@
248248
TCC += -Dsocketlen_t=int
249249
TCC += -DSQLITE_MAX_MMAP_SIZE=0
250250
</pre></blockquote>
251251
</ul>
252252
253
-<h2>5.0 Building a Static Binary on Linux using Docker</h2>
254
-
255
-Building a static binary on Linux is not as straightforward as it
256
-could be because the GNU C library requires that certain components be
257
-dynamically loadable. That can be worked around by building against a
258
-different C library, which is simplest to do by way of a container
259
-environment like [https://www.docker.com/ | Docker].
260
-
261
-The following instructions for building fossil using Docker
262
-were adapted from [https://fossil-scm.org/forum/forumpost/5dd2d61e5f | forumpost/5dd2d61e5f].
263
-These instructions assume that docker is installed and that the user running
264
-these instructions has permission to do so (i.e., they are <tt>root</tt> or
265
-are a member of the <tt>docker</tt> group).
266
-
267
-First, create a file named <tt>Dockerfile</tt> with the following contents:
268
-
269
-<pre><code>
270
-FROM alpine:edge
271
-RUN apk update \
272
- && apk upgrade \
273
- && apk add --no-cache \
274
- curl gcc make tcl \
275
- musl-dev \
276
- openssl-dev zlib-dev \
277
- openssl-libs-static zlib-static \
278
- && curl \
279
- "https://fossil-scm.org/home/tarball/fossil-src.tar.gz?name=fossil-src&uuid=trunk" \
280
- -o fossil-src.tar.gz \
281
- && tar xf fossil-src.tar.gz \
282
- && cd fossil-src \
283
- && ./configure \
284
- --static \
285
- --disable-fusefs \
286
- --with-th1-docs \
287
- --with-th1-hooks \
288
- && make
289
-</code></pre>
290
-
291
-Be sure to modify the <tt>configure</tt> flags, if desired. e.g., add <tt>--json</tt>
292
-for JSON support.
293
-
294
-From the directory containing that file, build it with docker:
295
-
296
-<pre><code># docker build -t fossil_static .</code></pre>
297
-
298
-If you get permissions errors when running that as a non-root user,
299
-be sure to add the user to the <tt>docker</tt> group before trying
300
-again.
301
-
302
-That creates a docker image and builds a static fossil binary inside
303
-it. That step will take several minutes or more, depending on the
304
-speed of the build environment.
305
-
306
-Next, create a docker container to host the image we just created:
307
-
308
-<pre><code># docker create --name fossil fossil_static</code></pre>
309
-
310
-Then copy the fossil binary from that container:
311
-
312
-<pre><code># docker cp fossil:/fossil-src/fossil fossil</code></pre>
313
-
314
-The resulting binary will be <em>huge</em> because it is built with
315
-debug info. To strip that information, reducing the size greatly:
316
-
317
-<pre><code># strip fossil</code></pre>
318
-
319
-To delete the Docker container and image (if desired), run:
320
-
321
-<pre><code># docker container rm fossil
322
-# docker image ls
323
-</code></pre>
324
-
325
-Note the IDs of the images named <tt>fossil_static</tt> and <tt>alpine</tt>, then:
326
-
327
-<pre><code>docker image rm THE_FOSSIL_ID THE_ALPINE_ID</code></pre>
253
+
254
+<h2 id="docker">5.0 Building a Docker Container</h2>
255
+
256
+Fossil ships a <tt>Dockerfile</tt> at the top of its source tree which
257
+you can build like so:
258
+
259
+<pre><code> $ docker build -t fossil --no-cache .</code></pre>
260
+
261
+If the image built successfully, you can create a container from it and
262
+test that it runs:
263
+
264
+<pre><code> $ docker run --name fossil -p 9999:8080/tcp fossil</code></pre>
265
+
266
+This shows us remapping the internal TCP listening port as 9999 on the
267
+host. As a rule, there's little point to using the "<tt>fossil server
268
+--port</tt>" feature inside a Docker container. Let it default to 8080
269
+internally, then remap it to wherever you want it on the host instead.
270
+
271
+Our stock <tt>Dockerfile</tt> configures Fossil with the default feature
272
+set, so you may wish to modify the <tt>Dockerfile</tt> to add
273
+configuration options, add APK packages to support those options, and so
274
+forth.
275
+
276
+It builds tip-of-trunk. To get a release version instead, append
277
+"<tt>?r=release</tt>" to the URL in the <tt>Dockerfile</tt>, then
278
+(re)build it.
279
+
280
+You may wish to direct Docker to copy an existing repo into the image at
281
+build time, rather than let it create a blank one automatically. Simply
282
+add this to the <tt>Dockerfile</tt> before the first "RUN" directive:
283
+
284
+<pre><code> COPY /local/path/to/my-project.fossil /jail/repo.fossil</code></pre>
285
+
286
+A potentially surprising feature of this container is that it runs
287
+Fossil as root, which causes [./chroot.md | Fossil's chroot jail
288
+feature] to kick in. Since a Docker container is a type of über-jail
289
+already, you may be wondering why we don't either:
290
+
291
+ # run <tt>fossil server --nojail</tt> to skip the internal chroot; or
292
+ # create a non-root user and force Docker to use that instead
293
+
294
+The reason is, although this container is quite stripped-down by today's
295
+standards, it's based on the [https://www.busybox.net/BusyBox.html |
296
+surprisingly powerful Busybox project]. (This author made a living for
297
+years in the early 1990s using Unix systems that were less powerful than
298
+this container.) If someone ever figured out how to make a Fossil binary
299
+execute arbitrary commands on the host or to open up a remote shell,
300
+they'd likely be able to island-hop from there into the rest of your
301
+network. We need this cute double-jail dance to keep the Fossil instance
302
+from accessing the Busybox features.
303
+
304
+We deem this risk low since a) it's never happened, that we know of;
305
+and b) we've turned off all of the risky features like TH1 docs.
306
+Nevertheless, we believe in defense-in-depth.
307
+
308
+Our 2-stage build process uses Alpine Linux only as a build host. Once
309
+we've got everything reduced to the two key static binaries — Fossil and
310
+Busybox — we throw all the rest of it away.
311
+
312
+A secondary benefit falls out of this process for free: it's arguably
313
+the easiest way to build a purely static Fossil binary for Linux. Most
314
+modern Linux distros make this surprisingly difficult, but Alpine's
315
+back-to-basics nature makes static builds work the way they used to,
316
+back in the day. If that's what you're after, you can skip the "run"
317
+command above and extract the executable from the image instead:
318
+
319
+<pre><code> $ docker create --name fossil_static fossil_static
320
+ $ docker cp fossil_static:/jail/bin/fossil .
321
+ $ docker container rm fossil_static
322
+ $ docker image rm fossil_static
323
+</code></pre>
324
+
325
+The resulting binary is the single largest file inside that container,
326
+at about 6 MiB. (It's built stripped.)
328327
329328
330329
<h2>6.0 Building on/for Android</h2>
331330
332331
<h3>6.1 Cross-compiling from Linux</h3>
333332
--- www/build.wiki
+++ www/build.wiki
@@ -248,85 +248,84 @@
248 TCC += -Dsocketlen_t=int
249 TCC += -DSQLITE_MAX_MMAP_SIZE=0
250 </pre></blockquote>
251 </ul>
252
253 <h2>5.0 Building a Static Binary on Linux using Docker</h2>
254
255 Building a static binary on Linux is not as straightforward as it
256 could be because the GNU C library requires that certain components be
257 dynamically loadable. That can be worked around by building against a
258 different C library, which is simplest to do by way of a container
259 environment like [https://www.docker.com/ | Docker].
260
261 The following instructions for building fossil using Docker
262 were adapted from [https://fossil-scm.org/forum/forumpost/5dd2d61e5f | forumpost/5dd2d61e5f].
263 These instructions assume that docker is installed and that the user running
264 these instructions has permission to do so (i.e., they are <tt>root</tt> or
265 are a member of the <tt>docker</tt> group).
266
267 First, create a file named <tt>Dockerfile</tt> with the following contents:
268
269 <pre><code>
270 FROM alpine:edge
271 RUN apk update \
272 && apk upgrade \
273 && apk add --no-cache \
274 curl gcc make tcl \
275 musl-dev \
276 openssl-dev zlib-dev \
277 openssl-libs-static zlib-static \
278 && curl \
279 "https://fossil-scm.org/home/tarball/fossil-src.tar.gz?name=fossil-src&uuid=trunk" \
280 -o fossil-src.tar.gz \
281 && tar xf fossil-src.tar.gz \
282 && cd fossil-src \
283 && ./configure \
284 --static \
285 --disable-fusefs \
286 --with-th1-docs \
287 --with-th1-hooks \
288 && make
289 </code></pre>
290
291 Be sure to modify the <tt>configure</tt> flags, if desired. e.g., add <tt>--json</tt>
292 for JSON support.
293
294 From the directory containing that file, build it with docker:
295
296 <pre><code># docker build -t fossil_static .</code></pre>
297
298 If you get permissions errors when running that as a non-root user,
299 be sure to add the user to the <tt>docker</tt> group before trying
300 again.
301
302 That creates a docker image and builds a static fossil binary inside
303 it. That step will take several minutes or more, depending on the
304 speed of the build environment.
305
306 Next, create a docker container to host the image we just created:
307
308 <pre><code># docker create --name fossil fossil_static</code></pre>
309
310 Then copy the fossil binary from that container:
311
312 <pre><code># docker cp fossil:/fossil-src/fossil fossil</code></pre>
313
314 The resulting binary will be <em>huge</em> because it is built with
315 debug info. To strip that information, reducing the size greatly:
316
317 <pre><code># strip fossil</code></pre>
318
319 To delete the Docker container and image (if desired), run:
320
321 <pre><code># docker container rm fossil
322 # docker image ls
323 </code></pre>
324
325 Note the IDs of the images named <tt>fossil_static</tt> and <tt>alpine</tt>, then:
326
327 <pre><code>docker image rm THE_FOSSIL_ID THE_ALPINE_ID</code></pre>
328
329
330 <h2>6.0 Building on/for Android</h2>
331
332 <h3>6.1 Cross-compiling from Linux</h3>
333
--- www/build.wiki
+++ www/build.wiki
@@ -248,85 +248,84 @@
248 TCC += -Dsocketlen_t=int
249 TCC += -DSQLITE_MAX_MMAP_SIZE=0
250 </pre></blockquote>
251 </ul>
252
253
254 <h2 id="docker">5.0 Building a Docker Container</h2>
255
256 Fossil ships a <tt>Dockerfile</tt> at the top of its source tree which
257 you can build like so:
258
259 <pre><code> $ docker build -t fossil --no-cache .</code></pre>
260
261 If the image built successfully, you can create a container from it and
262 test that it runs:
263
264 <pre><code> $ docker run --name fossil -p 9999:8080/tcp fossil</code></pre>
265
266 This shows us remapping the internal TCP listening port as 9999 on the
267 host. As a rule, there's little point to using the "<tt>fossil server
268 --port</tt>" feature inside a Docker container. Let it default to 8080
269 internally, then remap it to wherever you want it on the host instead.
270
271 Our stock <tt>Dockerfile</tt> configures Fossil with the default feature
272 set, so you may wish to modify the <tt>Dockerfile</tt> to add
273 configuration options, add APK packages to support those options, and so
274 forth.
275
276 It builds tip-of-trunk. To get a release version instead, append
277 "<tt>?r=release</tt>" to the URL in the <tt>Dockerfile</tt>, then
278 (re)build it.
279
280 You may wish to direct Docker to copy an existing repo into the image at
281 build time, rather than let it create a blank one automatically. Simply
282 add this to the <tt>Dockerfile</tt> before the first "RUN" directive:
283
284 <pre><code> COPY /local/path/to/my-project.fossil /jail/repo.fossil</code></pre>
285
286 A potentially surprising feature of this container is that it runs
287 Fossil as root, which causes [./chroot.md | Fossil's chroot jail
288 feature] to kick in. Since a Docker container is a type of über-jail
289 already, you may be wondering why we don't either:
290
291 # run <tt>fossil server --nojail</tt> to skip the internal chroot; or
292 # create a non-root user and force Docker to use that instead
293
294 The reason is, although this container is quite stripped-down by today's
295 standards, it's based on the [https://www.busybox.net/BusyBox.html |
296 surprisingly powerful Busybox project]. (This author made a living for
297 years in the early 1990s using Unix systems that were less powerful than
298 this container.) If someone ever figured out how to make a Fossil binary
299 execute arbitrary commands on the host or to open up a remote shell,
300 they'd likely be able to island-hop from there into the rest of your
301 network. We need this cute double-jail dance to keep the Fossil instance
302 from accessing the Busybox features.
303
304 We deem this risk low since a) it's never happened, that we know of;
305 and b) we've turned off all of the risky features like TH1 docs.
306 Nevertheless, we believe in defense-in-depth.
307
308 Our 2-stage build process uses Alpine Linux only as a build host. Once
309 we've got everything reduced to the two key static binaries — Fossil and
310 Busybox — we throw all the rest of it away.
311
312 A secondary benefit falls out of this process for free: it's arguably
313 the easiest way to build a purely static Fossil binary for Linux. Most
314 modern Linux distros make this surprisingly difficult, but Alpine's
315 back-to-basics nature makes static builds work the way they used to,
316 back in the day. If that's what you're after, you can skip the "run"
317 command above and extract the executable from the image instead:
318
319 <pre><code> $ docker create --name fossil_static fossil_static
320 $ docker cp fossil_static:/jail/bin/fossil .
321 $ docker container rm fossil_static
322 $ docker image rm fossil_static
323 </code></pre>
324
325 The resulting binary is the single largest file inside that container,
326 at about 6 MiB. (It's built stripped.)
 
327
328
329 <h2>6.0 Building on/for Android</h2>
330
331 <h3>6.1 Cross-compiling from Linux</h3>
332
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -180,12 +180,15 @@
180180
181181
This policy is particularly useful when running Fossil inside a
182182
restrictive container, anything from [./chroot.md | classic chroot
183183
jails] to modern [https://en.wikipedia.org/wiki/OS-level_virtualization
184184
| OS-level virtualization mechanisms] such as
185
-[https://en.wikipedia.org/wiki/Docker_(software) | Docker].
186
-([src:/file?name=Dockerfile&ci=trunk | We ship a <tt>Dockerfile</tt>].)
185
+[https://en.wikipedia.org/wiki/Docker_(software) | Docker]. Our
186
+([src:/file?name=Dockerfile&ci=trunk | stock <tt>Dockerfile</tt>]
187
+creates a container that's under 9 MiB on 64-bit Linux, including
188
+a capable [https://www.busybox.net/ | Busybox] environment for live
189
+debugging of the container's innards.)
187190
188191
Modern Linux systems tend to make full static linking
189192
[https://stackoverflow.com/questions/3430400/linux-static-linking-is-dead
190193
| difficult], but our official executables do statically link to OpenSSL
191194
to remove a version dependency, resulting in an executable that's around
192195
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -180,12 +180,15 @@
180
181 This policy is particularly useful when running Fossil inside a
182 restrictive container, anything from [./chroot.md | classic chroot
183 jails] to modern [https://en.wikipedia.org/wiki/OS-level_virtualization
184 | OS-level virtualization mechanisms] such as
185 [https://en.wikipedia.org/wiki/Docker_(software) | Docker].
186 ([src:/file?name=Dockerfile&ci=trunk | We ship a <tt>Dockerfile</tt>].)
 
 
 
187
188 Modern Linux systems tend to make full static linking
189 [https://stackoverflow.com/questions/3430400/linux-static-linking-is-dead
190 | difficult], but our official executables do statically link to OpenSSL
191 to remove a version dependency, resulting in an executable that's around
192
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -180,12 +180,15 @@
180
181 This policy is particularly useful when running Fossil inside a
182 restrictive container, anything from [./chroot.md | classic chroot
183 jails] to modern [https://en.wikipedia.org/wiki/OS-level_virtualization
184 | OS-level virtualization mechanisms] such as
185 [https://en.wikipedia.org/wiki/Docker_(software) | Docker]. Our
186 ([src:/file?name=Dockerfile&ci=trunk | stock <tt>Dockerfile</tt>]
187 creates a container that's under 9 MiB on 64-bit Linux, including
188 a capable [https://www.busybox.net/ | Busybox] environment for live
189 debugging of the container's innards.)
190
191 Modern Linux systems tend to make full static linking
192 [https://stackoverflow.com/questions/3430400/linux-static-linking-is-dead
193 | difficult], but our official executables do statically link to OpenSSL
194 to remove a version dependency, resulting in an executable that's around
195

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button