Build from source
Building from source is for working on Andromeda itself. You build the broker with Cargo and run it on your machine, and a container gives it the PostgreSQL server it needs. To only run Andromeda, install it with Docker instead.
What you need
You need rustup, git, cmake, a C compiler, and Docker or Podman for the database.
The repository's rust-toolchain.toml pins a nightly toolchain, nightly-2026-08-21, with clippy and rustfmt, and Cargo uses it inside the checkout. If rustup doesn't install it on the first build, run rustup toolchain install in the checkout. A stable toolchain can't build Andromeda, because the build passes -Zhigher-ranked-assumptions, which only nightly accepts.
cmake and the C compiler build the native code of the TLS library. A source archive of the repository builds the same broker as a clone, because the build reads nothing from the repository's history.
Docker or Podman runs only the database. Any server with at least PostgreSQL 15, PostGIS 3.0.0 and TimescaleDB 2.31.0 works too, and PostgreSQL lists everything the broker checks.
Building the broker
git clone https://github.com/mskvarc/andromeda.git
cd andromeda
cargo build --release --locked --bin andromeda
--locked builds with the dependency versions in Cargo.lock. The binary lands in target/release/andromeda. The first release build takes a while, and later builds reuse what is already compiled.
Installing it on your path
For an andromeda command you can run from anywhere, install it with Cargo from the checkout:
cargo install --path . --locked
This builds a release binary and copies it to ~/.cargo/bin, or to $CARGO_HOME/bin if you set that. A rustup install puts that directory on your PATH. To put the binary somewhere else, pass --root, which installs into <root>/bin:
cargo install --path . --locked --root /usr/local
Run the command from the root of the checkout, so that Cargo picks up the pinned toolchain and the build settings in .cargo/config.toml. The installed binary doesn't need the checkout afterwards. To update it, pull the new code and run the same command again, and Cargo replaces the old binary. cargo uninstall andromeda removes it.
The rest of this page assumes andromeda is on your PATH. If you skipped installing it, run ./target/release/andromeda from the checkout instead.
Starting PostgreSQL
The broker needs only a database to run. The setup below runs the published PostgreSQL image, the same one the Docker setup uses, with PostgreSQL 18.6, TimescaleDB 2.31.0 in the TSL edition, and PostGIS 3.6.4.
This setup is for development, so it keeps things short. The role, password and database are all andromeda, and the port is published on 127.0.0.1 only. Any deployment needs a strong password, which Docker shows how to generate.
- Docker Compose
- Docker
In a directory of its own, save this as docker-compose.yaml:
name: andromeda-dev
services:
postgresql:
image: ghcr.io/mskvarc/postgresql:18.6-timescaledb2.31.0-postgis3.6.4-tsl
restart: unless-stopped
environment:
POSTGRES_USER: andromeda
POSTGRES_PASSWORD: andromeda
POSTGRES_DB: andromeda
mem_limit: 4g
cpus: 2
shm_size: 1gb
ports:
- "127.0.0.1:5432:5432"
volumes:
- postgresql-data:/var/lib/postgresql
volumes:
postgresql-data:
Start the database, and wait until postgresql shows as healthy:
docker compose up -d
docker compose ps
With Podman, run podman compose instead. It needs docker-compose or podman-compose installed to run the file.
Start the database:
docker run -d --name postgresql \
--restart unless-stopped \
--memory 4g --cpus 2 --shm-size 1g \
-e POSTGRES_USER=andromeda \
-e POSTGRES_PASSWORD=andromeda \
-e POSTGRES_DB=andromeda \
-p 127.0.0.1:5432:5432 \
-v postgresql-data:/var/lib/postgresql \
ghcr.io/mskvarc/postgresql:18.6-timescaledb2.31.0-postgis3.6.4-tsl
Wait until it accepts connections:
until docker exec postgresql pg_isready -q -h 127.0.0.1; do sleep 1; done
With Podman, run the same commands with podman in place of docker.
The image tunes PostgreSQL to the memory and CPU limits, and its shared memory grows with the number of tenant databases, which is why both are set. PostgreSQL image explains what else the image does. To use a server of your own instead, give the broker its URL in the next step.
Running the broker
export ANDROMEDA__DATABASE__CONNECTION=postgres://andromeda:andromeda@localhost:5432/andromeda
andromeda
database.connection is the one setting without a default, and the broker refuses to start without it. Here it names the database you just started, as a URL. It can also be a table of its parts, host, port, user, password, database and parameters, each of which can be its own variable, such as ANDROMEDA__DATABASE__CONNECTION__PASSWORD. Everything else runs on its defaults. The API listens on 0.0.0.0:1056 in plaintext and the management endpoints on port 1086. The broker logs to standard output at info, and once it is serving it logs HTTP listener accepting connections with the address.
At startup the broker connects to the database and migrates it, and it migrates each tenant's database the first time it opens it, so there is no separate migration step. If it can't reach the database within database.acquire_timeout, 5 seconds by default, it stops with an error, so start the database first.
Changing settings
You can change any setting with an environment variable, as with ANDROMEDA__DATABASE__CONNECTION above, or in a file:
andromeda configuration generate -o andromeda.toml
andromeda --configuration andromeda.toml
configuration generate writes every key with its default and a comment. database.connection has no default, so the file shows it commented out, and the variable you exported still sets it. Without --configuration, the broker reads andromeda/andromeda.toml from your platform's configuration directory if the file exists. --host and --port override the address the API listens on. Configuration explains how the layers combine.
Checking it works
curl -i http://localhost:1056/ngsi-ld/v1/health
curl -i http://localhost:1086/readyz
Both should answer 200. The first returns the health report, with each component and its status, and a 503 means a component is down, usually the database.
curl http://localhost:1056/ngsi-ld/v1/version
This reports the broker's version and the toolchain it was built with, and the versions of PostgreSQL, PostGIS and TimescaleDB it found. Next, go to the Quickstart.
Stopping and starting again
Stop the broker with Ctrl+C. It stops accepting connections, gives the requests in flight up to server.graceful_drain_timeout (30 seconds) to finish, then stops its tenants and background tasks, and exits. The whole stop takes at most server.graceful_drain_timeout plus notifications.evaluation.drain_timeout, 60 seconds by default, however many tenants are loaded. Work still running when that deadline passes is abandoned, and the broker logs it as tenant_shutdown_cut_off or task_shutdown_cut_off. If a process manager runs the broker, let it wait the two timeouts plus 10 seconds before it kills the process, which is 70 seconds with the defaults.
After you pull newer code, remove the database and its data before you run the new build. A build from the main branch can change its migrations, and it may refuse databases an older build created. Upgrades explains why. Both of these remove every tenant's data.
- Docker Compose
- Docker
docker compose down -v
docker compose up -d
docker rm -f postgresql
docker volume rm postgresql-data
Then start the database again with the same docker run as above.
If it goes wrong
Troubleshooting covers build failures, a broker that won't start, and the first refusals.