Create a Debian 13 container on Proxmox 9, watch the task log scroll past, and there it is:
WARN: Systemd 257 detected. You may need to enable nesting.
Search that string and you get two answers. “It’s harmless, ignore it.” “Turn nesting on and move along.” Both are answers, but neither answers the why. Nobody tells you what the flag switches, what it hands the container that the container didn’t already have, or why the warning fires in exactly the same words on a guest that booted perfectly and on a guest whose console is a black box.
So I stripped the flag off eight of my nine containers to find out, measured what changed, and put it back a day later. Two days of work, one real leak, and much better notes. Here’s what Systemd 257 detected. You may need to enable nesting. actually means, what nesting=1 costs you, and how to decide.
Everything below is measured on that stack. I ran the de-nesting experiment across nine unprivileged containers on a three-node Proxmox 9.2.5 cluster (kernel 7.0.14-6-pve), eight of them Debian 13 with systemd 257 and one of them Ubuntu 26.04, and the numbers in the tables are readings from my own guests rather than anything I read on the internet.
What “Systemd 257 detected” means: a version check, and that’s it
Three terms are about to do a lot of work in this post.
A mount namespace is a container’s own private view of what is mounted where. Your guest sees one filesystem tree, the node sees a different one, and neither pollutes the other. procfs is the pretend filesystem at /proc that the kernel fills with live facts about the machine: total RAM, CPU count, how long it’s been up. lxcfs is the Proxmox piece that stands in front of a few of those /proc files inside a container and rewrites them, so the guest reads the limits you configured instead of the node’s real hardware.
Nesting controls exactly one thing: whether container root can create new mounts in the first of those three.
Now let’s look at the logic. The check is a function called check_systemd_nesting, living in src/PVE/LXC/Setup/Base.pm and added to pve-container by a Proxmox patch series. It stays quiet if any one of four conditions holds:
- the
featuresline containsnesting=1 - the container’s init isn’t systemd
- the systemd version can’t be read
- that version is 241 or older
In every other case it prints Systemd $sdver detected. You may need to enable nesting., with your guest’s version number pasted into the middle.
Every one of those four conditions is a configuration fact or a version number. Not one of them looks at whether your container is healthy, whether its console works, whether a single unit failed, or whether anything at all went wrong. If the guest runs systemd, if that systemd is newer than 241, and if the features line has no nesting=1, you get the warning. That’s it.
Which is why the number in the message means less than people think. WARN: Systemd 252 detected. You may need to enable nesting. and WARN: Systemd 249 detected. You may need to enable nesting. are the same warning about the same behavior; the digits are the systemd version your container distro happens to ship. Debian 12 reports 252, Ubuntu 22.04 reports 249, Debian 13 and recent Ubuntu report 257. People go hunting for “the systemd 255 nesting bug” and find nothing, because there isn’t one. That fruitless search is probably what brought you here.
The consequence that actually hit me: during my de-nesting run the warning fired on all eight Debian guests where it meant nothing whatsoever, and on the one Ubuntu guest where it turned out to be dead right. On the Ubuntu LXC I lost a working console from within Proxmox. Identical text, both times. So the warning can’t tell you whether anything is broken, in either direction. Only a console check told the two apart.
So should you turn nesting on?
Four cases. Find yours, and if a decision is all you came for, you can stop after the list. Everything below it is the measurement the list is standing on.
You’re running Docker, Podman, k3s, or nested LXC inside the container. Yes.
features: nesting=1,keyctl=1, both of them. Non-negotiable. Nesting alone gets you “operation not permitted” from Docker even though the systemd warning has helpfully disappeared, because the keyring operations are a separate permission.It’s an Ubuntu container. Leave nesting on, and here is my evidence up front: one Ubuntu 26.04 guest, one release, the only Ubuntu box in my lab. That is not a survey of every Ubuntu LTS and I’m not going to pretend it is one. What I have is a guest that lost its console as soon as I flipped the flag off, running a systemd that has diverged from Debian’s before. Treat Ubuntu as its own platform whenever a change touches systemd, and if you want to know how your Ubuntu release behaves, find out on a container you don’t care about.
It’s Debian 13, and you’re not running nested container runtimes. You can leave nesting off. Jellyfin, Sonarr, Radarr and the rest of a normal media stack don’t need nested namespaces or a cgroup tree of their own, so they’re fine either way; running them in Docker inside the container is the case that changes the answer. De-nesting is the tighter configuration and it’s genuinely viable, which most guides won’t tell you. Accept two things going in. The warning appears forever. And
runningturns intodegradedthe moment you de-nest, because three mount units start failing. From then on you judge the guest by the unit namessystemctl --failedprints, never by the summary word.You have a mixed fleet and no strong feelings. Pick one shape and apply it everywhere.
The rest of this post is what’s behind those four lines: what the flag switches, what it exposes when you switch it on, and what breaks when you leave it off.
What nesting=1 actually turns on
Proxmox describes the feature as exposing procfs and sysfs “to allow nested containers”, and notes that “systemd also uses this to isolate services”. True, and vague enough to be useless when you’re trying to decide.
Measured on my own guests, the single practical difference is one sentence long: with nesting, container root may create mounts in the container’s own root mount namespace, and without it those mounts are denied. Every downstream effect in this post flows from that one rule.
It is worth being equally clear about what the flag does not do, because the security writeups tend to leave this fuzzy. I probed a de-nested guest against a still-nested control and found no difference in cgroup writability, /proc/sched_debug, /sys/kernel/security, /proc/sys writability, or /sys/class/net. Nesting doesn’t grant ambient access to host state. Reaching the extra visibility takes a deliberate mount. And it doesn’t turn an unprivileged container into a privileged one, whatever the flag’s reputation suggests. Your UID mappings are untouched.

