Install — Docker

Docker is the fastest way to get an Ogmara L2 node running. The image is published to Docker Hub under the ogmara/ogmara repository with per-component tags. On first start the entrypoint auto-generates an annotated default config into a host directory you bind-mount, so you can edit it with your usual editor — no docker cp needed.

Prerequisite: you've completed Server Preparation (system user, directories, firewall). If you skipped any of it, do that first — this step depends on /etc/ogmara and /var/lib/ogmara/data existing on the host.

What you'll have when this is done

  • A running ogmara-l2 container, restart-policy unless-stopped, listening on the host on TCP/UDP 41720 (P2P) and TCP 41721 (API).
  • Two host bind-mounts you fully own: /etc/ogmara (holds the auto-generated ogmara.toml) and /var/lib/ogmara/data (holds the RocksDB chain state and the node's private key).
  • Two commands you'll use constantly from here on:
    • docker logs -f ogmara-l2 — live log stream (use --tail 100 for just the tail)
    • docker restart ogmara-l2 — apply config changes (the node reads its config once at startup)

After this page the node is up but not yet usable — it needs the four config blocks filled in. The Configuration page covers exactly what to edit and why.

Prepare the host paths

This step is mandatory for Docker. Server Preparation created /etc/ogmara and /var/lib/ogmara/data with sudo mkdir, which leaves them owned by root (or by the ogmara system user — neither matches your host UID). The container will run as your host user (via --user $(id -u):$(id -g) below) and needs write access to drop the auto-generated config and the RocksDB data there. If you skip these chowns, the container will crash-loop with Error: Permission denied (os error 13) in docker logs.

# Hand both directories to your host user so the container can write
# the auto-generated ogmara.toml and the RocksDB state, and so you can
# `nano /etc/ogmara/ogmara.toml` later without sudo.
sudo chown $(id -u):$(id -g) /etc/ogmara
sudo chown -R $(id -u):$(id -g) /var/lib/ogmara/data

Pull and run

# Pull the latest L2 node image. The `l2-node-latest` tag always tracks
# the newest release — see https://hub.docker.com/r/ogmara/ogmara/tags
# if you'd rather pin to a specific version (e.g. l2-node-0.63.1).
docker pull ogmara/ogmara:l2-node-latest

# Run the node. The --user flag makes the container run as your host
# user, so files it writes (including the config it's about to
# generate and the RocksDB chain state) end up owned by you on the
# host. Both /etc/ogmara and /var/lib/ogmara/data are bind-mounted,
# so you can inspect or back them up with your normal tools.
docker run -d \
  --name ogmara-l2 \
  --restart unless-stopped \
  --user $(id -u):$(id -g) \
  -p 41720:41720/tcp \
  -p 41720:41720/udp \
  -p 41721:41721/tcp \
  -v /var/lib/ogmara/data:/data \
  -v /etc/ogmara:/etc/ogmara \
  ogmara/ogmara:l2-node-latest

# Confirm the config was generated. You should see ogmara.toml owned
# by your user (not root or container-internal ogmara user).
ls -la /etc/ogmara/ogmara.toml

If docker logs ogmara-l2 shows Error: Permission denied (os error 13) repeating every few seconds, one of the chown steps above was skipped or the directory got recreated as root-owned. Re-run both sudo chown lines from the prep step — the next automatic restart (--restart unless-stopped) will succeed and the config and RocksDB state will appear.

The Docker entrypoint (l2-node v0.46.1+) auto-generates a Docker-correct default: data_dir = "/data" (matches the bind-mount target) and listen_addr = "0.0.0.0" (binds the API on the container's bridge interface so Docker's -p 41721:41721 forward actually delivers packets to the host). You still must fill in the [klever] URLs and contract address before the node can interact with the chain — see the Configuration page next. Other defaults stay safe: anchoring + metadata publication disabled, PoW spam-protection enabled.

Next steps

  1. Configuration — fill in the four required blocks of ogmara.toml (Klever endpoints, contract address, public URL, optional production features) and restart the container.
  2. Reverse Proxy & SSL — put Apache or Nginx in front of the node so it's reachable on your domain over HTTPS.
  3. Verify everything — health checks against the API and the WebSocket endpoint.
← Server Prep   Next: Configuration →