Build a Safe containerd 2.3 Config from Defaults

Generate containerd's defaults, make one deliberate change, and you get a config you can actually explain during an incident. By the end of this guide you will have a versioned containerd TOML file, a backup of the previous configuration, and a small change you can verify without guessing at undocumented defaults. The examples were checked with containerd 2.3.5 from the installed containerd.io package. Allow about 15 minutes, plus one containerd restart if you install the file at the system path.

Before you start

You need a shell on the containerd host, the containerd executable, and permission to read or write /etc/containerd if that is where the service gets its configuration. The commands that create a file in your home or working directory do not need elevated privileges. Commands that write under /etc, copy a system file, or restart the service do.

This guide changes configuration, which can interrupt container workloads when the daemon is restarted. Do not apply the final step during a deployment or maintenance window you cannot afford to interrupt. The generated file is a starting point, not a promise that every plugin on another host has the same defaults.

Checkpoint 1: identify the daemon and its config path

  1. Check the installed version and the command-line default for the configuration file.
containerd --version
containerd --help | sed -n '/--config/,+7p'

On the machine used for this guide, the first command reports containerd containerd v2.3.5. The daemon's default config path is /etc/containerd/config.toml. A file elsewhere is still usable when you pass its path with --config or -c; that does not change the system default.

Checkpoint 2: generate a matching baseline

  1. Write the running binary's default configuration into a private file.
umask 077
mkdir -p "$HOME/containerd-config-work"
containerd config default > "$HOME/containerd-config-work/config.toml"
sed -n '1,24p' "$HOME/containerd-config-work/config.toml"

The subcommand is containerd config default, even though the installed reference is named containerd-config(8). It prints TOML to standard output and does not start the daemon. On containerd 2.3.5, the output begins with version = 4, root = '/var/lib/containerd', state = '/run/containerd', and an import for /etc/containerd/conf.d/*.toml.

Keep this generated file as your comparison point. The root directory holds containerd metadata; the state directory holds runtime state. Changing either can make existing workloads appear to be missing, so leave them alone unless you have a migration plan.

Checkpoint 3: make one deliberate change

  1. Edit the private copy and set the debug log level to info.
editor "$HOME/containerd-config-work/config.toml"
grep -n -A4 '^\[debug\]' "$HOME/containerd-config-work/config.toml"

The generated file may contain an empty debug level because plugin defaults vary with the generated release. If you need a readable daemon log while diagnosing a problem, the documented debug levels are trace, debug, info, warn, error, fatal, and panic. Set only the field you intend to change:

[debug]
  level = 'info'

Do not copy a version 1 or version 2 example into a version 4 file without checking its plugin names. The configuration reference says that version 4 uses server plugins such as io.containerd.server.v1.grpc and io.containerd.server.v1.ttrpc. The older top-level [grpc], [ttrpc], [debug], and [metrics] sections are deprecated in version 4 and are migrated automatically, but a fresh file should follow the generated layout.

Checkpoint 4: install with a rollback copy

First inspect the destination. This prevents an accidental overwrite of a host-specific file.

sudo ls -l /etc/containerd/config.toml

If the file exists, make a timestamped backup before replacing it. This is a privileged operation and the backup filename is deliberately explicit:

sudo cp -a /etc/containerd/config.toml /etc/containerd/config.toml.before-containerd-guide
sudo install -o root -g root -m 0644 "$HOME/containerd-config-work/config.toml" /etc/containerd/config.toml

If there was no previous file, skip the cp command. Keep the generated copy under your home directory as a second recovery point. Never delete the backup merely because the first restart succeeds; a later edit can still introduce the failure.

Checkpoint 5: restart and verify the result

  1. Restart the service through the init system used on this host, then inspect its status.
sudo systemctl restart containerd
sudo systemctl --no-pager --full status containerd
containerd --version

A successful status shows the service as active. The version command only checks the executable, so treat the service status and its journal as the useful configuration checks:

sudo journalctl -u containerd -n 80 --no-pager

If the service fails, stop using the new file. Restore the backup and restart:

sudo cp -a /etc/containerd/config.toml.before-containerd-guide /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl --no-pager --full status containerd

That recovery command assumes the backup exists. If this was a new configuration and there was no prior file, move the installed file aside instead of inventing a replacement:

sudo mv /etc/containerd/config.toml /etc/containerd/config.toml.failed
sudo systemctl restart containerd

Do not troubleshoot by changing several values at once. Compare the failed file with the generated baseline, remove the last change, and read the journal for the first parse or plugin error.

Configuration traps worth checking

Done means