A minimal, self-hosted NIP-46 remote signing server for Nostr.
One dependency. One binary. One SQLite file.
You want to use your Nostr identity across multiple devices (phone, laptop, tablet) without copying your nsec everywhere. MicroBunker holds your key securely on a server and signs events on behalf of connected clients using the NIP-46 protocol.
- NIP-46 compliant โ works with any client that supports
bunker://URIs (Primal, Amethyst, Coracle, etc.) - Encrypted at rest โ keys stored with AES-256-GCM, derived from passphrase via scrypt
- Rotatable encryption โ change your passphrase without losing keys
- Multi-key โ manage multiple Nostr identities from one bunker
- Device management โ connect/revoke devices, see activity
- Web dashboard โ minimal UI for status and device management
- 1 dependency โ just
nostr-tools. Everything else is Bun built-ins.
- Bun v1.1+
# Install
git clone https://github.com/opencollective/microbunker.git
cd microbunker
bun install
# Initialize (generates bunker keypair, stores your nsec encrypted)
export BUNKER_PASSPHRASE="your-secret-passphrase"
bun run src/index.ts init
# Start the daemon
bun run src/index.ts start
# Generate a connection URI for your Nostr client
bun run src/index.ts connect
# โ bunker://abc123...?relay=wss://relay.nsec.app&secret=xyz789...
# Paste this into Primal, Amethyst, etc.| Command | Description |
|---|---|
init |
Interactive setup wizard |
start |
Start the NIP-46 daemon + web dashboard |
connect |
Generate a bunker:// connection URI |
add-key |
Add another Nostr identity |
devices |
List connected devices |
revoke <id> |
Revoke a device |
rotate-key |
Re-encrypt all keys with a new passphrase |
--data-dir <path>โ Custom data directory (default:~/.microbunker)
BUNKER_PASSPHRASEโ Required. Used to encrypt/decrypt keys at rest.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ MicroBunker โ
โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โ
โ โ NIP-46 Daemon โ โ Web Dashboard โ โ
โ โ (relay listener)โ โ (Bun.serve) โ โ
โ โโโโโโโโโโฌโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ SQLite (bun:sqlite) โโ
โ โ โข keys (encrypted nsecs) โโ
โ โ โข devices (connected clients) โโ
โ โ โข connection_tokens โโ
โ โ โข bunker_identity โโ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- Your bunker listens on Nostr relays for kind:24133 events addressed to it
- When a client (e.g., Primal) wants to sign as you, it sends an encrypted request
- The bunker decrypts the request, signs the event with your key, and sends back the signed event
- The client publishes the signed event โ it looks like it came from you
- Keys are encrypted at rest using AES-256-GCM
- The encryption key is derived from your passphrase using scrypt (N=16384, r=8, p=1)
- Each key has a unique salt and IV
- Format:
version:salt:iv:ciphertext:tag - Use
rotate-keyto re-encrypt everything with a new passphrase
Stored in ~/.microbunker/config.json:
{
"relays": ["wss://relay.nsec.app", "wss://relay.damus.io"],
"port": 7547,
"host": "127.0.0.1",
"dashboardToken": "your-dashboard-access-token",
"tokenExpiryMinutes": 15,
"logLevel": "info"
}[Unit]
Description=MicroBunker NIP-46 Server
After=network.target
[Service]
Type=simple
User=microbunker
Environment=BUNKER_PASSPHRASE=your-passphrase
ExecStart=/usr/local/bin/bun /opt/microbunker/src/index.ts start
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.targetThe dashboard runs on 127.0.0.1:7547 by default. Put nginx/caddy in front if you want HTTPS access.
server {
server_name bunker.yourdomain.com;
location / {
proxy_pass http://127.0.0.1:7547;
}
}- Custodial: This bunker holds your private key. The passphrase protects it at rest.
- Network: The dashboard should be behind a reverse proxy or accessed only over a trusted network.
- Tokens: Connection tokens are single-use and expire (default: 15 minutes).
- Revocation: Revoked devices are immediately rejected for all subsequent requests.
connectโ Establish a new sessionget_public_keyโ Return the user's public keysign_eventโ Sign an eventnip04_encrypt/nip04_decryptโ NIP-04 encryption/decryptionnip44_encrypt/nip44_decryptโ NIP-44 encryption/decryptionpingโ Health check
MIT