User Namespace Remapping in Docker

User Namespace Remapping in Docker

How Docker can make "root" inside a container mean absolutely nothing on the real host machine — closing one of the most dangerous gaps in container security, without changing a single line of your application.

Picture a hotel that issues every guest a keycard labeled “Master Key” — because, inside their own room, that’s exactly what it is: it opens the minibar, the safe, the thermostat controls, everything. The problem appears the moment someone realizes the same card, physically identical, also happens to open the manager’s office, the security room, and every other guest’s door too. For years, this was roughly the situation with Docker containers: a process running as “root” inside a container carried the user ID 0, and user ID 0 is a special, all-powerful identity to the Linux kernel — regardless of which container claims to be using it. If a container process ever broke out of its intended boundary, it could find itself standing in the hotel’s security office, not just its own room. User namespace remapping is Docker’s fix: it gives every container’s “root” a keycard that only ever opens doors inside that one room, no matter what the label printed on it says. This article explains, from first principles, exactly how that trick works.

1Core Concepts

Before we can appreciate the fix, we need to understand precisely what problem it fixes, and why that problem exists at all.

What does “root” actually mean to Linux?

On a Linux system, every process runs as a particular user, identified not by a name like “root” or “alice” but by a plain number called a User ID, or UID. The number 0 is reserved, by convention baked deep into the Linux kernel itself, for the “root” or superuser account — a user allowed to bypass almost every permission check on the system: reading any file, killing any process, loading kernel modules, mounting filesystems, and more. The name “root” is just a human-friendly label; to the kernel, all that matters is the number 0.

Everyday Analogy

Think of UID 0 like a building’s master key, identified purely by its physical shape, not by any name engraved on it. Any door lock that recognizes “this shape of key opens me” will open for it — the lock doesn’t know or care who is holding it, or what building they think they’re standing in.

Why is this a problem for containers specifically?

A container is not a separate computer — it is a regular Linux process, given the illusion of isolation through several kernel features (namespaces and control groups) that make it *look* like it has its own filesystem, its own process list, and its own network stack. Critically, without user namespace remapping, a process with UID 0 inside a container is also UID 0 on the underlying host machine — it’s the exact same master key shape, just being used inside a room that’s been decorated to look separate. If a vulnerability in the container runtime, the kernel, or the containerized application ever allows a process to “escape” its container boundary — for example, through a kernel bug or a badly configured mount — that escaping process carries its UID 0 identity straight out into the real host operating system, instantly becoming genuine root on the actual machine.

!
The Core Risk

Without remapping, “root in the container” and “root on the host” are the same identity as far as the kernel is concerned. Container isolation (namespaces, cgroups) makes escape hard, but it is not the same guarantee as making escape harmless — remapping addresses the second half of that problem.

The elegant solution: teach the kernel a different mapping

Linux has long supported a kernel feature called user namespaces (distinct from, but related to, the other namespaces containers use, like network or mount namespaces). A user namespace lets the kernel maintain a translation table: “inside this namespace, UID 0 actually corresponds to UID 231072 on the real system; UID 1 corresponds to 231073,” and so on. A process can genuinely believe, and behave as though, it is UID 0 — full permissions, full confidence — while the kernel quietly enforces that, outside its own namespace, it is nothing more than an ordinary, unprivileged, high-numbered user with no special powers at all.

Term

UID / GID

User ID / Group ID — the numeric identities the Linux kernel actually uses for permission checks, underneath human-readable usernames.

Term

User Namespace

A kernel construct that maps a range of UIDs/GIDs “inside” a namespace to a different range “outside” it, on the host.

Term

Remapping

Docker’s feature that automatically creates and applies this mapping to every container, without requiring the container image itself to know or care.

Term

subuid / subgid

Standard Linux configuration files that reserve blocks of UIDs and GIDs on the host for exactly this kind of remapping use.

“Remapping doesn’t make root inside the container less powerful in its own room — it makes sure that room is the only place its power applies.”

2Architecture & Components

Let’s identify every moving piece that Docker coordinates to make remapping work.

The Docker daemon: where the decision is made

User namespace remapping is a setting on the Docker daemon itself (dockerd), the background service that manages all containers on a host — not a per-container, per-run setting you toggle each time. It’s typically switched on once, system-wide, through the daemon’s configuration file, after which every new container created on that host is automatically subject to remapping (with a documented opt-out for specific containers that genuinely need to share the host’s real UID space).

