Files
pi-kit/pikit-web/onboarding/index.html
2026-01-02 23:03:00 -05:00

218 lines
9.4 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Welcome to your Pi-Kit</title>
<link rel="stylesheet" href="/style.css?v=2" />
</head>
<body>
<main class="card">
<header>
<div class="dot"></div>
<h1>Welcome to your Pi-Kit</h1>
</header>
<p class="welcome">Great news — youre already on your Pi-Kit and its responding.</p>
<div class="status-row" aria-live="polite">
<span class="status-chip" id="statusChip">Youre on HTTP — trust the CA or continue to HTTPS.</span>
</div>
<p class="subtle">
Everything stays on your local network. Lets move you to the secure (HTTPS) dashboard so you
can manage Pi-Kit safely.
</p>
<section class="steps">
<h3>Why switch to HTTPS?</h3>
<ul>
<li>Encrypts traffic on your LAN so no one can snoop your Pi-Kit dashboard.</li>
<li>Stops mixed-content / “not secure” browser warnings.</li>
<li>Needed for some browser features (clipboard, notifications, service workers).</li>
</ul>
</section>
<section class="steps">
<h3>If you see a warning</h3>
<ul>
<li>Brave/Chrome: click <strong>Advanced</strong><strong>Proceed</strong>.</li>
<li>Firefox: click <strong>Advanced</strong><strong>Accept the Risk & Continue</strong>.</li>
</ul>
<p>This warning is expected the first time. Its safe for your own Pi on your own network.</p>
</section>
<section class="steps">
<h3>Install the Pi-Kit CA (recommended, one-time)</h3>
<div class="ca-download">
<p>This removes future warnings for the Pi-Kit dashboard.</p>
<a class="ghost download-inline" id="downloadCa" href="http://pikit.local/assets/pikit-ca.crt" download>
Download Pi-Kit CA
</a>
</div>
<p class="subtle">After installing the CA, close and reopen your browser so it takes effect.</p>
<p class="checksum">SHA256: <code id="caHash" class="inline">Loading...</code></p>
<details>
<summary id="win">Windows</summary>
<p>Run <strong>mmc</strong> → Add/Remove Snap-in → Certificates (Computer) → Trusted Root CAs → Import <em>pikit-ca.crt</em>.</p>
</details>
<details>
<summary id="mac">macOS</summary>
<p>Double-click <em>pikit-ca.crt</em> → Always Trust.</p>
</details>
<details>
<summary id="linux">Linux</summary>
<p><strong>Arch-based:</strong> <code id="archCmd">curl -s http://pikit.local/assets/pikit-ca.crt -o /tmp/pikit-ca.crt && sudo install -m644 /tmp/pikit-ca.crt /etc/ca-certificates/trust-source/anchors/ && sudo trust extract-compat</code></p>
<button class="copy" data-target="archCmd">Copy Arch command</button>
<p><strong>Debian/Ubuntu:</strong> <code id="debCmd">curl -s http://pikit.local/assets/pikit-ca.crt -o /tmp/pikit-ca.crt && sudo cp /tmp/pikit-ca.crt /usr/local/share/ca-certificates/pikit-ca.crt && sudo update-ca-certificates</code></p>
<button class="copy" data-target="debCmd">Copy Debian/Ubuntu command</button>
<p><strong>Fedora/RHEL:</strong> <code id="fedoraCmd">curl -s http://pikit.local/assets/pikit-ca.crt -o /tmp/pikit-ca.crt && sudo cp /tmp/pikit-ca.crt /etc/pki/ca-trust/source/anchors/pikit-ca.crt && sudo update-ca-trust</code></p>
<button class="copy" data-target="fedoraCmd">Copy Fedora/RHEL command</button>
</details>
<details>
<summary id="bsd">BSD (FreeBSD / OpenBSD)</summary>
<code id="bsdCmd">fetch -o /tmp/pikit-ca.crt http://pikit.local/assets/pikit-ca.crt && sudo install -m644 /tmp/pikit-ca.crt /usr/local/share/certs/pikit-ca.crt && sudo certctl rehash</code>
<button class="copy" data-target="bsdCmd">Copy</button>
</details>
<div id="copyStatus" class="copy-status" aria-live="polite"></div>
</section>
<section class="actions">
<button id="continueBtn">Go to secure dashboard</button>
</section>
<p class="footnote">Once trusted, this page will auto-forward you to the secure dashboard.</p>
<p class="footnote">If the hostname ever fails, try http://&lt;pi-kit ip&gt;/ (or https://&lt;pi-kit ip&gt;/ — your browser will show the same warning to bypass).</p>
<script>
(function () {
const host = location.hostname || "pikit.local";
const target = `https://${host}`;
const hasCookie = document.cookie.includes("pikit_https_ok=1");
const statusChip = document.getElementById("statusChip");
const copyStatus = document.getElementById("copyStatus");
const downloadCa = document.getElementById("downloadCa");
const caHash = document.getElementById("caHash");
const caUrl = `http://${host}/assets/pikit-ca.crt`;
if (downloadCa) downloadCa.href = caUrl;
const cmdTemplates = {
archCmd: `curl -s ${caUrl} -o /tmp/pikit-ca.crt && sudo install -m644 /tmp/pikit-ca.crt /etc/ca-certificates/trust-source/anchors/ && sudo trust extract-compat`,
debCmd: `curl -s ${caUrl} -o /tmp/pikit-ca.crt && sudo cp /tmp/pikit-ca.crt /usr/local/share/ca-certificates/pikit-ca.crt && sudo update-ca-certificates`,
fedoraCmd: `curl -s ${caUrl} -o /tmp/pikit-ca.crt && sudo cp /tmp/pikit-ca.crt /etc/pki/ca-trust/source/anchors/pikit-ca.crt && sudo update-ca-trust`,
bsdCmd: `fetch -o /tmp/pikit-ca.crt ${caUrl} && sudo install -m644 /tmp/pikit-ca.crt /usr/local/share/certs/pikit-ca.crt && sudo certctl rehash`,
};
Object.entries(cmdTemplates).forEach(([id, cmd]) => {
const el = document.getElementById(id);
if (el) el.textContent = cmd;
});
async function fetchText(url) {
const res = await fetch(url, { cache: "no-store" });
if (!res.ok) return "";
return (await res.text()).trim();
}
async function fetchCaHashFromApi() {
const res = await fetch("/api/firstboot", { cache: "no-store" });
if (!res.ok) return "";
const data = await res.json();
return data?.ca_hash || "";
}
async function loadCaHash(retries = 10) {
if (!caHash) return;
try {
const assetHash = await fetchText("/assets/pikit-ca.sha256");
if (assetHash) {
caHash.textContent = assetHash.split(/\s+/)[0];
return;
}
} catch (err) {
// ignore and try API
}
try {
const apiHash = await fetchCaHashFromApi();
if (apiHash) {
caHash.textContent = apiHash;
return;
}
} catch (err) {
// fall through
}
if (retries > 0) {
caHash.textContent = "Generating...";
setTimeout(() => loadCaHash(retries - 1), 2000);
} else {
caHash.textContent = "Unavailable";
}
}
document.getElementById("continueBtn").addEventListener("click", () => {
window.location = target;
});
document.querySelectorAll(".copy").forEach((btn) => {
btn.addEventListener("click", async () => {
const id = btn.dataset.target;
const el = document.getElementById(id);
const text = el.textContent.trim();
try {
if (navigator.clipboard && window.isSecureContext) {
await navigator.clipboard.writeText(text);
} else {
const ta = document.createElement("textarea");
ta.value = text;
ta.style.position = "fixed";
ta.style.opacity = "0";
document.body.appendChild(ta);
ta.select();
document.execCommand("copy");
document.body.removeChild(ta);
}
const original = btn.dataset.label || btn.textContent;
btn.textContent = "Copied";
copyStatus.textContent = "Copied to clipboard.";
setTimeout(() => {
btn.textContent = original;
copyStatus.textContent = "";
}, 1600);
} catch (err) {
const original = btn.dataset.label || btn.textContent;
btn.textContent = "Failed";
copyStatus.textContent = "Copy failed. Try manual copy.";
setTimeout(() => (btn.textContent = original), 1500);
}
});
});
// Accordion: keep only one platform section open at a time
const detailBlocks = Array.from(document.querySelectorAll("details"));
detailBlocks.forEach((d) => {
d.addEventListener("toggle", () => {
if (!d.open) return;
detailBlocks.forEach((other) => {
if (other !== d) other.removeAttribute("open");
});
});
});
// No auto-open: let users expand the platform they need.
if (hasCookie) {
statusChip.textContent = "HTTPS trusted — redirecting…";
window.location = target;
} else {
statusChip.textContent = "Youre on HTTP — trust the CA or click Go to secure dashboard.";
}
loadCaHash();
})();
</script>
</body>
</html>