Skip to content

Server install (docker compose)

The canonical install is a self-contained tarball and a sudo ./install.sh. The tarball ships every docker image (ongrid, ongrid-web, singchia/frontier) so there's no Docker Hub pull — the install works in restrictive networks and air-gapped.

For air-gapped specifics see air-gapped install. For a faster walk-through see Quickstart. For the systemd-native install (no docker), see Linux server platform.

Prereqs

A Linux host with:

  • 4 GB RAM minimum, 8 GB recommended (Prometheus + Loki + Tempo + MySQL + manager all live here).
  • 20 GB free disk under /var/lib/ongrid (the data root). Adjust with ONGRID_DATA_DIR=… if you want it elsewhere — NFS / iSCSI / NVMe all work; it's a plain bind-mount.
  • Docker ≥ 24 with the docker compose v2 subcommand (docker compose version should print).
  • openssl — used by install.sh to mint the self-signed TLS cert on first boot if tls.crt / tls.key aren't already present.
  • Inbound TCP/443 open from your browser + every edge.
  • Inbound TCP/40012 open from every edge (the frontier broker).
  • A public IP or domain that all edges can reach. This goes into ONGRID_PUBLIC_URL and is the single most common misconfiguration.

Don't use a private IP for ONGRID_PUBLIC_URL

The installer auto-detects an IP and prompts you to confirm. If you accept a 10.x / 192.168.x / 172.16-31.x address but your edges live on the public internet, logs and traces will silently fail to push. The control-plane tunnel still works (it goes through nginx independently), so the edge looks healthy in the UI — but Loki and Tempo stay empty.

Install

bash
# Pick the latest tag at https://github.com/ongridio/ongrid/releases
VER=v0.7.159

gh release download "$VER" \
    --repo ongridio/ongrid \
    -p 'ongrid-*-linux-amd64.tar.xz*'

# Verify the sha256 — the .sha256 sidecar ships with each release.
sha256sum -c "ongrid-${VER}-linux-amd64.tar.xz.sha256"

tar xf "ongrid-${VER}-linux-amd64.tar.xz"
cd     "ongrid-${VER}-linux-amd64"

sudo ./install.sh

Useful flags:

FlagWhat
--mode systemdSwitch to native systemd install (no docker). Dispatches to systemd/install-systemd.sh. See Linux server platform.
--with-depssystemd-only. Auto-install mariadb + nginx + grafana via apt/dnf, pull pinned prom / loki / tempo / qdrant binaries with sha256 verify.
--profile monitoringcompose-only. Expose Prometheus on port 9090 to the host (useful for laptop dev; off by default in prod).
--no-seedcompose-only. Skip the admin-bootstrap banner output (when re-running an install).
--forcecompose-only. Reinstall on top of an existing install (preserves .env and data volume).

What install.sh does

In order:

  1. Preflight. Verifies the docker CLI is in $PATH, the daemon is reachable, and docker compose v2 is present. Bails early on any of those.

  2. Stage configs into ${ONGRID_INSTALL_DIR:-/opt/ongrid}/:

    • docker-compose.yml, .env.example, VERSION, frontier.yaml,
    • prometheus.yml (bind-mounted into the prom container at /etc/prometheus/),
    • prometheus-rules.yml (ADR-026 self-observability alerts),
    • loki-config.yaml, tempo-config.yaml,
    • grafana/ provisioning,
    • searxng/ settings,
    • edge/ (per-arch edge binaries + plugin binaries + upgrade bundle).
  3. Create host data dirs under ${ONGRID_DATA_DIR:-/var/lib/ongrid}/ and chown them to the uid each container's image runs as:

    • mysql/999:999 (mysql:8.0)
    • prometheus/65534:65534 (prom runs as nobody)
    • loki/10001:10001
    • tempo/10001:10001
    • grafana/472:472
    • embeddings/65532:65532 (manager nonroot user)

    Missing this on first boot is what makes prom/loki/tempo/grafana crash with permission denied on /<datadir>.

  4. Stage the bundled embedding model for offline RAG — /var/lib/ongrid/embeddings/fast-bge-small-zh-v1.5/. If you've already swapped in a custom model the installer leaves it alone.

  5. Refresh nginx config from the tarball and, if no certs are present in ${INSTALL_DIR}/certs/, generate a self-signed cert valid 365 days (CN=ongrid, SAN: DNS:ongrid, DNS:localhost, IP:127.0.0.1).

  6. Load docker images from images/ongrid.tar, images/frontier.tar, images/ongrid-web.tar via docker load. No registry pull required.

  7. Create or reuse .env. If ${INSTALL_DIR}/.env exists, keep it (--force does NOT overwrite operator-edited .env). If not, copy from .env.example. Then fill blanks with strong random values:

    • MYSQL_ROOT_PASSWORD, MYSQL_PASSWORD — 24 chars,
    • ONGRID_JWT_SECRET — 64 chars,
    • ONGRID_ADMIN_PASSWORD — 20 chars (recorded for the final banner),
    • GRAFANA_ADMIN_PASSWORD — 20 chars.
  8. Prompt for ONGRID_PUBLIC_URL if blank. 30-second countdown, default = best-guess host. Reads /dev/tty so it survives curl ... | bash.

  9. docker compose up -d with --env-file .env. No -f argument, so docker-compose.override.yml auto-loads if you've added one for tweaks.

  10. Poll https://localhost/healthz for up to 60 seconds via nginx. The manager's /healthz returns 200 once MySQL is reachable and the agent kernel is wired.

  11. Print the install banner — Web URL, API URL, tunnel endpoint, bootstrap admin email + password (only on first install).

