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
meshloomsystemd 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/datafor 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.envfile next to it, ideally by digest (MESHLOOM_IMAGE=ghcr.io/twinrocket/meshloom:X.Y.Z@sha256:…; each release’s signedOCI-DIGESTSasset 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.