Skip to content

Production

Choose one public front-door model:

  1. Shared store (Postgres or single-host SQLite).
  2. momo node + momo gateway on private/loopback binds.
  3. Optional momo edge on :80/:443 (static PEMs or Let’s Encrypt HTTP-01).
  4. DNS A/AAAA for app domains points at the edge host.

ACME prerequisites: public :80, DNS to the edge, --acme-email recommended, prefer --acme-staging first to avoid production rate limits.

B) Bring-your-own reverse proxy / cloud LB

Section titled “B) Bring-your-own reverse proxy / cloud LB”
  1. Shared Postgres store (postgres://…) reachable by all gateway and node processes.
  2. One or more momo node processes (one per Docker host), each with unique MOMO_NODE_ID.
  3. One or more momo gateway processes behind your edge load balancer.
  4. Shared MOMO_AUTH_TOKEN (+ mTLS) on every process.

Do not run momo edge if an external proxy already terminates TLS.

Single-host multi-process may use sqlite:///var/lib/momo/momo.db instead of Postgres. file:// is refused in production unless MOMO_ALLOW_FILE_STORE=1.

Terminal window
# From GitHub Releases (example)
VERSION=0.1.0
TARGET=x86_64-unknown-linux-gnu
curl -LO "https://github.com/lalitgehani/momo/releases/download/v${VERSION}/momo-${VERSION}-${TARGET}.tar.gz"
tar -xzf "momo-${VERSION}-${TARGET}.tar.gz"
sudo install -m 0755 "momo-${VERSION}-${TARGET}/momo" /usr/local/bin/momo

Or build from source:

Terminal window
make install # /usr/local/bin/momo
sudo make install-systemd # units + /etc/momo/momo.env

See deploy/systemd/README.md in the repo.

Terminal window
sudo cp deploy/momo.env.example /etc/momo/momo.env
sudo $EDITOR /etc/momo/momo.env # set store, auth, TLS, node id (+ optional MOMO_EDGE_*)
sudo make install-systemd
# or: sudo momo service install --all
sudo systemctl enable --now momo.target
# Optional greenfield edge (not part of momo.target by default):
# sudo systemctl enable --now momo-edge.service
sudo journalctl -u momo-node -u momo-gateway -u momo-edge -f
# equivalent: momo service logs --all -f

Hard rule: unit ExecStart must be foreground momo gateway|node|edge. Do not use momo start under systemd (parent exits after spawn and breaks Type=simple).

For laptop stacks without systemd:

Terminal window
export MOMO_RUNTIME_DIR=./.momo-runtime
momo start all --store file://./momo-state --node-id node-a
momo ps
momo logs gateway -f
momo stop --all

Compose optional edge profile:

Terminal window
# Generate local PEMs under deploy/certs/ first for static TLS.
docker compose -f deploy/docker-compose.momo.yml --profile edge up --build

Without --profile edge, compose behavior is unchanged (gateway still publishes 8080).

Container image (optional): ghcr.io/<owner>/momo:<tag> — pass gateway, node, or edge as the command. Node containers need the Docker socket mounted. Edge needs OpenSSL (image includes libssl3).

Edge logs an info line momo edge listening with bind addresses on start. ACME lifecycle events are greppable: acme_issue_start, acme_issue_success, acme_issue_failure, acme_renew_success, acme_renew_failure. Default CI / make test never hits production Let’s Encrypt; use make edge-smoke for edge unit gates, and a staging lab for live issuance.

On node B:

Terminal window
export MOMO_STORE=postgres://…
export MOMO_AUTH_TOKEN=
export MOMO_NODE_ID=node-b
export MOMO_ENV=production
export MOMO_LOG_FORMAT=json
# TLS vars…
momo node --node-id node-b --store "$MOMO_STORE" --auto-register \
--advertise-addr 10.0.0.12 --bind 0.0.0.0:50051

Or register without auto-register:

Terminal window
momo node link --node-id node-b \
--grpc-endpoint https://10.0.0.12:50051 \
--label zone=east \
--store "$MOMO_STORE"

Apply with selector or explicit node:

Terminal window
momo apply -f app.yml --node node-b --store "$MOMO_STORE" --wait
# or placement.selector.matchLabels in the AppSpec
  • Health: GET /healthz, GET /readyz on the gateway
  • Metrics: Metrics
  • Logs: journald / stdout JSON (MOMO_LOG_FORMAT=json)
  • Doctor: momo doctor --store … --gateway-url …
  • Gateway is stateless aside from in-memory route cache + client pool; scale horizontally.
  • Nodes are sticky to their Docker host; drain before maintenance (momo node drain).
  • Route reload after apply targets < 2s under normal store latency (see Baselines).