Home / Alt manpages / subuid(5)

  • subuid(5)
  • File format
  • linux

Configure Safe Subordinate UID Ranges in /etc/subuid

You will finish with a checked subordinate user ID range that a user namespace can use, plus a reversible way to remove it. The examples match shadow-utils 4.13, provided here by Ubuntu package passwd version 1:4.13+dfsg1-4ubuntu3.2.

Allow about ten minutes. You need a shell, an account to which the range will belong, and sudo access for changes. Reading the file is unprivileged on this machine; editing it or using usermod requires elevated privileges. This guide changes account configuration, so take a copy before altering an existing range.

1. Check which delegation source is active

The subuid(5) configuration can obtain ranges from local files or from a subid plugin selected in /etc/nsswitch.conf. The value is the single subid field. If it is files, entries come from /etc/subuid. If the value names a plugin, shadow-utils looks for a library named libsubid_VALUE.so; a missing value or plugin falls back to the files source.

$ grep '^subid:' /etc/nsswitch.conf || printf '%s\n' 'No subid entry: check the files fallback'

No output is expected here because this machine has no explicit subid line, so the local files fallback is in use. Do not assume that an empty grep means that every system uses the same source. Check the file on the host you are changing.

Checkpoint

Continue with /etc/subuid only when the selected source is local files, or when you have confirmed that the configured plugin also reads and writes that file. The useradd command only creates entries in /etc/subuid when file delegation is active.

2. Read the existing ranges

Each non-comment entry has three colon-separated fields: a login name or numeric UID, the first subordinate UID, and the number of subordinate UIDs in the range.

$ sudo awk -F: 'NF == 3 { printf "%s: first=%s count=%s last=%s\n", $1, $2, $3, $2 + $3 - 1 }' /etc/subuid
ftptest: first=100000 count=65536 last=165535
robin: first=165536 count=65536 last=231071
mailrelay: first=231072 count=65536 last=296607
dani: first=296608 count=65536 last=362143

The last value above is calculated, not stored in the file. For example, robin:165536:65536 covers 165536 through 231071 inclusive. Multiple ranges may belong to one user, so inspect all matching lines before adding another.

Do not edit a line by changing the count casually. A larger count changes the IDs delegated to that account and may overlap an allocation that belongs to somebody else. Keep a backup and choose a range that your host's namespace and storage design have reserved for this purpose.

3. Choose a range without guessing

For a new allocation, write down the first UID and count before running a command. This example reserves 65536 IDs beginning at 400000 for an existing account named alice. Replace both placeholders with values approved for your machine.

FIRST=400000
COUNT=65536
printf 'Proposed range: %s-%s\n' "$FIRST" "$((FIRST + COUNT - 1))"
grep -v '^#' /etc/subuid | awk -F: -v first="$FIRST" -v count="$COUNT" '
  BEGIN { last = first + count - 1 }
  NF == 3 {
    other_last = $2 + $3 - 1
    if (first <= other_last && last >= $2)
      print "overlap with " $1 ": " $2 "-" other_last
  }'

Expected output for the example is only the proposed range, with no line beginning overlap with. This check is a planning aid, not a complete policy decision: also account for ranges managed by another identity service, containers, or machines sharing the same UID space.

4. Add the range with usermod

Make a root-owned backup immediately before the change, then use usermod. The option accepts a hyphenated first-to-last range, not a first-and-count pair.

$ sudo cp --preserve=all /etc/subuid /etc/subuid.before-alice
$ sudo usermod --add-subuids 400000-465535 alice
$ grep '^alice:' /etc/subuid
alice:400000:65536

--add-subuids may be supplied more than once to add multiple ranges. The installed manual says this operation does not validate the range against SUB_UID_MIN, SUB_UID_MAX or SUB_UID_COUNT in /etc/login.defs. Validate your chosen range yourself before accepting a successful command.

Checkpoint

Confirm that the stored count is exactly 465535 - 400000 + 1, which is 65536. A successful usermod exit status only says the file operation completed; it does not prove that your namespace design is safe.

5. Test the file and understand its boundary

Re-run the range display and check that the account has the intended entries:

$ sudo awk -F: '$1 == "alice" { printf "%s: %s-%s (%s IDs)\n", $1, $2, $2 + $3 - 1, $3 }' /etc/subuid
alice: 400000-465535 (65536 IDs)
$ sudo test -s /etc/subuid && echo 'subuid file is non-empty'
subuid file is non-empty

/etc/subuid describes what an ordinary user may pass to newuidmap when configuring a user namespace. It does not itself create a namespace, map IDs, start a container or grant a process broader access. The mapping operation must still be performed by the relevant namespace tooling and must obey its own checks.

For large files, the manual recommends numeric UIDs instead of login names once there are roughly 10000 to 100000 or more entries, because parsing names can become noticeably slower. That is a performance choice, not a reason to change a small file to numeric form without a migration plan.

6. Undo an accidental addition

Do not remove an existing range until you know which namespace users depend on it. Removing delegation can break a container or other service, although it does not rewrite files owned by the subordinate IDs. Stop or reconfigure dependent workloads first.

For the example addition, make another backup and remove the exact same first-to-last range:

$ sudo cp --preserve=all /etc/subuid /etc/subuid.before-undo
$ sudo usermod --del-subuids 400000-465535 alice
$ grep '^alice:' /etc/subuid || echo 'alice has no remaining subuid entry for that exact allocation'

If the command fails or the result is not what you expected, restore the last backup only after checking that no other administrator changed the file meanwhile:

$ sudo cp --preserve=all /etc/subuid.before-undo /etc/subuid
$ sudo awk -F: '$1 == "alice" { print }' /etc/subuid

Restoring a file is an administrative change. Keep the backup until the affected workloads have been checked, then remove old backups deliberately rather than as part of a blind script.

Done means

  • The active subid source is known, and local file edits are being used only when file delegation applies.
  • Every entry has a login name or UID, a first subordinate UID and a count, separated by colons.
  • The selected range was checked against existing entries and recorded as an inclusive first-to-last interval.
  • usermod added or removed the exact intended range, with a root-owned backup retained.
  • The final mapping has been verified, and dependent namespaces were considered before any removal.