Proxmox

Proxmox LXC Setup: Create an Unprivileged Linux Container

An unprivileged Debian LXC shares the host kernel and stores its service data on a managed root disk.
Choose the guest, then account for its kernel, network and data.
A Debian system template creates the container filesystem. The running container shares the PVE host kernel and uses a managed root disk. Its eth0 interface connects through vmbr0 to an authorized LAN client. Selected guest data goes to a separate backup destination, while arbitrary host bind mounts need their own backup.
Choose the guest, then account for its kernel, network and data.Original Boxvirt diagram. Documentation-based example, not a screenshot or a lab result. View full size ↗

To set up LXC in Proxmox, download a supported Linux system-container template, create an unprivileged container, choose its storage and network, and start it. Install packages inside the container, then verify the service from another device. Before adding important data, decide how you will back it up and restore it.

This walkthrough builds a small Debian web server with its files inside the container’s root disk. Keeping that first layout simple makes it easier to understand what Proxmox manages and what a container backup can recover.

Scope and validation: this guide covers an existing standalone Proxmox VE 9 host and a Debian 13 system-container template. Sources were checked on November 8, 2026; the Proxmox manuals read identify themselves as 9.2.13. The procedure has not been executed on a test host. Confirm template availability, exact host build, firewall behavior and restore results on a separate lab before relying on this procedure.

Know what a container shares with the host

An LXC system container provides a Linux userspace while using the Proxmox host’s kernel. You do not attach an installer ISO or install a separate kernel as you would for a VM. Windows and FreeBSD therefore need a suitable VM rather than a Proxmox LXC container.

With an unprivileged container, guest root maps to an unprivileged identity on the host. That reduces the authority of processes inside the container. It does not provide a separate kernel or remove the need to maintain the host. See the Proxmox container guide and the existing VM or LXC decision worksheet if your application needs special devices, kernel modules or stronger separation.

This article uses a traditional Debian system-container template. It does not use an OCI application image or install Docker inside LXC. Those paths add different compatibility and privilege questions.

1. Choose a small, explicit starting configuration

The values below are an illustrative lab plan, not a measured sizing recommendation. The private addresses describe one example LAN. Substitute your actual bridge, unused guest ID, free address, gateway and DNS server.

SettingExampleWhy it matters
Container ID202, after checking it is unusedPVE uses the ID to identify configuration and tasks
Hostnameweb-ctGives the container a recognizable name
TemplateCurrent Debian 13 standard system templateSupplies Debian userspace; record the exact archive used
Unprivileged containerEnabledUses host user-namespace mapping for guest root
Root disk8 GiB on suitable managed storageHolds OS, packages and this example’s small web page
CPU1 coreExample CPU allocation, not a dedicated physical core
Memory1024 MiBA usage limit, not an exclusive host reservation
Swap0 MiB for this exampleNo container swap allowance; review for the actual workload
Networketh0 on existing vmbr0, no VLAN tagUses the already-working untagged lab LAN
IPv4192.168.40.22/24Must be unused and excluded from conflicting DHCP allocation
Gateway192.168.40.1Assumes this LAN router provides the route off the subnet
DNS192.168.40.1Assumes that same router actually provides DNS to this LAN

Check the host’s resource headroom using the RAM planning guide. Container memory and swap controls are limits under the host’s cgroup system. A swap allowance cannot create swap space that the host does not have. Hitting a memory limit can result in processes being killed; a stopped web service may be a resource problem rather than a network failure.

Use an existing working bridge. This walkthrough does not change the host’s management address, build a new VLAN or configure NAT. A bridge alone does not provide DHCP, routing or DNS. See Proxmox networking for that distinction.

2. Download a system-container template

In the PVE web interface, select storage that supports Container template content, open its template list and download the current Debian 13 standard template offered for your host architecture. The interface commonly labels this section CT Templates.

Record the exact archive name. Do not copy an old template filename from a tutorial: template revisions change independently of this article. Confirm Debian’s support status in the release information.

If Debian 13 is not offered, stop and check the host’s updates and template catalog rather than fetching an arbitrary archive from a third-party script. You can inspect the available catalog on the PVE host with:

pveam available --section system

The template archive and the container’s running root disk are different objects. For example, a Directory storage ID such as local may hold the download, while local-lvm holds guest volumes. LVM-Thin does not become a template library because its name contains “local.” The storage comparison explains content types.

3. Create the unprivileged container

Select Create CT and work through the wizard:

  1. Choose the intended node and an unused CT ID. Set web-ct as the example hostname. Keep Unprivileged container selected. Set a strong, unique root password for the console login used below. You may also add an SSH public key for planned SSH access; that key does not replace a password at the console login prompt. Keep credentials out of shared notes and screenshots.
  2. Select the Debian system template you downloaded.
  3. Place the root disk on the selected managed guest storage. For this example, allocate 8 GiB. Confirm free physical capacity as well as the virtual disk size.
  4. Set the example CPU, memory and swap limits. Leave additional features such as nesting, device access and FUSE disabled for this basic service.
  5. Configure eth0, the existing bridge, IPv4 address/prefix and gateway from the worksheet. Leave the VLAN tag empty only because this example uses an untagged bridge path. Enter the intended DNS server explicitly.
  6. Review the final configuration before creating the guest. Initially leave automatic start at host boot disabled so you can finish checks before adding a startup dependency.

