Skip to content

Blog · Bitcoin

Accepting bitcoin for hosting without a payment processor

Plenty of hosts advertise that they accept bitcoin. Follow the checkout through and you usually find a processor that takes custody of the coins, converts them to dollars, and — increasingly — wants identity documents before it will release anything. The host accepts bitcoin in the sense that a bureau de change accepts it.

This is what we do instead, in full, because a payment page that says "trust us" is worth less than one that explains itself.

The problem with processors

A payment processor sits between you and us and solves real problems: it watches the chain, it handles the exchange rate, it deals with underpayments. In return it introduces three of its own.

  • It takes custody. For a period your payment is the processor's asset, not yours and not ours. Processors have frozen funds, gone under, and exited jurisdictions.
  • It performs surveillance. Chain analysis on incoming payments is standard. Coins can be declined for where they have been, and you find out at checkout.
  • It creates an identity requirement. Not necessarily for you — for us. And a requirement on us tends to become a requirement on you.

If someone chooses bitcoin specifically to avoid an intermediary, routing them through an intermediary is not a feature.

The alternative: an extended public key

Bitcoin wallets are hierarchical. A single seed derives an effectively unlimited tree of keys, and crucially the tree splits: from an extended public key — an xpub, or in our case a zpub — you can derive every public address in a branch, and you cannot derive a single private key.

That asymmetry is the entire design.

Our web server holds the extended public key for one account. With it, the server can:

  • generate a brand new receiving address for every invoice;
  • recognise a payment to one of those addresses.

It cannot:

  • spend a single satoshi, ever, by any route.

The private keys are in a wallet that has never touched this machine. If this server were fully compromised tomorrow, the attacker would gain the ability to read addresses we were already printing publicly on invoice pages. There is no key to steal, because there has never been one here.

What it looks like in practice

account key:  zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4…
derive 0/0 →  bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu
derive 0/1 →  bc1qnjg0jd8228aq7egyzacy8cys3knf9xvrerkf9g
derive 0/2 →  …

Each invoice claims the next index. No address is ever reused, so nobody watching the chain can add up what our customers pay by watching a single address.

The exchange rate, and failing closed

Pricing in bitcoin means picking a rate, and picking a rate means trusting a source. A single price feed that returns a wrong number — through a bug, an outage, or interference — would let somebody buy a year of hosting for pennies, and it is unrecoverable the moment the address is displayed.

So we ask four independent exchanges, take the median, and compare the outer values. If fewer than two answer, or if they disagree by more than a few percent, we refuse to quote at all and the checkout says it is briefly unavailable.

A checkout outage costs us a sale. A bad rate costs us a server. That asymmetry decides the default, and it is why "temporarily unavailable" on our payment page is a feature rather than a fault.

Once quoted, the rate is locked for an hour. What you are shown is what you owe, whatever the market does while you are finding your wallet.

The awkward cases, which are most of the engineering

Slightly short

Wallets handle fees differently and some subtract from the amount you typed. Refusing a payment that is forty satoshis light would be technically defensible and commercially idiotic, so anything within a small tolerance settles as paid.

Genuinely short

The invoice shows exactly what arrived and exactly what is missing, payable to the same address. The important part: what you already sent is in our wallet and credited to your invoice the whole time. There is no state where your coins are somewhere ambiguous.

Overpaid

The excess becomes account credit, valued at the rate you paid, and comes off your next invoice automatically. No ticket required.

Paid after the quote expired

This is the one that trips up naive implementations. An expired quote is not an expired address — we keep watching every address we have ever issued, indefinitely, at a slower cadence. Someone who pays a two-week-old invoice has still paid us, and the alternative is money arriving that nobody ever looks at.

What this costs us

Some real things, and it is only fair to list them:

  • We carry the exchange-rate risk between your payment and whenever we convert.
  • Refunds are manual, and go out at the rate on the day — which we say plainly in the refund policy.
  • There is no chargeback mechanism, which protects us and removes a protection from you.
  • We had to build and test all of this, rather than pasting in a processor's snippet.

In exchange, nobody can freeze a payment between you and us, no third party gets a list of our customers, and we never have to ask you for identity documents to take your money.

The customer-facing version of this page is shorter. If you want to check the mechanism rather than take our word for it, every address we issue is on a public ledger and you can watch it settle in real time.

Related reading

Need a server to try this on?

KVM, full root, billed in bitcoin. From $12.00 a month.

See the plans