After install

You'll see a banner like:

text
===============================================================
  ongrid installation complete
===============================================================

Install dir:     /opt/ongrid
Version:         v0.7.159

Web UI:          https://203.0.113.10/
API URL:         https://203.0.113.10/api/v1
Tunnel endpoint: 203.0.113.10:40012   (for edges)

TLS: self-signed cert in /opt/ongrid/certs/ — browsers will warn
      on first visit. Replace tls.crt + tls.key with a real cert and
      'docker compose -f /opt/ongrid/docker-compose.yml restart nginx'.

---------------- bootstrap admin ----------------
email:    admin@example.com
password: 9Xp4hKqf1bL2zRq3Wn7v
>> Record this password NOW. It will not be shown again.
-------------------------------------------------

Record the admin password

The bootstrap password is shown once. It's also stored in /opt/ongrid/.env (mode 0600). If you lose both, reset via the reset-admin-password CLI or by editing the DB directly — see first-boot checklist.

Verify the stack

bash
# All containers should be Up
sudo docker compose -f /opt/ongrid/docker-compose.yml ps

# Manager health
curl -fk https://localhost/healthz

# Tail manager logs
sudo docker compose -f /opt/ongrid/docker-compose.yml logs -f ongrid

# Browse to the UI
open https://<your-host>/   # accept the TLS warning

Replacing the TLS cert

The self-signed cert is fine for trials but every browser will warn. For production drop a real cert (Let's Encrypt, your corp CA, or whatever) into /opt/ongrid/certs/:

bash
sudo cp fullchain.pem /opt/ongrid/certs/tls.crt
sudo cp privkey.pem   /opt/ongrid/certs/tls.key
sudo chmod 600        /opt/ongrid/certs/tls.key
sudo chmod 644        /opt/ongrid/certs/tls.crt
sudo docker compose -f /opt/ongrid/docker-compose.yml restart nginx

install.sh and upgrade.sh never overwrite operator-provided certs.

Wildcards work

nginx serves *.crt / *.key from certs/; the only filenames the container looks for are tls.crt and tls.key. Symlinks are fine if your cert manager (certbot, acme.sh, cert-manager) keeps the canonical copy elsewhere.

Where things land

PathOwnerPurpose
/opt/ongrid/docker-compose.ymlrootCompose definition.
/opt/ongrid/.envroot, 0600Secrets + tunables.
/opt/ongrid/certs/root, 0700tls.crt, tls.key.
/opt/ongrid/edge/rootEdge binaries, upgrade bundle (edge-bundle-<arch>-<ver>.tar.gz), install.sh, apply-pending-upgrade.sh. Served read-only via nginx at /edge/.
/opt/ongrid/prometheus.ymlrootProm scrape + remote_write config.
/opt/ongrid/grafana/rootProvisioning yamls (datasources, dashboards).
/var/lib/ongrid/mysql/999:999MySQL data. Back this up.
/var/lib/ongrid/prometheus/65534:65534Prom TSDB. 90d retention, 20GB cap by default.
/var/lib/ongrid/loki/10001:10001Loki chunks + index.
/var/lib/ongrid/tempo/10001:10001Tempo blocks.
/var/lib/ongrid/qdrant/rootVector store.
/var/lib/ongrid/grafana/472:472Grafana state (dashboards, users, SA token).
/var/lib/ongrid/embeddings/65532:65532Offline BGE model cache.
/var/log/ongrid/mixedManager log files.

What's next