The measured cost: one mount and lxcfs is gone
Now the part that made a security reviewer flag this as a medium finding in my lab, and the part almost nobody quantifies.
Inside a Proxmox container, /proc/meminfo and /proc/cpuinfo are lies told by lxcfs, and they’re lies you asked for: they report the limits you configured rather than the node’s real hardware. With nesting on, container root can mount a fresh procfs somewhere else and read straight around that masking.
I measured it on my hugo builder, a container I’d configured with 8 GB of RAM and 4 CPUs. Reproduce it on any nested guest of your own, as root inside the container:
mkdir -p /mnt/realproc
mount -t proc proc /mnt/realproc
head -1 /mnt/realproc/meminfo # reports the node's real MemTotal
cat /mnt/realproc/uptime
umount /mnt/realproc
Normal /proc on the left, that freshly mounted one on the right:
| Value | Guest view (lxcfs) | Fresh mount -t proc | Truth |
|---|---|---|---|
MemTotal | 8,388,608 kB | 65,607,300 kB | the node’s real RAM |
| processors | 4 | 20 | the node’s real CPU count |
uptime | 52,681 s | 2,365,585 s | the node’s real uptime (~27 days) |
Twenty-seven days of node uptime, sixty-five gigabytes of node RAM, and a CPU count that has nothing to do with the four cores you allocated. That is a real information leak and I’m not going to pretend otherwise.
I am also not going to inflate it. This is host information disclosure and not a container escape. The PID namespace still holds, so /proc/<pid> shows only the container’s own processes, and getting to any of it requires container root in the first place. If an attacker already has root inside your Jellyfin container, learning how much RAM the node has is not the worst thing happening to you that day.
nesting=1, including the internet-facing ones. If you expose a container through a reverse proxy, the honest statement is that a compromise which reaches container root also reveals your node’s hardware profile and uptime. Weigh that against needing the flag, and don’t let anyone tell you the leak isn’t real.Why modern systemd cares about any of this
Systemd stopped being an init system a while ago and became something closer to a tiny container orchestrator. It wants cgroup v2 delegation, which means the kernel handing systemd its own branch of the resource-control tree to carve up as it likes, and it wants namespaces so it can isolate individual services from each other.
Proxmox staff put the boundary plainly in a forum thread: “systemd versions >= 242 requires nesting to be able to create Linux namespaces, which is used to isolate services”. When those operations get refused, systemd doesn’t print a tidy error and carry on. It fails units, drops into degraded, and in the worst case never gets you a login prompt at all.
The specific failure documented upstream is Failed to set up credentials: Protocol error, repeating in [email protected] and console-getty.service. The getty never reaches a login prompt. noVNC and pct console both look dead while the container is otherwise running perfectly: answering SSH, serving its app, completely fine. That’s the scenario Proxmox added the warning for, and pve-container 6.0.19 put the matching note in the UI that nesting “may be required for systemd.”
Debian 13 keeps its console. Ubuntu doesn’t.
This is the most useful thing the whole experiment produced, and it contradicts a lot of what the internet will tell you.
I de-nested one container at a time, working up in importance, ready to stop at the first real failure. First, a small unimportant Debian 13 LXC, because nothing depends on it. Then my hugo builder. Then my audiobookshelf LXC, which has a read-only NFS bind mount from my storage server and would tell me quickly if host-side mounts broke. All three came back with working consoles.
With three holding, I did the rest in one pass, including the two guests I actually cared about: caddy at startup order 1 and pihole01 at startup order 0, the containers the entire lab depends on for TLS and DNS. Both came through. Eight Debian 13 guests, all on systemd 257, all de-nested, and every one of them started [email protected] and console-getty.service normally, put its credential tmpfs under /run/credentials/<unit>, and logged not a single Protocol error.
Then jellyfin, the lab’s only Ubuntu container (soon to be Debian too), lost its console exactly as the forum thread describes. I reverted the change.
So the boundary is not “systemd 257 needs nesting”. The boundary runs between distributions. Debian 13 in an LXC ships with enough LXC awareness to keep a console without the flag. Ubuntu leans on unrestricted systemd behavior and falls over. If you want the Debian side prepared before an upgrade, the lxc.generator sequence is covered in my Debian 12 to 13 LXC upgrade guide, and it’s the piece that makes running de-nested realistic at all.
One recovery detail is worth memorizing before you need it, because you will otherwise spend twenty minutes rediscovering it. A dead console does not mean a dead container. pct enter uses lxc-attach and is completely unaffected by nesting. You will open noVNC, get nothing, open it again, conclude the guest is hosed, and start planning a restore. Don’t. pct enter <VMID> from the node still works, which is exactly how I recovered Jellyfin.

