Infrastructure Architecture¶
1. System Overview¶
Research Relay LLC operates a vertically integrated e-commerce platform for RUO (Research Use Only) research chemicals. The architecture is built around MedusaJS v2 as the central e-commerce engine, with self-hosted Bitcoin payment infrastructure, specialized high-risk ACH processing, and a privacy-conscious communications stack.
All public-facing services sit behind Cloudflare for DNS, CDN, and DDoS protection. The Bitcoin payment rail runs on a dedicated NixOS server (shops-btc-01) using nix-bitcoin for reproducible, security-hardened deployment. Business operations use a lean SaaS stack: Zoho for email and accounting, Mercury for banking, and Koinly for crypto tax tracking.
Key design principles:
- Self-custody of Bitcoin -- BTCPay Server is self-hosted; no third-party holds funds
- MedusaJS as single source of truth -- products, orders, customers, inventory, fulfillment
- Privacy by default -- minimal PII storage, identity separation, Tor-enabled Bitcoin infrastructure
- Incremental payment rails -- BTC + ACH at launch, card processing added after 3+ months of bank history
2. Component Inventory¶
| Component | Technology | Hosting | Purpose |
|---|---|---|---|
| Storefront | Next.js | Cloudflare Pages or Vercel | Customer-facing website |
| Backend | MedusaJS v2 | VPS (TBD) or Railway | E-commerce engine, API, admin dashboard |
| Database | PostgreSQL | Same VPS or managed | Product catalog, orders, customers |
| BTC Payments | BTCPay Server | shops-btc-01 (nix-bitcoin) | Bitcoin + Lightning payment processing |
| Lightning | CLN + CLBOSS | shops-btc-01 | Lightning Network node, automated channel management |
| ACH Payments | Paycron | SaaS | ACH/eCheck bank transfer processing |
| Card Payments | Easy Pay Direct / Durango | SaaS | Credit/debit card processing (future) |
| Payment Gateway | Authorize.net | SaaS | Card payment gateway (future) |
| Sales Tax | Avalara or TaxJar | SaaS | Multi-state sales tax calculation and filing |
| Zoho Workplace | SaaS | Business email (@research-relay.com) | |
| Phone | OpenPhone | SaaS | Business phone number |
| Passwords | 1Password | SaaS (or self-hosted) | Credential management, TOTP 2FA |
| DNS / CDN | Cloudflare | SaaS | DNS, CDN, WAF, DDoS protection |
| Docs Site | MkDocs Material | Cloudflare Pages | Internal operations documentation |
| Banking | Mercury | SaaS | Business checking account |
| Accounting | Zoho Books | SaaS | Bookkeeping, invoicing, sales tax |
| Crypto Accounting | Koinly | SaaS | BTC transaction tracking, tax reporting |
| Domain | research-relay.com | Cloudflare Registrar | Primary domain |
3. Architecture Diagram¶
flowchart TB
subgraph Internet["Public Internet"]
Customer["Customer Browser"]
BTC_Network["Bitcoin Network"]
LN_Network["Lightning Network"]
end
subgraph Cloudflare["Cloudflare (DNS + CDN + WAF)"]
CF_DNS["DNS"]
CF_CDN["CDN / DDoS Protection"]
end
subgraph Frontend["Storefront"]
NextJS["Next.js Storefront<br/>Cloudflare Pages / Vercel"]
end
subgraph MedusaStack["MedusaJS Stack (VPS)"]
MedusaAPI["MedusaJS v2 API<br/>+ Admin Dashboard"]
PostgreSQL["PostgreSQL<br/>Database"]
end
subgraph BTCStack["Bitcoin Stack (shops-btc-01)"]
BTCPay["BTCPay Server"]
CLN["Core Lightning<br/>+ CLBOSS"]
Bitcoind["Bitcoin Core<br/>(pruned)"]
Nginx_BTC["nginx (TLS)"]
end
subgraph PaymentProviders["Payment Providers (SaaS)"]
Paycron["Paycron<br/>ACH/eCheck"]
AuthNet["Authorize.net<br/>Card Gateway (future)"]
end
subgraph ExternalServices["External Services"]
Avalara["Avalara / TaxJar<br/>Sales Tax"]
Carriers["USPS / UPS / FedEx<br/>Shipping Rates"]
ZohoMail["Zoho Mail<br/>Transactional Email"]
end
subgraph BusinessOps["Business Operations (SaaS)"]
Mercury["Mercury<br/>Banking"]
ZohoBooks["Zoho Books<br/>Accounting"]
Koinly["Koinly<br/>Crypto Accounting"]
end
Customer -->|"HTTPS"| CF_CDN
CF_CDN --> NextJS
NextJS -->|"REST API"| MedusaAPI
MedusaAPI --> PostgreSQL
MedusaAPI -->|"Greenfield API"| BTCPay
MedusaAPI -->|"ACH API"| Paycron
MedusaAPI -->|"Card API (future)"| AuthNet
MedusaAPI -->|"Tax Calculation"| Avalara
MedusaAPI -->|"Rate Quotes"| Carriers
MedusaAPI -->|"SMTP"| ZohoMail
BTCPay -->|"Webhooks"| MedusaAPI
Paycron -->|"Webhooks"| MedusaAPI
BTCPay --> CLN
BTCPay --> Bitcoind
CLN --> Bitcoind
Nginx_BTC --> BTCPay
CLN <-->|"P2P (port 9735)"| LN_Network
Bitcoind <-->|"P2P (port 8333)"| BTC_Network
Customer -->|"HTTPS"| Nginx_BTC
CF_DNS -->|"A record"| Nginx_BTC
BTCPay -.->|"CSV Export"| Koinly
MedusaAPI -.->|"Transaction Data"| ZohoBooks
Mercury -.->|"Bank Feeds"| ZohoBooks
4. DNS Records Plan¶
All DNS records are managed in Cloudflare. The domain research-relay.com is registered through Cloudflare Registrar.
A / CNAME Records¶
| Record | Type | Value | Proxy | Purpose |
|---|---|---|---|---|
research-relay.com |
CNAME | Cloudflare Pages / Vercel target | Yes | Storefront (Next.js) |
www.research-relay.com |
CNAME | research-relay.com |
Yes | WWW redirect to apex |
api.research-relay.com |
A | VPS IP address | Yes | MedusaJS backend API |
admin.research-relay.com |
CNAME | api.research-relay.com |
Yes | MedusaJS admin dashboard |
btcpay.research-relay.com |
A | shops-btc-01 IP address | No | BTCPay Server (direct, not proxied)1 |
docs.research-relay.com |
CNAME | Cloudflare Pages target | Yes | MkDocs internal docs (or internal only) |
MX Records (Zoho Mail)¶
| Priority | Record | Value |
|---|---|---|
| 10 | research-relay.com |
mx.zoho.com |
| 20 | research-relay.com |
mx2.zoho.com |
| 50 | research-relay.com |
mx3.zoho.com |
Email Authentication (SPF, DKIM, DMARC)¶
| Record | Type | Name | Value |
|---|---|---|---|
| SPF | TXT | research-relay.com |
v=spf1 include:zohomail.com -all |
| DKIM | TXT | zmail._domainkey |
(Unique key from Zoho admin console) |
| DMARC | TXT | _dmarc |
v=DMARC1; p=quarantine; rua=mailto:admin@research-relay.com |
SSL / ACME¶
| Record | Type | Name | Value | Purpose |
|---|---|---|---|---|
| ACME | TXT | _acme-challenge.btcpay |
(Auto-managed by Let's Encrypt) | TLS cert for BTCPay Server |
All Cloudflare-proxied domains get automatic TLS via Cloudflare's edge certificates. The BTCPay Server uses Let's Encrypt directly since it is not proxied through Cloudflare.
5. Data Flow: Order Lifecycle¶
The complete lifecycle of an order from browse to accounting reconciliation:
5.1 Browse and Cart¶
1. Customer visits research-relay.com
--> Cloudflare CDN serves Next.js storefront
2. Customer browses product catalog
--> Storefront calls MedusaJS API (GET /store/products)
--> Products include RUO compliance data, COA links, lot info
3. Customer adds items to cart
--> Storefront calls MedusaJS API (POST /store/carts)
--> MedusaJS creates cart with line items in PostgreSQL
5.2 Checkout¶
4. Customer enters shipping information
--> MedusaJS validates US-only address (50 states + DC)
5. Age verification + RUO acknowledgment
--> Customer confirms 18+ age requirement
--> Customer accepts RUO disclaimer (version tracked in compliance module)
--> Compliance checkout module records attestation
6. Tax calculation
--> MedusaJS calls Avalara/TaxJar API
--> Multi-state sales tax calculated based on shipping address
--> Tax amount added to order total
7. Shipping rate calculation
--> MedusaJS calls USPS/UPS/FedEx APIs
--> Real-time calculated rates presented to customer
--> Free standard shipping if order >= $200
--> $15 cold-chain surcharge if applicable
5.3 Payment¶
The customer chooses one of the available payment methods:
BTC / Lightning Path¶
8a. Customer selects "Pay with Bitcoin"
--> MedusaJS calls BTCPay Greenfield API to create invoice
--> BTCPay returns checkout link with BTC address + Lightning invoice
--> Customer sees QR code, amount in BTC, 15-minute countdown
9a. Customer pays from their wallet
--> Lightning: instant settlement, InvoiceSettled webhook fires immediately
--> On-chain: InvoiceProcessing fires (tx in mempool),
InvoiceSettled fires after 1 confirmation (~10 min)
10a. BTCPay sends webhook to MedusaJS
--> POST /hooks/payment/btcpay_btcpay
--> HMAC-SHA256 signature verified
--> Payment status updated: authorized --> captured
ACH Path¶
8b. Customer selects "Pay with Bank Transfer (ACH)"
--> MedusaJS calls Paycron API to initiate eCheck payment
--> Customer verifies bank account (Plaid instant or manual entry)
--> Customer accepts ACH debit mandate
9b. ACH payment enters processing
--> T+0: Payment submitted to ACH network
--> T+2 to T+4: Bank processes debit
--> T+4 to T+6: Funds arrive in Mercury account
10b. Paycron sends webhook to MedusaJS
--> Payment status updated: pending --> captured
--> Order status transitions to confirmed
5.4 Order Confirmation and Fulfillment¶
11. Order confirmed
--> MedusaJS creates order record in PostgreSQL
--> Email notification sent via Zoho Mail (order confirmation)
--> Customer sees order confirmation page
12. Fulfillment
--> Admin reviews order in MedusaJS dashboard
--> Items picked, packed (per fulfillment SOP)
--> Shipping label generated (USPS/UPS/FedEx)
--> Tracking number recorded in MedusaJS
--> Customer receives shipping notification email
13. Delivery
--> Signature required for orders >= $150
--> Tracking status updated via carrier webhooks
--> Customer receives delivery confirmation email
5.5 Accounting¶
14. Transaction recorded
--> USD payments: transaction flows through Mercury, syncs to Zoho Books
--> BTC payments: BTCPay records BTC amount, tx hash, FMV in USD
--> BTC CSV export imported to Koinly monthly for tax tracking
15. Monthly reconciliation
--> Match MedusaJS orders to payment records
--> BTC: reconcile BTCPay invoices with Medusa order IDs
--> ACH: reconcile Paycron settlements with Mercury deposits
--> Zoho Books: P&L, balance sheet, tax summary
--> Koinly: BTC income at FMV, capital gains tracking
6. Security Architecture¶
Network Security¶
- Cloudflare WAF -- Web Application Firewall on all proxied domains, blocks common attack patterns
- Cloudflare DDoS protection -- Automatic L3/L4/L7 DDoS mitigation
- HTTPS everywhere -- All public endpoints use TLS (Cloudflare edge certs for proxied domains, Let's Encrypt for BTCPay)
- BTCPay direct connection -- Not proxied through Cloudflare to preserve WebSocket and Lightning compatibility
Bitcoin Security¶
- Self-hosted BTCPay Server -- No third-party custody of Bitcoin; keys never leave the server or hardware wallet
- Hardware wallet for cold storage -- Coldcard or Trezor; seed phrase stamped on metal, stored physically
- xpub-only on-chain receiving -- BTCPay generates receiving addresses from xpub; spending requires hardware wallet signature
- Lightning hot wallet -- CLN manages channel keys on server; funded proportional to expected weekly volume (~500K sats)
- Sweep policy -- On-chain balance swept to cold storage at 0.01 BTC threshold via PSBT signed on hardware wallet
- Tor-enabled -- nix-bitcoin runs Bitcoin and Lightning P2P over Tor by default
- Encrypted backups -- Daily automated backup of BTCPay PostgreSQL and CLN database, encrypted with GPG
Credential Security¶
- 1Password -- All business credentials stored in 1Password vault (existing subscription)
- TOTP 2FA -- 1Password serves as TOTP authenticator for all services that support it
- Zoho 2FA -- MFA enabled on Zoho Workplace for email access
- Mercury 2FA -- Personal carrier phone number used for bank 2FA (not VoIP, per bank requirements)
- API keys -- BTCPay API key, webhook secrets, and payment provider credentials stored in server environment variables and 1Password
Privacy and Compliance¶
- No unnecessary PII storage -- MedusaJS stores only data required for order fulfillment
- CCPA compliance -- Privacy request handling via privacy@research-relay.com and web form
- DNT signals honored -- Non-essential tracking disabled when Do Not Track is detected
- Identity separation -- Business operations use business email/phone; personal details limited to bank KYC and state filings
- Northwest RA address -- Used for all public-facing disclosures; home address only in bank KYC files
7. Environments¶
Development¶
- Local machine using devenv/nix for reproducible environment
- MedusaJS dev server with hot reload
- Local PostgreSQL database
- BTCPay Server on Bitcoin testnet/signet (or mock for unit tests)
- See:
dev/medusa-dev-setup.md
Staging¶
- TBD -- Options under evaluation:
- Railway preview environments (automatic per PR)
- Separate VPS with staging database
- Docker Compose on development machine
- BTCPay on Bitcoin testnet for payment flow testing
Production¶
| Service | Host | Notes |
|---|---|---|
| MedusaJS + PostgreSQL | VPS (provider TBD) | Estimated $20-40/mo |
| Next.js Storefront | Cloudflare Pages (free tier) | Static generation + edge functions |
| BTCPay + CLN + bitcoind | shops-btc-01 (existing NixOS server) | Already provisioned |
| MkDocs | Cloudflare Pages (free tier) | Deployed from this repo |
| DNS | Cloudflare | Domain registered at Cloudflare Registrar |
8. Monthly Cost Summary¶
Estimated recurring infrastructure costs once all systems are operational:
Core Infrastructure¶
| Service | Provider | Monthly Cost | Notes |
|---|---|---|---|
| VPS (Medusa + PostgreSQL) | TBD | $20--40 | 4 CPU, 8 GB RAM, NVMe recommended |
| Cloudflare Pages | Cloudflare | $0 | Free tier for storefront + docs |
| Domain | Cloudflare Registrar | ~$1 | ~$12/year for .com |
| BTCPay Server | Self-hosted (shops-btc-01) | $0 | Server already provisioned |
SaaS Services¶
| Service | Provider | Monthly Cost | Notes |
|---|---|---|---|
| Business Email | Zoho Workplace | $3 | Workplace Standard plan |
| Business Phone | OpenPhone | $15 | Starter plan |
| Password Manager | 1Password | $0 | Existing subscription |
| Accounting | Zoho Books | $0--20 | Free plan initially, Standard at $15-20/mo |
| Crypto Accounting | Koinly | ~$4 | $49/year |
| Sales Tax | Avalara or TaxJar | $50--300 | Depends on transaction volume and states |
| Banking | Mercury | $0 | Free business checking |
Payment Processing (Per-Transaction)¶
| Method | Provider | Fee Structure |
|---|---|---|
| BTC / Lightning | BTCPay (self-hosted) | ~$0 receiving; ~$4-12/mo liquidity management |
| ACH / eCheck | Paycron | Custom pricing (est. 1-3% per transaction) |
| Card (future) | Easy Pay Direct / Durango | Custom pricing (est. 4-8% + reserves) |
Monthly Total Estimate¶
| Category | Low | High |
|---|---|---|
| Infrastructure | $21 | $41 |
| SaaS Services | $73 | $343 |
| Total (excl. per-txn fees) | $94 | $384 |
The wide range for SaaS is driven primarily by sales tax service costs ($50-300/mo). All other services are relatively fixed. Payment processing fees are transaction-dependent and not included in the monthly total.
-
BTCPay Server requires direct connections for WebSocket support and Lightning Network compatibility. Use Let's Encrypt via ACME on the server itself rather than Cloudflare proxy. ↩