Other install paths

Docker, systemd, Portainer, and a checkout for development.

The Installer one-liner covers the common case. This page explains it, plus Docker, Portainer, and a repository checkout.

What the one-liner does

/bin/bash -c "$(curl -fsSL https://get.meshloom.app)"

/bin/bash -c matters because the script asks questions. On Linux it offers native systemd or Docker. Docker may ask USB versus network only to emit a Compose devices: mapping. Radio transport itself is configured in the web UI.

Native systemd installation uses apt-get or dnf when a package is available. It installs:

  • the meshloom systemd unit
  • /etc/meshloom/meshloom.env
  • /var/lib/meshloom

If no package exists for the platform, the script falls back to a source install: it clones the latest release into a folder (default ~/meshloom) and runs install_service.sh. That install updates with git pull and a service restart, not from Settings → Updates.

Check it normally:

sudo systemctl status meshloom

install_service.sh from a clone

From an existing checkout:

bash scripts/setup/install_service.sh

The script is repeatable. Run it again after pulling a new version: it stops the service, rewrites the unit, reloads systemd, and starts it again. It does not configure bots or authentication; set MESHCORE_DISABLE_BOTS and MESHCORE_BASIC_AUTH_* in the environment yourself. Radio transport is configured in the web UI, not in the unit file.

Docker

The image is ghcr.io/twinrocket/meshloom. The repository includes docker-compose.example.yml. Important parts are:

  • ./data:/app/data for the SQLite database

  • an optional radio devices: mapping for USB (TCP and BLE are configured in the UI)

  • MESHCORE_DATABASE_PATH: data/meshcore.db

  • restart: unless-stopped

  • image: ${MESHLOOM_IMAGE:-ghcr.io/twinrocket/meshloom:latest}: pin a release in a .env file next to it, ideally by digest (MESHLOOM_IMAGE=ghcr.io/twinrocket/meshloom:X.Y.Z@sha256:…; each release’s signed OCI-DIGESTS asset lists it)

The container runs as root by default. To run it as uid 10001 instead, set MESHLOOM_RUN_AS_USER: "10001": the entrypoint hands ./data to that uid and adds the groups of the mapped serial devices; if the radio is still unreachable it stays root and logs a warning. Do not use it with Bluetooth. BLE needs further manual changes; see Radio transports.

A stack written by hand gets no in-app updates. The installer’s Docker mode adds a root helper on the host that pins the image by signed digest in .env and applies updates on request from Settings → Updates; it never edits docker-compose.yml.

Portainer

For a stack built from the repository, use docker-compose.dev.yaml and load .env.example values in Portainer:

MESHLOOM_HTTP_PORT=8123
MESHLOOM_DATA_PATH=/opt/docker/meshloom/data
MESHCORE_DATABASE_PATH=data/meshcore.db
MESHCORE_DISABLE_BOTS=false
MESHCORE_VAPID_SUBJECT=mailto:you@example.com
# MESHLOOM_COMMUNITY=0

MESHCORE_VAPID_SUBJECT is only the fallback when the Settings → Notifications VAPID subject is empty. Do not commit real VAPID addresses. Radio host and port are set in the web UI. A new empty data volume joins Community unless MESHLOOM_COMMUNITY=0. See Meshloom Community.

From a checkout

uv sync
uv run uvicorn app.main:app --reload

uv sync creates the project .venv; do not install these dependencies with apt or dnf. If uv run uvicorn reports ModuleNotFoundError: No module named 'meshcore', start here. See Troubleshooting.

For frontend development:

cd frontend
npm install
npm run dev

Vite listens on http://localhost:5173 and proxies /api to port 8000. For production:

cd frontend && npm install && npm run build && cd ..
uv run uvicorn app.main:app --host 0.0.0.0 --port 8000

If frontend/dist is absent, the backend checks frontend/prebuilt. If neither exists, it serves the API without static frontend routes. Run the repository quality checks from its root:

./scripts/quality/all_quality.sh

Database and updates

Installation Database location
systemd package /var/lib/meshloom
Docker ./data (mounted at /app/data)
Checkout data/meshcore.db, relative to the repository

MESHCORE_DATABASE_PATH moves the database. Updates do not replace it; SQLite migrations run at startup in user_version order.

Settings → Updates applies a Meshloom-only upgrade, from a signed source, when the helper is present. Otherwise:

sudo apt-get install --only-upgrade meshloom
sudo dnf install meshloom
sudo docker compose pull && sudo docker compose up -d

The default UI is http://127.0.0.1:8000. FastAPI’s generated API documentation is at /docs; it is not this site.