Skip to content

Proxmox deployment

The whole difference between a Proxmox install and a workstation install is one fact: the container has no graphics card. Everything else follows from that, plus the usual care about a service that has to survive a logout. This covers only what differs from Setup.

An unprivileged LXC is the right shape: no kernel modules, no device passthrough, no Docker.

Template Debian 13 or Ubuntu 24.04
Cores 4 (2 works; builds are slower)
RAM 4 GB (2 GB runs, but next build is tight)
Disk 20 GB - node_modules and .next are ~2 GB
Unprivileged yes · Nesting: not needed
Network a static IP or a DHCP reservation - you will be typing it a lot
Terminal window
pct create 120 local:vztmpl/debian-13-standard_amd64.tar.zst \
--hostname maven-teams \
--cores 4 --memory 4096 --rootfs local-lvm:20 \
--net0 name=eth0,bridge=vmbr0,ip=dhcp \
--unprivileged 1 --features nesting=0 \
--onboot 1
pct start 120
pct enter 120

--onboot 1 matters: a container that does not start with the node is a service that vanishes after the next reboot of the host.

Debian’s own nodejs is far too old - node:sqlite will not be there.

Terminal window
apt update && apt install -y curl git ca-certificates
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt install -y nodejs
node --version # must be >= 22.22.0

Do not run this as root - Workflows has shell steps and the agent CLIs have file access.

Terminal window
adduser --disabled-password --gecos "" maven
su - maven
Terminal window
git clone <your-repository-url> ~/maven-teams
cd ~/maven-teams
npm install
npm run build
export MAVEN_FORCE_CLOUD=1

MAVEN_FORCE_CLOUD overrides the GPU probe entirely. Provider keys are now required, not optional: with no GPU and no key a capability has nowhere to run, and the Local / Cloud screen says so. Paste the keys in Settings → Secrets before deciding anything is broken. For finer control, leave it unset and set each capability on that screen instead.

5 · The service, and the part everybody gets wrong

Section titled “5 · The service, and the part everybody gets wrong”

~/.config/systemd/user/maven-teams.service:

[Unit]
Description=MAVEN Teams
After=network.target
[Service]
Type=simple
WorkingDirectory=%h/maven-teams
Environment=NODE_ENV=production
Environment=PORT=3400
Environment=HOST=0.0.0.0
Environment=MAVEN_STATE_DIR=%h/.maven-teams
Environment=MAVEN_FORCE_CLOUD=1
Environment=MAVEN_MACHINE=proxmox
ExecStart=/usr/bin/npm start
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.target

MAVEN_MACHINE is the name this machine signs its events with; “proxmox” beats a container hostname you will not recognise in six months.

Terminal window
systemctl --user daemon-reload
systemctl --user enable --now maven-teams.service
exit # back to root
loginctl enable-linger maven

Without lingering, the service dies when the SSH session closes. It will look perfect while you are testing and be gone the moment you disconnect. Verify it survives: disconnect entirely, reconnect, and su - maven -c 'systemctl --user status maven-teams --no-pager'.

By default Teams binds 127.0.0.1 only - useless in a container. The unit above sets HOST=0.0.0.0; check it actually took:

Terminal window
ss -tlnp | grep 3400 # expect 0.0.0.0:3400, not 127.0.0.1:3400

Then from the LAN: http://<container-ip>:3400. Do not port-forward this to the internet. The PIN gate and the same-origin guard stop a browser on your own network acting on your behalf; they are not an authentication system. Remote access goes behind a VPN (WireGuard on the Proxmox host) or a reverse proxy that does real authentication.

Proxmox backs up the container, which covers everything; the piece that matters is small enough to copy on its own:

Terminal window
# from the host
pct exec 120 -- tar czf - -C /home/maven/.maven-teams events \
> /var/lib/vz/dump/maven-teams-events-$(date +%F).tar.gz

Restoring is tar xzf into the same place and a restart; the index catches up on the first request. Keep identity.json - regenerating it means this machine signs future events as a different machine.

Terminal window
su - maven
cd ~/maven-teams && git pull && npm install && npm run build
systemctl --user restart maven-teams

Take a Proxmox snapshot before a version you have not run before; rolling back a snapshot is instant.

Symptom Where to look
Nothing on :3400 systemctl --user status maven-teams, then journalctl --user -u maven-teams -n 100
Service vanishes after you log out loginctl show-user maven | grep Linger - must be yes
Transcription takes minutes MAVEN_FORCE_CLOUD=1 is not set, or is set in your shell but not in the unit
“Neither path works yet” on a capability No GPU and no provider key. Paste a key.
App starts, every page errors node --version - below 22.22 the index import throws
Search finds nothing curl -X POST http://localhost:3400/api/events/verify rebuilds the index
Audit log says the chain is broken Somebody edited log.jsonl. Restore from backup; do not repair by hand.