Component

dockerd (the daemon)

Reads the remapping configuration at startup and applies it to every container it subsequently creates.

Component

/etc/subuid & /etc/subgid

Standard Linux files listing which usernames own which ranges of “sub” UIDs and GIDs — Docker reads these to know which host ID range it’s allowed to use for remapping.

Component

The remapped root user

A dedicated, otherwise-ordinary system user Docker creates or designates (commonly named dockremap) that owns the host-side UID range containers get mapped into.

Component

The kernel’s user namespace subsystem

The actual enforcement mechanism — a feature of the Linux kernel itself, not something Docker implements from scratch, that Docker configures per container.

How the mapping range is chosen

By default, Docker reserves a contiguous block of UIDs — typically starting somewhere well above the range used by ordinary system accounts, such as 100000 or higher — and a matching block of GIDs, both usually sized at 65,536 IDs, matching the entire range of UIDs a single container is likely to ever use internally (0 through 65,535 covers essentially all conventional Linux UID usage). Every container UID from 0 up to 65,535 gets mapped, one-to-one, onto this reserved host range: container UID 0 becomes host UID 100000, container UID 1 becomes host UID 100001, and so forth.

flowchart LR
    subgraph Container["Inside the Container"]
        C0["UID 0 (root)"]
        C1["UID 1000 (app user)"]
    end
    subgraph Host["On the Real Host"]
        H0["UID 100000 (unprivileged)"]
        H1["UID 101000 (unprivileged)"]
    end
    C0 -- kernel remaps --> H0
    C1 -- kernel remaps --> H1
    style Container fill:#111111,stroke:#dc2626,color:#ffffff
    

Fig. 1 — Every UID a container process could ever hold is translated to a distinct, unprivileged, high-numbered UID on the actual host.

File ownership follows the same translation

The mapping doesn’t only apply to running processes — it also applies to file ownership. A file created by “root” inside the container (UID 0) is, on the host’s real filesystem, actually owned by the mapped host UID (say, 100000), not by the host’s genuine root account. This is why, if you inspect a container’s files directly from the host filesystem with remapping enabled, ownership numbers look unusually large and unfamiliar — that’s the remapping working exactly as intended.

i
One Mapping Per Daemon (By Default)

Out of the box, all containers on a given host typically share the same single remapped UID/GID range. Docker also supports configuring distinct ranges per user or per daemon instance for finer-grained isolation between different sets of containers, at the cost of extra configuration complexity.

3Internal Working

Now let’s trace exactly what the kernel and Docker do, mechanically, from daemon startup through to a running, remapped container.

Step one: daemon configuration is read at startup

When the Docker daemon starts with user namespace remapping enabled (via the userns-remap setting), it first determines which host user’s subuid/subgid ranges to use — either a specific username the administrator names, or an automatically created dedicated user reserved for this purpose. It reads the corresponding ranges from /etc/subuid and /etc/subgid.

Step two: a dedicated user namespace is created

The kernel supports creating new user namespaces via a specific system call. Docker uses this capability, together with the ranges it just read, to establish a UID/GID mapping: a formal kernel-level table declaring “UID X inside this namespace equals UID Y on the host,” repeated across the full reserved range.

Step three: every container process is launched inside that namespace

When a container starts, instead of launching its main process directly in the host’s default (root) user namespace, Docker launches it inside the newly created, remapped user namespace. From that moment on, every UID and GID the process sees, sets, or is checked against is automatically passed through the kernel’s translation table in both directions — the process’s own view is always in terms of the “inside” numbers (0, 1, 1000, etc.), while every permission check the kernel actually performs uses the real “outside” numbers.

1
USER NAMESPACE
PER REMAPPED CONFIGURATION
65536
TYPICAL UID/GID
RANGE SIZE
2
FILES CONSULTED
(subuid + subgid)

Step four: filesystem operations translate ownership transparently

When the containerized process creates a file while believing itself to be UID 0, the kernel’s virtual filesystem layer writes the actual, translated host UID (say, 100000) as that file’s owner on disk. Later, when the same or another process inside that same namespace reads the file’s ownership, the kernel translates it back the other direction, showing UID 0 again — the illusion is consistently maintained in both directions, for every operation, without the container’s software ever being aware any translation is happening.