Why you can’t make the warning go away
You can’t. There is no supported way to do it, and I checked properly before accepting that. Here are the three things I tried, all rejected:
Set features: nesting=0. Look at the first of those four conditions again. Only nesting=1 buys silence, so an explicit zero warns exactly like no features line at all.
Set ostype: unmanaged. This works, in the sense that a guillotine cures a headache. PVE then writes nothing into the guest: no /etc/hostname, no /etc/hosts, no /etc/resolv.conf, no network configuration. You’ve traded one cosmetic warning for hand-managing every container’s identity.
Patch Base.pm on the node. apt reverts the file on the next pve-container update, you now own a local diff on a hypervisor, and Jellyfin proved the warning is occasionally right. No.
While we’re here: /etc/.pve-ignore.<file> is unrelated, but people reach for it anyway. It stops PVE overwriting files inside the guest. It has nothing to do with the task-log warning.
The one place this genuinely hurts is automation. Several Proxmox Terraform providers treat any task with a non-zero warning count as a failure, so the container gets created successfully and then the provider refuses to save it to state. The task said “success with warnings” and the tooling only read the second word. Enabling nesting removes the warning and therefore the false failure, which is a genuinely irritating reason to change a security-relevant flag.
Check the flag before you change the flag
Every command from here on uses <VMID> as a placeholder. Swap in your own container’s ID, which pct list prints on the node next to each container’s name and status. Copying an example ID verbatim is how you reboot somebody else’s database at the wrong moment.
pct list # find your container's ID
pct config <VMID> # read its current features line
Look for the features: line. You’ll see one of three states:
- No
features:line at all, which means defaults, which means nesting is off. features: nesting=1, nesting on.features: nesting=1,keyctl=1, nesting plus kernel keyring, the usual shape for a container running Docker.
Changing it is one command plus a reboot:
pct config <VMID> # capture this first, it is your rollback reference
pct set <VMID> --features nesting=1 # or --delete features to remove it
pct reboot <VMID>
--features rewrites that whole line rather than adding to it. If pct config showed you nesting=1,keyctl=1, then passing --features nesting=1 silently drops keyctl, and Docker inside that guest breaks for a reason that looks nothing like this post. Pass every flag you want to keep, every time. --delete features has the same sharp edge, and it takes all of them at once.
Make the first change on a container you would be happy to lose. I walked the dependency chain a guest at a time and put DNS and TLS last, and the same order applies going the other way. If you are turning nesting on across a fleet, prove the full stop and start cycle on one throwaway guest before you touch the container everything else resolves through. A container you can rebuild in five minutes is worth more as a test subject than any amount of reading, this post included.
Features only apply on a full stop and start. This is where people lose an hour. You set the flag, nothing changes, you set it again, still nothing, and you start doubting the command. Proxmox rewrites and reapplies the LXC configuration only at container start, so anything short of tearing down and recreating the init process leaves the old namespaces in place. pct reboot does the full cycle. Rebooting from inside the container is not the same operation and shouldn’t be trusted here.
Then confirm with pct config <VMID> again, and open the console with pct console <VMID> or noVNC. Not because the console is important, but because the console is the exact thing that fails. If you get a black rectangle, get in with pct enter <VMID> and run journalctl -b -u console-getty.service. A repeating Failed to set up credentials: Protocol error is the nesting failure. Anything else is a different problem wearing the same costume.

