// Maximum request body size in bytes (or a size string when supplied
// via CLI / config file, e.g. "100MB"). 20 MiB default (#563) — a
// generous out-of-the-box limit for common workloads (larger `git
// push`, media uploads, bigger RDF documents). Raise via --body-limit
// / JSS_BODY_LIMIT for established app repos (#474); lower it for
// tighter memory-DoS protection.
bodyLimit: 20*1024*1024,
// SSL
sslKey: null,
sslCert: null,
// Features
multiuser: true,
conneg: false,
notifications: false,
// Identity Provider
idp: false,
idpIssuer: null,
// Subdomain mode (XSS protection)
subdomains: false,
baseDomain: null,
// Mashlib data browser
mashlib: false,
mashlibCdn: false,
mashlibVersion: '2.0.0',
mashlibModule: false,
// Git HTTP backend
git: false,
// CORS proxy (#378) — pod-hosted, WAC-gated proxy for browser apps to
// fetch arbitrary upstreams that don't return CORS headers.
corsProxy: false,
corsProxyMaxBytes: 50*1024*1024,// 50 MB ceiling on upstream response size
corsProxyTimeoutMs: 30_000,// 30 s deadline for upstream to send headers (504 if exceeded). The timeout does not apply during body streaming — body size is capped by corsProxyMaxBytes; see follow-up for streaming-phase timeout.
corsProxyMaxRedirects: 5,// each redirect re-validated for SSRF
// Nostr relay
nostr: false,
nostrPath: '/relay',
nostrMaxEvents: 1000,
// WebRTC signaling
webrtc: false,
webrtcPath: '/.webrtc',
// Terminal (WebSocket shell access)
terminal: false,
// Tunnel (decentralized ngrok)
tunnel: false,
tunnelPath: '/.tunnel',
// ActivityPub federation
activitypub: false,
apUsername: 'me',
apDisplayName: null,
apSummary: null,
apNostrPubkey: null,
// Invite-only registration
inviteOnly: false,
// Single-user mode (personal pod server)
singleUser: false,
// null = root pod (mounted at server origin, WebID at
// /profile/card.jsonld#me). A string mounts the pod at /<name>/ —
// useful when more than one Solid identity coexists on the same
// origin, or when the operator wants the pre-#348 /me/ shape.
singleUserName: null,
// Initial IDP password seeded on first single-user pod creation. If
// unset and --idp is enabled, the server prompts on a TTY or logs a
// warning and continues startup on non-TTY (so the pod is created but
// is not yet loggable until a password is set).
singleUserPassword: null,
// Provision a Schnorr secp256k1 owner key on pod creation, written
// to <pod>/private/privkey.jsonld in W3C CID v1.0 Multikey format
// (Phase 1 of #437). Off by default — keys-on-disk is a security
// tradeoff and we want operators to opt in deliberately.
provisionKeys: false,
// WebID-TLS client certificate authentication
webidTls: false,
// Storage quota (bytes) - 50MB default
defaultQuota: 50*1024*1024,
// Public mode - skip WAC, allow unauthenticated access
public: false,
// Read-only mode - disable PUT/DELETE/PATCH
readOnly: false,
// Live reload - inject script to auto-refresh browser on file changes
liveReload: false,
// HTTP 402 paid access
pay: false,
payCost: 1,
payMempoolUrl: 'https://mempool.space/testnet4',
payAddress: null,
payToken: null,
payRate: 1,
payChains: null,// comma-separated chain IDs, e.g. "tbtc3,tbtc4"
// MongoDB-backed /db/ route
mongo: false,
mongoUrl: 'mongodb://localhost:27017',
mongoDatabase: 'solid',
// MCP (Model Context Protocol) server — pod as a tool surface for agents (#490)
mcp: false,
// Logging
logger: true,
quiet: false,
logLevel: 'info',
// Paths
configPath: './.jss',
};
/**
* Map of environment variable names to config keys
// and clients fail with confusing OIDC discovery errors. If the
// operator pointed JSS at an external issuer, no footgun applies.
if(!config.idpIssuer){
console.warn('⚠️ --single-user is enabled but --idp is disabled and no --idp-issuer is set. Clients won\'t be able to authenticate. Use --idp, or pass an external --idp-issuer.');