Everyday Analogy

It works like an interpreter at a diplomatic meeting who translates every sentence in both directions, so fluently and instantly that both parties feel like they’re speaking directly to each other in their own language — neither side needs to know a translation is happening at all, yet everything they say and hear is fully translated, consistently, every single time.

Step five: privilege checks resolve against the real, unprivileged UID

This is the step that actually delivers the security benefit. When the containerized “root” process attempts something that touches the real host system directly — say, trying to access a host device file, or a file outside its container’s filesystem it somehow gained a path to — the kernel evaluates that request using the real, translated, unprivileged UID (100000), not UID 0. An unprivileged UID 100000 has no special powers on the host whatsoever, so the operation is denied exactly as it would be for any ordinary, non-root host user.

4Data Flow & Lifecycle

Let’s walk through the full lifecycle, from a fresh host installation to a container’s eventual removal.

1

Prerequisite: subuid/subgid ranges exist

The host system already has, or Docker creates, entries in /etc/subuid and /etc/subgid reserving a block of IDs for remapping use.

2

Daemon configuration

An administrator enables userns-remap in the Docker daemon’s configuration and restarts the daemon.

3

Daemon re-initialization

Docker reads the relevant subuid/subgid ranges and prepares the mapping tables it will apply to every subsequently created container.

4

Container creation

A new container is created; Docker allocates it into the remapped user namespace rather than the host’s default namespace.

5

Live execution

All of the container’s process activity and file operations pass transparently through the kernel’s UID/GID translation for the lifetime of the container.

6

Persisted data retains mapped ownership

Any files the container wrote to a volume or bind mount keep their translated, high-numbered host ownership even after the container stops, until something else changes it.

7

Container removal

When the container is removed, its namespace association ends; the reserved UID/GID range itself remains available for reuse by future containers under the same daemon configuration.

What happens across a container restart or image update

As long as the daemon’s remapping configuration doesn’t change, restarting a container, or replacing it with an updated image, results in the exact same mapping being applied again. The mapping is a property of the daemon’s configuration, not of any individual container instance, so it remains stable and predictable across the ordinary container lifecycle.

!
A Practical Lifecycle Snag

Files written to a bind-mounted host directory by a remapped container will show the translated, high-numbered UID as their owner when viewed directly from the host. Tools or scripts on the host expecting familiar, low-numbered ownership need to account for this, or explicitly adjust permissions afterward.

5Advantages, Disadvantages & Trade-offs

As with any security control, remapping is a genuine trade, not a free upgrade.

Advantages

  • Neutralizes one of the most severe consequences of a container escape: gaining genuine root on the host, even if the container process itself believes it is root.
  • Requires no changes to the containerized application — it works transparently at the kernel level for essentially any image.
  • Adds a strong extra layer of defense in depth on top of existing namespace and cgroup isolation, rather than replacing them.
  • Provides meaningful protection even against unknown, future container-escape vulnerabilities, because it limits the *consequences* of escape rather than depending on preventing it.
  • Aligns naturally with least-privilege security principles increasingly expected in regulated or security-conscious environments.

Disadvantages & Trade-offs

  • Historically incompatible, or only partially compatible, with certain Docker features, such as sharing the host’s network or IPC namespace with specific containers, in some Docker versions.
  • Complicates workflows that expect container file ownership to match familiar, low-numbered host UIDs, particularly for bind-mounted volumes.
  • Applies at the daemon level by default, meaning it’s an all-or-nothing setting for a given Docker installation unless more advanced per-user configuration is used.
  • Certain container images or workloads genuinely requiring real host-level privileges (rare, but they exist) need explicit, deliberate exceptions.
  • Adds a small, generally negligible amount of kernel-level translation overhead to UID/GID-related operations.

When enabling it is close to a no-brainer

Any multi-tenant environment — where containers from different teams, customers, or trust levels share the same underlying host — benefits enormously from remapping, because it directly limits the blast radius of a single compromised container. The same applies to any host running containers built from third-party or less-trusted images, where the possibility of an undiscovered vulnerability is inherently higher.

When teams hesitate, and why that hesitation is often outdated

