Caddy fronted the Hub at http://sovransystemsos.local, but the Hub already listens on 0.0.0.0:8937 itself, and nothing Caddy added is something it needs: - Not the name. That is avahi's: mDNS advertises a hostname, not a port, so the name resolves wherever the Hub listens. - Not TLS (the site was plain http), not authentication, not cache headers. The header block duplicated NoCacheMiddleware, and its Clear-Site-Data ("cache") overrode the app's stronger ("cache", "storage"). - Not access control, and this is the point. With ports 80/443 forwarded for public services, a Host header on those ports reached the Hub. That second door is how the reported bug happened, andc33457fguards it with an address check instead of closing it. The Hub is now served on port 8937 only, at http://sovransystemsos.local:8937, and Caddy has no site for it. The only thing Caddy answers on 80/443 is the public sites. Caddy keeps Ride The Lightning (:3051) and Mempool (:60847), because those do need it: Sovran_Bitcoin binds both to 127.0.0.1 and RTL's unit is sandboxed to loopback besides, so Caddy is how the local network reaches them. - caddy.nix: no Hub site. Caddy runs wherever RTL and Mempool do, which includes Bitcoin Node Only. There it did not run at all (enable was needsHttpsPorts || extraVhosts != ""), so :3051 and :60847 were open in the firewall with nothing listening. Ports 80/443 still follow needsHttpsPorts alone, so Node Only does not open them. The two sites are written only where their service exists; they were unconditional. - sovran-hub.nix: 8937 follows the new hub.directPort, 60847 follows Mempool. It used to be `[ 8937 60847 ]` on every role, Desktop Only included. - roles.nix: hub.directPort defaults to !roles.desktop: open on Server + Desktop and Bitcoin Node Only, closed on Desktop Only, where the Hub is reached from the machine itself through the desktop window on localhost. - The bind stays 0.0.0.0, which is IPv4 only: with that bind [::1]:8937 is refused and "localhost" falls back to 127.0.0.1. That is on purpose and is now said in the comment. An IPv6 listener would let in clients whose global addresses the Hub cannot tell from a stranger's, which is the question the previous commit declines to answer by guessing. - README, SECURITY.md and two strings in index.html give the new URL. Behaviour changes: the Hub's address gains :8937, and http://sovransystemsos.local on port 80 no longer reaches it. Bitcoin Node Only now runs Caddy. Evaluated with nix eval (nixpkgs as flake.lock pins it, Sovran_Bitcoin at the locked revision), firewall TCP ports per role:c33457fthis commit Server + Desktop 22 80 443 3051 8937 60847 22 80 443 3051 8937 Bitcoin Node Only 22 3051 8937 60847 22 3051 8937 60847 (Caddy now runs) Desktop Only 22 8937 60847 22 Port 22 is open on every role although sshd listens on loopback only; the last commit of this series deals with that. The Caddyfile the module really generates (the evaluated generator script, run, then `caddy validate` with Caddy 2.9.1): Node Only gets the two sites and nothing else; Server + Desktop with every domain configured gets the seven domain sites plus :3051 and :60847 and no mention of the Hub; with Bitcoin off there are no local-network sites; Node Only with Bitcoin off and no domains leaves Caddy off. Add tests/test_hub_direct.py and keep tests/test_caddy_lan_only.py for the two sites it still covers.
599 lines
31 KiB
HTML
599 lines
31 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>Sovran_SystemsOS — The Hub</title>
|
||
<link rel="stylesheet" href="/static/css/base.css?v={{ asset_version }}" />
|
||
<link rel="stylesheet" href="/static/css/buttons.css?v={{ asset_version }}" />
|
||
<link rel="stylesheet" href="/static/css/header.css?v={{ asset_version }}" />
|
||
<link rel="stylesheet" href="/static/css/layout.css?v={{ asset_version }}" />
|
||
<link rel="stylesheet" href="/static/css/tiles.css?v={{ asset_version }}" />
|
||
<link rel="stylesheet" href="/static/css/modals.css?v={{ asset_version }}" />
|
||
<link rel="stylesheet" href="/static/css/features.css?v={{ asset_version }}" />
|
||
<link rel="stylesheet" href="/static/css/onboarding.css?v={{ asset_version }}" />
|
||
<link rel="stylesheet" href="/static/css/support.css?v={{ asset_version }}" />
|
||
<link rel="stylesheet" href="/static/css/domain-setup.css?v={{ asset_version }}" />
|
||
<link rel="stylesheet" href="/static/css/security.css?v={{ asset_version }}" />
|
||
</head>
|
||
<body>
|
||
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
|
||
|
||
<!-- service glyphs -->
|
||
<!-- ═══ Real service logos — extracted verbatim from app/icons/*.svg ═══
|
||
(internal ids namespaced per icon to avoid collisions) -->
|
||
|
||
<!-- symbolic helpers (nav + modal internals) -->
|
||
<!-- Bitcoin nav icon: the OFFICIAL logo silhouette (paths taken verbatim
|
||
from app/icons/bitcoin-core.svg) rendered monochrome in currentColor
|
||
so it matches the symbolic sidebar set -->
|
||
<symbol id="g-btc-sym" viewBox="-34 -34 580 580">
|
||
<path fill="currentColor" d="M317.871 7.656c-137.12-34.192-276.024 49.28-310.2 186.44-34.208 137.136 49.256 276.048 186.36 310.24 137.16 34.199 276.063-49.265 310.256-186.408 34.192-137.152-49.264-276.08-186.416-310.272m50.936 211.872c-3.688 24.936-17.512 37.008-35.864 41.24 25.2 13.12 38.024 33.239 25.809 68.12-15.16 43.319-51.176 46.976-99.072 37.912l-11.624 46.584-28.088-7 11.472-45.96a1076 1076 0 0 1-22.384-5.809l-11.512 46.177-28.056-7 11.624-46.673c-6.561-1.68-13.225-3.464-20.024-5.168l-36.552-9.111 13.943-32.152s20.696 5.504 20.416 5.096c7.952 1.969 11.48-3.216 12.872-6.672l18.368-73.64.048-.2 13.104-52.568c.344-5.968-1.712-13.496-13.088-16.336.439-.296-20.4-5.072-20.4-5.072l7.472-30 38.736 9.673-.032.144c5.824 1.448 11.824 2.824 17.937 4.216L245.423 89.2l28.072 7-11.28 45.224c7.536 1.721 15.12 3.456 22.504 5.297l11.2-44.929 28.088 7-11.504 46.145c35.464 12.215 61.401 30.527 56.304 64.591"/>
|
||
<path fill="currentColor" d="m254.647 174.6-13.983 56.08c15.855 3.951 64.735 20.071 72.656-11.656 8.248-33.096-42.817-40.472-58.673-44.424"/>
|
||
<path fill="currentColor" d="m233.608 258.984-15.425 61.832c19.04 4.729 77.769 23.584 86.448-11.296 9.072-36.376-51.984-45.784-71.023-50.536"/>
|
||
</symbol>
|
||
|
||
<symbol id="g-chat" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M20 5.5v7a2.5 2.5 0 0 1-2.5 2.5H10l-4 3.2c-.6.5-1 .3-1-.5V5.5A2.5 2.5 0 0 1 7.5 3h10A2.5 2.5 0 0 1 20 5.5z"/>
|
||
<circle cx="8.7" cy="9.2" r="0.5" fill="currentColor"/><circle cx="12" cy="9.2" r="0.5" fill="currentColor"/><circle cx="15.3" cy="9.2" r="0.5" fill="currentColor"/>
|
||
</g>
|
||
</symbol>
|
||
|
||
<symbol id="g-antenna" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round">
|
||
<path d="M5.4 9.9a9.3 9.3 0 0 1 13.2 0"/>
|
||
<path d="M8.1 12.9a5.6 5.6 0 0 1 7.8 0"/>
|
||
<circle cx="12" cy="16.6" r="1.5" fill="currentColor" stroke="none"/>
|
||
<path d="M12 16.6V21"/>
|
||
</g>
|
||
</symbol>
|
||
|
||
<symbol id="g-lock" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round">
|
||
<rect x="5.5" y="10.5" width="13" height="9.5" rx="2.6"/>
|
||
<path d="M8.5 10.5V8a3.5 3.5 0 0 1 7 0v2.5"/>
|
||
<circle cx="12" cy="15" r="1.3" fill="currentColor" stroke="none"/>
|
||
</g>
|
||
</symbol>
|
||
<!-- nav + ui symbolic icons -->
|
||
<symbol id="g-home" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M4 11.2L12 4.5l8 6.7"/>
|
||
<path d="M6 10.5v8a1.2 1.2 0 0 0 1.2 1.2h9.6a1.2 1.2 0 0 0 1.2-1.2v-8"/>
|
||
<path d="M10 19.7v-5.4h4v5.4"/>
|
||
</g>
|
||
</symbol>
|
||
<symbol id="g-grid" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="1.9" stroke-linejoin="round">
|
||
<rect x="3.5" y="3.5" width="7.2" height="7.2" rx="2"/><rect x="13.3" y="3.5" width="7.2" height="7.2" rx="2"/>
|
||
<rect x="3.5" y="13.3" width="7.2" height="7.2" rx="2"/><rect x="13.3" y="13.3" width="7.2" height="7.2" rx="2"/>
|
||
</g>
|
||
</symbol>
|
||
<symbol id="g-server" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="1.9" stroke-linejoin="round">
|
||
<rect x="3.5" y="3.5" width="17" height="7.4" rx="2"/><rect x="3.5" y="13.1" width="17" height="7.4" rx="2"/>
|
||
<circle cx="7.2" cy="7.2" r="0.6" fill="currentColor"/><circle cx="7.2" cy="16.8" r="0.6" fill="currentColor"/>
|
||
</g>
|
||
</symbol>
|
||
<symbol id="g-dots" viewBox="0 0 24 24">
|
||
<g fill="currentColor">
|
||
<circle cx="5" cy="5" r="1.7"/><circle cx="12" cy="5" r="1.7"/><circle cx="19" cy="5" r="1.7"/>
|
||
<circle cx="5" cy="12" r="1.7"/><circle cx="12" cy="12" r="1.7"/><circle cx="19" cy="12" r="1.7"/>
|
||
<circle cx="5" cy="19" r="1.7"/><circle cx="12" cy="19" r="1.7"/><circle cx="19" cy="19" r="1.7"/>
|
||
</g>
|
||
</symbol>
|
||
<symbol id="g-refresh" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||
<path d="M20 12a8 8 0 1 1-2.9-6.2"/>
|
||
<path d="M20.6 2.6l-.5 4.9-4.6-1.7z" fill="currentColor" stroke="none"/>
|
||
</g>
|
||
</symbol>
|
||
<!-- Update System: down arrow into a tray (get / install updates) -->
|
||
<symbol id="g-update" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M12 4v10.5"/>
|
||
<path d="M7.8 10.3L12 14.5l4.2-4.2"/>
|
||
<path d="M4.5 16.5v2a2.5 2.5 0 0 0 2.5 2.5h10a2.5 2.5 0 0 0 2.5-2.5v-2"/>
|
||
</g>
|
||
</symbol>
|
||
<symbol id="g-box" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round">
|
||
<rect x="3.5" y="4" width="17" height="4.4" rx="1.6"/>
|
||
<path d="M5.2 8.4v9a2.4 2.4 0 0 0 2.4 2.4h8.8a2.4 2.4 0 0 0 2.4-2.4v-9"/>
|
||
<path d="M10 12.5h4"/>
|
||
</g>
|
||
</symbol>
|
||
<symbol id="g-shield-check" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M12 2.5 4.5 5.5v6c0 4.6 3.1 8 7.5 9.9 4.4-1.9 7.5-5.3 7.5-9.9v-6z"/>
|
||
<path d="M8.6 12l2.4 2.4 4.4-4.6"/>
|
||
</g>
|
||
</symbol>
|
||
<!-- Systems Operational: activity pulse (system health) — distinct from
|
||
the Security shield above -->
|
||
<symbol id="g-pulse" viewBox="0 0 24 24">
|
||
<path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M3 12h4l3-7 4 14 3-7h4"/>
|
||
</symbol>
|
||
<symbol id="g-lifebuoy" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round">
|
||
<circle cx="12" cy="12" r="8.6"/><circle cx="12" cy="12" r="3.6"/>
|
||
<path d="M6 6l3.2 3.2M18 6l-3.2 3.2M6 18l3.2-3.2M18 18l-3.2-3.2"/>
|
||
</g>
|
||
</symbol>
|
||
<symbol id="g-power" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||
<path d="M7.2 6.1a7 7 0 1 0 9.6 0"/>
|
||
<path d="M12 2.8v8.4"/>
|
||
</g>
|
||
</symbol>
|
||
<symbol id="g-logout" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M14 4h4.5A1.5 1.5 0 0 1 20 5.5v13a1.5 1.5 0 0 1-1.5 1.5H14"/>
|
||
<path d="M4 12h10M10.5 8.5 14 12l-3.5 3.5"/>
|
||
</g>
|
||
</symbol>
|
||
<symbol id="g-search" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||
<circle cx="11" cy="11" r="6.5"/>
|
||
<path d="M15.8 15.8 21 21"/>
|
||
</g>
|
||
</symbol>
|
||
<symbol id="g-copy" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round">
|
||
<rect x="9" y="9" width="11" height="11" rx="2.2"/>
|
||
<path d="M5.5 15H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v.5"/>
|
||
</g>
|
||
</symbol>
|
||
<symbol id="g-check" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.5l5 5 10-11"/></symbol>
|
||
<symbol id="g-chev" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" d="M9.5 5.5 16 12l-6.5 6.5"/></symbol>
|
||
<symbol id="g-x" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" d="M6 6l12 12M18 6 6 18"/></symbol>
|
||
<symbol id="g-wifi" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round">
|
||
<path d="M4.5 10.2a11 11 0 0 1 15 0"/>
|
||
<path d="M7.3 13.3a7 7 0 0 1 9.4 0"/>
|
||
<circle cx="12" cy="17" r="1.4" fill="currentColor" stroke="none"/>
|
||
</g>
|
||
</symbol>
|
||
<symbol id="g-key" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="7.5" cy="15.5" r="4"/>
|
||
<path d="M10.4 12.6 20 3M16.2 6.8l2.4 2.4M18.8 4.2l2.2 2.2"/>
|
||
</g>
|
||
</symbol>
|
||
<symbol id="g-alert" viewBox="0 0 24 24">
|
||
<g fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M12 3.6 22.2 20.4H1.8z"/>
|
||
<path d="M12 9.8v4.6"/><circle cx="12" cy="17.2" r="0.6" fill="currentColor" stroke="none"/>
|
||
</g>
|
||
</symbol>
|
||
</svg>
|
||
|
||
<!-- ═══ BOOT SPLASH ═══ covers the shell while the first data loads;
|
||
dashboard.js lifts it once the welcome cards are rendered -->
|
||
<div id="app-splash" role="status" aria-live="polite">
|
||
<div class="splash-card">
|
||
<div class="splash-ring">
|
||
<img src="/static/sovran-hub-icon.svg" alt="" width="64" height="64" />
|
||
<span class="splash-ring-arc" aria-hidden="true"></span>
|
||
</div>
|
||
<div class="splash-title">Starting The Hub</div>
|
||
<div class="splash-sub" id="splash-sub">Gathering your services…</div>
|
||
</div>
|
||
</div>
|
||
<script>
|
||
(function () {
|
||
var splash = document.getElementById("app-splash");
|
||
var sub = document.getElementById("splash-sub");
|
||
var lifted = false;
|
||
function lift() {
|
||
if (lifted || !splash) return;
|
||
lifted = true;
|
||
splash.classList.add("done");
|
||
setTimeout(function () {
|
||
if (splash && splash.parentNode) splash.parentNode.removeChild(splash);
|
||
}, 500);
|
||
}
|
||
window.__liftAppSplash = lift;
|
||
// Reassure the user if the backend is slow (e.g. right after a reboot)
|
||
setTimeout(function () {
|
||
if (!lifted && sub) sub.textContent = "Still starting\u2026 this can take a moment after a reboot.";
|
||
}, 8000);
|
||
// Never trap the user behind the splash
|
||
setTimeout(lift, 25000);
|
||
})();
|
||
</script>
|
||
|
||
<div class="app">
|
||
|
||
<!-- ═══ SIDEBAR ═══ -->
|
||
<aside class="sidebar" id="sidebar">
|
||
<div class="brand">
|
||
<img src="/static/sovran-hub-icon.svg" class="brand-logo" alt="The Hub" />
|
||
<div class="brand-text">
|
||
<div class="brand-title">The <em>Hub</em></div>
|
||
<div class="brand-sub">Sovran_SystemsOS v{{ sovran_version }}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<nav id="sidebar-nav" aria-label="Service categories"></nav>
|
||
|
||
<div class="nav-label">System</div>
|
||
<div id="sidebar-support"></div>
|
||
|
||
<!-- Feature Manager + Preferences (features.js) -->
|
||
<div id="sidebar-features"></div>
|
||
|
||
<div class="sidebar-spacer"></div>
|
||
</aside>
|
||
|
||
<!-- ═══ MAIN ═══ -->
|
||
<div class="main">
|
||
<header class="topbar">
|
||
<div class="page-title" id="page-title">Dashboard</div>
|
||
|
||
<div class="search-box">
|
||
<svg><use href="#g-search"/></svg>
|
||
<input id="search-input" type="text" placeholder="Search services…" autocomplete="off" />
|
||
</div>
|
||
|
||
<div class="top-actions">
|
||
<button class="btn btn-header-reboot" id="btn-header-reboot" title="Restart the entire computer">Reboot</button>
|
||
<button class="btn btn-logout" id="btn-logout" title="Sign out">Sign Out</button>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="content" id="content">
|
||
<!-- ═══ WELCOME DASHBOARD (default view) ═══ -->
|
||
<section class="welcome" id="welcome-view">
|
||
<div class="welcome-bg" aria-hidden="true">
|
||
<div class="orb orb-a"></div>
|
||
<div class="orb orb-b"></div>
|
||
<div class="orb orb-c"></div>
|
||
</div>
|
||
<div class="welcome-inner">
|
||
<div class="welcome-greeting" id="welcome-greeting">Hello</div>
|
||
<h1 class="welcome-title">Welcome to Your <em>Sovereign</em> Digital & Financial Life</h1>
|
||
<div class="welcome-meta">Sovran_SystemsOS v{{ sovran_version }}<span class="welcome-meta-sep">·</span><span id="welcome-role"></span></div>
|
||
<div class="welcome-cards" id="welcome-cards">
|
||
<div class="welcome-dyn" id="wc-systems"></div>
|
||
<div class="widget w-network" id="w-network">
|
||
<div class="widget-chip chip-green"><svg><use href="#g-wifi"/></svg></div>
|
||
<div class="w-body">
|
||
<h3>Network</h3>
|
||
<div class="net-row"><span class="net-k">LAN</span><span class="ip-value" id="ip-internal">…</span></div>
|
||
<div class="net-row"><span class="net-k">WAN</span><span class="ip-value" id="ip-external">…</span></div>
|
||
<div class="sub">sovransystemsos.local:8937</div>
|
||
</div>
|
||
</div>
|
||
<div class="welcome-dyn" id="wc-more"></div>
|
||
</div>
|
||
<button class="btn btn-ghost welcome-browse" id="welcome-browse-btn">Browse all services →</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ═══ SERVICES GRID ═══ -->
|
||
<div id="tiles-area" style="display:none">
|
||
<div class="dashboard-loading" role="status" aria-live="polite">
|
||
<span class="dashboard-loading-spinner" aria-hidden="true"></span>
|
||
<span>Loading service status…</span>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<!-- ═══ SYSTEMS OPERATIONAL MODAL (dashboard.js) ═══ -->
|
||
<div class="modal-overlay" id="systems-modal" role="dialog" aria-modal="true" aria-labelledby="systems-modal-title">
|
||
<div class="creds-dialog">
|
||
<div class="creds-header">
|
||
<span class="creds-title" id="systems-modal-title">
|
||
<span class="widget-chip chip-green" style="width:54px;height:54px;border-radius:16px"><svg style="width:27px;height:27px"><use href="#g-pulse"/></svg></span>
|
||
<span>Systems Operational</span>
|
||
</span>
|
||
<button class="creds-close-btn" id="systems-close-btn" title="Close">✕</button>
|
||
</div>
|
||
<div class="creds-body" id="systems-body">
|
||
<p class="creds-loading">Loading…</p>
|
||
</div>
|
||
<!-- Auto-launch preference (features.js) — moved here from the sidebar -->
|
||
<div class="sysprefs" id="autolaunch-slot"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Update modal -->
|
||
<div class="modal-overlay" id="update-modal" role="dialog" aria-modal="true" aria-labelledby="modal-title-text">
|
||
<div class="modal-dialog">
|
||
<div class="upd-header">
|
||
<span class="widget-chip chip-sovran upd-chip"><svg class="upd-chip-svg"><use href="#g-update"/></svg></span>
|
||
<span class="upd-title-wrap">
|
||
<span class="upd-title" id="modal-title-text">Sovran_SystemsOS Update</span>
|
||
<span class="upd-sub">
|
||
<span class="ver-chip">Sovran_SystemsOS v{{ sovran_version }}</span>
|
||
<span class="upd-pill" id="upd-pill"></span>
|
||
<span class="modal-spinner" id="modal-spinner"></span>
|
||
</span>
|
||
</span>
|
||
<button class="creds-close-btn" id="update-close-btn" title="Close">✕</button>
|
||
</div>
|
||
<div class="modal-body-scroll">
|
||
<div class="sysmodal-card">
|
||
<div class="sysmodal-card-title"><svg><use href="#g-server"/></svg>System Details</div>
|
||
<div class="sysstep"><div class="sysnum">1</div><div class="sysstep-x"><div class="sysstep-t">Current version</div><div class="sysval"><span class="sysval-text">{{ sovran_version }}</span></div></div></div>
|
||
<div class="sysstep"><div class="sysnum">2</div><div class="sysstep-x"><div class="sysstep-t">Release channel</div><div class="sysval"><span class="sysval-text">stable</span></div></div></div>
|
||
<div class="sysstep"><div class="sysnum">3</div><div class="sysstep-x"><div class="sysstep-t">Last checked</div><div class="sysval"><span class="sysval-text" id="upd-last-checked">—</span></div></div></div>
|
||
</div>
|
||
<div class="update-status-msg" id="modal-status">Checking for updates…</div>
|
||
<div class="modal-log" id="modal-log" aria-live="polite"></div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn-save" id="btn-save-report" style="display:none">Save Error Report</button>
|
||
<button class="btn btn-save" id="btn-retry-update-status" style="display:none">Retry Status</button>
|
||
<button class="btn btn-reboot" id="btn-retry-update" style="display:none">Retry Update</button>
|
||
<button class="btn btn-reboot" id="btn-reboot" style="display:none">Restart Entire System</button>
|
||
<span class="modal-footer-spacer"></span>
|
||
<button class="btn btn-close-modal" id="btn-close-modal" disabled>Close</button>
|
||
<button class="btn btn-primary" id="btn-check-again"><svg><use href="#g-refresh"/></svg>Check again</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Credentials info modal -->
|
||
<div class="modal-overlay" id="creds-modal" role="dialog" aria-modal="true" aria-labelledby="creds-modal-title">
|
||
<div class="creds-dialog">
|
||
<div class="creds-header">
|
||
<span class="creds-title" id="creds-modal-title">Service Info</span>
|
||
<button class="creds-close-btn" id="creds-close-btn" title="Close">✕</button>
|
||
</div>
|
||
<div class="creds-body" id="creds-body">
|
||
<p class="creds-loading">Loading…</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tech Support modal -->
|
||
<div class="modal-overlay" id="support-modal" role="dialog" aria-modal="true" aria-labelledby="support-modal-title">
|
||
<div class="creds-dialog">
|
||
<div class="creds-header">
|
||
<span class="creds-title">
|
||
<span class="widget-chip chip-neutral" id="support-modal-chip" style="width:54px;height:54px;border-radius:16px"><svg style="width:27px;height:27px"><use href="#g-lifebuoy"/></svg></span>
|
||
<span id="support-modal-title">Tech Support</span>
|
||
</span>
|
||
<button class="creds-close-btn" id="support-close-btn" title="Close">✕</button>
|
||
</div>
|
||
<div class="creds-body" id="support-body">
|
||
<p class="creds-loading">Loading…</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Domain Setup Modal -->
|
||
<div class="modal-overlay" id="domain-setup-modal" role="dialog" aria-modal="true" aria-labelledby="domain-setup-title">
|
||
<div class="creds-dialog">
|
||
<div class="creds-header">
|
||
<span class="creds-title" id="domain-setup-title">🌐 Domain Setup</span>
|
||
<button class="creds-close-btn" id="domain-setup-close-btn" title="Close">✕</button>
|
||
</div>
|
||
<div class="creds-body" id="domain-setup-body"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- SSL Email Modal -->
|
||
<div class="modal-overlay" id="ssl-email-modal" role="dialog" aria-modal="true" aria-labelledby="ssl-email-title">
|
||
<div class="creds-dialog domain-narrow-dialog">
|
||
<div class="creds-header">
|
||
<span class="creds-title" id="ssl-email-title">📧 SSL Certificate Email</span>
|
||
<button class="creds-close-btn" id="ssl-email-close-btn" title="Close">✕</button>
|
||
</div>
|
||
<div class="creds-body">
|
||
<p class="support-desc">Let's Encrypt needs an email address for SSL certificate notifications.</p>
|
||
<div class="domain-field-group">
|
||
<label class="domain-field-label" for="ssl-email-input">Email:</label>
|
||
<input class="domain-field-input" type="email" id="ssl-email-input" placeholder="you@example.com" />
|
||
</div>
|
||
<div class="domain-field-actions">
|
||
<button class="btn btn-close-modal" id="ssl-email-cancel-btn">Cancel</button>
|
||
<button class="btn btn-primary" id="ssl-email-save-btn">Save</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Feature Confirm Modal -->
|
||
<div class="modal-overlay" id="feature-confirm-modal" role="dialog" aria-modal="true" aria-labelledby="feature-confirm-title">
|
||
<div class="creds-dialog domain-narrow-dialog">
|
||
<div class="creds-header">
|
||
<span class="creds-title" id="feature-confirm-title">Confirm Action</span>
|
||
<button class="creds-close-btn" id="feature-confirm-close-btn" title="Close">✕</button>
|
||
</div>
|
||
<div class="creds-body">
|
||
<p class="support-desc" id="feature-confirm-message"></p>
|
||
<div class="domain-field-actions">
|
||
<button class="btn btn-close-modal" id="feature-confirm-cancel-btn">Cancel</button>
|
||
<button class="btn btn-primary" id="feature-confirm-ok-btn">Continue</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Port Requirements Modal -->
|
||
<div class="modal-overlay" id="port-requirements-modal" role="dialog" aria-modal="true" aria-labelledby="port-req-title">
|
||
<div class="creds-dialog">
|
||
<div class="creds-header">
|
||
<span class="creds-title" id="port-req-title">🔌 Router / Firewall Port Requirements</span>
|
||
<button class="creds-close-btn" id="port-req-close-btn" title="Close">✕</button>
|
||
</div>
|
||
<div class="creds-body" id="port-req-body"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Rebuild Modal -->
|
||
<div class="modal-overlay" id="rebuild-modal" role="dialog" aria-modal="true" aria-labelledby="rebuild-modal-title">
|
||
<div class="modal-dialog">
|
||
<div class="upd-header">
|
||
<span class="widget-chip chip-sovran upd-chip"><svg class="upd-chip-svg"><use href="#g-server"/></svg></span>
|
||
<span class="upd-title-wrap">
|
||
<span class="upd-title" id="rebuild-modal-title">Sovran_SystemsOS Rebuild</span>
|
||
<span class="upd-sub">
|
||
<span class="ver-chip">Sovran_SystemsOS v{{ sovran_version }}</span>
|
||
<span class="upd-pill" id="rebuild-pill"></span>
|
||
<span class="modal-spinner" id="rebuild-spinner"></span>
|
||
</span>
|
||
</span>
|
||
<button class="creds-close-btn" id="rebuild-close-hdr" title="Close">✕</button>
|
||
</div>
|
||
<div class="modal-body-scroll">
|
||
<div class="update-status-msg" id="rebuild-status">Rebuilding…</div>
|
||
<div class="modal-log" id="rebuild-log" aria-live="polite" style="display:none"></div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn-save" id="rebuild-save-report" style="display:none">Save Error Report</button>
|
||
<button class="btn btn-reboot" id="rebuild-reboot-btn" style="display:none">Restart Entire System</button>
|
||
<span class="modal-footer-spacer"></span>
|
||
<button class="btn btn-close-modal" id="rebuild-close-btn" disabled>Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Upgrade Modal (Node → Server+Desktop) -->
|
||
<div class="modal-overlay" id="upgrade-modal" role="dialog" aria-modal="true" aria-labelledby="upgrade-modal-title">
|
||
<div class="creds-dialog upgrade-dialog">
|
||
<div class="creds-header">
|
||
<span class="creds-title" id="upgrade-modal-title">🚀 Upgrade to Server + Desktop</span>
|
||
<button class="creds-close-btn" id="upgrade-close-btn" title="Close">✕</button>
|
||
</div>
|
||
<div class="creds-body">
|
||
<p class="support-desc">
|
||
Upgrading to the full <strong>Server + Desktop</strong> experience will unlock all services —
|
||
encrypted messaging, password management, cloud storage, website hosting, and more.
|
||
</p>
|
||
<div class="upgrade-info-box">
|
||
<p class="upgrade-info-title">Simple, guided setup:</p>
|
||
<ul class="upgrade-info-list">
|
||
<li>Sovran_SystemsOS walks you through getting your domain from <a href="https://njal.la" target="_blank" rel="noopener noreferrer">Njal.la</a> and connecting your services</li>
|
||
<li>To make your services available outside your home, complete one router task: forward ports <strong>80 and 443</strong> to this computer</li>
|
||
</ul>
|
||
</div>
|
||
<p class="support-desc">
|
||
⚠️ <strong>Heads-up:</strong> your domain points at your home internet connection,
|
||
so anyone can look up your home IP address. Domain privacy does not hide it.
|
||
</p>
|
||
<p class="support-desc">
|
||
The Hub guides you through every step.
|
||
</p>
|
||
<p class="support-desc upgrade-rebuild-note">
|
||
The system will rebuild after upgrading. This may take several minutes.
|
||
</p>
|
||
<div class="domain-field-actions">
|
||
<button class="btn btn-close-modal" id="upgrade-cancel-btn">Cancel</button>
|
||
<button class="btn btn-primary" id="upgrade-confirm-btn">Yes, Upgrade</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Security Reset overlay -->
|
||
<div class="security-reset-overlay" id="security-reset-overlay">
|
||
<!-- Phase 1: wiping in progress -->
|
||
<div class="reboot-card" id="security-reset-phase1">
|
||
<div class="security-reset-overlay-icon">🛡</div>
|
||
<h2 class="reboot-title">Security Reset In Progress</h2>
|
||
<p class="reboot-message">
|
||
⚠️ Wiping all data and credentials.<br />
|
||
<strong>Do not power off your computer.</strong><br />
|
||
This may take several minutes.
|
||
</p>
|
||
<div class="reboot-dots">
|
||
<span class="reboot-dot"></span>
|
||
<span class="reboot-dot"></span>
|
||
<span class="reboot-dot"></span>
|
||
</div>
|
||
<p class="reboot-submessage" id="security-reset-overlay-step">Erasing data and resetting credentials…</p>
|
||
</div>
|
||
<!-- Phase 2: password display -->
|
||
<div class="reboot-card" id="security-reset-phase2" style="display:none;">
|
||
<div class="security-reset-overlay-icon">🔑</div>
|
||
<h2 class="reboot-title">Security Reset Complete</h2>
|
||
<p class="security-reset-password-label">Your new login password is:</p>
|
||
<div class="security-reset-password-box" id="security-reset-new-password"> </div>
|
||
<p class="security-reset-password-warning">
|
||
✍️ <strong>Write this down now.</strong><br />
|
||
You will need it to log in to your computer<br />and the Sovran Hub at <em>sovransystemsos.local:8937</em>.
|
||
</p>
|
||
<button class="security-reset-reboot-btn" id="security-reset-reboot-btn" disabled>
|
||
I have written down my new password — Restart Entire System
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Reboot overlay -->
|
||
<div class="reboot-overlay" id="reboot-overlay">
|
||
<!-- Normal restarting card -->
|
||
<div class="reboot-card" id="reboot-main-card">
|
||
<div class="reboot-icon" aria-hidden="true"></div>
|
||
<h2 class="reboot-title">Restarting Entire System</h2>
|
||
<p class="reboot-message">
|
||
The entire computer is restarting, including the desktop and all hosted services.<br />
|
||
This page will reconnect automatically when Sovran_SystemsOS is back online.
|
||
</p>
|
||
<div class="reboot-dots" aria-hidden="true">
|
||
<span class="reboot-dot"></span>
|
||
<span class="reboot-dot"></span>
|
||
<span class="reboot-dot"></span>
|
||
</div>
|
||
<p class="reboot-submessage" id="reboot-submessage" aria-live="polite">Sending restart request…</p>
|
||
</div>
|
||
<!-- Error card (shown if restart request fails definitively) -->
|
||
<div class="reboot-card" id="reboot-error-card" style="display:none">
|
||
<div class="reboot-icon" aria-hidden="true"></div>
|
||
<h2 class="reboot-title">Restart could not be started</h2>
|
||
<p class="reboot-message">
|
||
The computer did not begin restarting. No services were intentionally stopped. Please try again.
|
||
</p>
|
||
<div class="reboot-error-actions">
|
||
<button class="btn btn-close-modal" id="reboot-error-close-btn">Close</button>
|
||
<button class="btn btn-restart-amber" id="reboot-error-retry-btn">Try Again</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Restart Confirm Dialog -->
|
||
<div class="modal-overlay" id="restart-confirm-modal" role="dialog" aria-modal="true" aria-labelledby="restart-confirm-title">
|
||
<div class="creds-dialog domain-narrow-dialog">
|
||
<div class="creds-header">
|
||
<span class="creds-title" id="restart-confirm-title">Restart the entire computer?</span>
|
||
</div>
|
||
<div class="creds-body">
|
||
<div id="restart-conflict-box" class="restart-conflict-box" style="display:none">
|
||
<p class="restart-conflict-title">The system cannot restart right now.</p>
|
||
<p class="restart-conflict-desc">A system update, rebuild, backup, restore, or security operation is currently running. Wait for it to finish, then try again.</p>
|
||
</div>
|
||
<p class="support-desc"><strong>This will reboot the physical machine running Sovran_SystemsOS — not just the Hub.</strong></p>
|
||
<p class="support-desc">The desktop and all hosted services will stop temporarily and restart with the computer. Anyone currently using these services will be disconnected.</p>
|
||
<p class="support-desc">The system usually returns within 1–3 minutes. This page will reconnect automatically.</p>
|
||
<div class="domain-field-actions">
|
||
<button class="btn btn-close-modal" id="restart-confirm-cancel-btn">Cancel</button>
|
||
<button class="btn btn-restart-amber" id="restart-confirm-ok-btn">Restart Entire System</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="/static/js/constants.js?v={{ asset_version }}"></script>
|
||
<script src="/static/js/state.js?v={{ asset_version }}"></script>
|
||
<script src="/static/js/helpers.js?v={{ asset_version }}"></script>
|
||
<script src="/static/js/domain-prereqs.js?v={{ asset_version }}"></script>
|
||
<script src="/static/js/tiles.js?v={{ asset_version }}"></script>
|
||
<script src="/static/js/service-detail.js?v={{ asset_version }}"></script>
|
||
<script src="/static/js/support.js?v={{ asset_version }}"></script>
|
||
<script src="/static/js/update.js?v={{ asset_version }}"></script>
|
||
<script src="/static/js/rebuild.js?v={{ asset_version }}"></script>
|
||
<script src="/static/js/features.js?v={{ asset_version }}"></script>
|
||
<script src="/static/js/security.js?v={{ asset_version }}"></script>
|
||
<script src="/static/js/dashboard.js?v={{ asset_version }}"></script>
|
||
<script src="/static/js/events.js?v={{ asset_version }}"></script>
|
||
</body>
|
||
</html>
|