Deploys the OpsCommandCenter Server (dashboard + API + SignalR + PostgreSQL) as a native systemd service on a fresh Ubuntu Server VM. No Docker, no manually-installed .NET runtime - the published binary is self-contained.
Status: written and cross-published successfully from the Windows dev machine, but not yet run against a real Ubuntu VM (none was available at the time this was built). Treat your first run as the first real test of this guide.
This part happens in your own Proxmox console, not something scripted here. What you need at the end of it:
- Ubuntu Server 22.04 or 24.04 LTS installed, with OpenSSH enabled during install
- A static LAN IP (or a DHCP reservation) so the dashboard URL doesn't change later
- At least 1 vCPU / 1 GB RAM / 10 GB disk (this is a lightweight app + a small Postgres database for a few hundred computer rows - not resource-hungry)
- SSH access from your Windows machine (
ssh <user>@<vm-ip>works)
From C:\Projects\OpsCommandCenter:
.\publish-server-linux.ps1This produces publish-linux\OpsCommandCenter.Server - a single self-contained linux-x64
executable (plus its appsettings*.json files alongside it). No Docker or WSL involved;
.NET's cross-publish works directly from Windows.
scp -r publish-linux deploy\ubuntu\opscommandcenter.service deploy\ubuntu\install.sh <user>@<vm-ip>:/tmp/opscc-deploy/(Create /tmp/opscc-deploy/ on the VM first if scp complains it doesn't exist:
ssh <user>@<vm-ip> "mkdir -p /tmp/opscc-deploy".)
ssh <user>@<vm-ip>
cd /tmp/opscc-deploy
sudo bash install.shThis script (deploy\ubuntu\install.sh):
- Installs PostgreSQL via
aptif it isn't already present, and enables it. - Creates a
opsccdatabase role andopsccdatabase (idempotent - leaves an existing role's password alone on re-run). - Creates an unprivileged
opscommandcentersystem account to run the service as. - Copies
publish-linux/*into/opt/opscommandcenter. - Installs
opscommandcenter.serviceinto/etc/systemd/system/and starts it (systemctl enable --now). - Opens port 5252 in
ufwifufwis active.
The database role is created with a placeholder password (CHANGE_ME). Change it right
after the first install:
sudo -u postgres psql -c "ALTER ROLE opscc PASSWORD 'yournewpassword';"
sudo nano /opt/opscommandcenter/appsettings.Production.json # update the matching password
sudo systemctl restart opscommandcentersudo systemctl status opscommandcenter
curl http://localhost:5252/api/computerssystemctl status should show active (running). The curl should return [] (empty array)
on a fresh install - that's correct, no Agents have reported in yet.
From another machine on the LAN, open http://<vm-ip>:5252 in a browser - you should see the
OpsCommandCenter dashboard (empty until an Agent starts reporting; see
agent-installation.md).
Re-run steps 2-4. install.sh is idempotent: it stops the running service, replaces the files
in /opt/opscommandcenter, and restarts it. Your database and its data are untouched.
- Service won't start / crashes immediately:
sudo journalctl -u opscommandcenter -n 50 --no-pager- most likely the Postgres connection string in
appsettings.Production.jsondoesn't match the actual role/password, or PostgreSQL itself isn't running (systemctl status postgresql).
- most likely the Postgres connection string in
- Dashboard unreachable from another PC but
curl localhost:5252works on the VM itself: checkufw status(port 5252 must be allowed) and that the systemd unit'sASPNETCORE_URLS=http://0.0.0.0:5252line is present - binding to0.0.0.0instead of the Kestrel defaultlocalhostis what makes it reachable from the LAN at all. - Want HTTPS later: put nginx in front of the app as a reverse proxy (
proxy_pass http://localhost:5252;) and get a certificate. Not needed for LAN-only use today, and no code changes are required in the app to add it later.