304 lines
14 KiB
Text
304 lines
14 KiB
Text
# ──────────────────────────────────────────────────────────────────
|
||
# 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 cp13–cp14) ──────────────────
|
||
# 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
|