# 1. Installing

Audience

This section assumes a moderate level of experience installing UNIX software.

This section describes what you need to install Charliecloud and how to do so.

Note that installing and using Charliecloud can be done as a normal user with no elevated privileges, provided that user namespaces have been enabled.

## 1.1. Build and install from source

### 1.1.1. Using release tarball

We provide tarballs with a fairly standard `configure` script. Thus, build and install can be as simple as:

    $ ./configure
    $ make
    $ sudo make install

If you don’t have sudo, you can:

> - Run Charliecloud directly from the build directory; add `$BUILD_DIR/bin` to your `$PATH` and you are good to go, without `make install`.

> - Install in a prefix you have write access to, e.g. in your home directory with `./configure --prefix=~`.

`configure` will provide a detailed report on what will be built and installed, along with what dependencies are present and missing.

### 1.1.2. From Git checkout

If you obtain the source code with Git, you must build `configure` and friends yourself. To do so, you will need the following. The versions in most common distributions should be sufficient.

> - Automake

> - Autoconf

> - Python’s `pip3` package installer and its `wheel` extension

Create `configure` with:

    $ ./autogen.sh

This script has a few options; see its `--help`.

Note that Charliecloud disables Automake’s “maintainer mode” by default, so the build system (Makefiles, `configure`, etc.) will never automatically be rebuilt. You must run `autogen.sh` manually if you need this. You can also re-enable maintainer mode with `configure` if you like, though this is not a tested configuration.

### 1.1.3. `configure` options

Charliecloud’s `configure` has the following options in addition to the standard ones.

#### 1.1.3.1. Feature selection: `--disable-FOO`

By default, all features that can be built will be built and installed. You can exclude some features with:

> option | don’t build/install
> --- | ---
> `--disable-ch-image` | `ch-image` unprivileged builder & image manager
> `--disable-html` | HTML documentation
> `--disable-man` | man pages
> `--disable-seccomp` | seccomp-based root emulation (`--seccomp`)
> `--disable-syslog` | logging to syslog (see individual man pages)
> `--disable-tests` | test suite

You can also say `--enable-FOO` to fail the build if `FOO` can’t be built.

#### 1.1.3.2. Dependency selection: `--with-FOO`

There are three Python-related dependency switches:

`--with-python=SHEBANG`

  Shebang line to use for Python scripts. Default: `/usr/bin/env python3`.

`--with-sphinx-build=PATH`

  Path to `sphinx-build` executable. Default: the `sphinx-build` found first in `$PATH`.

`--with-sphinx-python=PATH`

  Path to Python used by `sphinx-build`. Default: shebang of `sphinx-build`.

Some features of `ch-run` require linking with C libraries and can be enabled or disabled with `--with` options. For a library `libfoo`, if you specify:

> - Neither `--with-foo` nor `--without-foo`: Enable `libfoo` features if both the library and its development files are found; otherwise, disable them. (E.g., if you are installing `libfoo` from your Linux distribution, you probably need both `libfoo` and `libfoo-dev` packages.)

> - `--with-foo` or `--with-foo=yes`: Insist on a build with `libfoo`; `configure` fails if it can’t be built against.

> - `--without-foo` or `--with-foo=no`: Build without `libfoo` and don’t even try to find it.

If the include files and shared libraries are not in system-default paths, you will need to provide their locations with `--with-foo-include` and `--with-foo-lib`. If the latter is given, link it into `ch-run` with `RPATH`.

The specific features and flags are:

`--with-gc`

  Use the Boehm-Demers-Weiser conservative garbage collector. (Yes, C can be a garbage-collected language. See the contributors’ guide for gory details on `ch-run` memory management.)

  `--with-gc-include=DIR`

    Directory containing `gc.h`.

  `--with-gc-lib=DIR`

    Directory containing `libgc.so`.

`--with-json`

  Enable features that require JSON parsing, currently only CDI, by linking with Dave Gamble’s cJSON library. (Note there are a few similarly-named libraries that are not what you want.)

  `--with-json-include=DIR`

    Directory containing `cJSON.h`.

  `--with-json-lib=DIR`

    Directory containing `libcjson.so`.

`--with-squashfuse`

  Internal mounting of SquashFS image using SquashFUSE. Note that many distributions still have a version that is too old.

  `--with-squashfuse-include=DIR`

    Parent of directory containing `squashfuse.h`. (SquashFUSE likes to be included as `squashfuse/squashfuse.h`.)

  `--with-squashfuse-lib=DIR`

    Directory containing `libsquashfuse_ll.so`.

#### 1.1.3.3. Less strict build: `--enable-buggy-build`

Please do not use this option routinely, as that hides bugs that we cannot find otherwise.

