Install

Download, verify, run. The first node is free.

Semurg installs on your own machine, on-premises or in your own cloud. There is no account to create, nothing is uploaded, and the node does not call home.

One command

curl -fsSL https://one.semurg.io/install | sudo bash

As root, on a machine that meets the list below. It downloads the installer, checks it against the published checksum and runs it; the node then answers on http://localhost:4000/api/health. If the node should keep its data on separate disks, mount them at /data0, /data1, ... first (below); with none, it uses the disk it is installed on. To read the script before you run it: curl -fsSL https://one.semurg.io/install | less.

What it needs, and what it changes

Read from the installer itself, so this list changes when the installer does.

It needs

  • Ubuntu 24.04 on x86_64. The release is built against glibc 2.38: Ubuntu 22.04 ships 2.35 and the installer stops there. Another Ubuntu version is untested: the installer warns and continues, and stops if its glibc is older than 2.38.
  • At least 4 CPU threads, 8 GB of RAM and 20 GB free where it installs (/opt/semurg).
  • Root, and internet access to install a few runtime libraries (SEMURG_SKIP_NET=1 skips that check).
  • Each data disk mounted at its own /data0, /data1, ..., ext4 or xfs, with at least 10 GB free. With no data disk, the store goes on the system disk, under /var/lib/semurg/data.

It writes

  • The release, under /opt/semurg, and its settings in /etc/semurg; the API token is in /etc/semurg/semurg.env.
  • One service, /etc/systemd/system/semurg.service, started at boot. After 5 failures in 300 seconds it stops restarting and stays failed, so a fault is visible.
  • One command, /usr/local/bin/semurg.
  • These packages, through apt, where they are missing: ca-certificates, curl, locales, openssl, libtinfo6, zlib1g, libstdc++6, libgcc-s1, libncursesw6.
  • The store, on the data disks it found. It prints them as it goes: Found 2 data pipe(s) (discovered: 2 mounted data disk(s)): /data0,/data1.

It never

  • Partitions or formats a disk. A blank disk, an unmounted partition or 64 GiB of unpartitioned space is named and the install stops, and so does a /data path that is only a folder on the system disk. Preparing a disk is yours: see below. (SEMURG_ALLOW_UNUSED_DISKS=1 proceeds with the unused space left idle.)
  • Changes a kernel setting: no sysctl, no boot option, no kernel module, no huge pages.
  • Answers beyond this machine unless you say so: the API on 127.0.0.1:4000, the console on 127.0.0.1:4610, and its other listeners on loopback too. SEMURG_BIND chooses the API's address.
  • Installs over a finished install. A plain re-run is refused; a node takes a new release with semurg update --apply.

One exception: on a machine with neither systemd nor a container, it adds one line to /etc/security/limits.conf (root - memlock unlimited) and asks you to log in again before re-running it.

When it stops

The installer stops rather than install a node that will not work, and every stop prints what is wrong and what to do. These are its own words, read from the installer, in the order a run meets them. Do what it says, then run the command it names, which is usually the one you just ran.

