mirror of
https://github.com/Such-Software/smirk-backend-core.git
synced 2026-10-17 15:31:38 +02:00
docs(examples): operator cookbook — six deployment recipes + premium-relay spec
Add ready-to-run .env + README recipes (personal, public-free, friends, paid-access, paid-relay, community) and the premium-relay design overview, with audit fixes to the config template and spec: - Drop the inert INSTANCE_ID knob (config never read it) and document the real per-node id, which is derived from ADMIN_PUBLIC_URL. - Warn that a placeholder PUBLIC_API_URL is rejected at boot in production (Nostr identity is on by default); soften the recipe "boots today" status. - Remove dead template vars: BTC/LTC Core-RPC settings and the non-existent PUBLIC_EXPOSE_FEATURES (replaced with the real per-field landing switches). - Mark ALTCHA_HMAC_KEY conditional in PoW-off recipes; blank placeholder payment creds so a recipe doesn't ship a key that fails validation. - Fix premium-relay spec drift: the migration creates no premium_until index, disabled endpoints return 400/200 (not 404), and neutralize operator voice.
This commit is contained in:
+20
-20
@@ -10,16 +10,17 @@ Each recipe is a directory with:
|
||||
called out; copy the full `../../.env.example` and apply the deltas).
|
||||
- **`README.md`** — what it's for, what it costs to run, the legal/operational notes.
|
||||
|
||||
> **Status.** `personal/`, `public-free/`, and `paid-relay/` (the flagship — it
|
||||
> uses the shipped [premium-relay feature](../docs/design/premium-relay.md)) have
|
||||
> full `.env.example`s. `friends/`, `paid-access/`, and `community/` are summarized
|
||||
> below and get their own directories on the next pass.
|
||||
> Each recipe below has its own directory with a tuned `.env.example` and a short
|
||||
> README. `paid-relay/` is the flagship — it uses the shipped
|
||||
> [premium-relay feature](../docs/design/premium-relay.md).
|
||||
|
||||
## Every recipe, the same three steps
|
||||
1. `cp ../../.env.example .env`, then apply the recipe's deltas.
|
||||
2. Generate each secret: `openssl rand -hex 32` (`JWT_SECRET`, `SEED_FINGERPRINT_PEPPER`,
|
||||
`REFRESH_TOKEN_PEPPER`, `IP_SALT`, `ALTCHA_HMAC_KEY`, `ADMIN_*_SECRET`). Fill chain
|
||||
endpoints. `chmod 600 .env`.
|
||||
2. Set `PUBLIC_API_URL` to your real domain (a placeholder is rejected at boot in
|
||||
production). Generate each secret: `openssl rand -hex 32` (`JWT_SECRET`,
|
||||
`SEED_FINGERPRINT_PEPPER`, `REFRESH_TOKEN_PEPPER`, `IP_SALT`, `ADMIN_*_SECRET`, plus
|
||||
`ALTCHA_HMAC_KEY` only if the recipe sets `FEATURE_POW=true`). Fill chain endpoints.
|
||||
`chmod 600 .env`.
|
||||
3. Run the binary (migrations apply on boot). Reverse-proxy TLS; bind the API to
|
||||
`127.0.0.1`.
|
||||
|
||||
@@ -30,12 +31,12 @@ funds. **Self-hosting bypasses every gate.** Secrets are never committed.
|
||||
|
||||
| Recipe | For | Registration | Relay | Pitch | Status |
|
||||
|---|---|---|---|---|---|
|
||||
| [`personal/`](personal/) | Just you | open, no gate | off (or open, just you) | Your own sovereign backend | ✅ boots today |
|
||||
| [`public-free/`](public-free/) | A free public instance | **open + PoW** | off (v1) | What `api.smirk.cash` runs | ✅ boots today |
|
||||
| `friends/` | Your circle | **invite-only** | on, `inbox-outbox` | A backend for people you trust | 📝 2nd pass |
|
||||
| `paid-access/` | A paid wallet service | **pay-to-register** | optional | Charge once for a hosted wallet backend | 📝 2nd pass |
|
||||
| `paid-relay/` | Monetize a relay | **open + PoW** (free wallet) | on, **`premium-post`** | Free wallet, paid ($/quarter) Nostr posting | ✅ premium-relay shipped |
|
||||
| `community/` | A project/DAO space | invite | on, `author-allowlist` | A gated relay for a named group | 📝 2nd pass |
|
||||
| [`personal/`](personal/) | Just you | open, no gate | off (or open, just you) | Your own sovereign backend | ✅ set domain + secrets |
|
||||
| [`public-free/`](public-free/) | A free public instance | **open + PoW** | off (v1) | The shape a free public instance runs | ✅ set domain + secrets |
|
||||
| [`friends/`](friends/) | Your circle | **invite-only** | on, `inbox-outbox` | A backend for people you trust | ✅ |
|
||||
| [`paid-access/`](paid-access/) | A paid wallet service | **pay-to-register** | optional | Charge once for a hosted wallet backend | ✅ |
|
||||
| [`paid-relay/`](paid-relay/) | Monetize a relay | **open + PoW** (free wallet) | on, **`premium-post`** | Free wallet, paid ($/quarter) Nostr posting | ✅ premium-relay shipped |
|
||||
| [`community/`](community/) | A project/community space | invite | on, `author-allowlist` | A gated relay for a named group | ✅ |
|
||||
|
||||
## Recipe summaries (config deltas)
|
||||
|
||||
@@ -52,8 +53,8 @@ funds. **Self-hosting bypasses every gate.** Secrets are never committed.
|
||||
processor paying *your* wallet). A one-time access fee gates wallet creation. Non-custodial;
|
||||
you never touch funds (pull-model invoice reads only).
|
||||
- **`paid-relay`** — free wallet (open + PoW) **plus** `PREMIUM_ENABLED=true`,
|
||||
`RELAY_ENABLED=true`, `RELAY_WRITE_POLICY=premium-post`, `PREMIUM_AMOUNT` /
|
||||
`PREMIUM_CURRENCY` / `PREMIUM_PERIOD_DAYS`. Recurring revenue for relay posting; reads
|
||||
`RELAY_ENABLED=true`, `RELAY_WRITE_POLICY=premium-post`, `PREMIUM_CURRENCY` +
|
||||
`PREMIUM_PLANS` (`id:days:amount`). Recurring revenue for relay posting; reads
|
||||
open (v1). **Content posture:** running a relay carries user content — see the NCMEC/DMCA
|
||||
clauses in the published Terms (§6, §9.1). Spec: [premium-relay](../docs/design/premium-relay.md).
|
||||
- **`community`** — `REGISTRATION_REQUIRE_INVITE=true`, `RELAY_ENABLED=true` +
|
||||
@@ -61,8 +62,7 @@ funds. **Self-hosting bypasses every gate.** Secrets are never committed.
|
||||
|
||||
## Choosing
|
||||
|
||||
- Want **freedom**? `personal` (or `friends` for a group).
|
||||
- Want a **free public good**? `public-free`.
|
||||
- Want it to **pay for itself**? `paid-relay` (recurring, real utility) or `paid-access`
|
||||
(one-time). `paid-relay` is the flagship — recurring revenue tied to a service people
|
||||
actually value, and the live demo runs at `api.smirk.cash`.
|
||||
- Solo, or a trusted group → `personal` / `friends`.
|
||||
- A free public instance → `public-free`.
|
||||
- Cost recovery → `paid-relay` (recurring, tied to a real service — the flagship) or
|
||||
`paid-access` (a one-time signup fee).
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
# ── Recipe: community ────────────────────────────────────────────────────────
|
||||
# A gated space for a named project / community: invite-only registration plus a
|
||||
# relay that ONLY your registered members may publish to (author-allowlist). A
|
||||
# members-only Nostr space with its own DM inbox.
|
||||
#
|
||||
# ⚠️ Running a relay hosts user content — see ../LEGAL_AND_OPS.md.
|
||||
#
|
||||
# Start from ../../.env.example and apply the lines below. openssl rand -hex 32
|
||||
# for each secret.
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
SERVER_HOST=127.0.0.1
|
||||
SERVER_PORT=8080
|
||||
# REQUIRED: replace with YOUR real https domain. The your-domain.example placeholder
|
||||
# is rejected at boot in production (Nostr identity is on by default).
|
||||
PUBLIC_API_URL=https://api.your-domain.example/api/v1
|
||||
ENVIRONMENT=production
|
||||
|
||||
DATABASE_URL=postgresql:///smirk?host=/var/run/postgresql
|
||||
|
||||
JWT_SECRET=
|
||||
SEED_FINGERPRINT_PEPPER=
|
||||
REFRESH_TOKEN_PEPPER=
|
||||
IP_SALT=
|
||||
# ALTCHA_HMAC_KEY — only needed if you set FEATURE_POW=true (this recipe leaves PoW off).
|
||||
ALTCHA_HMAC_KEY=
|
||||
ADMIN_KEY_INTEGRITY_SECRET=
|
||||
|
||||
# Invite-only membership (mint codes with `smirk-admin mint-invite`).
|
||||
POW_REQUIRED=false
|
||||
REGISTRATION_REQUIRE_INVITE=true
|
||||
REGISTRATION_REQUIRE_PAYMENT=false
|
||||
|
||||
WALLET_RESTORE_POLICY=unlimited
|
||||
FEATURE_PRICES=true
|
||||
FEATURE_TIPS=false
|
||||
|
||||
# Relay on, members-only: only registered members may publish anything.
|
||||
RELAY_ENABLED=true
|
||||
RELAY_MODE=bundled
|
||||
RELAY_URL=wss://relay.your-domain.example
|
||||
RELAY_WRITE_POLICY=author-allowlist
|
||||
RELAY_INBOUND_POW_BITS=0
|
||||
RELAY_ADMISSION_BIND=127.0.0.1:8090
|
||||
|
||||
# Chain endpoints — see ../../.env.example.
|
||||
XMR_LWS_URL=
|
||||
XMR_LWS_ADMIN_URL=
|
||||
XMR_LWS_ADMIN_KEY=
|
||||
XMR_DAEMON_URL=
|
||||
WOW_LWS_URL=
|
||||
WOW_LWS_ADMIN_URL=
|
||||
WOW_LWS_ADMIN_KEY=
|
||||
WOW_DAEMON_URL=
|
||||
@@ -0,0 +1,9 @@
|
||||
# community — a members-only space for a project or group
|
||||
|
||||
Invite-only registration plus a relay that ONLY your registered members may publish
|
||||
to (`author-allowlist`) — a members-only Nostr space with its own DM inbox.
|
||||
|
||||
- **Config:** [`.env.example`](.env.example) — `REGISTRATION_REQUIRE_INVITE=true`,
|
||||
`RELAY_ENABLED=true`, `RELAY_WRITE_POLICY=author-allowlist`.
|
||||
- **Membership:** mint codes with `smirk-admin mint-invite`.
|
||||
- **Relay:** you host member content — see [`../LEGAL_AND_OPS.md`](../LEGAL_AND_OPS.md).
|
||||
@@ -0,0 +1,56 @@
|
||||
# ── Recipe: friends ──────────────────────────────────────────────────────────
|
||||
# A backend for a known group. Registration is invite-only (mint a code for each
|
||||
# person you trust); the relay is on with the locked-down inbox-outbox policy so
|
||||
# the group has a private DM inbox. No payment, generous restore.
|
||||
#
|
||||
# Start from ../../.env.example and apply the lines below. openssl rand -hex 32
|
||||
# for each secret.
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
SERVER_HOST=127.0.0.1
|
||||
SERVER_PORT=8080
|
||||
# REQUIRED: replace with YOUR real https domain. The your-domain.example placeholder
|
||||
# is rejected at boot in production (Nostr identity is on by default).
|
||||
PUBLIC_API_URL=https://api.your-domain.example/api/v1
|
||||
ENVIRONMENT=production
|
||||
|
||||
DATABASE_URL=postgresql:///smirk?host=/var/run/postgresql
|
||||
|
||||
JWT_SECRET=
|
||||
SEED_FINGERPRINT_PEPPER=
|
||||
REFRESH_TOKEN_PEPPER=
|
||||
IP_SALT=
|
||||
# ALTCHA_HMAC_KEY — only needed if you set FEATURE_POW=true (this recipe leaves PoW off).
|
||||
ALTCHA_HMAC_KEY=
|
||||
ADMIN_KEY_INTEGRITY_SECRET=
|
||||
|
||||
# Invite-only — hand out codes with `smirk-admin mint-invite --count <n>`.
|
||||
POW_REQUIRED=false
|
||||
REGISTRATION_REQUIRE_INVITE=true
|
||||
REGISTRATION_REQUIRE_PAYMENT=false
|
||||
|
||||
# A known group can restore as far back as they like.
|
||||
WALLET_RESTORE_POLICY=unlimited
|
||||
|
||||
FEATURE_PRICES=true
|
||||
FEATURE_TIPS=false
|
||||
|
||||
# Relay on, locked down: registered members publish their own events; anyone may
|
||||
# deliver a gift-wrapped DM to a member. (Running a relay hosts user content —
|
||||
# see ../LEGAL_AND_OPS.md.)
|
||||
RELAY_ENABLED=true
|
||||
RELAY_MODE=bundled
|
||||
RELAY_URL=wss://relay.your-domain.example
|
||||
RELAY_WRITE_POLICY=inbox-outbox
|
||||
RELAY_INBOUND_POW_BITS=0
|
||||
RELAY_ADMISSION_BIND=127.0.0.1:8090
|
||||
|
||||
# Chain endpoints — point at your own nodes / LWS. See ../../.env.example.
|
||||
XMR_LWS_URL=
|
||||
XMR_LWS_ADMIN_URL=
|
||||
XMR_LWS_ADMIN_KEY=
|
||||
XMR_DAEMON_URL=
|
||||
WOW_LWS_URL=
|
||||
WOW_LWS_ADMIN_URL=
|
||||
WOW_LWS_ADMIN_KEY=
|
||||
WOW_DAEMON_URL=
|
||||
@@ -0,0 +1,10 @@
|
||||
# friends — a backend for a known group
|
||||
|
||||
Invite-only registration plus a locked-down relay (`inbox-outbox`) so your circle
|
||||
has a private DM inbox. No payment; generous restore.
|
||||
|
||||
- **Config:** [`.env.example`](.env.example) — `REGISTRATION_REQUIRE_INVITE=true`,
|
||||
`RELAY_ENABLED=true`, `RELAY_WRITE_POLICY=inbox-outbox`.
|
||||
- **Invites:** mint codes with `smirk-admin mint-invite --count <n>` and hand them out.
|
||||
- **Relay:** you host user messages — review the content notes in
|
||||
[`../LEGAL_AND_OPS.md`](../LEGAL_AND_OPS.md).
|
||||
@@ -0,0 +1,61 @@
|
||||
# ── Recipe: paid-access ──────────────────────────────────────────────────────
|
||||
# A paid hosted wallet backend: a one-time fee gates NEW wallet creation (existing
|
||||
# wallets and self-hosters bypass it). Non-custodial and pull-model — the backend
|
||||
# only READS invoice status; funds go straight to your own wallet.
|
||||
#
|
||||
# ⚠️ Charging a fee has operational + legal implications — see ../LEGAL_AND_OPS.md.
|
||||
#
|
||||
# Start from ../../.env.example and apply the lines below. openssl rand -hex 32
|
||||
# for each secret.
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
SERVER_HOST=127.0.0.1
|
||||
SERVER_PORT=8080
|
||||
# REQUIRED: replace with YOUR real https domain. The your-domain.example placeholder
|
||||
# is rejected at boot in production (Nostr identity is on by default).
|
||||
PUBLIC_API_URL=https://api.your-domain.example/api/v1
|
||||
ENVIRONMENT=production
|
||||
|
||||
DATABASE_URL=postgresql:///smirk?host=/var/run/postgresql
|
||||
|
||||
JWT_SECRET=
|
||||
SEED_FINGERPRINT_PEPPER=
|
||||
REFRESH_TOKEN_PEPPER=
|
||||
IP_SALT=
|
||||
ALTCHA_HMAC_KEY=
|
||||
ADMIN_KEY_INTEGRITY_SECRET=
|
||||
|
||||
# Pay-to-register: a settled invoice is required to create a new wallet. Compose
|
||||
# with PoW if you like (FEATURE_POW is the master switch; POW_REQUIRED alone is
|
||||
# inert). Returning wallets never pay again.
|
||||
FEATURE_POW=true
|
||||
POW_REQUIRED=true
|
||||
REGISTRATION_REQUIRE_INVITE=false
|
||||
REGISTRATION_REQUIRE_PAYMENT=true
|
||||
|
||||
# Processor (BTCPay-compatible; also served by xmrcheckout / wowcheckout). Price
|
||||
# is fiat-denominated here (payable in any coin the processor offers).
|
||||
PAYMENT_PROVIDER=btcpay
|
||||
PAYMENT_PROVIDER_URL=https://pay.your-domain.example
|
||||
PAYMENT_STORE_ID=
|
||||
PAYMENT_API_KEY=
|
||||
PAYMENT_AMOUNT=5
|
||||
PAYMENT_CURRENCY=USD
|
||||
PAYMENT_CONFIRMATIONS=1
|
||||
PAYMENT_EXPIRES_MINUTES=60
|
||||
|
||||
WALLET_RESTORE_POLICY=bounded
|
||||
WALLET_MAX_RESTORE_DEPTH_DAYS=365
|
||||
FEATURE_PRICES=true
|
||||
FEATURE_TIPS=false
|
||||
RELAY_ENABLED=false
|
||||
|
||||
# Chain endpoints — see ../../.env.example.
|
||||
XMR_LWS_URL=
|
||||
XMR_LWS_ADMIN_URL=
|
||||
XMR_LWS_ADMIN_KEY=
|
||||
XMR_DAEMON_URL=
|
||||
WOW_LWS_URL=
|
||||
WOW_LWS_ADMIN_URL=
|
||||
WOW_LWS_ADMIN_KEY=
|
||||
WOW_DAEMON_URL=
|
||||
@@ -0,0 +1,13 @@
|
||||
# paid-access — a paid hosted wallet backend
|
||||
|
||||
A one-time fee gates creating a NEW wallet (existing wallets and self-hosters bypass
|
||||
it). Non-custodial and pull-model: the backend only reads invoice status, and funds
|
||||
go straight to your own wallet.
|
||||
|
||||
- **Config:** [`.env.example`](.env.example) — `REGISTRATION_REQUIRE_PAYMENT=true` +
|
||||
the `PAYMENT_*` processor block (BTCPay-compatible; also served by xmrcheckout /
|
||||
wowcheckout). Price is fiat-denominated, payable in any coin the processor offers.
|
||||
- **You are a merchant, not a money transmitter** — you sell access to your service
|
||||
and never hold user funds. Have clear Terms (what the fee buys, refunds, fair use),
|
||||
treat the fees as income, and see [`../LEGAL_AND_OPS.md`](../LEGAL_AND_OPS.md).
|
||||
- `PAYMENT_CONFIRMATIONS >= 1` (0-conf lets a paid invoice be reversed after signup).
|
||||
@@ -13,11 +13,12 @@
|
||||
|
||||
SERVER_HOST=127.0.0.1
|
||||
SERVER_PORT=8081
|
||||
# REQUIRED: replace with YOUR real https domain. The your-domain.example placeholder
|
||||
# is rejected at boot in production (Nostr identity is on by default).
|
||||
PUBLIC_API_URL=https://api.your-domain.example/api/v1
|
||||
ENVIRONMENT=production
|
||||
INSTANCE_ID=paid-relay-1
|
||||
|
||||
DATABASE_URL=postgresql:///smirk_v3_db?host=/var/run/postgresql
|
||||
DATABASE_URL=postgresql:///smirk?host=/var/run/postgresql
|
||||
|
||||
# Secrets (REQUIRED; openssl rand -hex 32 each).
|
||||
JWT_SECRET=
|
||||
@@ -28,6 +29,8 @@ ALTCHA_HMAC_KEY=
|
||||
ADMIN_KEY_INTEGRITY_SECRET=
|
||||
|
||||
# ── Free registration, PoW-gated (wallet use is always free) ──
|
||||
# FEATURE_POW is the master switch; POW_REQUIRED alone is inert without it.
|
||||
FEATURE_POW=true
|
||||
POW_REQUIRED=true
|
||||
REGISTRATION_REQUIRE_INVITE=false
|
||||
REGISTRATION_REQUIRE_PAYMENT=false
|
||||
@@ -58,8 +61,8 @@ PREMIUM_PLANS=quarter:90:5,halfyear:182:9,year:365:15
|
||||
# directly to YOUR wallet.
|
||||
PAYMENT_PROVIDER=btcpay
|
||||
PAYMENT_PROVIDER_URL=https://pay.your-domain.example
|
||||
PAYMENT_STORE_ID=your-store-id
|
||||
PAYMENT_API_KEY=your-processor-api-key
|
||||
PAYMENT_STORE_ID=
|
||||
PAYMENT_API_KEY=
|
||||
PAYMENT_CONFIRMATIONS=1
|
||||
PAYMENT_EXPIRES_MINUTES=60
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# paid-relay — free wallet, paid Nostr posting (the flagship)
|
||||
|
||||
A free wallet (open + PoW) **plus** a paid premium tier for **general** Nostr
|
||||
posting to your relay. Wallet-functional events — encrypted DMs, tips, swap
|
||||
coordination — stay **free** for registered users; premium unlocks general posting.
|
||||
Recurring revenue tied to a real service. Implements the
|
||||
[premium-relay feature](../../docs/design/premium-relay.md).
|
||||
|
||||
- **Config:** [`.env.example`](.env.example) — `RELAY_WRITE_POLICY=premium-post`,
|
||||
`PREMIUM_ENABLED=true`, tiered `PREMIUM_PLANS` (a built-in discount curve), and the
|
||||
`PAYMENT_*` processor block (reused from pay-to-register; BTCPay-compatible).
|
||||
- **Free vs paid:** the relay is free for what makes the wallet work; you pay to use
|
||||
it as your everyday relay. Reads stay open (v1); premium gates *writes*.
|
||||
- **Money:** you sell access to your relay (a fee), non-custodial + pull-model —
|
||||
never hold funds. `PAYMENT_CONFIRMATIONS >= 1`; validation rejects the unsafe combos.
|
||||
- **Content:** running a relay means hosting user content — a DMCA designated agent,
|
||||
a CSAM-reporting process, and acceptable-use terms apply. See
|
||||
[`../LEGAL_AND_OPS.md`](../LEGAL_AND_OPS.md).
|
||||
- **Resources:** the relay runs beside the wallet backend + LWS, so keep the size /
|
||||
retention / connection / rate caps (in `.env.example` and the nostr-rs-relay config
|
||||
under `deploy/relay`); move to `RELAY_MODE=external` on its own host if load climbs.
|
||||
@@ -7,9 +7,10 @@
|
||||
|
||||
SERVER_HOST=127.0.0.1
|
||||
SERVER_PORT=8080
|
||||
# REQUIRED: replace with YOUR real https domain. The your-domain.example placeholder
|
||||
# is rejected at boot in production (Nostr identity is on by default).
|
||||
PUBLIC_API_URL=https://your-domain.example/api/v1
|
||||
ENVIRONMENT=production
|
||||
INSTANCE_ID=my-personal-node
|
||||
|
||||
# Unix socket + peer auth (run the service as the DB-owning OS user) — no password.
|
||||
DATABASE_URL=postgresql:///smirk?host=/var/run/postgresql
|
||||
@@ -19,6 +20,7 @@ JWT_SECRET=
|
||||
SEED_FINGERPRINT_PEPPER=
|
||||
REFRESH_TOKEN_PEPPER=
|
||||
IP_SALT=
|
||||
# ALTCHA_HMAC_KEY — only needed if you set FEATURE_POW=true (this recipe leaves PoW off).
|
||||
ALTCHA_HMAC_KEY=
|
||||
|
||||
# No gates — it's just you.
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# personal — your own sovereign backend
|
||||
|
||||
Run the backend for yourself alone: no registration gates, unlimited restore, the
|
||||
relay optional. The smallest footprint; you are the only user.
|
||||
|
||||
- **Config:** [`.env.example`](.env.example) — all gates off,
|
||||
`WALLET_RESTORE_POLICY=unlimited`, relay off.
|
||||
- **Boot:** copy `.env.example` → `.env`, generate the secrets (`openssl rand -hex 32`),
|
||||
fill your chain endpoints, run the binary (migrations apply on boot). Bind the API
|
||||
to `127.0.0.1` behind your own TLS.
|
||||
- Non-custodial: the backend never sees your seed or spend keys — funds stay on-chain.
|
||||
@@ -1,7 +1,7 @@
|
||||
# ── Recipe: public-free ──────────────────────────────────────────────────────
|
||||
# A free, open public instance — anyone can register and use the wallet; spam is
|
||||
# gated by proof-of-work, not payment. This is (minus secrets) what the reference
|
||||
# instance api.smirk.cash runs.
|
||||
# gated by proof-of-work, not payment. This is (minus secrets) the shape a free,
|
||||
# open public instance runs.
|
||||
#
|
||||
# Start from ../../.env.example and apply the lines below. openssl rand -hex 32
|
||||
# for each secret.
|
||||
@@ -9,11 +9,12 @@
|
||||
|
||||
SERVER_HOST=127.0.0.1
|
||||
SERVER_PORT=8081
|
||||
# REQUIRED: replace with YOUR real https domain. The your-domain.example placeholder
|
||||
# is rejected at boot in production (Nostr identity is on by default).
|
||||
PUBLIC_API_URL=https://api.your-domain.example/api/v1
|
||||
ENVIRONMENT=production
|
||||
INSTANCE_ID=public-1
|
||||
|
||||
DATABASE_URL=postgresql:///smirk_v3_db?host=/var/run/postgresql
|
||||
DATABASE_URL=postgresql:///smirk?host=/var/run/postgresql
|
||||
|
||||
# Secrets (REQUIRED; openssl rand -hex 32 each).
|
||||
JWT_SECRET=
|
||||
@@ -23,7 +24,9 @@ IP_SALT=
|
||||
ALTCHA_HMAC_KEY=
|
||||
ADMIN_KEY_INTEGRITY_SECRET=
|
||||
|
||||
# Free registration, spam-gated by compute (ALTCHA proof-of-work).
|
||||
# Free registration, spam-gated by compute (ALTCHA proof-of-work). FEATURE_POW is
|
||||
# the master switch; POW_REQUIRED alone is inert without it.
|
||||
FEATURE_POW=true
|
||||
POW_REQUIRED=true
|
||||
REGISTRATION_REQUIRE_INVITE=false
|
||||
REGISTRATION_REQUIRE_PAYMENT=false
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# public-free — a free, open public instance
|
||||
|
||||
Anyone can register and use the wallet; spam is gated by proof-of-work, not
|
||||
payment. This is the shape a free, open public instance runs.
|
||||
|
||||
- **Config:** [`.env.example`](.env.example) — `POW_REQUIRED=true`, no invite/payment
|
||||
gate, `WALLET_RESTORE_POLICY=bounded` + PoW-priced, relay off at launch.
|
||||
- **Boot:** copy → `.env`, generate secrets, reuse your existing daemons / LWS, run
|
||||
the binary. Front it with TLS; bind the API to `127.0.0.1`.
|
||||
- No money changes hands, so there is no payment/consumer-sale surface — just have a
|
||||
Terms + Privacy that disclose what the backend receives (see
|
||||
[`../LEGAL_AND_OPS.md`](../LEGAL_AND_OPS.md)).
|
||||
Reference in New Issue
Block a user