# DGB backend — local or VPS ## Production layout (digibyte.x, as deployed) What actually runs today on the coinspectrum VPS, and the only thing the web wallet needs: | Piece | Where | Notes | |---|---|---| | vhost (Angie) | `/etc/angie/http.d/digibyte-x.conf` — served by **Angie** since 2026-09-16 (`systemctl reload angie`; `nginx.service` is inactive and `/etc/nginx/sites-enabled/digibyte-x` is a stale copy) — mirrored in [`nginx-digibyte-x.conf`](nginx-digibyte-x.conf) | SNI-selected on `digibyte.x`, self-signed cert pinned on-chain via the BNS `tls` record. Serves `/web/` (wallet), proxies `/p2p/*` → daemon and `/blockbook/*` → a public DGB Blockbook (Atomic Wallet's since 2026-10-11; NOWNodes before that, API key injected server-side from `/etc/dgb-core/nownodes.env` — switch with [`blockbook-upstream.sh`](blockbook-upstream.sh)), strict Content-Security-Policy on `/web/`. | | `dgb-daemon.service` | `/opt/dgb-wallet`, runs `packages/p2p/bin/dgb-daemon.ts` via tsx, binds `127.0.0.1:5174` | The wallet's only server-side component: header sync with reorg handling, BIP157/158 filter cache (packed 1000/file under `/var/lib/dgb-wallet/.dgb-wallet/p2p/packs/`), incremental balance scans remembered in `scans.json`, Dandelion++ broadcast with relay-echo verification. | | **No DigiByte Core, no Fulcrum** | — | Removed 2026-09-06. A full node with indexes needs ≥40 GB disk and ≥4 GB RAM; the VPS has neither, and the daemon does not use it. | Routine deploy from the dev box: **[`push.sh`](push.sh)** — `ops/push.sh` (web + daemon), `ops/push.sh web`, `ops/push.sh daemon`. It builds, ships, swaps atomically, restarts the daemon, verifies the served bundle hash and warns if the CSP hash for the inline script drifted. --- Deployment shapes documented below (the first two describe an optional DigiByte Core backend for `@dgb-wallet/rpc`; **not used by the web wallet**): - **[Local install on Windows](#local-install-windows-desktop)** — fastest to get running; DGB Core lives on your desktop under `D:\Program Files\DigiByte\`, RPC on `http://127.0.0.1:14022`. Best for development. - **[Turnkey RPC VPS install](#turnkey-vps-install)** — pruned DGB Core behind Caddy for the `@dgb-wallet/rpc` client, TLS-pinned via BCH BNS. Best when the wallet needs its own backend. - **[Wallet-site VPS install](#wallet-site-vps-install)** — hosts the built web wallet at a `.x`/`.dgb` name AND reverse-proxies `/p2p/` to the daemon, so visitors get Balance/Send without a local daemon. See `deploy-wallet.sh` + `Caddyfile.wallet` + `dgb-daemon.service`. - **[Wallet-subpath install](#wallet-subpath-install)** — same idea as above but mounts the wallet at `/web/` on an existing site (e.g. `digibyte.x/web`), leaving the site's `/` alone. See `deploy-wallet-web.sh` + `Caddyfile.wallet-web-snippet` + `dgb-daemon.service`. Both use the same `@dgb-wallet/rpc` client. Only the transport differs. --- ## Local install (Windows desktop) Requires: Windows 10/11, ~60 GB free disk (for pruned; grows slowly), 2+ GB RAM available for the Core process, an elevated PowerShell for the one-time Defender exclusion step. ```powershell cd "D:\Dev\SilentCode\Digibyte\ops" Set-ExecutionPolicy -Scope Process Bypass .\setup-local.ps1 ``` The script: 1. Downloads DGB Core `v8.26.2` for Windows, verifies SHA-256 against the release's `SHA256SUMS` 2. Installs binaries to `D:\Program Files\DigiByte\bin\` 3. Creates `D:\Program Files\DigiByte\data\` (chain data) and writes `digibyte.conf` with pruned settings, `disablewallet=1`, random 40-char RPC password 4. Adds `data\` to Windows Defender exclusions (real 3x sync speedup) 5. Creates a Startup shortcut so Core auto-starts at logon 6. Launches Core immediately for the initial sync At the end, prints: ``` RPC endpoint: http://127.0.0.1:14022 Username: dgb_xxxxxxxx Password: <40-char base64> ``` Paste those into your wallet's env for the RPC demo: ```powershell $env:DGB_RPC_URL='http://127.0.0.1:14022' $env:DGB_RPC_USER='dgb_xxxxxxxx' $env:DGB_RPC_PASSWORD='' npm run demo -w @dgb-wallet/rpc ``` Initial pruned sync takes ~4–8 hours on a 16 GB / SSD desktop. Monitor with: ```powershell & "D:\Program Files\DigiByte\bin\digibyte-cli.exe" -conf="D:\Program Files\DigiByte\digibyte.conf" getblockchaininfo | Select-Object -First 20 ``` **Uninstall:** kill `digibyted.exe`, delete `D:\Program Files\DigiByte`, remove the Startup shortcut from `shell:startup`, and (optionally) remove the Defender exclusion via Windows Security settings. **Flags:** - `-InstallDir "E:\dgb"` — install somewhere else - `-Version "8.26.2"` — pin a different Core release - `-SkipDefenderExclusion` — don't touch Defender (script will run without admin) - `-SkipStartup` — don't create the auto-start shortcut --- ## Turnkey VPS install Runs a pruned DigiByte Core node with wallet functionality disabled, behind Caddy for HTTPS + rate limiting. Total footprint: ~600 MB disk, 1 GB RAM, one CPU core. Fits comfortably on a €4/month VPS. ## What you get - **Chain state:** current UTXO set (~500 MB), always in sync - **Chain-state RPC methods available over HTTPS + basic auth:** - `scantxoutset` — the workhorse; scan UTXO set for descriptors/xpubs - `sendrawtransaction` — broadcast signed transactions - `estimatesmartfee` — fee estimation - `getblockchaininfo`, `getnetworkinfo`, `getrawmempool` - **Wallet functionality disabled** (`disablewallet=1`) — the node holds no keys, so RPC compromise leaks chain metadata at worst, never funds ## Fresh-VPS quickstart (Debian 12 / Ubuntu 24.04) Provision a VPS with public IPv4/IPv6. SSH in as root (or a sudo user). Then: ```bash # Fetch and run the setup script wget https://raw.githubusercontent.com//main/ops/setup.sh chmod +x setup.sh sudo ./setup.sh your-domain.example.com ``` The script: 1. Creates unprivileged `digibyte` user 2. Downloads DGB Core `v8.26.2`, verifies SHA-256 against the release's `SHA256SUMS` 3. Writes `digibyte.conf` (pruned, wallet disabled, RPC bound to localhost, random 40-char password) 4. Installs the systemd unit and starts `digibyted` 5. Installs Caddy, configures it for your domain with automatic Let's Encrypt TLS 6. Opens firewall ports 22 (SSH), 443 (HTTPS), 12024 (DGB P2P) 7. Prints the generated RPC credentials for you to paste into your wallet Expected total time: ~20 min including the initial pruned sync. ## Manual step-by-step If you'd rather understand each piece, see [MANUAL.md](MANUAL.md) — same steps as `setup.sh`, done by hand. ## Files in this directory | File | Purpose | |---|---| | `push.sh` | **Routine deploy from the dev box** — build, ship web bundle and/or daemon sources, restart, verify (see Production layout) | | `nginx-digibyte-x.conf` | Mirror of the live nginx vhost for digibyte.x (`@NOWNODES_API_KEY@` placeholder; render with `sed` as the file header shows) | | `blockbook-upstream.sh` / `.ps1` | `atomic` or `nownodes` — repoint the live `/blockbook/` proxy, test, reload, verify (`.ps1` from PowerShell, where `bash` is the WSL launcher; both pipe `blockbook-upstream.remote.sh` over ssh) | | `setup.sh` | RPC-VPS bootstrap (Core + Caddy in front of it) — optional Core backend, not deployed | | `deploy-wallet.sh` | Wallet-site VPS bootstrap (web bundle at `/` + P2P daemon reverse-proxy) | | `deploy-wallet-web.sh` | Wallet-subpath bootstrap — plain production build (relative `./` base), ships bundle to `/web/`, renders Caddy import snippet | | `digibyte.conf` | Sample Core config; script substitutes the domain and password | | `digibyte.service` | systemd unit for `digibyted` | | `dgb-daemon.service` | systemd unit for `@dgb-wallet/p2p`'s HTTP daemon | | `Caddyfile` | Caddy reverse-proxy config for the RPC-VPS shape (Core over HTTPS + basic auth) | | `Caddyfile.bns` | Same as `Caddyfile` but with a pinned self-signed cert (no ACME) | | `Caddyfile.wallet` | Serves `dist/` at `/` and proxies `/p2p/*` to `dgb-daemon` | | `Caddyfile.wallet-web-snippet` | Imported into an existing site's Caddyfile — adds `/web/*` (static) and `/p2p/*` (reverse-proxy) handlers | --- ## Wallet-site VPS install Hosts the built `@dgb-wallet/web-ui` bundle under a `.x`/`.dgb` BNS name, plus reverse-proxies `/p2p/*` to a local `dgb-daemon` so Balance and Send work without visitors running a daemon locally. Prereqs on the VPS: Debian 12 / Ubuntu 24.04, ≥2 GB RAM (8 GB heap ceiling for the daemon), public IPv4, ports 22/443 reachable, 12024 outbound for DGB P2P. ```bash # On your dev box — push the checkout to the VPS: scp -r D:\Dev\SilentCode\Digibyte user@vps:/opt/dgb-wallet # On the VPS: sudo /opt/dgb-wallet/ops/deploy-wallet.sh digibyte.x ``` The script installs Caddy + Node 20, `npm install`s the monorepo, builds the web bundle to `/var/www/dgb-wallet/`, generates a self-signed cert with CN=`digibyte.x`, wires the daemon into systemd, and prints the exact BCH BNS UPD payload: ```bash # On your BCH-wallet host (has D:\Dev\NameCoin): cd D:\Dev\NameCoin node src/update.js digibyte.x '{ "ip": "", "tls": "", "u": "https://digibyte.x" }' ``` After 1–2 BCH confirmations, `resolveEndpoint('digibyte.x')` returns the pinned pair and any wallet-aware client validates the TLS handshake against the fingerprint. Balance/Send tabs in the deployed bundle POST to `/p2p/balance` and `/p2p/broadcast`, transparently proxied to the daemon. --- ## Wallet-subpath install Use this when the target host already serves other content at `/` and the wallet lives at `/web/` — e.g. the current `digibyte.x/web` layout, where the apex hosts existing pages and only the wallet section is added. Difference from the previous section: `deploy-wallet.sh` overwrites `/etc/caddy/Caddyfile` and manages its own TLS cert. `deploy-wallet-web.sh` does neither — it renders an import snippet, optionally wires it into an existing Caddyfile between sentinel markers, and inherits whatever TLS the host already has configured. ```bash # On your dev box: scp -r D:\Dev\SilentCode\Digibyte user@vps:/opt/dgb-wallet # On the VPS — automatic wiring: sudo /opt/dgb-wallet/ops/deploy-wallet-web.sh --merge /etc/caddy/Caddyfile # …or, manual wiring — script prints the exact three lines to paste # inside your existing :443 { } block: sudo /opt/dgb-wallet/ops/deploy-wallet-web.sh ``` The script: 1. Installs Caddy + Node 20 if missing. 2. `npm install`s the monorepo and runs a plain `npm run build -w @dgb-wallet/web-ui`. Production builds use a relative `./` asset base; `index.html` carries an inline script that re-anchors a `` at `…/web/` at runtime, so one bundle serves both `https://digibyte.x/web/` and the `navigate.st/bns/digibyte.x/web/` gateway. The script refuses to run if `DGB_UI_BASE` is set, and aborts if `dist/index.html` lacks `./assets/…` references or the runtime `` script. 3. Rsyncs `packages/web-ui/dist/` → `/web/` (default `/var/www/dgb-wallet/web/`). 4. Creates the `dgb-wallet` system user and installs `dgb-daemon.service` (systemd) bound to `127.0.0.1:5174`. 5. Renders `Caddyfile.wallet-web-snippet` with `@SITE_ROOT@` substituted to `/etc/caddy/snippets/dgb-wallet.caddyfile`. 6. With `--merge `: idempotently inserts (or replaces between `# --- START DGB WALLET IMPORT ---` / `# --- END DGB WALLET IMPORT ---`) an `import` line inside the last `:443 { }` block in the target Caddyfile, then `caddy validate` and reload. Without `--merge`: prints the three-line insert for the operator to paste by hand. 7. Prints the final wallet URLs (`/web/`, `/p2p/health`, `/p2p/balance`, `/p2p/broadcast`) and the redeploy one-liner. Flags: - `--merge ` — Caddyfile to inject the import line into. - `--site-root ` — override the `/var/www/dgb-wallet` default. The bundle always lands under `/web/`. Rollback: remove the three sentinel lines from the host Caddyfile and `systemctl reload caddy`. `systemctl disable --now dgb-daemon` stops the P2P daemon. `/web/` can be `rm -rf`'d without touching anything else the site serves. ## Wallet-side Point `@dgb-wallet/rpc` at `https://your-domain.example.com` with the credentials `setup.sh` printed. See [../packages/rpc/README.md](../packages/rpc/README.md) for the demo. ## Security notes Web wallet (nginx + daemon): - **Strict CSP on `/web/`.** `script-src 'self'` plus the sha256 of the one inline script (the runtime `` fix). Recompute with `node packages/web-ui/scripts/csp-hash.mjs` after editing `packages/web-ui/index.html`; `push.sh` warns on drift. Built asset tags carry `integrity=` (SRI) so a tampered asset file fails to load. - **No keys on the server.** The daemon only ever sees xpubs / scripts to scan and signed transaction bytes to broadcast. - **Blockbook is opt-in** and proxied so the upstream sees the VPS's IP, not the user's; the API key never reaches the browser. Optional Core backend (`setup.sh` shape): - **Wallet is disabled on the node.** Even a full RPC compromise cannot spend funds — there are no keys on the server. - **RPC is not exposed on port 14022.** Core binds RPC to `127.0.0.1` only. All external access goes through Caddy on 443 with TLS + basic auth. - **Rate limiting.** Caddy config limits any single IP to 60 requests/minute per endpoint (`scantxoutset` is cheap on a pruned node but not free). - **Keep the RPC password strong.** The setup script generates a 40-char random one; don't shorten it. If you lose it, regenerate on the VPS and rewrite `digibyte.conf`. - **No wallet method whitelist yet.** With `disablewallet=1` there's nothing sensitive to whitelist against; future hardening could restrict to only the six methods listed above. Low priority given the disabled-wallet posture. ## What's next Once this is running, `@dgb-wallet/rpc` connects to it in seconds. Recovery flow becomes: ``` seed → derive addresses (offline) → scantxoutset via VPS → real balances → sign PSBT (offline) → broadcast via VPS ``` Whole loop, real chain data, no local Core install, no third-party service. Full self-sovereignty as soon as the VPS is yours.