Production
Topology
Section titled “Topology”Choose one public front-door model:
A) Greenfield with momo edge
Section titled “A) Greenfield with momo edge”- Shared store (Postgres or single-host SQLite).
momo node+momo gatewayon private/loopback binds.- Optional
momo edgeon:80/:443(static PEMs or Let’s Encrypt HTTP-01). - 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”- Shared Postgres store (
postgres://…) reachable by all gateway and node processes. - One or more
momo nodeprocesses (one per Docker host), each with uniqueMOMO_NODE_ID. - One or more
momo gatewayprocesses behind your edge load balancer. - 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.
Install from release
Section titled “Install from release”# From GitHub Releases (example)VERSION=0.1.0TARGET=x86_64-unknown-linux-gnucurl -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/momoOr build from source:
make install # /usr/local/bin/momosudo make install-systemd # units + /etc/momo/momo.envsystemd
Section titled “systemd”See deploy/systemd/README.md in the repo.
sudo cp deploy/momo.env.example /etc/momo/momo.envsudo $EDITOR /etc/momo/momo.env # set store, auth, TLS, node id (+ optional MOMO_EDGE_*)sudo make install-systemd# or: sudo momo service install --allsudo systemctl enable --now momo.target# Optional greenfield edge (not part of momo.target by default):# sudo systemctl enable --now momo-edge.servicesudo journalctl -u momo-node -u momo-gateway -u momo-edge -f# equivalent: momo service logs --all -fHard 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).
Local detach (dev)
Section titled “Local detach (dev)”For laptop stacks without systemd:
export MOMO_RUNTIME_DIR=./.momo-runtimemomo start all --store file://./momo-state --node-id node-amomo psmomo logs gateway -fmomo stop --allCompose optional edge profile:
# Generate local PEMs under deploy/certs/ first for static TLS.docker compose -f deploy/docker-compose.momo.yml --profile edge up --buildWithout --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).
Observability
Section titled “Observability”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.
Link a second node
Section titled “Link a second node”On node B:
export MOMO_STORE=postgres://…export MOMO_AUTH_TOKEN=…export MOMO_NODE_ID=node-bexport MOMO_ENV=productionexport 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:50051Or register without auto-register:
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:
momo apply -f app.yml --node node-b --store "$MOMO_STORE" --wait# or placement.selector.matchLabels in the AppSpecObservability
Section titled “Observability”- Health:
GET /healthz,GET /readyzon the gateway - Metrics: Metrics
- Logs: journald / stdout JSON (
MOMO_LOG_FORMAT=json) - Doctor:
momo doctor --store … --gateway-url …
Capacity notes
Section titled “Capacity notes”- 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).