Overview

This guide covers the complete setup of a Plex Media Server running in an LXC container on Proxmox VE, including NFS storage integration and Intel GPU passthrough for hardware transcoding.

Environment Details

  • Host: Proxmox VE 8.4.8 (kernel 6.8.12-13-pve)
  • Hardware: Intel N97 processor with integrated UHD Graphics
  • Storage: NFS shares from NAS (nas.my.domain.com)
  • Container: Ubuntu 22.04 LTS template

Prerequisites

1. Enable IOMMU on Proxmox Host

Ensure IOMMU is enabled in the kernel command line:

cat /proc/cmdline
# Should show: intel_iommu=on iommu=pt

2. Verify GPU Availability

Check that the Intel GPU is available and in its own IOMMU group:

# List VGA controllers
lspci | grep -i vga
# Output: 00:02.0 VGA compatible controller: Intel Corporation Alder Lake-N [UHD Graphics]

# Check IOMMU groups
find /sys/kernel/iommu_groups/ -type l | grep "00:02.0"
# Output: /sys/kernel/iommu_groups/0/devices/0000:00:02.0

3. Verify NFS Exports

Check available NFS shares from your storage server:

showmount -e nas.my.domain.com

Step 1: Prepare NFS Mounts on Proxmox Host

Create Mount Points

mkdir -p /mnt/nfs/{video,music,audiobooks,photo,homevideo,plex-config}

Install NFS Client

apt update && apt install -y nfs-common

Configure Persistent NFS Mounts

Add entries to /etc/fstab:

cat >> /etc/fstab << 'EOF'

# NFS mounts for Plex
nas.my.domain.com:/mnt/media/video /mnt/nfs/video nfs defaults,noatime,rsize=8192,wsize=8192,timeo=14 0 0
nas.my.domain.com:/mnt/media/music /mnt/nfs/music nfs defaults,noatime,rsize=8192,wsize=8192,timeo=14 0 0
nas.my.domain.com:/mnt/media/audiobooks /mnt/nfs/audiobooks nfs defaults,noatime,rsize=8192,wsize=8192,timeo=14 0 0
nas.my.domain.com:/mnt/media/photo /mnt/nfs/photo nfs defaults,noatime,rsize=8192,wsize=8192,timeo=14 0 0
EOF

Mount All NFS Shares

mount -a
df -h | grep nas  # Verify mounts

Step 2: Create Plex LXC Container

Download Ubuntu Template

pveam download local ubuntu-22.04-standard_22.04-1_amd64.tar.zst

Create Container with GPU Passthrough

The container was created using a community script, but here’s the equivalent manual configuration:

pct create 101 local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst \
  --hostname plex \
  --memory 2048 \
  --cores 4 \
  --rootfs local-lvm:32 \
  --net0 name=eth0,bridge=vmbr0,ip=xxx.xxx.xxx.222/24,gw=xxx.xxx.xxx.254 \
  --mp0 /mnt/nfs/video,mp=/media/video \
  --mp1 /mnt/nfs/music,mp=/media/music \
  --mp2 /mnt/nfs/photo,mp=/media/photos \
  --unprivileged 0 \
  --features nesting=1 \
  --onboot 1

Add GPU Passthrough Configuration

Add these lines to the container configuration (/etc/pve/lxc/101.conf):

# GPU passthrough configuration
lxc.cgroup2.devices.allow: c 226:128 rwm
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file
lxc.cgroup2.devices.allow: c 226:0 rwm
lxc.mount.entry: /dev/dri/card0 dev/dri/card0 none bind,optional,create=file
lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir

Step 3: Configure Container Permissions

Start the Container

pct start 101

Fix Media File Permissions

The NFS-mounted files are owned by nobody:1001, but Plex runs as the plex user. Create a matching group:

# Inside the container
pct exec 101 -- groupadd -g 1001 media-group
pct exec 101 -- usermod -a -G media-group plex

Verify GPU Access

# Check GPU devices
pct exec 101 -- ls -la /dev/dri/
# Should show: card0 and renderD128 owned by root:video

# Verify plex user has video group access
pct exec 101 -- id plex
# Should include groups: video,media-group

