diff --git a/iso/overlay/airootfs/etc/hostname b/iso/overlay/airootfs/etc/hostname new file mode 100644 index 0000000..76051cd --- /dev/null +++ b/iso/overlay/airootfs/etc/hostname @@ -0,0 +1 @@ +proksi diff --git a/iso/overlay/airootfs/etc/issue b/iso/overlay/airootfs/etc/issue new file mode 100644 index 0000000..42ea414 --- /dev/null +++ b/iso/overlay/airootfs/etc/issue @@ -0,0 +1,6 @@ + + Furtka Live Installer starting… + + Once ready, open http://proksi.local:5000 on another device + on your network. The exact URL will appear below. + diff --git a/iso/overlay/airootfs/etc/systemd/system/furtka-issue.service b/iso/overlay/airootfs/etc/systemd/system/furtka-issue.service new file mode 100644 index 0000000..d1768ed --- /dev/null +++ b/iso/overlay/airootfs/etc/systemd/system/furtka-issue.service @@ -0,0 +1,12 @@ +[Unit] +Description=Write Furtka /etc/issue with current IP for the console welcome +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/furtka-update-issue +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/iso/overlay/airootfs/etc/systemd/system/multi-user.target.wants/furtka-issue.service b/iso/overlay/airootfs/etc/systemd/system/multi-user.target.wants/furtka-issue.service new file mode 120000 index 0000000..1b8a2e3 --- /dev/null +++ b/iso/overlay/airootfs/etc/systemd/system/multi-user.target.wants/furtka-issue.service @@ -0,0 +1 @@ +../furtka-issue.service \ No newline at end of file diff --git a/iso/overlay/airootfs/usr/local/bin/furtka-update-issue b/iso/overlay/airootfs/usr/local/bin/furtka-update-issue new file mode 100755 index 0000000..e0b649f --- /dev/null +++ b/iso/overlay/airootfs/usr/local/bin/furtka-update-issue @@ -0,0 +1,23 @@ +#!/bin/bash +# Regenerates /etc/issue so the live-ISO console tells the user which URL +# to open in their browser. Shows proksi.local (via avahi/mDNS) as the +# preferred URL and the raw IP as a fallback for networks where mDNS +# doesn't work. Reload at the end nudges agetty to redraw. +set -e + +ip=$(ip -4 -o addr show scope global 2>/dev/null | awk '{print $4}' | cut -d/ -f1 | head -1) + +{ + echo + echo " Open Furtka in a browser on another device on your network:" + echo + echo " http://proksi.local:5000 (easy — try this first)" + if [ -n "$ip" ]; then + echo " http://${ip}:5000 (fallback if the first doesn't work)" + fi + echo + echo " Then follow the wizard to install Furtka on this machine." + echo +} > /etc/issue + +agetty --reload 2>/dev/null || true diff --git a/webinstaller/app.py b/webinstaller/app.py index e7e3dde..69bf035 100644 --- a/webinstaller/app.py +++ b/webinstaller/app.py @@ -5,7 +5,7 @@ import subprocess from pathlib import Path from drives import list_scored_devices -from flask import Flask, redirect, render_template, request, url_for +from flask import Flask, jsonify, redirect, render_template, request, url_for app = Flask(__name__) @@ -269,5 +269,25 @@ def install_log_view(): ) +@app.route("/install/log.json") +def install_log_json(): + log = INSTALL_LOG.read_text() if INSTALL_LOG.exists() else "" + return jsonify(log=log, progress=parse_install_progress(log)) + + +@app.route("/install/reboot", methods=["POST"]) +def install_reboot(): + # Only allow rebooting once the install has actually finished — we don't + # want a panicked click during install to reboot mid-pacstrap. + log = INSTALL_LOG.read_text() if INSTALL_LOG.exists() else "" + if parse_install_progress(log)["status"] != "done": + return redirect(url_for("install_log_view")) + subprocess.Popen( + ["/usr/bin/systemctl", "reboot"], + start_new_session=True, + ) + return render_template("install/rebooting.html") + + if __name__ == "__main__": app.run(debug=True, port=5000) diff --git a/webinstaller/templates/install/log.html b/webinstaller/templates/install/log.html index 392ca3a..00e530d 100644 --- a/webinstaller/templates/install/log.html +++ b/webinstaller/templates/install/log.html @@ -2,29 +2,96 @@ {% block title %}Installing… · Furtka Installer{% endblock %} {% block head_extra %} +{# Fallback for users with JS disabled — otherwise the JS below takes over + and updates in-place so the log
doesn't re-collapse. #} + {% endblock %} {% block step_indicator %}Installing{% endblock %} {% block content %} +

+{% if progress.status == "done" %}Furtka is ready +{% elif progress.status == "error" %}Installation hit a snag +{% else %}Installing Furtka{% endif %} +

+

+{% if progress.status == "done" %}Installation finished. Remove the installer USB / eject the ISO, then click Reboot. +{% elif progress.status == "error" %}Something went wrong. Open the details below and share them so we can help. +{% else %}This takes a few minutes. Don't close this page or power off the machine.{% endif %} +

+ {% if progress.status == "done" %} -

Furtka is ready

-

Installation finished. Remove the USB / eject the installer image, then reboot.

-{% elif progress.status == "error" %} -

Installation hit a snag

-

Something went wrong. Open the details below and share them so we can help.

-{% else %} -

Installing Furtka

-

This takes a few minutes. Don't close this page or power off the machine.

+
+
+ +
+
{% endif %}
-
+
-

{{ progress.phase }} · {{ progress.percent }}%

+

{{ progress.phase }} · {{ progress.percent }}%

Show details -
{{ log or "(waiting for install to start)" }}
+
{{ log or "(waiting for install to start)" }}
+ + {% endblock %} diff --git a/webinstaller/templates/install/rebooting.html b/webinstaller/templates/install/rebooting.html new file mode 100644 index 0000000..a9754f8 --- /dev/null +++ b/webinstaller/templates/install/rebooting.html @@ -0,0 +1,10 @@ +{% extends "base.html" %} + +{% block title %}Rebooting · Furtka Installer{% endblock %} +{% block step_indicator %}Done{% endblock %} + +{% block content %} +

Rebooting…

+

The machine is restarting. This page will stop responding in a moment — that's expected.

+

When the machine comes back up, log in with the username and password you set during the install.

+{% endblock %}