A production-grade federated website hosting service where users deploy static sites and independent nodes form a cryptographically verified network. No single company controls the infrastructure — anyone can run a node.
Federated Hosting lets users:
- Log in via OIDC Auth (OpenID Connect)
- Upload website files (HTML, CSS, JS, images, fonts) to object storage
- Deploy their site — gets a unique domain, version-tracked, atomically committed
- Replicate — the deploy is automatically mirrored to all active federation peers via signed
site_syncevents - Serve — any node in the network can serve any site, routed by host header
Independent operators run nodes. Each node has an Ed25519 cryptographic identity, participates in the federation protocol, and can host and replicate sites for the network.
→ Full operator guide: docs/SELF_HOSTING.md
The short version:
git clone https://github.com/The-No-Hands-company/Federated-Hosting.git
cd Federated-Hosting
cp .env.example .env
# Edit .env — the required vars are: ISSUER_URL, OIDC_CLIENT_ID, COOKIE_SECRET,
# DATABASE_URL, PUBLIC_DOMAIN, and your S3 credentials
docker compose up -dRequired configuration before the server will start:
| Variable | How to get it |
|---|---|
ISSUER_URL + OIDC_CLIENT_ID |
Set up Authentik, Keycloak, or Auth0. See SELF_HOSTING.md → Auth |
COOKIE_SECRET |
openssl rand -hex 32 |
DATABASE_URL |
PostgreSQL connection string |
PUBLIC_DOMAIN |
Your node's public hostname |
OBJECT_STORAGE_ENDPOINT + credentials |
AWS S3, Cloudflare R2, MinIO, or Backblaze B2 |
See docs/DEPLOYMENT.md for the complete environment variable reference, and docs/PRODUCTION_CHECKLIST.md before going live.
- Node.js 24+
- pnpm 10+
- PostgreSQL database
- S3-compatible object storage (MinIO via Docker Compose works)
git clone https://github.com/The-No-Hands-company/Federated-Hosting.git
cd Federated-Hosting
pnpm installDATABASE_URL=postgresql://user:password@localhost:5432/fedhost
ISSUER_URL=https://your-oidc-provider/
OIDC_CLIENT_ID=your-client-id
COOKIE_SECRET=dev-only-change-in-production
PUBLIC_DOMAIN=localhost:8080
OBJECT_STORAGE_ENDPOINT=http://localhost:9000
OBJECT_STORAGE_ACCESS_KEY=minioadmin
OBJECT_STORAGE_SECRET_KEY=minioadmin
DEFAULT_OBJECT_STORAGE_BUCKET_ID=fedhost-sites
NODE_ENV=developmentpnpm --filter @workspace/db run migratepnpm run dev # starts API on :8080 and frontend on :25231pnpm run build- OIDC Auth (OpenID Connect + PKCE) — users own their sites
- Presigned URL upload flow to object storage
- Host-header site serving —
your-domain.comroutes to the right files - My Sites dashboard + drag-and-drop deploy UI
- Ed25519 key pairs — each node has a cryptographic identity
/.well-known/federationdiscovery endpoint- Signed handshakes — nodes verify each other's identity before peering
- Federation event log — persistent record of all handshakes, pings, syncs
- Deploy → automatic replication to all active peers
- Host-header routing middleware — serves any registered site domain
- Per-node capacity API — storage stats, site counts, bandwidth
- Auto-initialises local node with Ed25519 keys on startup
- Network-wide capacity overview
- Helmet (CSP, HSTS, X-Frame-Options, X-Content-Type-Options)
- Rate limiting — 200 req/min global; 20 req/min on auth/upload
- Gzip compression
- Structured pino logging with request IDs (X-Request-ID)
AppErrorclass +asyncHandler— clean error propagation- Global error handler — structured JSON errors, no stack traces in prod
- DB transactions on deploy — atomic, never partial
- Database indexes on all hot query paths
- Graceful shutdown — drains connections on SIGTERM/SIGINT
- React
ErrorBoundary— friendly fallback UI on crashes - Auto-retry with exponential backoff; no retries on 4xx
See docs/API.md for the full REST API reference.
Base URL: https://your-node/api
| Method | Path | Description |
|---|---|---|
| GET | /health |
Full health check |
| GET | /health/live |
Liveness probe |
| GET | /health/ready |
Readiness probe |
| GET | /auth/user |
Current user |
| GET | /nodes |
List nodes (paginated) |
| POST | /nodes |
Register node |
| GET | /sites |
List sites (paginated) |
| POST | /sites |
Create site |
| POST | /sites/:id/files/upload-url |
Get presigned upload URL |
| POST | /sites/:id/files |
Register uploaded file |
| POST | /sites/:id/deploy |
Deploy site |
| GET | /sites/:id/deployments |
Deployment history |
| GET | /federation/meta |
Node metadata |
| POST | /federation/handshake |
Initiate handshake |
| POST | /federation/ping |
Signed ping |
| GET | /federation/peers |
Federation peers (paginated) |
| GET | /federation/events |
Event log (paginated) |
| GET | /capacity/summary |
Network capacity |
See docs/ARCHITECTURE.md for full system design.
Browser → Federated Hosting UI (Vite/React)
↓
API Server (Express 5, TypeScript)
↓
┌───────┴───────┐
PostgreSQL Object Storage
(Drizzle) (presigned URLs)
↓
Federation Peers (other nodes, Ed25519 verified)
.
├── artifacts/
│ ├── api-server/ # Express 5 API server
│ │ └── src/
│ │ ├── app.ts # Middleware stack
│ │ ├── index.ts # Startup + graceful shutdown
│ │ ├── lib/ # federation, objectStorage, errors, logger, pagination
│ │ ├── middleware/ # authMiddleware, hostRouter, errorHandler, rateLimiter
│ │ └── routes/ # auth, deploy, federation, nodes, sites, capacity, health
│ └── federated-hosting/ # React + Vite frontend
│ └── src/
│ ├── pages/ # Dashboard, MySites, DeploySite, Federation, Nodes, Sites
│ └── components/ # Layout, ErrorBoundary, UI components
├── lib/
│ ├── api-spec/ # OpenAPI 3.1 specification
│ ├── api-client-react/ # Generated React Query hooks (Orval)
│ ├── api-zod/ # Generated Zod schemas (Orval)
│ ├── db/ # Drizzle ORM schema + migrations
│ │ └── src/schema/ # nodes, sites, deployments, federation, auth
│ └── integrations/ # auth-web, object-storage
├── scripts/ # Seed + utility scripts
├── docs/ # Architecture, API, Contributing, Security
├── LICENSE
└── README.md
Two production-ready websites are included in the sites/ directory. They can be deployed into your node automatically:
# Start the API server first (creates the local node), then:
pnpm --filter @workspace/scripts run seed:sites| Site | Domain | Description |
|---|---|---|
| Federated Hosting | fedhosting.app |
Landing page explaining what Federated Hosting is, for everyday users — not developers. Includes animated network visualisation, live node/site stats, and a guided "how it works" section. |
| The No Hands Company | nohands.company |
Company portfolio — all No Hands Company projects, values, and contact information. |
Both sites are plain HTML/CSS/JS — no build step required. They are stored in sites/fedhosting-landing/ and sites/nohands-company/.
See CONTRIBUTING.md for how to get started, code style, and the PR process.
See SECURITY.md for the vulnerability disclosure policy and security model.
MIT — Copyright (c) 2025 The No Hands Company