morphit/ops/env/relay.env.example

304 lines
14 KiB
Text
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ──────────────────────────────────────────────────────────────────
# Morphit relay — environment variables
#
# Copy this file to /etc/morphit/relay.env on the VPS, set the
# real values, chmod 0600, chown the morphit-relay user.
#
# sudo mkdir -p /etc/morphit
# sudo cp ops/env/relay.env.example /etc/morphit/relay.env
# sudoedit /etc/morphit/relay.env
# sudo chown morphit-relay:morphit-relay /etc/morphit/relay.env
# sudo chmod 0600 /etc/morphit/relay.env
#
# Every variable is parsed by apps/relay/src/config/index.ts —
# if you set a value the schema rejects, the relay refuses to
# boot with a clear error.
# ──────────────────────────────────────────────────────────────────
# ─── Required — chain identity ─────────────────────────────────────
# Blurt account the relay operates from. Must be the registered
# account name with the active key whose path is below.
# REQUIRED — no default.
MORPHIT_RELAY_ACCOUNT=morphit-relay
# Path to the file holding the ACTIVE private key of MORPHIT_RELAY_ACCOUNT.
#
# Two supported formats:
#
# 1. Plaintext WIF (legacy / dev convenience): one line, starts
# with "5..." or "K...". The relay reads the key directly.
#
# 2. Encrypted envelope (ADR-0010 §4, recommended for prod):
# a JSON file produced by scripts/encrypt-active-key.ts.
# The relay prompts for the passphrase on stdin at boot.
# Requires the systemd unit's StandardInput=tty-force,
# or run the relay in the foreground for the first boot.
#
# Create (plaintext, dev):
# sudo mkdir -p /etc/morphit/keys
# sudo nano /etc/morphit/keys/relay-active.key # paste the WIF, save
# sudo chown morphit-relay:morphit-relay /etc/morphit/keys/relay-active.key
# sudo chmod 0400 /etc/morphit/keys/relay-active.key
#
# Upgrade to encrypted envelope (production):
# cd /opt/morphit-relay
# tsx scripts/encrypt-active-key.ts \
# /etc/morphit/keys/relay-active.key \
# /etc/morphit/keys/relay-active.enc
# # Point this var to the .enc file, restart the relay with a
# # pty attached, enter the passphrase when prompted.
# # Then: sudo shred -u /etc/morphit/keys/relay-active.key
#
# The relay refuses to start if this file is readable by group or
# other. REQUIRED — no default.
MORPHIT_RELAY_ACTIVE_KEY_FILE=/etc/morphit/keys/relay-active.key
# ─── Required — database ───────────────────────────────────────────
# Postgres URL shared with the indexer. ADR-0011 §8: the relay
# drains the relay_pending_transfers queue here to deliver welcome
# bonuses, dust refills, and loyalty BP rewards.
#
# The literal '__SET_BEFORE_DEPLOY__' is a sentinel: the relay
# refuses to boot while the URL still contains it. Replace with
# the password you set when running init.sql (see
# docs/RUN-A-MORPHIT-NODE.md step 7).
#
# Typical single-host deployment: same connection string as
# MORPHIT_INDEXER_DATABASE_URL. Split deployments are also fine —
# adjust user/host/db.
MORPHIT_RELAY_DATABASE_URL=postgresql://morphit_indexer:__SET_BEFORE_DEPLOY__@127.0.0.1:5432/morphit_indexer
# ─── Optional — persistent signing secrets ─────────────────────────
# Two HMAC secrets sign invite tokens + ALTCHA anti-bot challenges.
# LEAVE THESE UNSET (commented out) and the relay generates a secure
# RANDOM secret per boot — fine for most operators, since both have a
# ~10-minute TTL, so only in-flight invites/challenges drop on a
# restart. Set a persistent value ONLY if you want invites/challenges
# to survive relay restarts. If you set one, generate a fresh random
# secret per instance:
# openssl rand -base64 32
# Never reuse passwords; never share between operators; rotating
# invalidates all outstanding invite tokens. The relay REFUSES TO BOOT
# if either is set to a known placeholder or is shorter than 16 chars
# (leaving it unset is always valid — that's the secure ephemeral
# default).
# Signs invite tokens (one-time-use account-creation links).
# MORPHIT_RELAY_INVITE_HMAC_SECRET=
# Signs ALTCHA anti-bot puzzle challenges.
# MORPHIT_RELAY_ALTCHA_HMAC_SECRET=
# ─── Required — persistent state directory ────────────────────────
# Where the relay keeps:
# - the kill-switch sentinel file (`SIGNUPS_DISABLED`)
# - the persisted daily signup-ceiling counter
#
# The directory must exist and be writable by morphit-relay.
# If unset, the kill switch and ceiling persistence are disabled
# (counter resets on every restart) — useful for dev only.
#
# Recommended:
# sudo mkdir -p /var/lib/morphit-relay
# sudo chown morphit-relay:morphit-relay /var/lib/morphit-relay
# sudo chmod 0700 /var/lib/morphit-relay
MORPHIT_RELAY_DATA_DIR=/var/lib/morphit-relay
# Optional override of the ceiling-persist file location. Defaults
# to ${DATA_DIR}/signup-ceiling.json when unset.
# MORPHIT_RELAY_SIGNUP_CEILING_PERSIST_PATH=
# ─── HTTP server ──────────────────────────────────────────────────
# Where the relay listens. Production: loopback only with nginx
# fronting it. Dev: bind 0.0.0.0 directly.
MORPHIT_RELAY_LISTEN_HOST=127.0.0.1
MORPHIT_RELAY_LISTEN_PORT=8080
# Public origin URL as advertised to clients. Used for CORS
# responses and self-identification.
MORPHIT_RELAY_PUBLIC_ORIGIN=https://yourdomain.com
# CORS allowlist. Only origins in this list get CORS headers on
# the response. Comma-separated. Add community mirrors
# (.onion / .loki / .b32.i2p variants) here as they come online;
# each mirror operator owns the CORS decision for their own
# instance.
MORPHIT_RELAY_ALLOWED_ORIGINS=https://yourdomain.com
# ─── Chain RPC ─────────────────────────────────────────────────────
# Blurt RPC endpoints the relay reads chain state from.
# Comma-separated. Rotates across them on transient failure.
MORPHIT_RELAY_BLURT_RPC=https://rpc.drakernoise.com,https://blurtrpc.dagobert.uk,https://rpc.blurt.blog,https://rpc.beblurt.com,https://rpc.blurt.one,https://blurt-rpc.saboin.com
# ─── Rate limits ───────────────────────────────────────────────────
# AVAILABILITY_RATE_PER_MIN: per-IP, cheap reads (name availability).
MORPHIT_RELAY_AVAILABILITY_RATE_PER_MIN=60
# ─── Trusted-proxy IPs (§32 CRITICAL — reverse-proxy posture) ────
# Comma-separated list of IPs/CIDRs that the relay trusts as
# forward proxies. X-Forwarded-For headers from these sources
# are respected; from any other source they are ignored.
#
# CRITICAL: if you have BunkerWeb or another reverse proxy in
# front of the relay, you MUST set this to the proxy's address.
# Mis-setting means EITHER (a) all signups appear from the
# proxy's IP (no per-IP rate limit, easy abuse) OR (b) untrusted
# X-Forwarded-For headers are honored (trivial signup-source
# spoofing).
#
# Default: empty (no proxies trusted; uses socket peer IP). When
# BunkerWeb is colocated on the same host (default deploy), set
# to the Docker bridge subnet 172.17.0.0/16.
# MORPHIT_RELAY_TRUSTED_PROXY_IPS=
# CREATE_RATE_PER_HOUR: per-IP, write to chain (account create).
MORPHIT_RELAY_CREATE_RATE_PER_HOUR=5
# CREATE_RATE_PER_DAY: long-window signup cap per IP (ADR-0010 §4).
# Stacks with the per-hour limit; both must pass.
MORPHIT_RELAY_CREATE_RATE_PER_DAY=2
# Spacing between consecutive create attempts from the same IP,
# in minutes. 60 = one signup per hour even if hourly limit
# allows more bursts.
MORPHIT_RELAY_CREATE_SPACING_MINUTES=60
# ─── Drain-defense (Part 47 kill switch + ceiling) ────────────────
# Master toggle. Flip to false to immediately stop new-user
# signups; existing users keep working. Useful during incidents,
# maintenance, or while investigating an active drain attack.
# The kill-switch sentinel file (touch ${DATA_DIR}/SIGNUPS_DISABLED)
# is a faster equivalent that doesn't need a service restart.
MORPHIT_RELAY_SIGNUP_ENABLED=true
# Hard daily ceiling — total successful signups from THIS instance
# in a 24h rolling window. When the count is reached the relay
# returns 503 with a clear message until the window rolls. Default
# 50 fits a small instance; raise after observing your real volume.
MORPHIT_RELAY_SIGNUP_DAILY_CEILING=50
# Sequential-name detector — flags signups that share a long common
# prefix from the same source (e.g. user1, user2, user3 from one IP).
# Part of the §38.7 diamond-hardened preset.
# Enable the sequential detector. Default: true.
# MORPHIT_RELAY_SEQUENTIAL_DETECTOR_ENABLED=true
# Number of sequential-prefix signups before escalation. Default: 2.
# MORPHIT_RELAY_SEQUENTIAL_THRESHOLD=2
# Time window (ms) for sequential-prefix detection. Default: 3600000
# (1 hour).
# MORPHIT_RELAY_SEQUENTIAL_WINDOW_MS=3600000
# Minimum common-prefix length to count as "sequential". Default: 3.
# MORPHIT_RELAY_SEQUENTIAL_MIN_PREFIX=3
# High-value (short) name policy — names ≤ threshold are treated
# as high-value (premium / namesquatter-likely) and subject to the
# policy below.
#
# Policy values:
# strict (default) — refuse signup
# flag — accept but raise an operator alert
# off — disable (no special treatment)
# MORPHIT_RELAY_HIGHVALUE_NAME_POLICY=strict
# Names with length ≤ this threshold trigger the high-value policy.
# Default: 4 (so 1-4 character names are high-value).
# MORPHIT_RELAY_HIGHVALUE_SHORT_NAME_THRESHOLD=4
# ─── ALTCHA anti-bot puzzle ────────────────────────────────────────
# After this many failed signup attempts in the per-IP window,
# the next signup attempt requires solving an ALTCHA proof-of-work
# puzzle. Lower = more friction for legitimate users; higher =
# more bot tolerance. Default 3.
MORPHIT_RELAY_ALTCHA_TRIGGER_COUNT=3
# Difficulty knob for the puzzle. Higher = more browser CPU per
# solve. Default 2,000,000 = ~1-3 seconds on a typical phone.
MORPHIT_RELAY_ALTCHA_MAXNUMBER=2000000
# ─── Queue drainer (ADR-0011 §8) ───────────────────────────────────
# Interval between queue poll cycles in milliseconds. Default 1
# minute. Shorter delivers bonuses faster at the cost of more
# RPC calls.
MORPHIT_RELAY_QUEUE_POLL_INTERVAL_MS=60000
# Max rows drained per cycle. Default 20. Each row takes ~3s to
# broadcast + confirm, so 20 fits a 60s cycle with headroom.
MORPHIT_RELAY_QUEUE_BATCH_SIZE=20
# Per-row retry ceiling. When a row's error_count reaches this
# value the drainer stops auto-retrying it; the row stays in
# the table with broadcast_at=NULL for operator investigation.
# Combined with exponential backoff (1m, 2m, 4m, ...), 3 failures
# = ~7 minutes of automatic recovery before escalation.
MORPHIT_RELAY_QUEUE_MAX_RETRIES=3
# Chain account_creation_fee in BLURT — the relay pays this inline per
# account_create signup. Operator-config FALLBACK only: the relay reads
# the live value from the chain DGP per broadcast (the evaluator requires
# an exact match) and uses this only if the chain value is unparseable.
# The indexer also uses it for fee monitoring.
# Must match the chain DGP (`get_chain_properties.account_creation_fee`).
# Default: 100 BLURT.
# MORPHIT_INDEXER_ACCOUNT_CREATION_FEE_BLURT=100
# ─── Operator visibility ──────────────────────────────────────────
# When true, /v1/health returns version + uptime + RC balance.
# When false, returns only {"status":"ok"}. Slightly more info
# leak when true; you may prefer false in adversarial settings.
MORPHIT_RELAY_VERBOSE_HEALTH=true
# ─── Web Push notifications (Part 122 cp13cp14) ──────────────────
# Push notifications deliver alerts to users even when the
# Morphit tab is closed or the phone is locked. Optional —
# without these three keys, push is disabled and users on your
# instance see "Not supported on this device" in Settings.
# In-tab notification channels (title-bar prefix, favicon dot,
# OS notifications, audio cue, vibration) keep working without
# Web Push.
#
# One-time setup: bash scripts/generate-vapid-keys.sh
# Paste its three output lines below (replace the placeholder
# mailto: address with a real one — push services may contact
# you there if something goes wrong with your pushes).
#
# MORPHIT_RELAY_VAPID_PUBLIC_KEY=
# MORPHIT_RELAY_VAPID_PRIVATE_KEY=
# MORPHIT_RELAY_VAPID_SUBJECT=mailto:operator@your-domain.example
# Optional tuning (sane defaults baked in):
# MORPHIT_RELAY_PUSH_POLL_INTERVAL_MS=2000
# MORPHIT_RELAY_PUSH_BATCH_SIZE=50
# MORPHIT_RELAY_PUSH_MAX_AGE_SECONDS=3600
# MORPHIT_RELAY_PUSH_MAX_CONSECUTIVE_FAILURES=5
# When true (default, cp14), /v1/push/subscribe requires every
# request to carry a valid posting-key signature. Set to false
# only during a brief frontend roll-forward window where the new
# signed-subscribe client hasn't deployed yet. Documented in
# OPERATIONS.md §42.5.
# MORPHIT_RELAY_PUSH_REQUIRE_SIGNED=true
# ─── Dead env-var aliases (REMOVED — DO NOT SET) ──────────────────
# Listed here so operators upgrading from older configs don't
# wonder why their custom value isn't taking effect:
#
# MORPHIT_RELAY_LISTEN -> superseded by LISTEN_HOST + LISTEN_PORT