Files
keysat-docs/install.html
T
Keysat 19a969f797 Topnav: brand logo links to keysat.xyz; drop redundant Marketing entry
Standard docs-site convention: top-left brand goes to the marketing
home, the 'Docs' badge next to it signals you're in the docs section.
The separate 'Marketing' nav item is no longer needed once the brand
itself handles that link.
2026-05-11 09:57:36 -05:00

197 lines
9.9 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Keysat Docs — Install &amp; setup</title>
<link rel="icon" type="image/svg+xml" href="assets/favicon.svg">
<link rel="stylesheet" href="docs.css">
</head>
<body>
<div class="topnav">
<a href="https://keysat.xyz" class="brand" title="Back to keysat.xyz"><img src="assets/keysat-mark.svg" alt=""><span>Keysat</span></a>
<span class="docs-tag">Docs</span>
<nav>
<a href="install.html" class="active">Install</a>
<a href="integrate.html">Integrate</a>
<a href="wire-format.html">Wire format</a>
<a href="operate.html">Operate</a>
</nav>
</div>
<div class="layout">
<aside class="side">
<div class="group">
<div class="glabel">Get started</div>
<a href="index.html">Introduction</a>
<a href="install.html" class="active">Install &amp; setup</a>
<a href="integrate.html">Integrate the SDK</a>
</div>
<div class="group">
<div class="glabel">Concepts</div>
<a href="index.html#architecture">Architecture</a>
<a href="index.html#products-policies">Products &amp; policies</a>
<a href="index.html#discounts">Discount codes</a>
<a href="index.html#revocation">Revocation strategy</a>
</div>
<div class="group">
<div class="glabel">Reference</div>
<a href="wire-format.html">Wire format</a>
<a href="integrate.html#api">Admin API</a>
<a href="integrate.html#sdks">SDKs</a>
</div>
<div class="group">
<div class="glabel">Operate</div>
<a href="operate.html#backups">Backups</a>
<a href="operate.html#migrate">Migrate hardware</a>
<a href="operate.html#troubleshooting">Troubleshooting</a>
</div>
</aside>
<main class="prose">
<div class="crumb">Get started · Install &amp; setup</div>
<h1>Install &amp; setup.</h1>
<p class="lead">From bare Start9 to your first issued license, in roughly the order you&rsquo;ll do it. Allow about an afternoon.</p>
<h2 id="prereq">Prerequisites</h2>
<ul>
<li>A Start9 server running StartOS 0.4.x (Server Pro, Server One, or DIY install).</li>
<li>Administrative access to the StartOS dashboard.</li>
<li>About 2 GB of free disk for Keysat itself; BTCPay&rsquo;s requirements are larger and depend on your Bitcoin node mode.</li>
</ul>
<h2 id="install">Step 1 — Install Keysat</h2>
<p>Two ways. Either gets you to the same place.</p>
<h3>Option A: from the Keysat marketplace (recommended)</h3>
<ol>
<li>In your StartOS dashboard, go to <strong>Marketplace &rarr; Add</strong>.</li>
<li>Paste <code>https://registry.keysat.xyz</code> as the URL.</li>
<li>Find <em>Keysat</em> in the marketplace listing and click <strong>Install</strong>.</li>
</ol>
<h3>Option B: sideload</h3>
<ol>
<li>Download <code>keysat_x86_64.s9pk</code> from the <a href="https://github.com/keysat-xyz/keysat/releases">GitHub releases page</a>.</li>
<li>In your StartOS dashboard, go to <strong>Sideload</strong> and drag the file in.</li>
<li>Click <strong>Install</strong>.</li>
</ol>
<p>BTCPay Server is declared as a required dependency. If you don&rsquo;t have it installed yet, StartOS will prompt you to install it as part of the same flow.</p>
<h2 id="operator-name">Step 2 — Set your operator name</h2>
<p>Open the Keysat service page in StartOS. Go to <strong>Actions &rarr; Set operator name</strong>. Pick a short label that identifies <em>you</em> as the seller &mdash; e.g. "aurora-software", "northpath", "my-name". This shows up on the public purchase pages and in the audit log.</p>
<p>This change is live-reloaded; you don&rsquo;t need to restart the service.</p>
<h2 id="connect-btcpay">Step 3 — Connect BTCPay</h2>
<p>Make sure BTCPay Server is running and has at least one <strong>store</strong> with a configured <strong>payment method</strong> (on-chain wallet or Lightning node). Without a payment method, BTCPay will reject Keysat&rsquo;s invoice creation.</p>
<p>In Keysat&rsquo;s service page, click <strong>Actions &rarr; Connect BTCPay</strong>. You&rsquo;ll be redirected to BTCPay&rsquo;s authorize page, where you grant Keysat the permissions it needs:</p>
<ul>
<li><code>btcpay.store.canviewinvoices</code></li>
<li><code>btcpay.store.cancreateinvoice</code></li>
<li><code>btcpay.store.canmodifywebhooks</code></li>
</ul>
<p>Once you confirm, BTCPay redirects back to Keysat with an API key and store id. Keysat:</p>
<ol>
<li>Stores the API key and store id in its local SQLite (encrypted at rest by StartOS).</li>
<li>Registers an outbound webhook subscription on the store, pointed at Keysat&rsquo;s <code>/btcpay</code> webhook endpoint.</li>
<li>Verifies the connection by fetching the store&rsquo;s payment-method list.</li>
</ol>
<div class="callout">
<i data-lucide="info"></i>
<p><strong>Connect is idempotent.</strong> If you click it again later, Keysat detects the existing connection and returns success without re-authorizing. To force a re-authorize, run the <strong>Disconnect BTCPay</strong> action first.</p>
</div>
<p>Click <strong>Actions &rarr; Check BTCPay connection</strong> to verify the wiring. It should report:</p>
<pre class="code"><span class="c"># Expected output:</span>
status: <span class="s">connected</span>
store: <span class="s">YOUR_STORE_ID</span>
webhook: <span class="s">registered</span>
payment_methods: <span class="s">[BTC-OnChain, BTC-LightningNetwork]</span></pre>
<p>If <code>payment_methods</code> is empty, head back to BTCPay and configure at least one before continuing.</p>
<h2 id="admin-key">Step 4 — Get your admin API key</h2>
<p>Go to <strong>Actions &rarr; Show admin API key</strong>. This reveals the 64-hex-character key that gates all <code>/v1/admin/*</code> endpoints, including the admin UI.</p>
<div class="callout warn">
<i data-lucide="alert-triangle"></i>
<p><strong>Treat this key like a password.</strong> Anyone with it can issue, revoke, or read every license you&rsquo;ve ever sold. Don&rsquo;t paste it into Slack. Don&rsquo;t check it into Git.</p>
</div>
<h2 id="admin-ui">Step 5 — Open the admin UI</h2>
<p>Click the <strong>Launch UI</strong> button on Keysat&rsquo;s service page. (StartOS surfaces this for any service that defines a <code>type: 'ui'</code> interface.) Paste the admin key from the previous step into the sign-in form.</p>
<p>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).</p>
<h2 id="first-product">Step 6 — Define your first product</h2>
<p>In the admin UI, go to <strong>Products &rarr; Create a new product</strong> and fill in:</p>
<ul>
<li><strong>Slug</strong> &mdash; lowercase, hyphens, will appear in the public URL. e.g. <code>bitcoin-ticker-pro</code>.</li>
<li><strong>Display name</strong> &mdash; shown on the buyer&rsquo;s purchase page and on receipts.</li>
<li><strong>Description</strong> &mdash; one or two sentences; rendered as plain text.</li>
<li><strong>Price (sats)</strong> &mdash; an integer. e.g. <code>50000</code> for ~$30 USD at current rates.</li>
</ul>
<p>The product is created with no policies attached. Next:</p>
<h2 id="first-policy">Step 7 — Define a default policy</h2>
<p>Go to <strong>Policies &rarr; Create a new policy</strong>. Pick the product, then:</p>
<ul>
<li>Set <strong>slug</strong> to <code>default</code>. This is the policy consumed by the public purchase flow; other slugs are reserved for manual issuance.</li>
<li>Set <strong>duration_seconds</strong>. Common choices: <code>0</code> (perpetual), <code>31536000</code> (1 year), <code>2592000</code> (30 days for trials).</li>
<li>Set <strong>max_machines</strong>. Use <code>1</code> for single-seat licenses or <code>0</code> for unlimited.</li>
<li>Optionally add <strong>entitlements</strong> &mdash; comma-separated feature flags. These are baked into the signed key and your app reads them at verify time.</li>
</ul>
<h2 id="purchase-url">Step 8 — Share your purchase URL</h2>
<p>Your public purchase URL is now live at:</p>
<pre class="code">https://&lt;your-keysat-host&gt;/buy/&lt;product-slug&gt;</pre>
<p>Buyers hit it, see your product, click "Pay", and BTCPay&rsquo;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.</p>
<p>Test it end-to-end by creating a free-license discount code and redeeming it &mdash; the same code path runs, just without the payment leg.</p>
<h2 id="next">What&rsquo;s next</h2>
<div class="next-grid">
<a class="next-card" href="integrate.html">
<span class="eyebrow">Hook it up</span>
<h4>Integrate the SDK &rarr;</h4>
<p>Embed your public key in your app and verify licenses offline.</p>
</a>
<a class="next-card" href="operate.html">
<span class="eyebrow">Run it</span>
<h4>Operate &rarr;</h4>
<p>Backups, migration to new hardware, and troubleshooting.</p>
</a>
</div>
</main>
<aside class="toc">
<div class="label">On this page</div>
<a href="#prereq">Prerequisites</a>
<a href="#install">1. Install Keysat</a>
<a href="#operator-name">2. Set operator name</a>
<a href="#connect-btcpay">3. Connect BTCPay</a>
<a href="#admin-key">4. Get admin key</a>
<a href="#admin-ui">5. Open the admin UI</a>
<a href="#first-product">6. First product</a>
<a href="#first-policy">7. Default policy</a>
<a href="#purchase-url">8. Purchase URL</a>
</aside>
</div>
<script src="https://unpkg.com/lucide@latest"></script>
<script>lucide.createIcons();</script>
</body>
</html>