Why I put the flag back the next day
My own answer is case 4, and I landed on nesting everywhere. Two reasons, one better than the other.
The good reason is uniformity. Running eight de-nested containers next to one nested container means every future question (“is this a nesting symptom?”) has to be answered twice, and every new container inherits whichever shape I happened to copy from. A split fleet is a tax you pay on every unrelated problem for as long as the fleet exists.
The weaker reason is my automation controller, which sandboxes the tooling it runs and stopped working de-nested. Sandboxing needs to create mounts in the container’s root mount namespace, which is the exact thing de-nesting forbids. The mechanism is at least coherent. But I’ll be honest: I never isolated the specific failing operation before I reverted, so what I have is a strong correlation and a judgment call, not a proof. If I ever want the leak closed on the guests that don’t run that tooling, step one is reproducing that failure on a throwaway container rather than another fleet-wide pass.
Two days, one confirmed leak, and I ended up exactly where I started with far better notes. Worth it anyway.

What running de-nested actually costs, day to day
If you go the other way, here’s the price list. Three systemd units cannot mount on a de-nested guest, and they fail on every boot:
| Unit | Consequence |
|---|---|
tmp.mount | /tmp is a plain directory on the rootfs instead of a tmpfs. It eats guest disk and survives reboots. Debian’s tmpfiles.d still ages files out on the standard 10-day rule |
run-lock.mount | Cosmetic. /run/lock still exists as drwxrwxrwt inside the /run tmpfs |
dev-mqueue.mount | POSIX message queues unavailable |
Those three failures are why systemctl is-system-running reports degraded on every de-nested guest. That’s expected output. Nothing is wrong with the guest. findmnt /tmp settles which side you’re on: a tmpfs line means the mount landed, and no output at all means /tmp is a plain directory on the root disk.
The journal reports them as mount: /tmp: tmpfs already mounted on /dev/shm, which is util-linux misdiagnosing a refused mount by naming a completely unrelated tmpfs that happens to exist. Nothing was double-mounted. Nothing is wrong with /dev/shm. You’ll grep that string, find people with genuine double-mount problems, and chase the wrong thing for an afternoon.
One knock-on effect that matters specifically for media servers: with nesting on, /tmp is a tmpfs, which means RAM. If your transcoder writes scratch files to /tmp you’re transcoding into memory. Jellyfin’s TranscodingTempPath defaults to /var/cache/jellyfin/transcodes, so it dodges this by default, but check yours rather than assuming. Dashboard > Playback shows the current value, and grep TranscodingTempPath against Jellyfin’s encoding.xml gets the same answer without opening a browser. The same check catches the opposite failure when you’re de-nested, where scratch I/O lands on the container’s root disk.
Two things I explicitly confirmed do not break without nesting, because both get claimed as reasons to keep the flag:
Per-unit systemd sandboxing still works. I exercised
PrivateTmp=yes,ProtectSystem=strict,ProtectHome=yesandPrivateNetwork=yeswithsystemd-runon a de-nested guest and every one succeeded. Only the container’s root mount namespace is restricted; per-unit namespaces are unaffected. Your service hardening is intact either way.Host-side bind mounts still work. My audiobook container’s
lxc.mount.entryfor its NFS media directory is set up by LXC from the host rather than by the container, so it re-attached normally: read-only enforced, all libraries present. Bind mounts are not a nesting feature.
When it doesn’t work
The warning still appears on a container you’re certain you set the flag on. Then the flag didn’t take. Run pct config <VMID> and read the features: line with your own eyes, and if it’s there, you skipped the full stop and start. This is the single most common version of this problem and it’s always one of those two things.
You enabled nesting, the warning went away, and systemctl is-system-running still says degraded. Fine, now find out which unit. Run systemctl --failed inside the container and judge it by name. On my automation controller, sys-kernel-config.mount fails and always has, nested or not, because configfs isn’t usable in an unprivileged LXC in either configuration. On my Ubuntu guest, netplan-configure.service fails for reasons that have nothing to do with containment. Both are cosmetic, and both would have sent me chasing nesting if I’d trusted the summary word instead of the unit list.
journalctl -b -p err isn’t empty on a healthy de-nested container either, because refused mounts log at error priority. Judge such a guest by which errors it has, not by whether it has any. With nesting restored, an empty priority-error journal goes back to being the normal expectation.
Your Terraform apply fails while the Proxmox UI cheerfully shows the container running. Read the actual task log. If the only entry is the systemd nesting warning, the create succeeded and your provider is counting warnings as errors. Enable nesting or use a provider version that doesn’t do that.
And if you’ve enabled nesting, done a proper stop and start, and systemd is still degraded with real failures, stop tuning flags. The container template may ship stale or incompatible systemd configuration, and rebuilding from a current Debian 13 or Ubuntu template with nesting=1 set from creation is usually faster than the archaeology.
Where that leaves you
WARN: Systemd 257 detected. You may need to enable nesting. is a version check with no health check behind it. Treat it as a prompt to look, not a defect to fix. The flag it points at controls exactly one thing: whether container root can create mounts in the container’s own root mount namespace. The cost of granting that is a real, measurable procfs leak of your node’s hardware profile, reachable only by an attacker who already has root inside the guest.
Check pct config before you change anything. Test the change on one container you can afford to break. Reboot fully afterward. And decide once, for the whole fleet, then write down why. A split fleet makes you re-answer this question every time something unrelated breaks.
If you’re arriving here from a Debian 12 to 13 upgrade that went sideways, the credential errors and the lxc.generator fix are covered in the Debian 12 to 13 LXC upgrade guide. If you’re still deciding between privileged and unprivileged containers underneath all this, I wrote about the unprivileged LXC decision and about UID and GID mapping for bind mounts, which is the next wall you hit after this one.
Sources
- Proxmox VE documentation, Linux Container: https://pve.proxmox.com/wiki/Linux_Container