By default, Charliecloud builds with `CFLAGS` including `-Wall -Werror`. The principle here is that we prefer diagnostics that are as noisy as practical, so that problems are identified early and we can fix them. We prefer `-Werror` unless there is a specific reason to turn it off. For example, this approach identified a buggy `configure` test (issue #798).

Many others recommend the opposite. For example, Gentoo’s “Common mistakes” guide advises against `-Werror` because it causes breakage that is “random” and “without purpose”. There is a well-known blog post from Flameeyes that recommends `-Werror` be off by default and used by developers and testers only.

In our opinion, for Charliecloud, these warnings are most likely the result of real bugs and shouldn’t be hidden (i.e., they are neither random nor without purpose). Our code should have no warnings, regardless of compiler, and any spurious warnings should be silenced individually. We do not have the resources to test with a wide variety of compilers, so enabling `-Werror` only for development and testing, as recommended by others, means that we miss potentially important diagnostics — people typically do not pay attention to warnings, only errors.

That said, we recognize that packagers and end users just want to build the code with a minimum of hassle. Thus, we provide the `configure` flag:

`--enable-buggy-build`

  Remove `-Werror` from `CFLAGS` when building.

Don’t hesitate to use it. But if you do, we would very much appreciate if you:

> 1. File a bug explaining why! We’ll fix it.

> 2. Remove it from your package or procedure once we fix that bug.

#### 1.1.3.4. Disable bundled Lark package: `--disable-bundled-lark`

This option is minimally supported and not recommended. Use only if you really know what you are doing.

Charliecloud uses the Python package Lark for parsing Dockerfiles and image references. Because this package is developed rapidly, and recent versions have important features and bug fixes not yet available in common distributions, we bundle the package with Charliecloud.

If you prefer a separately-installed Lark, either via system packages or `pip`, you can use `./configure --disable-bundled-lark`. This excludes the bundled Lark from being installed or placed in `make dist` tarballs. It does not remove the bundled Lark from the source directory; if you run from the source directory (i.e., without installing), the bundled Lark will be used if present regardless of this option.

Bundled Lark is included in the tarballs we distribute. You can remove it and re-build `configure` with `./autogen.sh --rm-lark --no-lark`. If you are starting from a Git checkout, bundled Lark is installed by default by `./autogen.sh`, but you can prevent this with `./autogen.sh --no-lark`.

The main use case for these options is to support package maintainers. If this is you and does not meet your needs, please get in touch with us and we will help.

#### 1.1.3.5. Avoid potentially troublesome informational tests: `--disable-impolite-checks`

`configure` performs a lot of checks that do not inform decisions but are simply informational, for the report at the end. These checks replicate run-time decisions; their purpose is to offer guidance on what to expect at run time.

Some of these checks trigger alerts in some situations. for example, writing files in `/proc` confuses the Gentoo package build sandbox.

Option `--disable-impolite-checks` skips these checks. The only consequence is a somewhat less informative report.

## 1.2. Install with package manager

Charliecloud is also available using a variety of distribution and third-party package managers.

Maintained by us:

> - Spack; install with `+builder` to get `ch-image`.

> - Fedora/EPEL; check for available versions with `{yum,dnf} list charliecloud`.

Maintained by others:

> - Debian

> - Gentoo

> - NixOS

> - SUSE and openSUSE

Note that Charliecloud development moves quickly, so double-check that packages have the version and features you need.

Pull requests and other collaboration to improve the packaging situation are particularly welcome!

## 1.3. Dependencies

Charliecloud’s philosophy on dependencies is that they should be (1) minimal and (2) granular. For any given feature, we try to implement it with the minimum set of dependencies, and in any given environment, we try to make the maximum set of features available.

This section documents Charliecloud’s dependencies in detail. Do you need to read it? If you are installing Charliecloud on the same system where it will be used, probably not. `configure` will issue a report saying what will and won’t work. Otherwise, it may be useful to gain an understanding of what to expect when deploying Charliecloud.

Note that we do not rigorously track dependency versions. We update the minimum versions stated below as we encounter problems, but they are not tight bounds and may be out of date. It is worth trying even if your version is documented to be too old. Please let us know any success or failure reports.

Finally, the run-time dependencies are lazy; specific features just try to use their dependencies and fail if there’s a problem, hopefully with a useful error message. In other words, there’s no version checking or whatnot that will keep you from using a feature unless it truly doesn’t work in your environment.

### 1.3.1. User namespaces

Charliecloud’s fundamental principle of a workflow that is fully unprivileged end-to-end requires unprivileged user namespaces. In order to enable them, you need a vaguely recent Linux kernel with the feature compiled in and active.

Some distributions need configuration changes. For example:

- Debian Stretch needs sysctl `kernel.unprivileged_userns_clone=1`.

- RHEL/CentOS 7.4 and 7.5 need both a kernel command line option and a sysctl. RHEL/CentOS 7.6 and up need only the sysctl. Note that Docker does not work with user namespaces, so skip step 4 of the Red Hat instructions, i.e., don’t add `--userns-remap` to the Docker configuration (see issue #97).

Note: User namespaces always fail in a chroot with `EPERM`. If `configure` detects that it’s in a chroot, it will print a warning in its report. One common scenario where this comes up is packaging, where builds often happen in a chroot. However, like all the run-time `configure` tests, this is informational only and does not affect the build.

### 1.3.2. Supported architectures

Charliecloud should work on any architecture supported by the Linux kernel, and we have run Charliecloud containers on x86-64, ARM, and Power. However, it is currently tested only on x86_64 and ARM.

Most builders are also fairly portable; e.g., see Docker’s supported platforms.

### 1.3.3. libc

We want Charliecloud to work with any C99/POSIX libc, though it is only tested with glibc and musl, and other libc’s are very likely to have problems. (Please report these bugs!) Non-glibc libc’s will currently need a standalone libargp (see issue #1260).

### 1.3.4. Details by feature

This section is a comprehensive listing of the specific dependencies and versions by feature group. It is auto-generated from the definitive source, `configure.ac`.

Listed versions are minimums, with the caveats above. Everything needs a POSIX shell and utilities.

The next section contains notes about some of the dependencies.

#### 1.3.4.1. Building Charliecloud

required:

> - C99 compiler

> - libraries

> - $CPPFLAGS

> - $CFLAGS

> - $LDFLAGS

extended glob patterns in --unset-env:

error messages include symbolic errno constant:

garbage collection:

> - enabled

> - libgc

> - gc.h

> - GC_set_markers_count()

JSON features:

> - enabled

> - libcjson

> - cJSON.h

`ch-run` internal SquashFS mounting:

> - enabled

> - libfuse3

> - libsquashfuse_ll

> - ll.h header

documentation:

> - HTML enabled

> - man pages enabled

> - `sphinx-build` ≥ 1.2.3

> - `sphinx-build` Python

> - “docutils” module ≥ 0.14

> - “sphinx-rtd-theme” module ≥ 0.2.4

#### 1.3.4.2. Building images

with `ch-image`:

> - enabled

> - Python shebang line

> - Python in shebang ≥ 3.6

> - “lark” module

> - “requests” module ≥ 2.6.0

> - `ch-run`

with `ch-image` using build cache:

> - `ch-image`:

> - Git ≥ 2.28.1

with `ch-image` using RSYNC instruction:

> - `ch-image`:

> - rsync ≥ 3.1.0

#### 1.3.4.3. Managing container images

build from Dockerfile:

> - `ch-image` builder

> - access to an image repository

pack images from builder storage to tarball:

> - `ch-image` builder

pack images from builder storage to SquashFS:

> - `ch-image` builder

> - `mksquashfs` ≥ 4.2

Note: Pulling/pushing images from/to a repository is currently done using the builder directly.

#### 1.3.4.4. Running containers

`ch-run`:

> - user+mount namespaces

run SquashFS images:

> - manual mount with SquashFUSE ≥ 0.1.100

> - internal mount with libsquashfuse

fake system calls with seccomp(2):

> - enabled

> - tested working

writeable overlay (--write-fake):

> - fully functional

inject nVidia GPU libraries:

> - `nvidia-container-cli` ≥ 1.0.0

> - nVidia libraries & executables present

#### 1.3.4.5. Test suite

basic tests, all stages:

> - test suite enabled

> - `ch-run`

> - any builder above

> - access to Docker Hub or mirror

> - Bats ≥ 1.2.0

> - Bash ≥ 4.1

> - `wget` ≥ 1.11

more complete tests:

> - basic tests

> - documentation built

> - ShellCheck ≥ 0.9.0

> - generic sudo

debugging tests:

> - more tests

> - DOT ≥ 2.30.1

> - git2dot ≥ 0.8.3

recommended tests, tar-unpack mode:

> - basic tests

> - more tests

recommended tests, squash-unpack mode:

> - basic tests

> - more tests

> - pack/unpack SquashFS images

recommended tests, squash-mount mode:

> - recommended, squash-unpack mode:

> - internal SquashFS mounting

### 1.3.5. Notes on specific dependencies

This section describes additional details we have learned about some of the dependencies. Note that most of these are optional. It is in alphabetical order by dependency.

#### 1.3.5.1. Bash

When Bash is needed, it’s because:

> - Shell scripting is a lot easier in Bash than POSIX shell, so we use it for scripts applicable in contexts where it’s very likely Bash is already available.

> - It is required by our testing framework, Bats.

#### 1.3.5.2. Buildah

Charliecloud uses Buildah’s “rootless” mode and `ignore-chown-errors` storage configuration for a fully unprivileged workflow with no sudo and no setuid binaries. Note that in this mode, images in Buildah internal storage will have all user and group ownership flattened to UID/GID 0.

If you prefer a privileged workflow, Charliecloud can also use Buildah with setuid helpers `newuidmap` and `newgidmap`. This will not remap ownership.

To configure Buildah in rootless mode, make sure your config files are in `~/.config/containers` and they are correct. Particularly if your system also has configuration in `/etc/containers`, problems can be very hard to diagnose.

#### 1.3.5.3. C compiler

We test with GCC. Core team members use whatever version comes with their distribution.

In principle, any C99 compiler should work. Please let us know any success or failure reports.

Intel `icc` is not supported because it links extra shared libraries that our test suite can’t deal with. See PR #481.

#### 1.3.5.4. image repository access

`FROM` instructions in Dockerfiles and image pushing/pulling require access to an image repository and configuring the builder for that repository. Options include:

> - Docker Hub, or other public repository such as gitlab.com or NVIDIA’s NCG container registry.

> - A private Docker-compatible registry, such as a private Docker Hub or GitLab instance.

> - Filesystem directory, for builders that support this (e.g., `ch-image`).

#### 1.3.5.5. Python

We use Python for scripts that would be really hard to do in Bash, when we think Python is likely to be available.

#### 1.3.5.6. ShellCheck

ShellCheck is a very thorough and capable linter for shell scripts. In order to pass the full test suite, all the shell scripts need to pass ShellCheck.

While it is widely available in distributions, the packaged version is usually too old. Building from source is tricky because it’s a Haskell program, which isn’t a widely available tool chain. Fortunately, the developers provide pre-compiled static binaries on their GitHub page.

#### 1.3.5.7. Sphinx

We use Sphinx to build the documentation; the theme is sphinx-rtd-theme.

Minimum versions are listed above. Note that while anything greater than the minimum should yield readable documentation, we don’t test quality with anything other than what we use to build the website, which is usually but not always the most recent version available on PyPI.

If you’re on Debian Stretch or some version of Ubuntu, installing with `pip3` will silently install into `~/.local`, leaving the `sphinx-build` binary in `~/.local/bin`, which is often not on your path. One workaround (untested) is to run `pip3` as root, which violates principle of least privilege. A better workaround, assuming you can write to `/usr/local`, is to add the undocumented and non-standard `--system` argument to install in `/usr/local` instead. (This matches previous `pip` behavior.) See Debian bugs 725848 and 820856.

#### 1.3.5.8. SquashFS and SquashFUSE

The SquashFS workflow requires SquashFS Tools to create SquashFS archives.

To mount these archives using `ch-run`’s internal code, you need:

1. libfuse3, including:

   - development files, which are probably available in your distribution, e.g., `libfuse3-dev`. (Build time only.)

   - The `fusermount3` executable, which often comes in a distro package called something like `fuse3`. This is typically installed setuid, but Charliecloud does not need that; you can `chmod u-s` the file or build/install as a normal user.

2. SquashFUSE v0.1.105 or later, excluding v0.3.0 (we need the `libsquashfuse_ll` shared library). Version 0.3.0 contains an incompatible function signature change that was reverted in 0.4.0. This must be installed, not linked from its build directory, though it can be installed in a non-standard location.

Without these, you can still use a SquashFS workflow but must mount and unmount the filesystem archives manually. You can do this using the executables that come with SquashFUSE, and the version requirement is much less stringent.

Note

If `libfuse2` development files are available but those for `libfuse3` are not, SquashFUSE will still build and install, but the proper components will not be available, so Charliecloud’s `configure` will say it’s not found.

#### 1.3.5.9. sudo, generic

Privilege escalation via sudo is used in the test suite to:

> - Prepare fixture directories for testing filesystem permissions enforcement.

> - Test `ch-run`’s behavior under different ownership scenarios.

(Note that Charliecloud also uses `sudo docker`; see above.)

#### 1.3.5.10. Wget

Wget is used to demonstrate building an image without a builder (the main test image used to exercise Charliecloud itself).

## 1.4. Command line tab completion

Charliecloud offers experimental tab completion for Bash users. This feature is currently implemented for `ch-image`, `ch-run`, and `ch-convert`. For details on setting up tab completion, as well as general documentation, see ch-completion.bash.