It stopsWhat to do
“must run as root”Use: curl -fsSL https://one.semurg.io/install | sudo bash
“checksum mismatch (expected the published checksum)”Re-run; if it persists email semurg@semurg.org
“Another Semurg install is already running (lock: /run/semurg-install.lock).”Wait for it to finish, or remove the lock file if it is stale, then re-run.
“REFUSED: this node already has a COMPLETED Semurg install”semurg update --apply (checks the signed manifest, verifies, swaps, restarts, rolls back on failure). Say what you mean: SEMURG_INSTALL_MODE=upgrade bash ./semurg-install.sh (keeps the env, snapshots the release, replaces it)
Inside a container started without the memory-lock limit the engine needsThis is a container limit, not an OS one. Start the container with --ulimit memlock=-1 . The published container image passes these flags for you (see In a container, below). Then re-run.
On a machine with neither systemd nor a container, when the memory-lock limit is too lowAdded 'root - memlock unlimited' to /etc/security/limits.conf -- LOG OUT and LOG BACK IN (a fresh PAM session is required; a re-exec cannot self-fix), then re-run this installer.
“Semurg requires Ubuntu (found 'your OS'). Aborting.”Install on Ubuntu 24.04 (this build links glibc 2.38; 22.04 ships 2.35 and needs a separate build).
“Semurg R11 is x86-64 (amd64) ONLY -- this machine is 'your CPU' (ARM / Apple Silicon).”Semurg cannot run on ARM, emulated or native. Run it on a cloud x86_64 Linux VM (any provider), or on Windows install WSL2 (an x86_64 Linux) and run this same installer inside it.
“This Semurg build needs glibc >= 2.38 but this system has your glibc (e.g. Ubuntu 22.04 ships 2.35).”Install on Ubuntu 24.04+ (glibc >= 2.38), or ask Semurg for a build matching your OS.
“No internet connectivity (needed to install runtime libraries).”Connect the machine to the internet, or pre-install: ca-certificates curl openssl libtinfo6 zlib1g. Then re-run.
“Need >= 4 CPU cores (found N).”Use a machine with at least 4 cores.
“Need >= 8 GB RAM (found N GB).”Use a machine with at least 8 GB RAM.
“Need >= 20 GB free on … (found N GB).”Free up disk space or set SEMURG_INSTALL_DIR to a bigger disk.
“/data0 is a DIRECTORY on the OS disk, not a mounted data disk (it would be a pipe in name only)”Mount a real data disk (ext4/xfs) at each /data* path, or remove the directory, then re-run. The install page's "prepare your data disks" section has the exact commands. Nothing was changed.
When a /data path is mounted, but on a filesystem other than the ones in the list aboveMount a real data disk (ext4/xfs) at each /data* path, or remove the directory, then re-run. The install page's "prepare your data disks" section has the exact commands. Nothing was changed.
“This machine has capacity Semurg would NOT use: …found N mounted data pipe(s). Every unused disk is a pipe left idle.”Prepare them as /dataN data disks (the install page's "prepare your data disks": partition, mkfs.xfs, mount at /dataN, add to /etc/fstab) and re-run - OR re-run with SEMURG_ALLOW_UNUSED_DISKS=1 to proceed knowingly with N pipe(s). Nothing was changed.
When a data path cannot take the engine's direct writes (a network share, tmpfs, a container overlay or a desktop shared folder)Point SEMURG_DATA_DIR / SEMURG_STRIPE_ROOTS at a local ext4/xfs disk on NVMe/SSD (not tmpfs/NFS/overlay/zfs/9p), then re-run.
“The data path /data0 has only N GB free (need >= 10 GB for the store + first-boot preload).”Free space on that filesystem, or point SEMURG_DATA_DIR / SEMURG_STRIPE_ROOTS at a larger disk, then re-run.
When the install's own self-test finds the engine did not start fully on this machine: the install stops and the service is stopped. In a container the usual cause is a missing --ulimit memlock=-1 or --security-opt seccomp=unconfined, or a data path that is not ext4 or xfsFix the cause and re-run this installer (a failed install leaves no completion marker, so a plain re-run works). To finish anyway, knowingly: SEMURG_ACCEPT_SELFTEST_FAIL=1 sudo ./semurg-install.sh . Full output: /var/log/semurg-install.log

Or step by step

1. Download 2. Verify 3. Run 4. Check the installer archive checksum and release key one command, as root the node answers on localhost
Step 2 is the one people skip. It is the step that tells you the bytes you downloaded are the bytes we published.

The one command above does steps 1 to 3 for you. Step by step lets you make its two checks yourself: the checksum and the release key. Either way, give the node its data disks first (below).

Before step 3: give the node its data disks

The installer stripes the store across every /data* that is its own mounted disk (one stripe root each, in sorted order), and falls back to the system disk when the machine has none. It refuses, by name, a /data0 that is only a folder on the operating-system disk, and a disk it could use but cannot (blank, unmounted, or unpartitioned space). So mount each data disk at its own /data0, /data1, ... before you run it; each must meet the data-disk line in the list above. To choose the roots yourself, set SEMURG_STRIPE_ROOTS (a comma list).

1. See what the machine has. A disk with no partitions and no mount point is blank; free space at the end of an operating-system disk shows as a "Free Space" row. Your device names will differ: read them here.

lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT
sudo parted /dev/nvme0n1 unit GB print free

2. A blank whole disk (here nvme2n1): one partition, one filesystem.

sudo parted -s /dev/nvme2n1 mklabel gpt mkpart data0 ext4 0% 100%
sudo mkfs.ext4 -L data0 /dev/nvme2n1p1

3. Free space at the end of an operating-system disk (here nvme0n1; START is the Start of its last "Free Space" row). Never touch a partition the system already uses.

sudo parted -s -a optimal /dev/nvme0n1 mkpart data2 ext4 STARTGB 100%
sudo partprobe /dev/nvme0n1 && lsblk /dev/nvme0n1
sudo mkfs.ext4 -L data2 /dev/nvme0n1p3

4. Mount each one by UUID, so a reboot finds it. Repeat for /data1, /data2, ... with each device.

sudo mkdir -p /data0
echo "UUID=$(sudo blkid -s UUID -o value /dev/nvme2n1p1) /data0 ext4 defaults,noatime,nofail 0 2" | sudo tee -a /etc/fstab
sudo mount /data0

5. Check, then install. Every line must show its own device. The installer then prints the data disks it found, each with its device and size (the first line is quoted in the list above).

findmnt -o TARGET,SOURCE,FSTYPE,SIZE /data0 /data1 /data2 /data3
Before you type mkfs: it erases the device. Use it only on disks or free space you mean to give Semurg. The installer prints each disk's size, but the store is spread evenly, so with disks of unequal size the smallest fills first, and writes to what it holds then fail: give it disks of similar size where you can. Prepare the disks BEFORE step 3: the installer reads /data* once and writes what it found to /etc/semurg/semurg.env. A plain re-run on a finished node is refused. SEMURG_INSTALL_MODE=reinstall re-scans the disks, so never use it on a node that holds data after adding or removing a data disk. (Updating in place with semurg update is safe; it does not rediscover.)

On Linux

1. Download the installer.

curl -fsSLO https://one.semurg.io/dl/semurg-r11-installer.tar.gz

2. Verify it before you run it. Two checks. The first fetches the published checksums and checks your copy against the installer's line; it prints exactly one line, semurg-r11-installer.tar.gz: OK. The second unpacks the archive and checks that the release key inside it is Semurg's: the sha256 of semurg_release.pub must be the value printed here, which is also written into the installer's own text, and the installer refuses to run with any other key. If either check does not match, stop and tell us.

curl -fsSL https://one.semurg.io/dl/SHA256SUMS | grep ' semurg-r11-installer.tar.gz$' | sha256sum -c -
tar xzf semurg-r11-installer.tar.gz && sha256sum semurg_installer/semurg_release.pub

Release key fingerprint (sha256 of semurg_release.pub):
b1de2e5678b5ab0457c62281a84efe73c24a17fe2cc2f7d38ea59d46b33ae2c3
The same value is written in the README.md inside the archive and in the installer script itself, so you have a copy that does not depend on this page. If any two of them differ, one of them was changed: stop and tell us.

3. Run it.

cd semurg_installer && sudo ./semurg-install.sh

4. Check the node answers.

curl -s http://localhost:4000/api/health

In a container

The container image and its compose file are published beside the installer, and verified the same way.

curl -fsSLO https://one.semurg.io/dl/semurg-docker.tar.gz
curl -fsSL https://one.semurg.io/dl/SHA256SUMS | grep ' semurg-docker.tar.gz$' | sha256sum -c -
tar xzf semurg-docker.tar.gz && docker compose up

A container binds the port you publish, so it reaches the network by design. Give it a token before you expose it, and keep your data directory on a mounted volume so it outlives the container.

Read it first, if you prefer. The installer is a shell script, and you can read the whole thing before running anything: curl -fsSL https://one.semurg.io/install | less

Then, in the next two minutes

Keep the token

The SUCCESS banner prints your API token, and it is stored in /etc/semurg/semurg.env. Every API call carries it as Authorization: Bearer. Without it the API answers 401 on purpose.

Write, then read

One ingest call writes a passage and one query call reads it back. A new node comes up with a small sample graph already loaded (a Panama Papers subset from the ICIJ Offshore Leaks data), so a traversal answers straight away; the installer's banner says how to start empty instead. The exact commands, with what each returns, are on /develop.

Open your cluster admin console

Every node ships its own. The installer prints one URL and the one-time admin secret at the end of its run; from r11.24 the sign-in also asks for the six-digit code from an authenticator app, enrolled from the banner file the installer names (/opt/semurg/tmp/.admin_bootstrap_banner, which also holds eight recovery codes and is removed on your first sign-in). One way in.

What the node does, and does not do

Your data stays put

Everything is written to the data directory on that machine. There is no upload, no telemetry to us, and no account.

It binds locally by default

The node answers on localhost until you deliberately expose it. If you bind it to the network without setting a token, it refuses to serve rather than serve anonymously.

The first node stays free

Free forever, not a trial. Paid licences start at the second node; see pricing.

Updating a node. sudo semurg update --check says whether a newer release exists, and sudo semurg update --apply applies it, rolling back by itself if the new release does not come up. A node upgrading from r11.52 or older runs its old updater once more; the fixed updater takes effect from the following upgrade.