Some teams avoid remapping because of past friction with specific advanced networking or storage configurations. Docker’s own compatibility with these features has matured considerably over time, and many of the older limitations have been resolved or worked around through documented configuration patterns, so it is worth re-evaluating older assumptions against current Docker versions before ruling remapping out.

Rule of Thumb

If you wouldn’t hand a random contractor the actual root password to your host machine, don’t run their container image without user namespace remapping enabled — the two situations carry surprisingly similar risk if a container escape ever occurs.

6Security

Let’s examine precisely what threat model this feature addresses, and just as importantly, what it does not.

The specific attack it defuses

The canonical scenario user namespace remapping defends against is a privilege-escalating container escape: a bug in the container runtime, the kernel, or a misconfiguration (such as an overly permissive mount) that lets a process step outside its container’s intended boundary. Without remapping, if that escaping process was root inside the container, it is root outside it too — full, unrestricted control of the host. With remapping enabled, the same escaping process is still just an ordinary, unprivileged, oddly-numbered user on the host, unable to read other users’ files, install software, or access most of the system.

Scenario

Kernel vulnerability exploited

Even if a container process exploits a kernel bug to briefly step outside its container’s filesystem view, its underlying UID remains the mapped, unprivileged one for any permission check the kernel performs.

Scenario

Misconfigured mount

If a container is accidentally given access to a sensitive host path, remapping still limits what its “root” user can actually do with that access, since it isn’t real root.

Scenario

Malicious or compromised image

A deliberately hostile image that assumes it can leverage container root for host-level mischief instead finds itself constrained to an unprivileged identity.

What remapping does not protect against

Remapping does not prevent a container escape from happening in the first place — it limits the *damage* an escape can do. It also does nothing to protect data or secrets that are simply exposed carelessly inside the container itself (an attacker who compromises the containerized application directly, without ever needing to escape, still sees whatever that application can see). Nor does it replace the need for other standard container hardening practices, such as running containers with a non-root user by convention, dropping unnecessary Linux capabilities, using read-only filesystems where possible, and applying seccomp or AppArmor/SELinux profiles.

ADR-EX-001 · Anti-Pattern Avoid
The Mistake

Treating user namespace remapping as a full substitute for running containers as a non-root user, or for other hardening controls like capability dropping.

Why It’s Risky

Remapping addresses one specific failure mode — escape leading to real host root — but does not reduce what a compromised, still-contained application can access or do within its own container boundary.

The Better Approach

Layer remapping alongside non-root container users, minimal Linux capabilities, read-only root filesystems, and mandatory access control profiles, as complementary, independent defenses.

Interviewer’s Corner

A frequent system design and security interview question: “If a container’s main process already runs as a non-root user inside the container, do you still need user namespace remapping?” The strong answer is yes — a non-root user reduces what the containerized application itself can do, but a *separate* escalation path (like a kernel exploit granting UID 0 mid-attack, or a poorly written setuid binary inside the image) could still hand an attacker UID 0 inside the container. Remapping ensures that even that UID 0 carries no special power once it’s outside the container’s own namespace, providing protection that is independent of, and complementary to, the application’s own configured user.

7Monitoring, Logging & Metrics

Remapping is largely invisible when working correctly — here’s how to confirm it’s actually active and stays that way.

SignalWhat it tells youWhere to look
Daemon info outputConfirms whether user namespace remapping is currently active for the whole daemondocker info on the host
Container process UID (host view)Verifies a specific running container’s processes actually show a high, unprivileged UID from the host’s perspectiveHost process listing tools, filtered to the container’s process IDs
File ownership on mounted volumesConfirms files written by the container carry the expected translated, high-numbered ownershipHost filesystem listing of the relevant mount path
subuid/subgid file contentsConfirms the reserved ID range configuration matches what’s expected and hasn’t drifted/etc/subuid and /etc/subgid
Daemon startup logsSurfaces any errors or warnings if remapping configuration failed to apply at daemon startDocker daemon logs

The single most useful verification habit

The most direct way to build confidence that remapping is genuinely active is to compare a process’s UID as reported *inside* a running container against the UID of that same process as seen *from the host*. Inside, it should show the familiar low number (commonly 0 for root); from the host’s own process view, it should show the translated, high-numbered UID instead. Seeing this mismatch consistently is direct, first-hand confirmation that the translation is working exactly as designed.

Everyday Analogy

