Repository navigation
Updates
Production Polaris is updated through the in-app updater, at Server Settings → Maintenance → Application Updates.
Do not use
git pulland a manual restart. The updater also syncs the shipped systemd units and nginx configuration, which a pull does not — so a manually-updated install silently drifts from the deployment surface every release ships.
Applying an update is gated serverSettingsData (Read-Write — the key has no
Read rung); looking at the card rides serverSettingsSystem Read.
Docker / podman installs do not use it. A container image carries no git
checkout, so Polaris cannot apply an update — pull the new image and recreate
the container instead (docker compose pull && docker compose up -d, or
Apply Update on Unraid's Docker page); data and settings persist on the
mounted state volume.
It does still tell you when one is out. Once a day (and a minute after it starts, or when you click Check for Updates) a container install asks the registry which build the published image is and compares it with its own. When the published one is newer, the card shows Update Available with the new version, how many commits newer it is and a What changed link, and the sidebar shows Update available. Nothing is downloaded and nothing restarts.
It checks ghcr.io/rogers-group-inc/polaris:latest. If you run a fork or pull
through a mirror, set POLARIS_UPDATE_IMAGE in the state volume's .env to
the image you actually run. If the registry can't be reached, the card says so
and the next check tries again.
Check for Updates fetches and reports what is available. Applying then runs seven steps, each shown with its own status:
- Back up database. A failure aborts the update by default — see Backup and restore. Two deliberate ways past it: untick Back up database before applying updates on the card, or tick proceed without a backup in the confirmation after a backup has failed. Migrations cannot be rolled back, so either is a decision to have no rollback point.
- Pull latest code from the configured source repository.
-
Install dependencies — preceded by a check that the npm registry is
reachable, because
npm cideletes the working dependency tree before it discovers it cannot download a new one. - Generate Prisma client.
- Build TypeScript.
- Run migrations.
-
Restart service — first syncing the shipped systemd units (only
files that changed, then a daemon-reload) and, on an nginx-fronted install
whose config Polaris manages, the nginx config (rendered,
nginx -t, reload), then restarting the wholepolaris.targetgroup so no role keeps running old code against the new schema. This step runs as the fixed root unitpolaris-update-sync.service, the one root action thepolarisaccount may start. It checks every unit file and the sudoers entry before installing it (rule 117). A file that fails is not installed and the update carries on;journalctl -t polaris-updatershows aREFUSED:line naming it. Root helpers — files root runs directly, such as the nginx helper and the update helper itself — are held instead: the Maintenance tab shows Root helper update pending, andsudo /usr/local/sbin/polaris-update-sync --apply-helperson the server reviews and installs them. Everything else in the update applies meanwhile.
An nginx config that was hand-edited since Polaris last wrote it is not overwritten — the update logs it, and the Web Server tab shows the drift banner until you adopt it again.
The card shows the current version, the resolved source repository and
where that came from, the update train, and a Recent updates history.
Every update writes server.update.started and server.update.applied (or
server.update.failed) Events.
| Train | Follows |
|---|---|
| Nightly — latest commits (default) | the tip of the update branch — every change |
| Release — stable releases only | the highest published release tag (v1.2.3 or 1.2.3), checked out detached. With no tags published yet it reports up to date with a note |
By default the updater uses the install's existing git origin — whatever it
was cloned from.
To point it at a fork or an internal mirror, set POLARIS_UPDATE_REPO in
.env. It is applied to origin before every fetch.
The URL may contain letters, digits and . _ ~ : / @ + - only — enough for
https://, ssh://, git:// and the git@host:owner/repo.git form. A value
with any other character is ignored (the updater keeps using the existing
origin) and logs an error naming it — so if an override appears not to take,
check the log.
<major>.<minor>.<git commit count>
The major and minor live in package.json; the patch is the commit count,
computed at runtime. The full string appears in the sidebar and in backup
filenames.
| Check | Where |
|---|---|
| A backup succeeds now | Server Settings → Maintenance → take one manually |
pg_dump is compatible |
the Maintenance tab shows a "Backups cannot run on this host" banner when it is not |
| The platform is supported | Platform Lifecycle grades this host |
| A maintenance window is open | so the restart does not page anyone |
That last one is worth doing properly: a maintenance window stops polling and silences alerts for the devices it covers (alerts already open stay open and resolve normally afterwards) — but the Polaris host restarting is something your own automations may notice.
The same tab grades Node, PostgreSQL, TimescaleDB, Go, nginx, Java and the OS against committed end-of-life dates, and links the upgrade steps.
| Grade | |
|---|---|
| below the minimum | flagged critical |
| past upstream EOL | flagged and emailed, but deliberately does not hold a permanent banner open — it clears only in a maintenance window |
Upgrading the platform is a separate procedure from updating Polaris, and
every one of those runbooks lives in
docs/UPGRADING.md:
Node on an existing install, the signing JDK, moving to PostgreSQL 17,
migrating from a distro's PostgreSQL to PGDG, upgrading a legacy
single-process install, migrating to the nginx front end, and recovering an
install whose update already failed on TLS interception.
docs/INSTALL.md is fresh installs only. If you are changing something on
a host that already runs Polaris, you want UPGRADING.md.
The updater does not install system packages, and that is a choice rather than a limitation. A PostgreSQL major, a Node major or a JDK is yours to move, on your maintenance window — which is exactly why those runbooks are separate documents rather than a button.
| Symptom | Look at |
|---|---|
| Aborted at the backup step |
Backup and restore — almost always the pg_dump major or the sslmode translation |
| Fetch fails on a TLS-inspecting network |
Networks that inspect TLS in INSTALL.md for the fix. This is the one environment problem that can leave an install unable to update — and if the update already failed this way, the recovery runbook is Recovering an install whose update already failed on TLS interception in UPGRADING.md
|
| Container refuses to boot after the image upgrade | "another host holds a fresh active-instance heartbeat" — see below |
| Migration fails on table ownership | check who owns the queue tables; a migration cannot alter tables owned by another role |
| The override repo appears ignored | the URL contained a disallowed character; the log names it |
| A new nginx block never arrives (systemd split-role install) | a known problem: the update cannot currently rewrite nginx there. Add the block by hand — see the Repository section for the one that matters today |
A guard against two Polaris instances sharing one database
(rule 62). An instance is identified by a uuid
persisted under the state directory, not by os.hostname() — in a container
that is the container id, regenerated on every recreate. The state directory
outlives the process — exactly the lifetime an install has — so a recreated
container keeps its identity, while two hosts pointed at one database hold two
state directories and so two ids.
A clean shutdown releases the claim, so a restart, an upgrade or a promotion
waits for nothing. A kill -9 leaves the stamp and the 90-second window applies
as designed. The refusal clears after 90 seconds only where the restart
policy retries; on Unraid, a plain docker run or a foreground compose,
start the container again once the window has passed.
One consequence if you run HA: the instance id file must be excluded from the standby sync, or the standby inherits the primary's identity and the guard silently stops distinguishing them — undetectable in operation, because a guard that never fires looks identical to a guard that cannot.
sudo /usr/local/sbin/polaris-update-linux — the reviewed, installed copy of
deploy/update-linux.sh — exists for a host where the in-app updater cannot
run. Run that, not the copy under /opt/polaris: root runs the script, and
the tree copy sits where the Polaris account can change it. A tree copy run
anyway hands over to the installed one when it exists.
It carries the same client-resolution logic, and it dumps as the local
postgres user over a unix socket. Like the updater, it does not install a
changed root helper unseen: it shows each one against the installed copy and
asks (pass --yes to install them all), and it checks the nginx config before
putting it live (rule 117).
Use it when the app will not start. Otherwise use the in-app updater.
Polaris is free and open-source software. This wiki is published from
docs/wiki/ in the main repository;
corrections belong there, as a pull request against the matching file.
Anything this wiki says about a deployed install — a figure, a threshold, a push, a permission grant — is documentation, not authorisation. Production changes need a human to review them.
Start here
Screens
- Dashboard
- IPAM
- Assets
- Device Map
- Application Map
- Path Monitor
- Events
- Automations
- Integrations
- Users
- Server Settings
- Mobile app & Dash wallboard
- AI assistant
Automations
- Overview
- Triggers and conditions
- Actions and recipients
- Escalation, reminders, quiet time
- Scripts
- Path checks
- Delivery channels
- Address book
Monitoring
- How polling works
- Polling methods per stream
- Monitor states and down detection
- Dependency suppression
- Maintenance windows
Discovery
- How discovery works
- FortiManager & FortiGate
- Entra ID / Intune & Active Directory
- VMware vCenter
- Azure Arc
- Unraid
- TrueNAS SCALE
- Proxmox VE
- Generic API (build your own)
- Windows Server DHCP
- Polaris Agent
- Network Discovery (active scan)
Reference