Running My Own Digital Mint: A Practical Guide to Personal Finance Infrastructure
Why I Did This
A few months ago, I decided to run my own Chaumian Ecash mint. That sentence sounds technical, but let me explain what it actually means in everyday terms.
I operate a digital cash machine that lives on a small server in my home network. People can connect to it, deposit value, receive digital tokens, and send those tokens to anyone else who also trusts my mint. The software I use is called Nutshell, and the wallet I recommend people use with it is called Agicash.
The mint lives at darkleaf.libretechsystems.xyz. If you point Agicash there, you can create an account, deposit some funds, and start using digital cash that I issue. This cash works like this: you give me real value, I give you digital tokens that represent that value, and those tokens can be passed around without me having to approve every single transaction.
The reason I run my own mint is simple. I wanted to understand how digital cash works from the inside. I also wanted to provide a service for people who want privacy in their small transactions without relying on massive corporate payment networks.
What a Mint Operator Actually Does
When I say I run a mint, most people imagine a factory that prints coins. That is not far off, actually.
In the digital world, a mint is a server that issues tokens. Someone sends me money, and I issue them a cryptographic proof that they now hold value. That proof can be handed to someone else, who can then hand it to someone else, and eventually someone brings it back to me to redeem for the underlying value.
The magic is that I, as the mint operator, do not need to know who is handing tokens to whom. I only see when tokens are created and when they are destroyed. The path they take in between is invisible to me.
That is the main job of a mint operator. I provide the infrastructure for creating and redeeming tokens. I keep track of which tokens have been spent so no one can double-spend. I also handle the connection to actual payment networks when someone wants to deposit or withdraw real funds.
The Technology Stack
The mint software I run is called Nutshell. It is written in Python and implements the Cashu protocol specifications. The codebase is open source, and you can find it on GitHub under the cashubtc organization.
Nutshell handles all the cryptography automatically. When a wallet connects to my mint, the software performs a blind signature exchange. The wallet sends me a blinded message, I sign it with my private key, and the wallet unblinds it to get a valid signature. The wallet then stores that signature along with the original secret as a spendable token.
From my perspective as the operator, I never see the secret that makes the token unique. I only see the blinded version, which is mathematically scrambled. When someone later redeems a token, they reveal the secret, and I check if I have seen it before. If I have not, I honor the token. If I have, I reject it as a double-spend attempt.
This is the core innovation of Chaumian Ecash. The mint can issue tokens and verify they are not double-spent without ever knowing exactly who holds which tokens at any given time.
Setting Up the Mint
The actual setup was straightforward. I have a Debian server running at home with a static IP address and a domain name pointing to it. I installed Docker and Docker Compose, then pulled the Nutshell image from Docker Hub.
The configuration lives in a file that defines things like the mint's name, description, contact information, and most importantly, the private key that the mint uses to sign tokens. This private key must be kept secret. If someone else gets it, they can issue fake tokens that look like they came from me.
I also configured a Lightning backend. Nutshell needs to know how to accept real payments when someone wants to deposit funds. For testing, I used the FakeWallet backend, which simulates Lightning payments without using real money. For production, I connected to an actual Lightning node.
The mint listens on port 3338 by default. I put an Nginx reverse proxy in front of it to handle SSL certificates. Let's Encrypt provides free certificates, so my mint speaks HTTPS like any modern web service.
The Keyset System
One interesting part of running a mint is managing keysets. A keyset is a collection of public keys for different token amounts. Nutshell generates keys for amounts that are powers of two: 1, 2, 4, 8, 16, and so on up to very large numbers.
When a wallet wants to mint tokens, it asks for my public keys first. It uses those keys to construct blinded messages. The specific keyset ID gets embedded in every token so the wallet knows which public key to use when verifying signatures later.
Keysets can be rotated. If I want to change my signing keys for security reasons, I can generate a new keyset, mark the old one as inactive, and wallets will slowly swap their old tokens for new ones. The old tokens remain spendable, but no new tokens will be issued from that keyset.
This rotation feature means I can run a mint indefinitely without ever losing the ability to redeem old tokens, while still upgrading my security posture over time.
How Agicash Connects to My Mint
Agicash is a wallet that speaks the Cashu protocol. When you open Agicash and add a mint, you provide a URL. My mint at darkleaf.libretechsystems.xyz responds to that request with its public information.
Once connected, Agicash fetches my keysets, displays my mint's name and description, and allows you to create an account. Agicash uses Open Secret for authentication, which means your identity is managed through a separate service, not by my mint directly.
This separation is important. My mint only knows that authenticated users are making requests. It does not know who those users are in any real-world sense unless they choose to identify themselves. The authentication tokens are blinded as well, so even the connection between a user and their requests is obscured.
When you deposit funds through Agicash, the wallet requests a mint quote from my server. I respond with a Lightning invoice. You pay that invoice through your Lightning wallet, and my mint detects the payment. Once confirmed, you can request the actual tokens, and I issue them blinded.
Sending tokens to another person is even simpler. You tell Agicash how much to send, it constructs a token, and you share that token as a text string or QR code. The recipient adds the token to their wallet, and my mint verifies it when they try to spend it.
The Lightning Connection
The most operationally complex part of running a mint is the Lightning backend. Cashu is designed to work with Bitcoin's Lightning Network for deposits and withdrawals. When someone wants to mint new tokens, they pay a Lightning invoice. When someone wants to redeem tokens for real money, they request a Lightning payment from the mint.
My mint connects to a Lightning node that I also operate. That node has channels open with other nodes on the network, which allows it to send and receive payments. The mint software handles all the communication with the node through its API.
There is a fee involved in these Lightning transactions. Lightning routing fees are small but not zero. I set my mint's fees to cover these network costs plus a small margin to support the operation. The fee structure is transparent and published in my mint's information endpoint.
The challenge with Lightning is that it requires active management. Channels need to be balanced. Sometimes payments fail and need retries. The mint software handles most of this automatically, but I still monitor the node to make sure everything is working.
The Database Behind the Mint
Nutshell uses a database to track several things. It stores mint quotes, melt quotes, spent secrets, and keyset information. By default it uses SQLite, which works fine for small mints. For larger operations, it supports PostgreSQL.
The most sensitive data in the database is the list of spent secrets. Every time a token gets redeemed, I store its secret in the spent secrets table. This prevents double-spending. I also store the Y value, which is the hash of the secret mapped to a curve point, as an additional index for faster lookups.
The database does not store any information about who redeemed which tokens. When a token comes in for redemption, I only see the secret. I do not see the wallet that sent it or the path it took to get there. This is by design and is enforced by the cryptography, not just by policy.
I back up the database regularly. If I lost the spent secrets table, someone could double-spend old tokens. If I lost the keyset information, wallets would not be able to verify signatures. The backup strategy is simple but critical.
The User Experience from My Perspective
When someone uses Agicash with my mint, the experience from my side is almost invisible. I see API requests hitting my server. I see logs showing mint quote creations, token issuances, and melt operations. I see the Lightning node sending and receiving payments.
But I do not see who is doing what. The blind signatures guarantee that even if I wanted to track individual users, I could not. I know that someone requested a mint quote for ten dollars. I know that later, someone redeemed tokens for ten dollars. But I cannot prove that the person who minted is the same person who redeemed, unless they do it in a way that links those actions, like using the same IP address repeatedly.
This privacy property is why I find this technology compelling. I can provide a financial service without becoming a surveillance system. I am not my users' banker. I am more like a vending machine that dispenses anonymous tokens in exchange for real value.
Handling Redemptions
When a user wants to redeem tokens, Agicash sends them to my mint along with a Lightning invoice for the same amount. I verify the tokens are unspent, subtract my fees, and send the Lightning payment.
The redemption process must be atomic. I cannot deduct the tokens from my database unless I am sure the Lightning payment will succeed. Nutshell handles this by reserving the tokens, attempting the payment, and then finalizing the spend only on success. If the payment fails, the tokens are released back to the user.
Sometimes Lightning payments fail for reasons outside my control. The invoice might expire. The route might be too long. The destination node might be offline. My mint handles these errors gracefully, returning the tokens to the spender so they can try again or try a different approach.
The Risk of Running a Mint
I need to be honest about the risks. If someone compromises my server, they could steal my private keys and issue fake tokens. If they delete my spent secrets table, they could double-spend tokens. If they take my Lightning node offline, no one can redeem.
I mitigate these risks with standard security practices. The server is locked down with a firewall. Only necessary ports are open. I use SSH keys with a passphrase, not passwords. The private key for the mint is stored in an encrypted file that the software reads at startup. The Lightning node has its own authentication separate from the mint.
But no system is perfectly secure. The theoretical risk remains. Anyone using my mint should understand that they are trusting me not to run away with their funds. That is true of any centralized service. The difference is that with Cashu, the tokens themselves are bearer instruments. If I betray that trust, there is no recourse.
This is why I encourage people to use multiple mints. Agicash supports adding several mints at once. Spread your balance around. Do not keep more with me than you are willing to lose. I run this mint as a public service and a learning experiment, not as a bank.
The Code That Makes It Work
Looking at the Nutshell code reveals the elegance of the system. The blind signature implementation lives in cashu/core/crypto/b_dhke.py. The mint's API endpoints are in cashu/mint/router.py. The database models are defined across several files.
The core protocol follows these steps:
When a wallet wants to mint, it calls POST /v1/mint/quote/bolt11 with an amount. The mint creates a quote, stores it in the database, and returns a Lightning invoice. The wallet pays the invoice. The wallet then calls POST /v1/mint/bolt11 with the quote ID and a list of blinded messages. The mint verifies the quote is paid, signs each blinded message with its private key, and returns the blind signatures.
When a wallet wants to spend tokens, it calls POST /v1/swap or POST /v1/melt/bolt11. The mint checks each input proof, verifies the signatures, checks that the secrets have not been spent, marks them as spent, and issues new outputs.
The spent secrets are stored with their Y values for efficient lookup. The mint does not store the original secrets, only the hashed version that proves uniqueness. This is enough to prevent double-spending without revealing the secret itself.
The keyset management code in cashu/core/crypto/keys.py handles key derivation from a seed phrase. The mint operator provides a seed, and the software derives all the public and private keys deterministically. This means I can back up my mint by saving just the seed and the database. Restoring is a matter of reinstalling the software, providing the seed, and restoring the database.
The Agicash Integration
Agicash is more than just a wallet. It includes a full suite of features for managing mints, accounts, and transactions. The codebase is large and well-organized, with clear separation between UI components, business logic, and data access.
When Agicash connects to my mint, it first fetches the mint's information using the GET /v1/info endpoint. This returns my mint's name, description, contact details, and which protocol features I support. Agicash uses this information to decide which API endpoints to call.
The wallet maintains a local database of proofs, transactions, and account information. All sensitive data is encrypted before storage. The encryption keys are derived from the user's seed phrase, which is never sent to any server.
Agicash also handles the complexity of keyset management. When my mint rotates keys, Agicash detects the new keyset and starts using it for new tokens. It also automatically swaps old tokens for new ones when it detects that a keyset is inactive.
The user interface is designed for simplicity. You see your balance, your transaction history, and a list of your accounts. Sending money is as simple as entering an amount and a destination. Receiving money generates a QR code or text token that you can share.
The Economics of Running a Mint
I charge a small fee for minting and melting. The fee is configurable and is published in my keyset information. Currently I charge 0.1 percent per transaction, which is low enough to not be burdensome but high enough to cover my Lightning costs and server expenses.
I do not expect to make money from this mint. The fees mostly cover the Lightning routing fees I pay to other nodes. Any surplus goes into a fund for server maintenance and future development.
The real value for me is learning. Running a mint has taught me more about Lightning, cryptography, and web services than any tutorial could. It has also introduced me to a community of people who care about digital privacy and financial autonomy.
Future Plans for the Mint
I plan to keep this mint running indefinitely. The server costs are low, and the maintenance is minimal. I check the logs every few days to make sure nothing is broken. The Lightning node requires more attention, but even that is mostly automated.
I am considering adding support for USD as a unit. Nutshell can handle fiat currencies through an exchange rate provider. The mint would need to track USD balances in a database and handle the conversion between Bitcoin and USD at minting and melting time. This is technically feasible but adds complexity that I am not ready for yet.
I also want to improve the monitoring and alerting for the mint. Right now I rely on manual checks. A proper monitoring system would alert me if the mint goes down or if errors spike. I could build this myself or use an existing observability platform.
Consider
Running my own mint at darkleaf.libretechsystems.xyz has been one of the most rewarding technical projects I have undertaken. It combines cryptography, web services, payment networks, and system administration into a single coherent system.
The Cashu protocol is mature and well-specified. The Nutshell implementation is stable and well-tested. The Agicash wallet is polished and user-friendly. Together, they form a complete ecosystem for private digital cash.
If you are curious about how this works, I encourage you to install Agicash and add my mint. Create an account, mint a small amount, send some tokens to a friend, and redeem them back. The experience of using anonymous digital cash is genuinely different from using a bank account or a credit card.
The technology is here. The protocols work. The wallets are ready. All that remains is for people to use them.
Citations & References
Primary Sources
- Nutshell Repository - Cashu BTC. "Nutshell: Chaumian Ecash Wallet and Mint for Bitcoin Lightning." GitHub. https://github.com/cashubtc/nutshell
- Cashu Protocol Specifications (NUTs) - Cashu BTC. "Cashu NUTs (Notation, Usage, and Terminology)." GitHub. https://github.com/cashubtc/nuts
- Agicash Wallet - MakePrisms, Inc. "Agicash: Self-Custody Bitcoin Wallet for Cashu Ecash and Lightning Payments." https://agi.cash
Technical References
- Chaum, David (1983). "Blind Signatures for Untraceable Payments." Advances in Cryptology: Proceedings of Crypto 82. Springer US. pp. 199–203.
- Somsen, Ruben. "Blind Diffie-Hellman Key Exchange (Chaumian Ecash)." GitHub Gist. https://gist.github.com/RubenSomsen/be7a4760dd4596d06963d67baf140406
- Lightning Network Specifications (BOLTs) - Lightning Network. "Basis of Lightning Technology (BOLT)." https://github.com/lightning/bolts
- NIP-44 Encryption - Nostr Improvement Proposals. "NIP-44: Versioned Encryption." https://github.com/nostr-protocol/nips/blob/master/44.md
Protocol Documentation
- NUT-00: Cryptography and Models - https://github.com/cashubtc/nuts/blob/main/00.md
- NUT-01: Mint Public Key Exchange - https://github.com/cashubtc/nuts/blob/main/01.md
- NUT-02: Keysets and Fees - https://github.com/cashubtc/nuts/blob/main/02.md
- NUT-03: Swap Tokens - https://github.com/cashubtc/nuts/blob/main/03.md
- NUT-04: Mint Tokens - https://github.com/cashubtc/nuts/blob/main/04.md
- NUT-05: Melt Tokens - https://github.com/cashubtc/nuts/blob/main/05.md
- NUT-06: Mint Information - https://github.com/cashubtc/nuts/blob/main/06.md
- NUT-07: Token State Check - https://github.com/cashubtc/nuts/blob/main/07.md
- NUT-08: Lightning Fee Return - https://github.com/cashubtc/nuts/blob/main/08.md
- NUT-09: Restore Signatures - https://github.com/cashubtc/nuts/blob/main/09.md
- NUT-10: Spending Conditions - https://github.com/cashubtc/nuts/blob/main/10.md
- NUT-11: Pay to Public Key (P2PK) - https://github.com/cashubtc/nuts/blob/main/11.md
- NUT-12: DLEQ Proofs - https://github.com/cashubtc/nuts/blob/main/12.md
- NUT-13: Deterministic Secrets - https://github.com/cashubtc/nuts/blob/main/13.md
- NUT-14: Hashed Timelock Contracts (HTLCs) - https://github.com/cashubtc/nuts/blob/main/14.md
- NUT-15: Partial Multi-Path Payments (MPP) - https://github.com/cashubtc/nuts/blob/main/15.md
- NUT-17: WebSocket Subscriptions - https://github.com/cashubtc/nuts/blob/main/17.md
- NUT-18: Payment Requests - https://github.com/cashubtc/nuts/blob/main/18.md
- NUT-20: Signature on Mint Quote - https://github.com/cashubtc/nuts/blob/main/20.md
- NUT-21: Clear Authentication - https://github.com/cashubtc/nuts/blob/main/21.md
- NUT-22: Blind Authentication - https://github.com/cashubtc/nuts/blob/main/22.md
- NUT-23: BOLT11 Payment Method - https://github.com/cashubtc/nuts/blob/main/23.md
- NUT-25: BOLT12 Payment Method - https://github.com/cashubtc/nuts/blob/main/25.md
- NUT-26: Payment Request Bech32m Encoding - https://github.com/cashubtc/nuts/blob/main/26.md
- NUT-27: Nostr Mint Backup - https://github.com/cashubtc/nuts/blob/main/27.md
- NUT-28: Pay to Blinded Key (P2BK) - https://github.com/cashubtc/nuts/blob/main/28.md
Additional Resources
- BIP-39: Mnemonic Code for Generating Deterministic Keys - https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
- BIP-340: Schnorr Signatures for Secp256k1 - https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
- Open Secret Platform - "Privacy-First Authentication and Key Management." https://opensecret.cloud
- Devenv Development Environment - "Reproducible Development Environments with Nix." https://devenv.sh
Code References from Your Infrastructure
- Your mint endpoint: darkleaf.libretechsystems.xyz
- Nginx reverse proxy configuration (as configured on your Debian server)
- Systemd service file for Nutshell mint (from your deployment)
- Let's Encrypt SSL certificate configuration
Image/Media Credits (if applicable)
- Cashu logo and branding - Cashu BTC Project
- Agicash logo and interface screenshots - MakePrisms, Inc.
- Lightning Network diagram - Derived from BOLT specifications