Files
DanConwayDev 3f8157693f docs: point GRASP references at Nostr Git
Move current GRASP specification links from GitHub to GitWorkshop.

Link audit output to its exact pinned specification commit.

Use NIP-05 cloning for ngit-grasp and ngit.dev for the ngit homepage.

Leave the archived migration link unchanged as a historical record.

Validated with rustfmt and the 54-test grasp-audit library suite.
2026-09-04 13:59:46 +00:00

494 lines
21 KiB
Bash

# ngit-grasp Configuration
#
# Configuration Priority (highest to lowest):
# 1. CLI flags (e.g., --domain example.com)
# 2. Environment variables (e.g., NGIT_DOMAIN=example.com)
# 3. This .env file
# 4. Built-in defaults
#
# Run `ngit-grasp --help` for all CLI options
# ============================================================================
# REQUIRED
# ============================================================================
# Domain where this instance is hosted (required, used in GRASP validation)
# CLI: --domain <domain>
# No default - must be set
# NGIT_DOMAIN=
# Public URL path where this instance is mounted
# Use / for a domain-root service or a normalized path such as /grasp
# CLI: --base-path <path>
# Default: /
# NGIT_BASE_PATH=/
# ============================================================================
# SERVER CONFIGURATION
# ============================================================================
# Server bind address (IP:PORT)
# CLI: --bind-address <address>
# Default: 127.0.0.1:7334
# NGIT_BIND_ADDRESS=127.0.0.1:7334
# Trusted reverse-proxy address ranges (comma-separated IPv4/IPv6 CIDRs)
# Forwarded, X-Forwarded-For, and X-Real-IP are ignored unless the TCP peer
# matches one of these ranges. Keep empty for direct/public listeners.
# When trusting a proxy, keep the ngit-grasp backend unreachable from
# untrusted networks and include every trusted hop in a forwarding chain.
# CLI: --trusted-proxy-cidrs <cidrs>
# Default: (empty)
# Example for a reverse proxy on the same host:
# NGIT_TRUSTED_PROXY_CIDRS=127.0.0.1/32,::1/128
# ============================================================================
# RELAY IDENTITY AND INFORMATION (NIP-05 / NIP-11)
# ============================================================================
# Relay operator's nsec (private key) for signing and authentication
# Used for:
# - NIP-05 _@domain well-known identity when served at the domain root
# - Seeding the startup kind-0 bot profile and kind-10002 relay list when
# absent both locally and on the user-index relays
# - Trusted admission of service events authored by this identity (for example, ngit-ci)
# - NIP-11 relay information document (pubkey field derived from this nsec)
# - NIP-42 authentication when syncing from other relays
# - Future: WoT-based rate limiting of syncing relays
#
# Never accepted on the command line, so it cannot appear in process listings.
# systemd: use the relay_owner_nsec credential (highest precedence)
# Default: Loaded from/saved to .relay-owner.nsec in the current directory.
# If the file doesn't exist, a new key is generated with mode 0600.
# Empty or invalid configured values stop startup instead of rotating identity.
# NGIT_RELAY_OWNER_NSEC=nsec1...
# Relay name shown in NIP-11 information document
# CLI: --relay-name <name>
# Default: ${domain} grasp relay (e.g., "gitnostr.com grasp relay")
# NGIT_RELAY_NAME=My GRASP Relay
# Relay description shown in NIP-11 information document
# CLI: --relay-description <description>
# Default: Git Nostr Relay - a grasp implementation
# NGIT_RELAY_DESCRIPTION="A GRASP-compliant Git relay with Nostr authorization"
# ============================================================================
# STORAGE
# ============================================================================
# Path to store Git repositories
# CLI: --git-data-path <path>
# Default: ./data/git
# NGIT_GIT_DATA_PATH=./data/git
# Path to store Nostr relay data
# CLI: --relay-data-path <path>
# Default: ./data/relay
# NGIT_RELAY_DATA_PATH=./data/relay
# Restrict the automatic startup storage- and authorization-integrity passes
# to these comma-separated repository identifiers. Leave empty/unset for the
# required full sweep. Use a scope only for staged validation, then remove it.
# CLI: --startup-integrity-identifiers <identifier,...>
# Default: (empty; check every installed identifier family)
# NGIT_STARTUP_INTEGRITY_IDENTIFIERS=repo-one,repo-two
# Database backend for Nostr events
# CLI: --database-backend <backend>
# Options: lmdb, memory
# Default: lmdb
# - lmdb: LMDB backend (persistent, general purpose) - RECOMMENDED
# - memory: In-memory database (fastest, no persistence, uses temp dirs)
#
# Note: When using 'memory' backend, git_data_path and relay_data_path
# are automatically set to temporary directories for ephemeral testing.
# NGIT_DATABASE_BACKEND=lmdb
# ============================================================================
# METRICS
# ============================================================================
# Enable Prometheus metrics endpoint at /metrics
# CLI: --metrics-enabled
# Default: true
# NGIT_METRICS_ENABLED=true
# Connections per IP before flagging as potential abuse in metrics
# (display only, no rate limiting - purely for monitoring visibility)
# CLI: --metrics-connection-per-ip-abuse-threshold <count>
# Default: 10
# NGIT_METRICS_CONNECTION_PER_IP_ABUSE_THRESHOLD=10
# Number of top bandwidth repositories to track in metrics
# CLI: --metrics-top-n-repos <count>
# Default: 10
# NGIT_METRICS_TOP_N_REPOS=10
# ============================================================================
# LOGGING
# ============================================================================
# Application log level or explicit tracing filter expression
# CLI: --log-level <level>
# Default: info
# Options: error, warn, info, debug, trace
# Bare levels keep dependency logging at warn
# Can also use filter expressions: ngit_grasp=debug,actix_web=info
# NGIT_LOG_LEVEL=info
# ============================================================================
# PROACTIVE SYNC (GRASP-02)
# ============================================================================
# Bootstrap relay URL for initial sync (optional)
# Additional relays are automatically discovered from repository announcements
# that list our service domain.
# CLI: --sync-bootstrap-relay-url <url>
# Default: (none - relay discovery from stored announcements only)
# NGIT_SYNC_BOOTSTRAP_RELAY_URL=wss://relay.example.com
# Enable GRASP-03 Sync+ mailbox discovery on top of proactive GRASP-02 sync
# CLI: --sync-plus-enabled <true|false>
# Default: true
# NGIT_SYNC_PLUS_ENABLED=true
# Relays receiving the relay-owner kind 0/10002 identity events and used to
# discover eligible accepted repository participants' NIP-65 relay lists
# CLI: --user-index-relays <comma-separated-websocket-urls>
# Default: wss://purplepag.es,wss://index.hzrd149.com,wss://indexer.coracle.social
# NGIT_USER_INDEX_RELAYS=wss://purplepag.es,wss://index.hzrd149.com,wss://indexer.coracle.social
# Bounded inbox fallbacks for eligible authors whose NIP-65 list was not found
# CLI: --sync-plus-fallback-relays <comma-separated-websocket-urls>
# Default: wss://relay.ditto.pub,wss://relay.damus.io,wss://nos.lol,wss://relay.primal.net
# NGIT_SYNC_PLUS_FALLBACK_RELAYS=wss://relay.ditto.pub,wss://relay.damus.io,wss://nos.lol,wss://relay.primal.net
# Soft limit on recursive query-frontier members below each event which directly
# tags a repository root. Direct root-tagging events do not consume this limit.
# CLI: --sync-recursive-descendant-limit <count>
# Default: 500
# NGIT_SYNC_RECURSIVE_DESCENDANT_LIMIT=500
# Maximum backoff time in seconds for sync relay reconnection
# CLI: --sync-max-backoff-secs <seconds>
# Default: 3600 (1 hour)
# NGIT_SYNC_MAX_BACKOFF_SECS=3600
# Interval in seconds for checking disconnected relays and attempting reconnection
# Set to lower value for faster reconnection testing
# CLI: --sync-disconnect-check-interval-secs <seconds>
# Default: 60
# NGIT_SYNC_DISCONNECT_CHECK_INTERVAL_SECS=60
# Base backoff time in seconds for relay reconnection
# Used for exponential backoff: base * 2^(failures-1)
# Set to 1 for faster test cycles
# Note: The connection timeout is capped at this value
# CLI: --sync-base-backoff-secs <seconds>
# Default: 5
# NGIT_SYNC_BASE_BACKOFF_SECS=5
# Disable NIP-77 negentropy sync (use REQ+EOSE instead)
# When enabled, sync will use REQ+EOSE instead of negentropy for history sync
# Primarily useful for testing that sync works without negentropy support
# CLI: --sync-disable-negentropy
# Default: false
# NGIT_SYNC_DISABLE_NEGENTROPY=false
# Allow event-directed sync targets that are not globally reachable
# (loopback, private, link-local addresses and local hostnames). Disables the
# SSRF protection for untrusted announcement/PR relay and clone URLs; intended
# only for tests and closed development networks. The operator-configured
# bootstrap relay is always allowed regardless of this setting.
# CLI: --sync-allow-non-global-targets
# Default: false
# NGIT_SYNC_ALLOW_NON_GLOBAL_TARGETS=false
# ============================================================================
# REJECTED EVENTS INDEX
# ============================================================================
# Hot cache duration in seconds for rejected announcements
# Stores full event objects for immediate re-processing when dependencies resolve
# Too short (<30s): Miss events from slow relays
# Too long (>5min): Waste memory
# CLI: --rejected-hot-cache-duration-secs <seconds>
# Default: 120 (2 minutes)
# NGIT_REJECTED_HOT_CACHE_DURATION_SECS=120
# Cold index expiry in seconds for rejected announcements
# Stores metadata only to prevent repeated downloads of rejected events
# CLI: --rejected-cold-index-expiry-secs <seconds>
# Default: 604800 (7 days)
# NGIT_REJECTED_COLD_INDEX_EXPIRY_SECS=604800
# Hours before removing relay from naughty list
# Relays with persistent infrastructure issues (DNS, TLS, protocol errors) are
# tracked separately and retried after this expiration period
# CLI: --naughty-list-expiration-hours <hours>
# Default: 12
# NGIT_NAUGHTY_LIST_EXPIRATION_HOURS=12
# ============================================================================
# HOLDING DB AND DELETION-REQUEST CLEANUP
# ============================================================================
# Retention window in seconds for deleted events kept in holding DB
# Used by startup catch-up and periodic expiration cleanup
# Must be greater than 0
# CLI: --holding-retention-secs <seconds>
# Default: 7776000 (90 days)
# NGIT_HOLDING_RETENTION_SECS=7776000
# Interval in seconds between holding DB and deletion-request retention background
# cleanup passes. This cadence does not alter timestamp-derived retention deadlines.
# Must be greater than 0
# CLI: --holding-cleanup-interval-secs <seconds>
# Default: 86400 (24 hours)
# NGIT_HOLDING_CLEANUP_INTERVAL_SECS=86400
# ============================================================================
# GRASP-05 ARCHIVE MODE
# ============================================================================
# Accept all repository announcements (⚠️ WARNING: Storage/bandwidth risk)
# When enabled, any repository can be mirrored to this relay
# CLI: --archive-all
# Default: false
# NGIT_ARCHIVE_ALL=false
# Whitelist specific repos/pubkeys/identifiers for archiving
# Comma-separated list supporting three formats:
# <npub> - Archive all repos from this pubkey
# <npub>/<identifier> - Archive specific repo
# <identifier> - Archive repos with this identifier (any pubkey)
#
# CLI: --archive-whitelist <list>
# Default: (empty)
# Examples:
# NGIT_ARCHIVE_WHITELIST=npub1alice...
# NGIT_ARCHIVE_WHITELIST=npub1alice...,npub1bob.../linux
# NGIT_ARCHIVE_WHITELIST=bitcoin-core,linux,rust
# NGIT_ARCHIVE_WHITELIST=
# Archive GRASP services: comma-separated list of GRASP server domains to archive
# Archives all repositories from the specified GRASP server domains
# Must be bare domains only (e.g., git.example.com, NOT wss://git.example.com)
# Mutually exclusive with NGIT_ARCHIVE_ALL and NGIT_ARCHIVE_WHITELIST
# Automatically sets NGIT_ARCHIVE_READ_ONLY to true by default
# CLI: --archive-grasp-services <list>
# Default: (empty)
# Examples:
# NGIT_ARCHIVE_GRASP_SERVICES=git.example.com
# NGIT_ARCHIVE_GRASP_SERVICES=git.example.com,git.nostr.dev,relay.gitnostr.com
# NGIT_ARCHIVE_GRASP_SERVICES=
# Archive read-only mode (relay is read-only sync of archived repositories)
# When true:
# - NIP-11 includes GRASP-05 in supported_grasps
# - NIP-11 curation field describes archive scope
# - Repository announcements not listing this service are accepted per whitelist/archive-all
# When false:
# - Archive mode disabled (standard GRASP-01 operation)
#
# CLI: --archive-read-only
# Default: true if NGIT_ARCHIVE_ALL, NGIT_ARCHIVE_WHITELIST, or NGIT_ARCHIVE_GRASP_SERVICES is set, false otherwise
# Note: Setting to true without archive config causes startup error
# Note: Cannot be used with NGIT_REPOSITORY_WHITELIST (mutually exclusive)
# NGIT_ARCHIVE_READ_ONLY=
# ============================================================================
# GRASP-06 CONTRIBUTOR PR SUBMISSION
# ============================================================================
# Enable GRASP-06 contributor PR submission endpoint at /prs/<npub>/<identifier>.git
#
# When enabled, the relay exposes an unauthenticated PR submission endpoint that
# accepts pushes of refs/nostr/<event-id> from any contributor. Security relies
# on the signed PR/PR-Update events the refs reference, not on HTTP-level auth.
#
# When disabled (default), /prs/* returns 404 and event-acceptance is unchanged.
#
# See: https://gitworkshop.dev/danconwaydev.com/grasp/tree/master/06.md
# See: docs/explanation/grasp-06-contributor-pr-submission.md
#
# CLI: --grasp06-enable
# Default: false
# NGIT_GRASP06_ENABLE=false
# ============================================================================
# GRASP-08 PRIVATE SERVICE
# ============================================================================
# Require whitelisted authentication for all Nostr WebSocket reads/writes and
# all standard Git Smart HTTP requests.
# Cannot be combined with the intentionally unauthenticated GRASP-06 endpoint.
#
# CLI: --private-mode
# Default: false
# NGIT_PRIVATE_MODE=false
# Permanently configured service-wide members as comma-separated npubs. Every
# entry is validated at startup; malformed entries fail closed. The effective
# GRASP-08 whitelist also includes NIP-11 owners of relays referenced by
# accepted repository announcements.
#
# CLI: --private-members <npubs>
# Default: (empty; at least one member is required in private mode)
# NGIT_PRIVATE_MEMBERS=npub1alice...,npub1bob...
#
# Canonical external origin signed in Git NIP-98 credentials. Set this when
# TLS terminates at a reverse proxy or a non-loopback service uses plain HTTP.
# It must be an http(s) origin without a path, query, or fragment.
# NGIT_PRIVATE_PUBLIC_ORIGIN=https://private.example
# ============================================================================
# DELETION REQUESTS (NIP-09 AND NIP-62)
# ============================================================================
# Deletion request disrespector: ignore NIP-09 and NIP-62 requests (archival mode)
#
# When enabled, incoming NIP-09 (kind 5) deletion requests and NIP-62
# request-to-vanish events are STORED but NOT acted upon: their targets remain
# fully accessible. This makes the relay an archival server, preserving content
# and preventing "left-pad" scenarios. NIP-11 supported_nips will NOT advertise
# NIP-09 (deletion) or NIP-62 (request to vanish) in this mode.
#
# This ONLY affects NIP-09 and NIP-62 user-initiated requests. It does NOT
# prevent blacklist-triggered deletions (operator moderation: spam/malware/abuse).
#
# When disabled (default), both request types are honoured: their targets are
# deleted and re-submission stays rejected. NIP-09 and NIP-62 are advertised in
# NIP-11.
#
# See: docs/explanation/repository-lifecycle.md
#
# CLI: --deletion-request-disrespector
# Default: false
# NGIT_DELETION_REQUEST_DISRESPECTOR=false
# Deletion-request retention applies to accepted NIP-09 deletion requests and
# NIP-62 request-to-vanish events. All values are integer seconds. Unused clocks
# start at relay-observed first_seen_at; used clocks start at last_used_at.
# "Additional" periods begin after their corresponding served period ends.
# Used requests remain served indefinitely when deletion-request-disrespector is true.
# Seconds permit short tests; production periods should be at least one day and
# comfortably exceed worst-case deletion/archive processing time.
# How long an unused request remains served from first_seen_at
# CLI: --deletion-request-retention-unused-served-secs <seconds>
# Default: 2592000 (30 days)
# NGIT_DELETION_REQUEST_RETENTION_UNUSED_SERVED_SECS=2592000
# Additional time an unused request remains unserved but eligible to gate
# CLI: --deletion-request-retention-unused-unserved-gating-additional-secs <seconds>
# Default: 15552000 (180 days)
# NGIT_DELETION_REQUEST_RETENTION_UNUSED_UNSERVED_GATING_ADDITIONAL_SECS=15552000
# Normal-mode time a used request remains served after last_used_at
# CLI: --deletion-request-retention-used-served-after-last-used-secs <seconds>
# Default: 23328000 (270 days; 9 fixed 30-day months)
# NGIT_DELETION_REQUEST_RETENTION_USED_SERVED_AFTER_LAST_USED_SECS=23328000
# Additional normal-mode time a used request remains unserved but continues gating
# CLI: --deletion-request-retention-used-unserved-gating-additional-secs <seconds>
# Default: 7776000 (90 days; 3 fixed 30-day months)
# NGIT_DELETION_REQUEST_RETENTION_USED_UNSERVED_GATING_ADDITIONAL_SECS=7776000
# ============================================================================
# REPOSITORY WHITELIST
# ============================================================================
# Whitelist specific repos/pubkeys/identifiers for GRASP-01 acceptance
# Comma-separated list supporting three formats (same as archive whitelist):
# <npub> - Accept all repos from this pubkey (if they list our service)
# <npub>/<identifier> - Accept specific repo (if it lists our service)
# <identifier> - Accept repos with this identifier (if they list our service)
#
# Difference from archive whitelist:
# - Repository whitelist: Announcements MUST list our service AND match whitelist
# - Archive whitelist: Announcements don't need to list our service, just match whitelist
#
# CLI: --repository-whitelist <list>
# Default: (empty - all repos listing our service are accepted)
# Examples:
# NGIT_REPOSITORY_WHITELIST=npub1alice...
# NGIT_REPOSITORY_WHITELIST=npub1alice...,npub1bob.../linux
# NGIT_REPOSITORY_WHITELIST=bitcoin-core,linux,rust
# Note: Cannot be used with NGIT_ARCHIVE_READ_ONLY=true (mutually exclusive)
# Note: When set, NIP-11 curation field will indicate curated repository acceptance
# NGIT_REPOSITORY_WHITELIST=
# ============================================================================
# REPOSITORY BLACKLIST
# ============================================================================
# Blacklist specific repos/pubkeys/identifiers to reject
# Comma-separated list supporting three formats (same as whitelist formats):
# <npub> - Block all repos from this pubkey
# <npub>/<identifier> - Block specific repo
# <identifier> - Block repos with this identifier (any pubkey)
#
# Blacklist takes precedence over ALL whitelists:
# - Blacklisted repos are rejected even if they match archive or repository whitelists
# - Blacklisted repos are rejected even if they list our service
#
# Rejection reasons indicate the match type:
# - "Repository owner <npub> is blacklisted" (npub format)
# - "Repository <npub>/<identifier> is blacklisted" (npub/identifier format)
# - "Repository identifier <identifier> is blacklisted" (identifier format)
#
# CLI: --repository-blacklist <list>
# Default: (empty - no repositories are blacklisted)
# Examples:
# NGIT_REPOSITORY_BLACKLIST=npub1spam...
# NGIT_REPOSITORY_BLACKLIST=npub1alice.../bad-repo
# NGIT_REPOSITORY_BLACKLIST=malware-repo,spam-repo
# NGIT_REPOSITORY_BLACKLIST=
# Automatically restore repositories that were previously deleted by blacklist
# parity when they are no longer blacklisted and still within holding retention.
# Runs once on startup as part of startup parity orchestration.
# CLI: --blacklist-auto-restore
# Default: false
# NGIT_BLACKLIST_AUTO_RESTORE=false
# ============================================================================
# EVENT BLACKLIST
# ============================================================================
# Blacklist events from specific authors (npubs)
# Comma-separated list of npubs whose events are rejected
# ALL events from these authors are blocked from both relay storage and purgatory
#
# Event blacklist takes precedence over ALL other validation:
# - Blacklisted events are rejected before any other policy checks
# - Applies to announcements, state events, PRs, and all other event types
# - Events never reach purgatory (rejected immediately)
#
# Rejection reason:
# - "Event author <npub> is blacklisted"
#
# CLI: --event-blacklist <list>
# Default: (empty - no events are blacklisted by author)
# Examples:
# NGIT_EVENT_BLACKLIST=npub1spam...
# NGIT_EVENT_BLACKLIST=npub1spam...,npub1abuser...
# NGIT_EVENT_BLACKLIST=
# ============================================================================
# RATE LIMITING & DOS PROTECTION
# ============================================================================
# Maximum total connections to the relay
# When unset (default), connections are unlimited (defers to OS fd limits and infrastructure controls)
# CLI: --max-connections <count>
# Default: unlimited
# NGIT_MAX_CONNECTIONS=4096
# Discoverable sync limits and the Git-specific event-size limit
# NGIT_RELAY_MAX_SUBSCRIPTIONS=500
# NGIT_RELAY_FILTER_LIMIT=500
# NGIT_RELAY_MAX_EVENT_SIZE_BYTES=196608