For the IPv4-only worksheet, leave IPv6 configuration on Manual rather than requesting a routable address. This does not disable the IPv6 stack or constitute a firewall policy. If your real LAN provides routable IPv6, configure and test its permitted paths alongside IPv4.

Retain your intended Proxmox firewall policy. The NIC’s Firewall checkbox is only one control in that system; it does not create the application’s allow rules or prove isolation. Define and test the permitted client-to-service path before treating the guest as reachable only by selected users.

After creation, read the configuration on the PVE host, substituting the actual ID:

pct config 202

Check that unprivileged: 1 is present, the intended root storage is used, and net0 has the right bridge, address and gateway. A wrongly selected storage or address is easier to correct now than after the service holds important data.

4. Start Debian and verify its network

Start the container, open its console in PVE and log in as root with the password you set in the creation wizard. The following commands run inside the Debian container, not in the node’s host shell:

cat /etc/os-release
uname -r
ip -br address
ip route
cat /etc/resolv.conf

Expect Debian 13 userspace, the planned IPv4 address on eth0 and the correct default route and resolver. uname -r reports the shared host kernel; a different Debian userspace version does not imply an independently booted guest kernel.

Use hostname resolution to check DNS:

getent ahosts deb.debian.org

If the address or route is wrong, correct the container’s PVE network configuration before editing competing network settings inside Debian. If addressing is correct but name resolution fails, inspect the configured resolver and its reachability. DNS failures and routing failures need different fixes.

Refresh the package lists in the container:

apt update

Resolve failures before updating packages:

apt upgrade

These are guest maintenance commands. They update the container’s packages, not the Proxmox host. Read the proposed transaction and any prompts; Debian’s APT manual describes package operations and error handling.

5. Install one small service and test both ends

Inside the container, install Debian’s packaged nginx and curl:

apt install nginx curl

Keep this demonstration private: the page contains no credentials and does not publish PVE administration or open an internet-facing port. Configure HTTPS and application access controls separately before hosting sensitive content.

Check the nginx configuration, using its documented configuration test:

nginx -t

If the test succeeds, enable and start the service inside the container:

systemctl enable --now nginx

Request the local page:

curl --head http://127.0.0.1/

For the unmodified default site, expect an HTTP 200 response. Read the status line: curl can complete a connection successfully while the server returns an HTTP error such as 404 or 500.

Now, from an authorized device on the example LAN, test the container address instead:

curl --head http://192.168.40.22/

A successful local response proves something different from a successful remote response. The latter also exercises the guest NIC, bridge path and firewall policy. Expect the same default site and HTTP 200 from the allowed client. Use the real assigned address rather than copying the example onto an unrelated network.

Restart the container through PVE, reconnect and repeat the requests. This checks that the service starts again and the intended address survives a guest restart. You do not need a QEMU Guest Agent for this system container.

6. Know which data the backup includes

For the first version of this service, keep its web content and configuration inside the managed root disk. When adding a data mount later, make the backup decision at the same time:

Where the data livesWhat to check
Managed root diskCheck the guest backup job and its completed contents
Additional managed storage volumeExplicitly check the mount’s Backup option; inclusion is not automatic
Host directory exposed through a bind mountIts contents are excluded from the ordinary container backup; protect them separately
Device mount or external serviceEstablish its separate backup and consistent recovery procedure

The Proxmox backup manual distinguishes these cases. A backup job showing success does not establish that a bind-mounted directory was copied. A ZFS-backed volume managed by PVE should not be confused with an arbitrary host-directory bind mount.

Guest snapshots are useful for certain short-lived changes, but copies on the same failed storage cannot provide independent recovery. Use a backup destination that remains accessible after losing the host or its local pool. Review the backup and restore checklist before storing important content. For a separate backup server, the PBS setup walkthrough covers the datastore, connection and first recovery check.

Test a restore under a different identity

In PVE, select the intended backup storage and create a backup of the container. Choose a supported mode for the actual storage and consistency needs. Snapshot-mode LXC backups require snapshot support for all included volumes; do not infer that capability from a VM’s successful live backup.

Then restore to a different unused CT ID on a suitable lab target. Keep the restored container’s NIC disconnected from the production LAN before its first start: a restored static address can conflict with the original. Inspect its configuration and service locally, then use an isolated test network or a deliberately reassigned identity for a remote test.

Confirm the expected files and configuration are present, nginx starts and the page can be read. Reconnect or publish nothing automatically. For an actual application, add its database, authentication and external-data checks to this procedure.

Troubleshoot the failing layer

SymptomWhat to check first
No usable eth0 addressPVE NIC settings, selected bridge, intended static configuration or DHCP service
Address works locally but remote requests failListener, firewall rules and the client’s bridge/VLAN/routed path
Local IP services work but apt update cannot resolve hostsGuest resolver configuration and DNS reachability
Service disappears under loadMemory limits, guest logs and the host’s available resources
Added bind mount is not writableGuest/host identity mapping, permissions and mount read-only flags
Restore starts but files are missingBackup exclusions and data outside the managed root disk

For host-directory permissions, establish the numeric UID/GID mapping and the application’s real service identity. Do not solve the problem by switching to privileged mode or making every file world-writable.

Once network, service and restore checks pass, set a deliberate host-boot startup order if needed and record the template, resource limits, data locations and backup policy. The useful result is a container you understand well enough to maintain and recover.

KEEP EXPLORING

Related guides