Since you are comfortable with the configuration and want a professional, proper systems administration approach, mitigating the security risk of idmap is straightforward.
The security risk exists only if you map the container to a privileged or shared host user (like your primary personal account, UID 1000, which might have sudo access or own sensitive host configurations). If a bad actor breaks out of the container via a Docker/LXC exploit, they land on the host with the permissions of that mapped UID.
To completely mitigate this risk, you create a "Black Hole" or "Empty Room" configuration. You punch a hole through the LXC isolation, but you make sure the hole leads to a user that has absolutely zero power on the host system.
Here are the exact methods to lock this down:
Do not map the LXC container to UID 1000. Create a dedicated, unprivileged system account on the Proxmox host that exists solely to own this dataset.
On the Proxmox Host:
# Create a dedicated group and user (e.g., UID/GID 2500)
# -M: No home directory
# -s /usr/sbin/nologin: Cannot log into a shell
groupadd -g 2500 immich_storage
useradd -u 2500 -g 2500 -M -s /usr/sbin/nologin immich_storage
# Chown the ZFS dataset to this dead user
chown -R 2500:2500 /tank/immich_dataWhy this works: If the container is compromised and the attacker executes a container escape as UID 2500, they land on the host as immich_storage. This user has no shell, no home directory, belongs to no privileged groups, and owns absolutely nothing on the host except the photos they already compromised anyway. The isolation is practically maintained.
The LXC Math for UID 2500:
Your /etc/pve/lxc/XXX.conf would look like this:
lxc.idmap: u 0 100000 2500
lxc.idmap: g 0 100000 2500
lxc.idmap: u 2500 2500 1
lxc.idmap: g 2500 2500 1
lxc.idmap: u 2501 102501 63035
lxc.idmap: g 2501 102501 63035
And your host /etc/subuid and /etc/subgid gets:
root:2500:1
Since you are using ZFS, you have an incredibly powerful security layer at the filesystem level. You can instruct the host kernel to completely neuter what can be done with files residing on that specific dataset.
On the Proxmox Host:
zfs set setuid=off tank/immich_data
zfs set devices=off tank/immich_data
zfs set exec=off tank/immich_dataWhy this works:
exec=off: If an attacker manages to upload a malicious binary or script into your Immich library via a web vulnerability, the host kernel will flat-out refuse to execute it from that directory.setuid=off: Prevents the creation of SUID binaries in the dataset, effectively destroying a common privilege escalation vector.devices=off: Prevents the creation of device nodes (like fake/dev/sdafiles) which is a common trick used in container escape attacks.
By default, Docker containers run their internal processes as root (UID 0 inside the container, which maps to UID 100000 in your LXC).
To cleanly align Docker with your idmap, you instruct Docker to run the Immich services explicitly as your mapped user (2500).
In your docker-compose.yml, you can pass the user context to the Immich server and machine learning containers:
services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
user: "2500:2500" # Force process to run as our mapped UID/GID
# ... rest of config(Note: Be careful with the PostgreSQL and Redis containers, as they often require initializing their internal directories as root before dropping to their own UIDs. For Immich's main data volume, setting the user on immich-server and immich-machine-learning is usually sufficient).
Because you need to enable Nesting to run Docker in the LXC, Proxmox slightly relaxes AppArmor profiles to allow Docker to create its own namespaces.
Do not be tempted to check the "Privileged container" box or turn off AppArmor completely to troubleshoot Docker issues. Keep the container Unprivileged, leave AppArmor enabled (the default for Proxmox LXCs), and only enable the specific features needed: Nesting and (if Postgres complains) keyctl.
By mapping the LXC to a dedicated nologin user and applying ZFS noexec/nosuid flags, you completely neutralize the risks of idmap. You get exactly what you want: a perfectly clean Proxmox host filesystem with native UIDs, without compromising the hypervisor's security.