Silent Mode Hephaestus — the docker-compose + Caddyfile + auth-proxy that runs code.silentmode.st and hephaestus.x. BCH wallet auth via OIDC, Sia cold storage, restic backups. Open source.
Find a file
Local Dev 04bf46b174 feat(hephaestus.x): landing 'Sign in' becomes a Bitcoin Cash wallet dropdown
- site/hephaestus.x/index.html: replace single 'Sign in with wallet' CTA with
  a <details> dropdown labelled 'Bitcoin Cash wallet'. Menu items:
    Sign in       -> /user/oauth2/hephaestus-wallet#import
    Sign up       -> /user/oauth2/hephaestus-wallet#create   (pill: easiest)
    WizardConnect -> /user/oauth2/hephaestus-wallet#connect  (pill: most private)
  Same emoji + copy scheme as the wallet accordion, so the landing previews
  the choices the user will see after clicking through.

- Hephaestus/auth-proxy/public/wallet.js: renderTabs() now reads location.hash
  and auto-opens the matching <details> option on load (create/import/connect).
  Fragments survive Forgejo's OAuth redirect chain, so a click on 'Sign up'
  from the landing lands the user directly on the Create accordion.
2026-09-02 22:13:55 +02:00
auth-proxy feat(hephaestus.x): landing 'Sign in' becomes a Bitcoin Cash wallet dropdown 2026-09-02 22:13:55 +02:00
caddy feat(hephaestus): BCH wallet as default login (3-option picker + Caddy redirect) 2026-08-31 17:50:49 +02:00
forgejo feat(gateway,hephaestus): forward proxied headers + trust Silent Mode CA 2026-08-31 16:23:43 +02:00
scripts feat(hephaestus): make hephaestus.x served from VPS with Sia as DR backup 2026-08-31 15:52:41 +02:00
.env.example chore(hephaestus): track .env.example template 2026-08-31 02:53:55 +02:00
docker-compose.yml feat(gateway,hephaestus): forward proxied headers + trust Silent Mode CA 2026-08-31 16:23:43 +02:00
PROTOCOL.md Snapshot in-progress work: Ariadne mobile, Theseus password manager, Hephaestus 2026-08-14 23:17:18 +02:00
README.md Snapshot in-progress work: Ariadne mobile, Theseus password manager, Hephaestus 2026-08-14 23:17:18 +02:00

Hephaestus

Decentralized code forge. Forgejo web UI on a VPS, Sia network for durable storage, Bitcoin Cash wallet signatures for identity — no email required.

Architecture

User browser
    │
    ├── OIDC login via wallet signature ──▶ auth-proxy ──▶ (issues id_token)
    │                                                            │
    └── Forgejo web UI  ◀─── OIDC handshake ────────────────────┘
                │
                ├── live git repos, Postgres   ──▶  local SSD on VPS (hot path)
                └── LFS, attachments, packages,
                    archive downloads, backups  ──▶  sia.storage S3 (cold path)
  • Identity: users generate or import a BCH wallet client-side. Their cashaddr is their username. Login = signing a challenge.
  • Hot storage: live .git bare repos + Postgres live on the VPS's local disk. Git operations stay fast.
  • Cold storage: every large or immutable blob (LFS, attachments, release artifacts, package registries) lives on sia.storage via its S3-compatible endpoint. Forgejo speaks S3 natively.
  • Backups: nightly restic snapshot of repos + pg_dump to a second bucket. Dual-write to independent storage for the belt-and-suspenders story since sia.storage caps liability at ~$100.

Why sia.storage instead of self-hosted renterd for MVP

  • Their free tier gives 50 GB pooled + 4 Gbps throughput with no monthly egress meter
  • Standard S3 API — zero code changes to Forgejo
  • No Sia wallet management, no SC volatility, no contract-formation ops
  • Swap to self-hosted renterd later without touching Forgejo config (both speak S3)

Quota math

The 50 GB sia.storage free tier is one pooled resource we allocate to Forgejo users via Forgejo's built-in per-user quotas.

Our tier Per-user quota Users on Free (50 GB) Users on Plus (500 GB) Users on Pro (5 TB)
Free 500 MB ~100 ~1,000 ~10,000
Pro 10 GB ~5 ~50 ~500
Team 50 GB ~1 ~10 ~100

Quickstart

cp .env.example .env
# fill in SIA_STORAGE_ACCESS_KEY, SIA_STORAGE_SECRET_KEY, SIA_STORAGE_BUCKET
docker compose up -d
open http://localhost:3000

First launch:

  1. Forgejo initialises Postgres and its schema
  2. Auth-proxy generates its OIDC signing keypair
  3. On first browser visit, the login page offers "Generate new BCH wallet" or "Import wallet"
  4. After signing the challenge you're logged into Forgejo — your cashaddr is your username

Directory layout

Hephaestus/
├── docker-compose.yml         # forgejo + postgres + auth-proxy
├── .env.example
├── forgejo/
│   └── app.ini.template       # config with sia.storage S3 + OIDC + quotas
├── auth-proxy/
│   ├── Dockerfile
│   ├── package.json
│   └── src/                   # Fastify OIDC provider
│       ├── index.ts
│       ├── oidc.ts
│       ├── verify.ts          # BCH signed-message verification
│       └── sessions.ts
├── auth-proxy/public/
│   ├── login.html             # Wallet UI
│   └── wallet.js              # Client-side keygen + signing (libauth)
├── scripts/
│   ├── smoke-test-s3.sh       # Verify sia.storage handles multipart LFS
│   └── backup-restic.sh       # Nightly backup
└── PROTOCOL.md                # Wallet-auth flow spec

Status

  • MVP scaffolding: complete
  • Wallet auth: functional (challenge + signature verify, no persistence beyond cashaddr)
  • sia.storage backend: config template ready; must run scripts/smoke-test-s3.sh before trusting LFS
  • Restic backup: template ready, needs cron wiring
  • WalletConnect: deferred to Phase 2
  • BCNR-name registration for code.silentmode.st: separate task in Ariadne stack

Known unknowns

  1. sia.storage S3 multipart maturity. Their roadmap targets full S3 compatibility Q3 2026 — partial today. Smoke test verifies this before we depend on it for LFS.
  2. Account-recovery UX for wallet loss. No email = no password reset. Users must back up their mnemonic. Docs will hammer this. Phase 2: social recovery via BCH multisig.
  3. Content moderation workflow. sia.storage ToS bans certain content classes; we need our own AUP + takedown flow before public launch.