It’s like checking a hotel guest’s card twice: once by asking the guest what their card is called (“the Master Key,” they’ll say, entirely sincerely), and once by asking hotel security which doors that literal, physical card actually opens. A correctly remapped system will always give you two different-sounding answers to what’s really the same underlying object.

Operational checklist

  • After any change to daemon configuration, confirm remapping status again rather than assuming the setting took effect.
  • Track which images or containers, if any, have been deliberately exempted from remapping, and periodically re-justify each exemption.
  • Audit bind-mounted host directories for unexpected ownership patterns that might indicate a misconfigured or unintended remapping range.
  • Include remapping status as a standard item in any host security baseline or compliance checklist for container infrastructure.

8Design Patterns & Anti-patterns

How mature platform teams structure their use of this feature, and traps that catch less experienced ones.

Pattern

Enable at the daemon level as a baseline

Turn remapping on for the entire Docker installation by default, treating any container that needs an exception as a deliberate, documented, and reviewed decision.

Pattern

Combine with non-root container users

Configure images to run as a non-root user internally as well, so that remapping and in-container least-privilege reinforce each other rather than relying on just one.

Pattern

Isolate genuinely privileged workloads separately

Rather than disabling remapping cluster-wide for a handful of workloads that need real host privileges, run those specific workloads on a dedicated host or daemon instance with its own explicit configuration.

Anti-pattern

Disabling remapping cluster-wide for one exceptional case

Turning off a strong, blanket security control for an entire fleet of hosts just to accommodate one workload’s edge-case requirement removes protection far more broadly than the actual need justifies.

The “convenience during debugging” anti-pattern

A subtle trap: temporarily disabling remapping to make debugging file-permission confusion “easier,” then forgetting to re-enable it afterward. Because the effects of missing remapping are invisible during normal operation — everything simply works, right up until an escape attempt occurs — this kind of drift can go unnoticed for a long time. Treating remapping status as something to verify, not just configure once, closes this gap.

ADR-EX-002 · Design Pattern Recommended
The Pattern

Bake remapping configuration into infrastructure-as-code or golden host images, rather than configuring it manually per host, and add an automated check that fails a host’s provisioning if remapping isn’t active as expected.

Why It Works

It turns a security setting that could silently drift or be forgotten into a codified, version-controlled, and continuously verified property of every host in the fleet.

9Best Practices & Common Mistakes

Practical guidance for rolling this out on a real fleet of hosts without unpleasant surprises.

Best Practices

  • Test remapping thoroughly in a staging environment first, particularly for workloads using bind mounts, shared volumes, or advanced networking modes.
  • Document the exact reserved subuid/subgid range in use, and avoid letting it overlap with real system account UID ranges.
  • Plan explicitly for how bind-mounted host directories will handle the translated ownership, rather than discovering the issue mid-incident.
  • Pair remapping with the other standard container hardening practices — non-root users, minimal capabilities, read-only filesystems — rather than relying on it alone.
  • Keep Docker itself reasonably up to date, since compatibility between remapping and other features has genuinely improved across releases.

Common Mistakes

  • Assuming remapping is enabled by default — historically, it has been an opt-in setting requiring explicit daemon configuration.
  • Being surprised by unfamiliar, high-numbered file ownership on bind-mounted host directories, and misdiagnosing it as a bug rather than expected behavior.
  • Disabling remapping broadly to solve a narrow, specific compatibility issue, rather than seeking a targeted workaround or exception.
  • Forgetting that a single daemon typically applies one shared mapping to all its containers by default, which affects how isolated different containers’ mapped identities really are from each other.
  • Never actually verifying, from the host’s point of view, that a “remapped” container’s processes show the expected translated UID.
i
A Useful Habit

Before rolling remapping out fleet-wide, run your standard suite of containerized workloads against it in staging and specifically inspect any bind-mounted directories afterward — this single step catches the majority of real-world compatibility surprises early.

10Real-world & Industry Examples

Where this kind of defense shows up in real operational practice across the industry.

Multi-tenant container hosting platforms

Any platform that runs containers on behalf of multiple different customers on shared infrastructure treats container escape as one of its most serious threat scenarios, since one tenant’s compromised container could otherwise threaten every other tenant sharing that host. User namespace remapping is a standard part of the defense-in-depth stack such platforms build around container isolation.

Financial and regulated industries

