Monorepo for wisp.place. A static site hosting service built on top of the AT Protocol. wisp.place
1# Wisp Hosting Service 2 3Minimal microservice for hosting static sites from the AT Protocol. Built with Hono and Bun. 4 5## Features 6 7- **Custom Domain Hosting**: Serve verified custom domains 8- **Wisp.place Subdomains**: Serve registered `*.wisp.place` subdomains 9- **DNS Hash Routing**: Support DNS verification via `hash.dns.wisp.place` 10- **Direct File Serving**: Access sites via `sites.wisp.place/:identifier/:site/*` (no DB lookup) 11- **Firehose Worker**: Listens to AT Protocol firehose for new `place.wisp.fs` records 12- **Automatic Caching**: Downloads and caches sites locally on first access or firehose event 13- **SSRF Protection**: Hardened fetch with timeout, size limits, and private IP blocking 14 15## Routes 16 171. **Custom Domains** (`/*`) 18 - Serves verified custom domains (example.com) 19 - DB lookup: `custom_domains` table 20 212. **Wisp Subdomains** (`/*.wisp.place/*`) 22 - Serves registered subdomains (alice.wisp.place) 23 - DB lookup: `domains` table 24 253. **DNS Hash Routing** (`/hash.dns.wisp.place/*`) 26 - DNS verification routing for custom domains 27 - DB lookup: `custom_domains` by hash 28 294. **Direct Serving** (`/sites.wisp.place/:identifier/:site/*`) 30 - Direct access without DB lookup 31 - `:identifier` can be DID or handle 32 - Fetches from PDS if not cached 33 - **Automatic HTML path rewriting**: Absolute paths (`/style.css`) are rewritten to relative paths (`sites.wisp.place/:identifier/:site/style.css`) 34 35## Setup 36 37```bash 38# Install dependencies 39bun install 40 41# Copy environment file 42cp .env.example .env 43 44# Run in development 45bun run dev 46 47# Run in production 48bun run start 49``` 50 51## Environment Variables 52 53- `DATABASE_URL` - PostgreSQL connection string 54- `PORT` - HTTP server port (default: 3001) 55- `BASE_HOST` - Base domain (default: wisp.place) 56 57## Architecture 58 59- **Hono**: Minimal web framework 60- **Postgres**: Database for domain/site lookups 61- **AT Protocol**: Decentralized storage 62- **Jetstream**: Firehose consumer for real-time updates 63- **Bun**: Runtime and file serving 64 65## Cache Structure 66 67``` 68cache/sites/ 69 did:plc:abc123/ 70 sitename/ 71 index.html 72 style.css 73 assets/ 74 logo.png 75``` 76 77## Health Check 78 79```bash 80curl http://localhost:3001/health 81``` 82 83Returns firehose connection status and last event time. 84 85## HTML Path Rewriting 86 87When serving sites via the `/s/:identifier/:site/*` route, HTML files are automatically processed to rewrite absolute paths to work correctly in the subdirectory context. 88 89**What gets rewritten:** 90- `src` attributes (images, scripts, iframes) 91- `href` attributes (links, stylesheets) 92- `action` attributes (forms) 93- `poster`, `data` attributes (media) 94- `srcset` attributes (responsive images) 95 96**What's preserved:** 97- External URLs (`https://example.com/style.css`) 98- Protocol-relative URLs (`//cdn.example.com/script.js`) 99- Data URIs (`data:image/png;base64,...`) 100- Anchors (`/#section`) 101- Already relative paths (`./style.css`, `../images/logo.png`) 102 103**Example:** 104```html 105<!-- Original HTML --> 106<link rel="stylesheet" href="/style.css"> 107<img src="/images/logo.png"> 108 109<!-- Served at /s/did:plc:abc123/mysite/ becomes --> 110<link rel="stylesheet" href="sites.wisp.place/did:plc:abc123/mysite/style.css"> 111<img src="sites.wisp.place/did:plc:abc123/mysite/images/logo.png"> 112``` 113 114This ensures sites work correctly when served from subdirectories without requiring manual path adjustments. 115 116## Security 117 118### SSRF Protection 119 120All external HTTP requests are protected against Server-Side Request Forgery (SSRF) attacks: 121 122- **5-second timeout** on all requests 123- **Size limits**: 1MB for JSON, 10MB default, 100MB for file blobs 124- **Blocked private IP ranges**: 125 - Loopback (127.0.0.0/8, ::1) 126 - Private networks (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) 127 - Link-local (169.254.0.0/16, fe80::/10) 128 - Cloud metadata endpoints (169.254.169.254) 129- **Protocol validation**: Only HTTP/HTTPS allowed 130- **Streaming with size enforcement**: Prevents memory exhaustion from large responses