Add Proxmox LXC deployment guide
Covers NixOS LXC (recommended, uses the flake module) and Debian/Ubuntu LXC (traditional setup). Includes PostgreSQL setup, systemd service, nginx reverse proxy, backup strategies, and update instructions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,297 @@
|
|||||||
|
# Deploying buildfor_life_repair on Proxmox LXC
|
||||||
|
|
||||||
|
This guide covers deploying the app in a lightweight LXC container on Proxmox VE.
|
||||||
|
|
||||||
|
## Option A: NixOS LXC (Recommended)
|
||||||
|
|
||||||
|
NixOS is ideal for LXC — declarative config, small footprint, reproducible builds.
|
||||||
|
|
||||||
|
### 1. Create the LXC container
|
||||||
|
|
||||||
|
Download the NixOS LXC template (or build one):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# On Proxmox host
|
||||||
|
pveam update
|
||||||
|
pveam download local nixos-24.11-default_20241101_amd64.tar.xz
|
||||||
|
|
||||||
|
# Create container (adjust ID, storage, resources)
|
||||||
|
pct create 200 local:vztmpl/nixos-24.11-default_20241101_amd64.tar.xz \
|
||||||
|
--hostname bflr \
|
||||||
|
--memory 1024 \
|
||||||
|
--swap 512 \
|
||||||
|
--cores 2 \
|
||||||
|
--storage local-lvm \
|
||||||
|
--rootfs local-lvm:8 \
|
||||||
|
--net0 name=eth0,bridge=vmbr0,ip=dhcp \
|
||||||
|
--unprivileged 1 \
|
||||||
|
--features nesting=1
|
||||||
|
|
||||||
|
pct start 200
|
||||||
|
```
|
||||||
|
|
||||||
|
If no NixOS template is available, use the [nixos-infect](https://github.com/elitak/nixos-infect) script on a Debian LXC, or build a NixOS LXC image with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nix build github:nix-community/nixos-generators#lxc
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Configure NixOS
|
||||||
|
|
||||||
|
SSH into the container and edit `/etc/nixos/configuration.nix`:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
bflr = builtins.getFlake "git+https://git.b4l.co.th/B4L/buildfor_life_repair.git";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
bflr.nixosModules.default
|
||||||
|
];
|
||||||
|
|
||||||
|
# PostgreSQL
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
ensureDatabases = [ "buildfor_life_repair" ];
|
||||||
|
ensureUsers = [{
|
||||||
|
name = "bflr";
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
}];
|
||||||
|
authentication = ''
|
||||||
|
local buildfor_life_repair bflr trust
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# The app
|
||||||
|
services.buildfor-life-repair = {
|
||||||
|
enable = true;
|
||||||
|
port = 3000;
|
||||||
|
databaseUrl = "postgresql://bflr@localhost/buildfor_life_repair";
|
||||||
|
baseUrl = "http://bflr.local:3000"; # or your domain
|
||||||
|
openFirewall = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Optional: nginx reverse proxy with SSL
|
||||||
|
# services.nginx = {
|
||||||
|
# enable = true;
|
||||||
|
# virtualHosts."repair.example.com" = {
|
||||||
|
# forceSSL = true;
|
||||||
|
# enableACME = true;
|
||||||
|
# locations."/".proxyPass = "http://127.0.0.1:3000";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [ 3000 ];
|
||||||
|
|
||||||
|
system.stateVersion = "24.11";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Build and switch
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nixos-rebuild switch
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Create the first user
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Enter the app directory
|
||||||
|
cd /var/lib/buildfor-life-repair
|
||||||
|
|
||||||
|
# Run the create-user script
|
||||||
|
nix run git+https://git.b4l.co.th/B4L/buildfor_life_repair.git -- \
|
||||||
|
npx tsx scripts/create-user.ts admin@b4l.co.th yourpassword "Admin"
|
||||||
|
```
|
||||||
|
|
||||||
|
Or connect to the database directly:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -u postgres psql buildfor_life_repair
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Option B: Debian/Ubuntu LXC
|
||||||
|
|
||||||
|
If you prefer a traditional setup.
|
||||||
|
|
||||||
|
### 1. Create the LXC container
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# On Proxmox host
|
||||||
|
pct create 200 local:vztmpl/debian-12-standard_12.2-1_amd64.tar.zst \
|
||||||
|
--hostname bflr \
|
||||||
|
--memory 1024 \
|
||||||
|
--swap 512 \
|
||||||
|
--cores 2 \
|
||||||
|
--storage local-lvm \
|
||||||
|
--rootfs local-lvm:8 \
|
||||||
|
--net0 name=eth0,bridge=vmbr0,ip=dhcp \
|
||||||
|
--unprivileged 1 \
|
||||||
|
--features nesting=1
|
||||||
|
|
||||||
|
pct start 200
|
||||||
|
pct enter 200
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Install dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt update && apt upgrade -y
|
||||||
|
apt install -y curl git postgresql
|
||||||
|
|
||||||
|
# Install Node.js 22
|
||||||
|
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
|
||||||
|
apt install -y nodejs
|
||||||
|
|
||||||
|
# Install build tools for native modules (sharp)
|
||||||
|
apt install -y build-essential python3 libvips-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Set up PostgreSQL
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -u postgres psql <<EOF
|
||||||
|
CREATE USER bflr WITH PASSWORD 'your-secure-password';
|
||||||
|
CREATE DATABASE buildfor_life_repair OWNER bflr;
|
||||||
|
GRANT ALL PRIVILEGES ON DATABASE buildfor_life_repair TO bflr;
|
||||||
|
\c buildfor_life_repair
|
||||||
|
GRANT ALL ON SCHEMA public TO bflr;
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Clone and build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create app user
|
||||||
|
useradd -m -s /bin/bash bflr
|
||||||
|
su - bflr
|
||||||
|
|
||||||
|
git clone https://git.b4l.co.th/B4L/buildfor_life_repair.git
|
||||||
|
cd buildfor_life_repair
|
||||||
|
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Create .env
|
||||||
|
cat > .env <<EOF
|
||||||
|
DATABASE_URL=postgresql://bflr:your-secure-password@localhost:5432/buildfor_life_repair
|
||||||
|
UPLOAD_DIR=/home/bflr/buildfor_life_repair/static/uploads
|
||||||
|
BASE_URL=http://your-ip:3000
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Push schema
|
||||||
|
npm run db:push
|
||||||
|
|
||||||
|
# Create first user
|
||||||
|
npm run create-user -- admin@b4l.co.th yourpassword "Admin"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Create systemd service
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# As root
|
||||||
|
cat > /etc/systemd/system/bflr.service <<EOF
|
||||||
|
[Unit]
|
||||||
|
Description=buildfor_life_repair
|
||||||
|
After=network.target postgresql.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=bflr
|
||||||
|
WorkingDirectory=/home/bflr/buildfor_life_repair
|
||||||
|
EnvironmentFile=/home/bflr/buildfor_life_repair/.env
|
||||||
|
Environment=NODE_ENV=production
|
||||||
|
Environment=PORT=3000
|
||||||
|
Environment=HOST=0.0.0.0
|
||||||
|
ExecStart=/usr/bin/node build/index.js
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
# Hardening
|
||||||
|
NoNewPrivileges=true
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=read-only
|
||||||
|
ReadWritePaths=/home/bflr/buildfor_life_repair/static/uploads
|
||||||
|
PrivateTmp=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable --now bflr
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Verify
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl status bflr
|
||||||
|
curl http://localhost:3000
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Resource recommendations
|
||||||
|
|
||||||
|
| Resource | Minimum | Recommended |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| CPU | 1 core | 2 cores |
|
||||||
|
| RAM | 512 MB | 1024 MB |
|
||||||
|
| Disk | 4 GB | 8 GB |
|
||||||
|
|
||||||
|
Add more disk if storing many device images/documents.
|
||||||
|
|
||||||
|
## Reverse proxy (optional)
|
||||||
|
|
||||||
|
If running behind nginx on the Proxmox host or another LXC:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name repair.example.com;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/repair.example.com/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/repair.example.com/privkey.pem;
|
||||||
|
|
||||||
|
client_max_body_size 50M; # for image uploads
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://192.168.1.x:3000; # LXC IP
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Backups
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Database dump (add to cron)
|
||||||
|
pg_dump -U bflr buildfor_life_repair > /backup/bflr-$(date +%Y%m%d).sql
|
||||||
|
|
||||||
|
# Or use Proxmox's built-in LXC backup
|
||||||
|
vzdump 200 --storage backup --mode snapshot
|
||||||
|
```
|
||||||
|
|
||||||
|
## Updating
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Debian/Ubuntu
|
||||||
|
su - bflr
|
||||||
|
cd buildfor_life_repair
|
||||||
|
git pull
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
npm run db:push
|
||||||
|
exit
|
||||||
|
systemctl restart bflr
|
||||||
|
|
||||||
|
# NixOS
|
||||||
|
nixos-rebuild switch --flake git+https://git.b4l.co.th/B4L/buildfor_life_repair.git
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user