11760cc295
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.
191 lines
9.7 KiB
HTML
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 & 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 & 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 & 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 & setup</div>
|
|
<h1>Install & setup.</h1>
|
|
<p class="lead">From bare Start9 to your first issued license, in roughly the order you’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’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 → 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’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 → Set operator name</strong>. Pick a short label that identifies <em>you</em> as the seller — 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’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’s invoice creation.</p>
|
|
|
|
<p>In Keysat’s service page, click <strong>Actions → Connect BTCPay</strong>. You’ll be redirected to BTCPay’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’s <code>/btcpay</code> webhook endpoint.</li>
|
|
<li>Verifies the connection by fetching the store’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 → 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 → 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’ve ever sold. Don’t paste it into Slack. Don’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’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 → Create a new product</strong> and fill in:</p>
|
|
|
|
<ul>
|
|
<li><strong>Slug</strong> — lowercase, hyphens, will appear in the public URL. e.g. <code>bitcoin-ticker-pro</code>.</li>
|
|
<li><strong>Display name</strong> — shown on the buyer’s purchase page and on receipts.</li>
|
|
<li><strong>Description</strong> — one or two sentences; rendered as plain text.</li>
|
|
<li><strong>Price (sats)</strong> — 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 → 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> — 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://<your-keysat-host>/buy/<product-slug></pre>
|
|
|
|
<p>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.</p>
|
|
|
|
<p>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.</p>
|
|
|
|
<h2 id="next">What’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 →</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 →</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>
|