Skip to content
ivralo
Sections

Docs / Install

Install on a server

One command installs ivralo on a server with nobody at the keyboard: the model is an endpoint on another machine, the database may already exist, and the work is a repository on this one.

What you need

  • Linux (macOS works the same way). Windows is supported for developer use; on a server, see the notes at the end.
  • git, and access to the ivralo repository. The repository is private and nothing is on PyPI; access is given on request (write to us). The default source is git+ssh://, which uses the ssh key of the user who runs the install.
  • A model endpoint that speaks OpenAI's protocol: vLLM, llama.cpp's server or a LiteLLM proxy.
  • The service's repository, cloned on the server. That is the workspace ivralo investigates in.

uv and PostgreSQL are taken care of by the install, as below.

The one command

From a copy of the repository's scripts/install.sh:

sh scripts/install.sh \
  --model-url http://gpu-box:8000/v1 --model my-model \
  --workspace /srv/shop --token \
  --git-name "ivralo" --git-email ivralo@corp.example

The script does three things:

  1. Installs uv with uv's own installer, only when uv is missing. That is the one thing it downloads and runs that is not ivralo.
  2. Installs ivralo as a global command on Python 3.13, with the pg extra that carries a PostgreSQL: uv tool install --python 3.13 --force "ivralo[pg] @ <source>". Where no wheel of the extra exists for the platform, it installs ivralo without it and says so.
  3. Runs ivralo init --server with every other argument you gave it, and --home ~/ivralo unless you name another.
Script optionWhat it does
--ref <tag or branch>Installs that ref, such as --ref v0.1.2. The script's own option; it is not passed on.
IVRALO_SOURCEWhere ivralo comes from. Default git+ssh://git@github.com/kemalcalak/ivralo.git; use git+https://github.com/kemalcalak/ivralo.git with git credentials over https.
IVRALO_PYTHONThe Python to install for. Default 3.13, the one ivralo is tested on.

The same steps by hand

curl -LsSf https://astral.sh/uv/install.sh | sh        # only when uv is missing
uv tool install --python 3.13 --force 'ivralo[pg] @ git+ssh://git@github.com/kemalcalak/ivralo.git'
ivralo init --server --yes --home ~/ivralo \
  --model-url http://gpu-box:8000/v1 --model my-model \
  --workspace /srv/shop --token \
  --git-name "ivralo" --git-email ivralo@corp.example

Add @v0.1.2 to the source to pin a release. uv tool update-shell adds uv's tool directory to your shell profile. init prints the export IVRALO_HOME=... line to put in the profile of the user that runs ivralo.

Secrets never go on the command line, where a process list or a shell history would keep them. Put them in the environment of the command, and init writes them into the home's .env:

IVRALO_OPENAI_COMPATIBLE_KEY=... GITHUB_ACCESS_TOKEN=... ivralo init --server ...

What --server does

ivralo init --server is ivralo init with the questions answered for a machine like this:

  • It asks nothing (--yes), except whether to run the project's install step, which only a typed --yes answers.
  • It installs no browser, pulls no Ollama model and sets no git hooks. --browser, --pull and --hooks bring any of them back.
  • It writes IVRALO_WEB=false, and IVRALO_KNOWLEDGE=false unless --embed-model names an embedding model.
  • It writes IVRALO_MODE=server (Server mode and incidents).
  • It finds a PostgreSQL by itself (--postgres auto).

Each of these is a line in the home's .env. A line you changed is never touched, so running the command again is an upgrade, not a reset.

OptionWrites
--model-url <url> with --model <name>IVRALO_OPENAI_COMPATIBLE_URL and IVRALO_MODEL=openai-compatible:<name>, the name as the endpoint serves it
--embed-model <name>IVRALO_EMBED_MODEL, a name at the same endpoint; the knowledge index stays on and needs pgvector
--postgres auto, managed or a URLWhere the database comes from (PostgreSQL); a URL is written as IVRALO_DB_URL and never printed
--tokenThe local API's token file, api-token in the home, owner-only; its path is printed, the token never
--workspace <path>IVRALO_WORKSPACE; the repository is trusted, since naming it is the yes, and a starter IVRALO.md is written if it has none
--git-name, --git-emailivralo's own git identity, below

Git identity and forge credential

In server mode an unattended run may commit and open a draft pull request from a branch it made, so the install asks two more things.

Who ivralo is on git. A name and an e-mail of ivralo's own, never yours: ivralo tells its commits from a person's by that address, so init refuses the operator's global user.email and the repository's. They go into <home>/gitconfig; your own git config is only read. Under --yes without the two options the row is red.

How ivralo signs in to the forge. There is one forge: github.com, or the host of IVRALO_GITHUB_URL for an Enterprise server. origin must use https on that host; an ssh remote is refused. The credential is looked for in this order:

  1. GITHUB_ACCESS_TOKEN already in the home's .env;
  2. GITHUB_ACCESS_TOKEN in the environment init runs in, then written into .env;
  3. at a terminal only, gh's own login, after a yes (never under --yes);
  4. at a terminal, the token itself, typed hidden.

Make it a fine-grained token with contents: write on the repositories ivralo works in and pull requests: write, nothing else. init checks it once: whose it is, its scopes, and whether it reaches the repository. A token carrying admin:*, delete_repo or workflow is refused and not written. With no credential at all, ivralo investigates and reports, and opens no pull request.

The project's install step

A language server and the project's own checks need the project's dependencies, which a fresh clone does not have. So init --server runs the repository's install step after the repository is trusted. It reads the step from the repository's own files, in order: an install: line under # Commands in IVRALO.md, a CI workflow, the Dockerfile, the code blocks of README.md and CONTRIBUTING.md, a root JSON file's packageManager field. The row says which command it ran and where it read it.

The step goes through the shell policy like any command, and runs unattended only under a typed --yes. When IVRALO.md declares a language server, init then builds the code index and ends red, with exit 1, if a declared server produced no symbols. The step's clock is IVRALO_INSTALL_TIMEOUT, 1800 seconds by default.

Checking it

export IVRALO_HOME=~/ivralo
ivralo doctor

Its forge section shows the git identity, the forge credential and the mode; providers asks the model endpoint for its model list. Every problem is one line with its fix (ivralo doctor).

Reaching the API through an ssh tunnel

ivralo serve opens the local API on 127.0.0.1 only, port 61017 by default, behind the token --token made. Nothing binds it elsewhere. To reach it from your own machine, forward the port:

ssh -L 61017:127.0.0.1:61017 you@server        # on your machine
ivralo serve                                    # on the server, in the repository
TOKEN=$(ssh you@server cat ~/ivralo/api-token)  # and use it from your machine

ivralo serve runs in the foreground until stopped; keeping it alive as a service is up to your own service manager.

Upgrading

Run the same command again, or the script. uv tool install --force replaces the program, and init keeps the home's .env, skills, token and everything else, rewriting only the settings you pass. Nothing updates the home's skill shelf for you; doctor's environment section says when the new version carries more skills than the shelf holds.