Organizations operating under strict security compliance regimes commonly document and audit their container runtime hardening posture as part of regulatory or customer security reviews, and least-privilege identity mapping for containerized processes is a natural, easily explainable control to include in that posture.

Kubernetes and orchestrated environments

The same underlying Linux kernel user namespace mechanism that Docker’s remapping relies on has increasingly been adopted in Kubernetes itself, reflecting a broader industry trend of treating “container root does not mean host root” as an increasingly expected baseline for container security, rather than an advanced, optional add-on.

1
SHARED HOST KERNEL
ACROSS ALL CONTAINERS
0
CODE CHANGES NEEDED
IN CONTAINERIZED APPS
2015+
ROUGH ERA THIS FEATURE
BECAME AVAILABLE IN DOCKER

The recurring theme across these examples is that as soon as containers from different trust levels ever share a physical or virtual host — whether that’s different customers, different teams, or simply different, less-trusted third-party images — the case for identity remapping stops being a nice-to-have and starts being a baseline expectation of responsible container operations.

11Frequently Asked Questions

Q1Does enabling user namespace remapping require changing my container images?
No. The remapping happens entirely at the kernel and Docker daemon level. Images continue to run their processes as whichever UID they normally use internally, unaware that any translation is occurring.
Q2If my container already runs as a non-root user, do I still need this feature?
Yes. A non-root container user reduces what the application itself can do, but doesn’t protect against a separate privilege-escalation path granting UID 0 inside the container mid-attack. Remapping ensures even that UID 0 carries no real power outside the container.
Q3Why do files on my bind-mounted host directory show strange, high-numbered ownership?
That’s the remapping working as intended — a file “owned by root” inside the container is actually owned by the translated, high-numbered host UID on the real filesystem, since that’s the true identity the kernel enforces outside the container’s namespace.
Q4Is remapping enabled by default in Docker?
No, historically this has required explicit configuration on the Docker daemon. It’s an opt-in security hardening feature rather than an automatic default, so administrators need to deliberately enable and verify it.
Q5Does remapping protect against a compromised application inside the container?
Not directly. If an attacker compromises the application itself without ever escaping the container, they can still see and do whatever that application’s own permissions allow inside the container. Remapping specifically limits the damage if the attacker manages to escape the container boundary entirely.
Q6Can different containers on the same host have different remapped ranges?
By default, containers under a single Docker daemon configuration typically share one common mapping, though Docker does support more advanced, finer-grained configurations for distinguishing ranges per user in certain setups.
Q7Does this feature slow down my containers?
The UID/GID translation performed by the kernel is extremely lightweight, and any performance impact is generally negligible for the overwhelming majority of workloads.
Q8What’s the relationship between user namespaces and the other namespaces containers use, like network namespaces?
They’re independent kernel features that Docker combines together. Network, mount, and process ID namespaces create the isolated “view” a container has of the system; the user namespace specifically governs identity and permission translation, addressing a different, complementary aspect of isolation.
Q9Is there ever a legitimate reason to run a specific container without remapping?
Occasionally, yes — certain workloads genuinely need to interact with host-level resources using real privileged identities. These should be treated as deliberate, narrowly scoped, and well-documented exceptions rather than a reason to disable remapping broadly.

12Summary and Key Takeaways

What to remember

  • User namespace remapping ensures that a process which is UID 0 (root) inside a container is actually a different, unprivileged, high-numbered UID on the real host — closing a serious gap where container “root” and host root used to be the same identity.
  • It relies on the Linux kernel’s own user namespace feature, configured via reserved subuid/subgid ranges, and applied by the Docker daemon to every container by default once enabled.
  • The translation is fully transparent to the containerized application — no code changes, no awareness inside the container that any remapping is happening.
  • It specifically defends against the worst-case consequence of a container escape: gaining genuine host root, rather than preventing escapes from happening in the first place.
  • It should be treated as one layer of defense in depth, alongside non-root container users, minimal Linux capabilities, and mandatory access control profiles — not a replacement for any of them.
  • Real-world friction points, like unfamiliar file ownership on bind mounts, are expected side effects of the mapping working correctly, not bugs to be alarmed by.
  • For any environment sharing hosts across different trust levels — multi-tenant platforms, regulated industries, or fleets running less-trusted third-party images — enabling remapping should be treated as a near-default baseline, not an optional extra.