Deploying Next.js on a Proxmox LXC Container

π¨π»βπ» Felix - Full Stack Web Developer
I'm Felix, a passionate web developer specializing in frontend development with React.js and backend development with Node.js, Firebase, and Supabase. I love creating dynamic and user-friendly web applications that provide seamless experiences for users.
π Frontend Development: Crafting responsive and engaging frontend experiences using React.js is where I excel. My attention to detail and design skills help me create visually appealing and intuitive user interfaces.
βοΈ Backend Development: In the backend, I am well-versed in Node.js, Firebase, and Supabase. Leveraging these technologies, I build robust backend solutions that support my frontend applications, ensuring smooth functionality and efficient data management.
π₯ Firebase & Supabase: I leverage Firebase and Supabase as backend-as-a-service platforms to streamline database management, authentication, and real-time data synchronization. These tools enhance the performance of my web applications significantly.
π‘ Innovative Solutions: With a creative mindset and problem-solving approach, I continuously seek innovative solutions to deliver high-quality web applications that meet user requirements and industry standards.
π Passionate & Dedicated: I'm committed to staying updated with the latest trends and technologies in web development. My dedication to honing my skills ensures that I deliver exceptional results in every project I undertake.
No Docker. No VMs. Just a lean Linux container, pnpm, PM2, and Nginx β running in production.
Date: April 17, 2026 Self-Hosting Next.js Proxmox Linux pnpm
Running a Next.js app in production doesn't have to mean spinning up a full virtual machine or wiring together a Docker stack. If you're already on Proxmox, LXC containers give you the isolation you need at a fraction of the resource cost. This is a walkthrough of exactly how we deployed the noc_allocation Next.js project on a Proxmox LXC container β from a blank container to a live app with a process manager and reverse proxy.
π‘ LXC containers share the host kernel, making them faster to spin up and significantly lighter on RAM and CPU than full VMs β ideal for running Node.js apps on a homelab or internal server.
The Stack
| Layer | Tool |
|---|---|
| Container | Proxmox LXC (Ubuntu 22.04) |
| Runtime | Node.js v24 |
| Package Manager | pnpm v10 |
| Process Manager | PM2 v6 |
| Reverse Proxy | Nginx |
Step 1 β Create the LXC Container
In the Proxmox web UI:
Go to CT Templates and download
ubuntu-22.04-standardClick Create CT and configure:
Hostname:
noc-appDisk: 8GB+
CPU: 1β2 cores
RAM: 512MBβ1GB
Network: DHCP (or static IP)
Start the container and open its Shell
Step 2 β Install Node.js and pnpm
Update the system and install Node.js 20 LTS via NodeSource:
# Update the system
apt update && apt upgrade -y
apt install -y curl git
# Install Node.js 20
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs
Install pnpm and configure its global bin directory:
curl -fsSL https://get.pnpm.io/install.sh | sh -
source ~/.bashrc
pnpm setup
source ~/.bashrc
pnpm --version # confirm
Step 3 β Clone and Build the App
Clone the repository and install dependencies:
cd /opt
git clone https://github.com/Blackie360/noc_allocation.git
cd noc_allocation
pnpm install
pnpm build
β οΈ If your app uses environment variables, create a
.env.localfile before runningpnpm build. Missing env vars during build can cause silent failures at runtime.
# Example .env.local
nano .env.local
Step 4 β Install and Configure PM2
PM2 is a production process manager for Node.js. It keeps your app running in the background, restarts it on crashes, and hooks into systemd to survive container reboots.
Install PM2 globally via pnpm:
pnpm add -g pm2
pm2 --version # confirm
Start the Next.js app:
pm2 start pnpm --name "noc_allocation" -- start
Check it's running:
pm2 status
You should see something like this:
Enable auto-start on container reboot:
pm2 save
pm2 startup systemd
# Copy and run the command it outputs, then:
pm2 save
PM2 writes a systemd service file at /etc/systemd/system/pm2-root.service and enables it automatically. Your app now survives container restarts without any manual intervention.
Step 5 β Set Up Nginx as a Reverse Proxy
Next.js runs on port 3000 by default. Nginx sits in front of it on port 80, forwarding requests and handling connection upgrades for WebSocket support.
Install Nginx:
apt install -y nginx
Create the site config:
nano /etc/nginx/sites-available/noc_allocation
Paste this:
server {
listen 80;
server_name _;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Enable the site and reload Nginx:
rm /etc/nginx/sites-enabled/default
ln -s /etc/nginx/sites-available/noc_allocation /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
systemctl enable nginx
What's Running Now
| Service | Port | Status | Role |
|---|---|---|---|
| Next.js (PM2) | 3000 | β online | App server |
| Nginx | 80 | β online | Reverse proxy |
| pm2-root.service | β | β enabled | Boot persistence |
The app is accessible at http://10.169.81.160 on the internal network. Since this is a private LXC IP, it's only reachable within the Proxmox host's network
Redeploying After Code Changes
Every future deployment is just four commands:
cd /opt/noc_allocation
git pull
pnpm install && pnpm build
pm2 restart noc_allocation
Useful PM2 Commands
| Command | What it does |
|---|---|
pm2 status |
View all processes |
pm2 logs noc_allocation |
Live log stream |
pm2 restart noc_allocation |
Restart the app |
pm2 monit |
Live CPU/memory dashboard |
pm2 stop noc_allocation |
Stop without removing |
pm2 delete noc_allocation |
Remove from PM2 entirely |
pm2 flush noc_allocation |
Clear logs |
Written April 2026 Β· Deployed on Proxmox LXC Β· noc_allocation Β· Next.js + pnpm + PM2 + Nginx



