Files
keysat-docs/install.html
T
Keysat 11760cc295 Drop redundant top-right nav from docs pages
The left sidebar already covers Install / Integrate / Wire format /
Operate across its four groups (Get started, Concepts, Reference,
Operate). The top-right nav duplicated those links one level up. On
mobile it was already hidden via @media rule, so the sidebar was
always the canonical navigation. Now it's the only navigation —
cleaner topbar, no duplication.
2026-05-11 09:59:19 -05:00

191 lines
9.7 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>
</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>