Install & setup.
From bare Start9 to your first issued license, in roughly the order you’ll do it. Allow about an afternoon.
Prerequisites
- A Start9 server running StartOS 0.4.x (Server Pro, Server One, or DIY install).
- Administrative access to the StartOS dashboard.
- About 2 GB of free disk for Keysat itself; BTCPay’s requirements are larger and depend on your Bitcoin node mode.
Step 1 — Install Keysat
Two ways. Either gets you to the same place.
Option A: from the Keysat marketplace (recommended)
- In your StartOS dashboard, go to Marketplace → Add.
- Paste
https://registry.keysat.xyzas the URL. - Find Keysat in the marketplace listing and click Install.
Option B: sideload
- Download
keysat_x86_64.s9pkfrom the GitHub releases page. - In your StartOS dashboard, go to Sideload and drag the file in.
- Click Install.
BTCPay Server is declared as a required dependency. If you don’t have it installed yet, StartOS will prompt you to install it as part of the same flow.
Step 2 — Set your operator name
Open the Keysat service page in StartOS. Go to Actions → Set operator name. Pick a short label that identifies you as the seller — e.g. "aurora-software", "northpath", "my-name". This shows up on the public purchase pages and in the audit log.
This change is live-reloaded; you don’t need to restart the service.
Step 3 — Connect BTCPay
Make sure BTCPay Server is running and has at least one store with a configured payment method (on-chain wallet or Lightning node). Without a payment method, BTCPay will reject Keysat’s invoice creation.
In Keysat’s service page, click Actions → Connect BTCPay. You’ll be redirected to BTCPay’s authorize page, where you grant Keysat the permissions it needs:
btcpay.store.canviewinvoicesbtcpay.store.cancreateinvoicebtcpay.store.canmodifywebhooks
Once you confirm, BTCPay redirects back to Keysat with an API key and store id. Keysat:
- Stores the API key and store id in its local SQLite (encrypted at rest by StartOS).
- Registers an outbound webhook subscription on the store, pointed at Keysat’s
/btcpaywebhook endpoint. - Verifies the connection by fetching the store’s payment-method list.
Connect is idempotent. If you click it again later, Keysat detects the existing connection and returns success without re-authorizing. To force a re-authorize, run the Disconnect BTCPay action first.
Click Actions → Check BTCPay connection to verify the wiring. It should report:
# Expected output: status: connected store: YOUR_STORE_ID webhook: registered payment_methods: [BTC-OnChain, BTC-LightningNetwork]
If payment_methods is empty, head back to BTCPay and configure at least one before continuing.
Step 4 — Get your admin API key
Go to Actions → Show admin API key. This reveals the 64-hex-character key that gates all /v1/admin/* endpoints, including the admin UI.
Treat this key like a password. Anyone with it can issue, revoke, or read every license you’ve ever sold. Don’t paste it into Slack. Don’t check it into Git.
Step 5 — Open the admin UI
Click the Launch UI button on Keysat’s service page. (StartOS surfaces this for any service that defines a type: 'ui' interface.) Paste the admin key from the previous step into the sign-in form.
From here on, you mostly work in the admin UI. The StartOS Actions tab is reserved for setup-only operations (operator name, BTCPay connect/disconnect/check, show admin key).
Step 6 — Define your first product
In the admin UI, go to Products → Create a new product and fill in:
- Slug — lowercase, hyphens, will appear in the public URL. e.g.
bitcoin-ticker-pro. - Display name — shown on the buyer’s purchase page and on receipts.
- Description — one or two sentences; rendered as plain text.
- Price (sats) — an integer. e.g.
50000for ~$30 USD at current rates.
The product is created with no policies attached. Next:
Step 7 — Define a default policy
Go to Policies → Create a new policy. Pick the product, then:
- Set slug to
default. This is the policy consumed by the public purchase flow; other slugs are reserved for manual issuance. - Set duration_seconds. Common choices:
0(perpetual),31536000(1 year),2592000(30 days for trials). - Set max_machines. Use
1for single-seat licenses or0for unlimited. - Optionally add entitlements — comma-separated feature flags. These are baked into the signed key and your app reads them at verify time.
Step 8 — Share your purchase URL
Your public purchase URL is now live at:
https://<your-keysat-host>/buy/<product-slug>
Buyers hit it, see your product, click "Pay", and BTCPay’s checkout takes over. On payment confirmation, Keysat receives a webhook from BTCPay, signs a license, and emails it to the buyer (if they entered an email) and shows it on the receipt page.
Test it end-to-end by creating a free-license discount code and redeeming it — the same code path runs, just without the payment leg.