Fix ISO installer: remove ports dialog, fix Plymouth paths/logo, add welcome page, fix pixelated icon, fix disko args
Agent-Logs-Url: https://github.com/naturallaw777/staging_alpha/sessions/6b00bbbd-8ed5-4ef2-b2fc-bfbe6361e77c Co-authored-by: naturallaw777 <99053422+naturallaw777@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
f4a644dc05
commit
48826590de
Binary file not shown.
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 31 KiB |
252
iso/installer.py
252
iso/installer.py
@@ -117,11 +117,8 @@ class InstallerWindow(Adw.ApplicationWindow):
|
|||||||
self.nav = Adw.NavigationView()
|
self.nav = Adw.NavigationView()
|
||||||
self.set_content(self.nav)
|
self.set_content(self.nav)
|
||||||
|
|
||||||
# Check for internet before anything else
|
# Always show the landing/welcome page first
|
||||||
if check_internet():
|
self.push_landing()
|
||||||
self.push_welcome()
|
|
||||||
else:
|
|
||||||
self.push_no_internet()
|
|
||||||
|
|
||||||
# ── Navigation helpers ─────────────────────────────────────────────────
|
# ── Navigation helpers ─────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -197,54 +194,93 @@ class InstallerWindow(Adw.ApplicationWindow):
|
|||||||
|
|
||||||
return box
|
return box
|
||||||
|
|
||||||
# ── No Internet Screen ─────────────────────────────────────────────────
|
# ── Landing / Welcome Screen ───────────────────────────────────────────
|
||||||
|
|
||||||
def push_no_internet(self):
|
def push_landing(self):
|
||||||
|
"""First screen: always shown. Welcomes the user and checks connectivity."""
|
||||||
outer = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
|
outer = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
|
||||||
|
|
||||||
status = Adw.StatusPage()
|
# Hero
|
||||||
status.set_title("No Internet Connection")
|
hero = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8)
|
||||||
status.set_description(
|
hero.set_margin_top(40)
|
||||||
"An active internet connection is required to install Sovran_SystemsOS.\n\n"
|
hero.set_margin_bottom(16)
|
||||||
"Please connect an Ethernet cable or configure Wi-Fi,\n"
|
hero.set_halign(Gtk.Align.CENTER)
|
||||||
"then press Retry."
|
|
||||||
)
|
|
||||||
status.set_icon_name("network-offline-symbolic")
|
|
||||||
status.set_vexpand(True)
|
|
||||||
outer.append(status)
|
|
||||||
|
|
||||||
|
if os.path.exists(LOGO):
|
||||||
|
try:
|
||||||
|
img = Gtk.Image.new_from_file(LOGO)
|
||||||
|
img.set_pixel_size(320)
|
||||||
|
hero.append(img)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
title = Gtk.Label()
|
||||||
|
title.set_markup("<span size='xx-large' weight='heavy'>Welcome to Sovran SystemsOS</span>")
|
||||||
|
title.set_margin_top(8)
|
||||||
|
hero.append(title)
|
||||||
|
|
||||||
|
sub = Gtk.Label()
|
||||||
|
sub.set_markup("<span size='large' style='italic' foreground='#888888'>Be Digitally Sovereign</span>")
|
||||||
|
hero.append(sub)
|
||||||
|
|
||||||
|
outer.append(hero)
|
||||||
|
|
||||||
|
sep = Gtk.Separator()
|
||||||
|
sep.set_margin_start(40)
|
||||||
|
sep.set_margin_end(40)
|
||||||
|
sep.set_margin_top(8)
|
||||||
|
outer.append(sep)
|
||||||
|
|
||||||
|
# Internet requirement notice
|
||||||
|
notice = Gtk.Label()
|
||||||
|
notice.set_markup(
|
||||||
|
"<span size='medium'>"
|
||||||
|
"Before installation begins, please ensure you have an <b>active internet connection</b>.\n"
|
||||||
|
"Sovran SystemsOS downloads packages during installation and requires internet access\n"
|
||||||
|
"to complete the process. Connect via <b>Ethernet cable</b> or configure <b>Wi-Fi</b> now."
|
||||||
|
"</span>"
|
||||||
|
)
|
||||||
|
notice.set_justify(Gtk.Justification.CENTER)
|
||||||
|
notice.set_wrap(True)
|
||||||
|
notice.set_margin_top(20)
|
||||||
|
notice.set_margin_start(48)
|
||||||
|
notice.set_margin_end(48)
|
||||||
|
outer.append(notice)
|
||||||
|
|
||||||
|
# Inline offline warning banner (hidden by default)
|
||||||
|
self._offline_banner = Adw.Banner()
|
||||||
|
self._offline_banner.set_title(
|
||||||
|
"No internet connection detected. Please connect Ethernet or Wi-Fi and try again."
|
||||||
|
)
|
||||||
|
self._offline_banner.set_revealed(False)
|
||||||
|
self._offline_banner.set_margin_top(12)
|
||||||
|
self._offline_banner.set_margin_start(40)
|
||||||
|
self._offline_banner.set_margin_end(40)
|
||||||
|
outer.append(self._offline_banner)
|
||||||
|
|
||||||
|
outer.append(Gtk.Label(label="", vexpand=True))
|
||||||
|
|
||||||
|
# Check & Continue button
|
||||||
btn_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=12)
|
btn_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=12)
|
||||||
btn_box.set_halign(Gtk.Align.CENTER)
|
btn_box.set_halign(Gtk.Align.CENTER)
|
||||||
btn_box.set_margin_bottom(32)
|
btn_box.set_margin_bottom(32)
|
||||||
|
|
||||||
retry_btn = Gtk.Button(label="Retry")
|
connect_btn = Gtk.Button(label="Check Connection & Continue →")
|
||||||
retry_btn.add_css_class("suggested-action")
|
connect_btn.add_css_class("suggested-action")
|
||||||
retry_btn.add_css_class("pill")
|
connect_btn.add_css_class("pill")
|
||||||
retry_btn.connect("clicked", self.on_retry_internet)
|
connect_btn.connect("clicked", self._on_landing_connect)
|
||||||
btn_box.append(retry_btn)
|
btn_box.append(connect_btn)
|
||||||
|
|
||||||
outer.append(btn_box)
|
outer.append(btn_box)
|
||||||
|
|
||||||
self.push_page("No Internet", outer)
|
self.push_page("Sovran_SystemsOS Installer", outer)
|
||||||
|
|
||||||
def on_retry_internet(self, btn):
|
def _on_landing_connect(self, btn):
|
||||||
if check_internet():
|
if check_internet():
|
||||||
# Pop the no-internet page and proceed to welcome
|
self._offline_banner.set_revealed(False)
|
||||||
try:
|
|
||||||
self.nav.pop()
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
self.push_welcome()
|
self.push_welcome()
|
||||||
else:
|
else:
|
||||||
dlg = Adw.MessageDialog()
|
self._offline_banner.set_revealed(True)
|
||||||
dlg.set_transient_for(self)
|
|
||||||
dlg.set_heading("Still Offline")
|
|
||||||
dlg.set_body(
|
|
||||||
"Could not reach the internet.\n"
|
|
||||||
"Please check your network connection and try again."
|
|
||||||
)
|
|
||||||
dlg.add_response("ok", "OK")
|
|
||||||
dlg.present()
|
|
||||||
|
|
||||||
# ── Step 1: Welcome & Role ─────────────────────────────────────────────
|
# ── Step 1: Welcome & Role ─────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -341,140 +377,7 @@ class InstallerWindow(Adw.ApplicationWindow):
|
|||||||
if radio.get_active():
|
if radio.get_active():
|
||||||
self.role = radio.get_name()
|
self.role = radio.get_name()
|
||||||
break
|
break
|
||||||
self.push_port_requirements()
|
self.push_disk_detect()
|
||||||
|
|
||||||
# ── Step 1b: Port Requirements Notice ─────────────────────────────────
|
|
||||||
|
|
||||||
def push_port_requirements(self):
|
|
||||||
"""Inform the user about required router/firewall ports before install."""
|
|
||||||
outer = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
|
|
||||||
|
|
||||||
# Detect internal IP at install time
|
|
||||||
internal_ip = "this machine's LAN IP"
|
|
||||||
try:
|
|
||||||
import subprocess as _sp
|
|
||||||
_r = _sp.run(["hostname", "-I"], capture_output=True, text=True, timeout=5)
|
|
||||||
if _r.returncode == 0:
|
|
||||||
_parts = _r.stdout.strip().split()
|
|
||||||
if _parts:
|
|
||||||
internal_ip = _parts[0]
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Warning banner
|
|
||||||
banner = Adw.Banner()
|
|
||||||
banner.set_title(
|
|
||||||
"⚠ Port Forwarding Setup Required — configure your router before install"
|
|
||||||
)
|
|
||||||
banner.set_revealed(True)
|
|
||||||
banner.set_margin_top(16)
|
|
||||||
banner.set_margin_start(40)
|
|
||||||
banner.set_margin_end(40)
|
|
||||||
outer.append(banner)
|
|
||||||
|
|
||||||
intro = Gtk.Label()
|
|
||||||
intro.set_markup(
|
|
||||||
"<span foreground='#a6adc8'>"
|
|
||||||
"Many Sovran_SystemsOS features require <b>port forwarding</b> to be configured "
|
|
||||||
"in your router's admin panel. This means telling your router to forward "
|
|
||||||
"specific ports to <b>this machine's internal LAN IP</b>.\n\n"
|
|
||||||
"Services like Element Video/Audio Calling and Matrix Federation "
|
|
||||||
"<b>will not work for clients outside your LAN</b> unless these ports are "
|
|
||||||
"forwarded to this machine."
|
|
||||||
"</span>"
|
|
||||||
)
|
|
||||||
intro.set_wrap(True)
|
|
||||||
intro.set_justify(Gtk.Justification.FILL)
|
|
||||||
intro.set_margin_top(14)
|
|
||||||
intro.set_margin_start(40)
|
|
||||||
intro.set_margin_end(40)
|
|
||||||
outer.append(intro)
|
|
||||||
|
|
||||||
ip_label = Gtk.Label()
|
|
||||||
ip_label.set_markup(
|
|
||||||
f"<span foreground='#89b4fa' font_desc='monospace'>"
|
|
||||||
f" Forward ports to this machine's internal IP: <b>{internal_ip}</b>"
|
|
||||||
f"</span>"
|
|
||||||
)
|
|
||||||
ip_label.set_margin_top(10)
|
|
||||||
ip_label.set_margin_start(40)
|
|
||||||
ip_label.set_margin_end(40)
|
|
||||||
outer.append(ip_label)
|
|
||||||
|
|
||||||
sw = Gtk.ScrolledWindow()
|
|
||||||
sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
|
|
||||||
sw.set_vexpand(True)
|
|
||||||
sw.set_margin_start(40)
|
|
||||||
sw.set_margin_end(40)
|
|
||||||
sw.set_margin_top(12)
|
|
||||||
sw.set_margin_bottom(8)
|
|
||||||
|
|
||||||
ports_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12)
|
|
||||||
|
|
||||||
port_sections = [
|
|
||||||
(
|
|
||||||
"🌐 Web / HTTPS (all domain-based services)",
|
|
||||||
[("80", "TCP", "HTTP (redirects to HTTPS)"),
|
|
||||||
("443", "TCP", "HTTPS")],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"💬 Matrix Federation (Matrix-Synapse)",
|
|
||||||
[("8448", "TCP", "Server-to-server federation")],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"🎥 Element Video & Audio Calling (LiveKit / Element-call)",
|
|
||||||
[("7881", "TCP", "LiveKit WebRTC signalling"),
|
|
||||||
("7882-7894", "UDP", "LiveKit media streams"),
|
|
||||||
("5349", "TCP", "TURN over TLS"),
|
|
||||||
("3478", "UDP", "TURN (STUN / relay)"),
|
|
||||||
("30000-40000", "TCP/UDP", "TURN relay (WebRTC media)")],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"🖥 Remote SSH (optional — only if you want WAN SSH access)",
|
|
||||||
[("22", "TCP", "SSH")],
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
for section_title, rows in port_sections:
|
|
||||||
group = Adw.PreferencesGroup()
|
|
||||||
group.set_title(section_title)
|
|
||||||
|
|
||||||
for port, proto, desc in rows:
|
|
||||||
row = Adw.ActionRow()
|
|
||||||
row.set_title(f"Port {port} ({proto})")
|
|
||||||
row.set_subtitle(desc)
|
|
||||||
group.add(row)
|
|
||||||
|
|
||||||
ports_box.append(group)
|
|
||||||
|
|
||||||
note = Gtk.Label()
|
|
||||||
note.set_markup(
|
|
||||||
"<span foreground='#6c7086' size='small'>"
|
|
||||||
"ℹ In your router's admin panel (usually at 192.168.1.1), find the "
|
|
||||||
"\"<b>Port Forwarding</b>\" section and add a rule for each port above with "
|
|
||||||
"the destination set to <b>this machine's internal IP</b>. "
|
|
||||||
"These ports only need to be forwarded to this specific machine — "
|
|
||||||
"this does <b>NOT</b> expose your entire network.\n"
|
|
||||||
"To verify forwarding is working, test from a device on a different network "
|
|
||||||
"(e.g. a phone on mobile data) or check your router's port forwarding page."
|
|
||||||
"</span>"
|
|
||||||
)
|
|
||||||
note.set_wrap(True)
|
|
||||||
note.set_justify(Gtk.Justification.FILL)
|
|
||||||
note.set_margin_top(8)
|
|
||||||
ports_box.append(note)
|
|
||||||
|
|
||||||
sw.set_child(ports_box)
|
|
||||||
outer.append(sw)
|
|
||||||
|
|
||||||
outer.append(self.nav_row(
|
|
||||||
back_label="← Back",
|
|
||||||
back_cb=lambda b: self.nav.pop(),
|
|
||||||
next_label="I Understand →",
|
|
||||||
next_cb=lambda b: self.push_disk_detect(),
|
|
||||||
))
|
|
||||||
|
|
||||||
self.push_page("Network Port Requirements", outer, show_back=True)
|
|
||||||
|
|
||||||
# ── Step 2a: Disk Detect ──────────────────────────────────────────────
|
# ── Step 2a: Disk Detect ──────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -773,7 +676,6 @@ class InstallerWindow(Adw.ApplicationWindow):
|
|||||||
status = Adw.StatusPage()
|
status = Adw.StatusPage()
|
||||||
status.set_title(title)
|
status.set_title(title)
|
||||||
status.set_description(subtitle)
|
status.set_description(subtitle)
|
||||||
status.set_icon_name("emblem-synchronizing-symbolic")
|
|
||||||
status.set_vexpand(False)
|
status.set_vexpand(False)
|
||||||
outer.append(status)
|
outer.append(status)
|
||||||
|
|
||||||
@@ -830,10 +732,10 @@ class InstallerWindow(Adw.ApplicationWindow):
|
|||||||
cmd = [
|
cmd = [
|
||||||
"sudo", "disko", "--mode", "destroy,format,mount",
|
"sudo", "disko", "--mode", "destroy,format,mount",
|
||||||
f"{FLAKE}/iso/disko.nix",
|
f"{FLAKE}/iso/disko.nix",
|
||||||
"--arg", "device", f'"{boot_path}"'
|
"--arg", "device", boot_path
|
||||||
]
|
]
|
||||||
if data_path:
|
if data_path:
|
||||||
cmd += ["--arg", "dataDevice", f'"{data_path}"']
|
cmd += ["--arg", "dataDevice", data_path]
|
||||||
run_stream(cmd, buf)
|
run_stream(cmd, buf)
|
||||||
|
|
||||||
GLib.idle_add(append_text, buf, "\n=== Generating hardware config ===\n")
|
GLib.idle_add(append_text, buf, "\n=== Generating hardware config ===\n")
|
||||||
|
|||||||
@@ -10,15 +10,15 @@ pkgs.stdenv.mkDerivation {
|
|||||||
mkdir -p $out/share/plymouth/themes/sovran
|
mkdir -p $out/share/plymouth/themes/sovran
|
||||||
cp ${./assets/splash-logo.png} $out/share/plymouth/themes/sovran/logo.png
|
cp ${./assets/splash-logo.png} $out/share/plymouth/themes/sovran/logo.png
|
||||||
|
|
||||||
cat > $out/share/plymouth/themes/sovran/sovran.plymouth <<'EOF'
|
cat > $out/share/plymouth/themes/sovran/sovran.plymouth <<EOF
|
||||||
[Plymouth Theme]
|
[Plymouth Theme]
|
||||||
Name=Sovran Systems
|
Name=Sovran Systems
|
||||||
Description=Sovran Systems Splash
|
Description=Sovran Systems Splash
|
||||||
ModuleName=script
|
ModuleName=script
|
||||||
|
|
||||||
[script]
|
[script]
|
||||||
ImageDir=/share/plymouth/themes/sovran
|
ImageDir=$out/share/plymouth/themes/sovran
|
||||||
ScriptFile=/share/plymouth/themes/sovran/sovran.script
|
ScriptFile=$out/share/plymouth/themes/sovran/sovran.script
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat > $out/share/plymouth/themes/sovran/sovran.script <<'EOF'
|
cat > $out/share/plymouth/themes/sovran/sovran.script <<'EOF'
|
||||||
|
|||||||
Reference in New Issue
Block a user