Restart Plex Service

pct exec 101 -- systemctl restart plexmediaserver

Step 4: Performance Optimization

Monitor Resource Usage

# Check current usage
pct exec 101 -- top -bn1
pct exec 101 -- free -h

Optimal Resource Allocation

Based on testing, these settings provide optimal performance:

  • CPU: 4 cores (full utilization of Intel N97)
  • Memory: 2GB (sufficient for 2-3 concurrent transcodes)
  • Swap: 512MB (adequate for occasional spikes)

Update container resources:

pct set 101 --cores 4 --memory 2048

Step 5: Verify Installation

Check Container Status

pct list
# Should show: 101 running plex

pct config 101 | grep -E '(cores|memory|mp[0-9])'

Test Media Access

# Verify Plex can read media files
pct exec 101 -- sudo -u plex ls /media/video/movies/ | head -5

Access Plex Web Interface

Navigate to: http://xxx.xxx.xxx.222:32400/web

Container Configuration Summary

Final Container Specs

  • VMID: 101
  • Hostname: plex
  • IP Address: xxx.xxx.xxx.222/24
  • MAC Address: BC:24:11:C0:DD:E6
  • Resources: 4 CPU cores, 2GB RAM, 512MB swap
  • Storage: 32GB root filesystem

Mount Points

/media/video      → /mnt/nfs/video
/media/music      → /mnt/nfs/music
/media/photos     → /mnt/nfs/photo

GPU Capabilities

  • Hardware: Intel UHD Graphics (Alder Lake-N)
  • Transcoding: H.264/H.265 hardware acceleration
  • Device Access: /dev/dri/card0, /dev/dri/renderD128

Performance Metrics

Memory Usage

  • Base Plex processes: ~280MB
  • During transcoding: +50-100MB per stream
  • Library scanning: +100-200MB (temporary)

CPU Performance

  • Idle: <5% CPU usage
  • Single 1080p transcode: 40-60% CPU
  • Hardware transcoding: Significantly reduced CPU load

Storage I/O

  • NFS performance: Excellent with gigabit networking
  • Concurrent streams: 2-3x 1080p without bottlenecks

Troubleshooting

Common Issues

Permission Denied on Media Files

# Check file ownership
pct exec 101 -- ls -la /media/video/
# Should show: nobody media-group

# Verify plex user groups
pct exec 101 -- id plex
# Should include: media-group(1001)

GPU Not Available

# Check GPU passthrough
pct exec 101 -- ls -la /dev/dri/
# Should show both card0 and renderD128

# Verify permissions
pct exec 101 -- sudo -u plex test -r /dev/dri/renderD128 && echo "OK" || echo "FAIL"

NFS Mount Issues

# Check mounts on host
df -h | grep nas

# Remount if needed
mount -a

Security Considerations

Container Security

  • Unprivileged: Container runs as unprivileged (safer)
  • Group Access: Limited to specific media groups (1001, video)
  • Network: Isolated to specific VLAN/subnet
  • GPU: Device passthrough without host driver conflicts

Network Security

  • Firewall: Configure appropriate rules for port 32400
  • VPN: Consider restricting external access
  • SSL: Enable HTTPS in Plex settings for remote access

Maintenance

Regular Tasks

# Update container packages
pct exec 101 -- apt update && apt upgrade -y

# Check Plex service status  
pct exec 101 -- systemctl status plexmediaserver

# Monitor resource usage
pct exec 101 -- htop

# Check library scan progress
# Access via web interface at http://xxx.xxx.xxx.222:32400/web

Backup Strategy

  • Container backup: Use Proxmox backup jobs
  • Plex database: Located in container at /var/lib/plexmediaserver/
  • Media content: Already on NAS with redundancy

Conclusion

This setup provides a robust, high-performance Plex Media Server with:

  • ✅ Hardware-accelerated transcoding
  • ✅ Efficient resource utilization
  • ✅ Scalable NFS storage integration
  • ✅ Container isolation and security
  • ✅ Easy maintenance and monitoring

The Intel N97 processor with hardware transcoding can handle 2-3 concurrent 1080p streams efficiently, making this an excellent budget-friendly media server solution.

References