feat: webinstaller writes archinstall config + execs install, styled
Wires the live-ISO wizard from "shows three screens" to "actually invokes
archinstall on the chosen disk", plus first-pass styling so it stops looking
like raw <h1>/<form>.
Webinstaller flow:
- S1 form gains username/password/password2/language with server-side
validation (hostname/username regex, ≥8 char password, match check).
- /install/run writes user_configuration.json + user_credentials.json
(creds 0600) to FURTKA_STATE_DIR (default /tmp/furtka), then execs
`archinstall --config … --creds … --silent` as a backgrounded subprocess.
- /install/log renders the subprocess output via meta-refresh polling.
- FURTKA_DRY_RUN=1 short-circuits the exec for testing.
- archinstall flag names verified against `archinstall --help` in an
archlinux container before committing.
Drive list:
- drives.py now filters via `lsblk … -o NAME,SIZE,TYPE` keeping TYPE=disk,
so the live ISO's own squashfs (loop) and CD-ROM (rom) stop appearing
as install targets.
Boot menu:
- iso/build.sh sed-rebrands "Arch Linux install medium" →
"Furtka Live Installer" across grub/, syslinux/, and efiboot/loader/
entries. Verified zero leftovers against the current releng profile.
Styling:
- static/style.css adopts the website's design tokens (palette,
typography, gate-mark accent), with light + dark via prefers-color-scheme.
- New base.html with header (gate SVG + FURTKA·INSTALLER wordmark + step
indicator) and footer; all install templates extend it.
- Drive picker uses radio cards with score chip; overview uses a summary
table and a destructive "wipe drive" button.
Tests: 17 pass (4 new in test_app.py covering validation + config builders,
2 new in test_drives.py covering the lsblk filter). Ruff clean.
README roadmap updated to mark these done and explicitly defer the
26.0-alpha release until archinstall actually completes end-to-end on a VM.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 10:54:49 +02:00
|
|
|
{% extends "base.html" %}
|
|
|
|
|
|
|
|
|
|
{% block title %}Installing… · Furtka Installer{% endblock %}
|
2026-04-14 17:07:57 +02:00
|
|
|
{% block head_extra %}
|
2026-04-14 18:08:59 +02:00
|
|
|
{# Fallback for users with JS disabled — otherwise the JS below takes over
|
|
|
|
|
and updates in-place so the log <details> doesn't re-collapse. #}
|
|
|
|
|
<noscript>
|
2026-04-14 17:07:57 +02:00
|
|
|
{% if progress.status == "running" %}<meta http-equiv="refresh" content="3">{% endif %}
|
2026-04-14 18:08:59 +02:00
|
|
|
</noscript>
|
2026-04-14 17:07:57 +02:00
|
|
|
{% endblock %}
|
feat: webinstaller writes archinstall config + execs install, styled
Wires the live-ISO wizard from "shows three screens" to "actually invokes
archinstall on the chosen disk", plus first-pass styling so it stops looking
like raw <h1>/<form>.
Webinstaller flow:
- S1 form gains username/password/password2/language with server-side
validation (hostname/username regex, ≥8 char password, match check).
- /install/run writes user_configuration.json + user_credentials.json
(creds 0600) to FURTKA_STATE_DIR (default /tmp/furtka), then execs
`archinstall --config … --creds … --silent` as a backgrounded subprocess.
- /install/log renders the subprocess output via meta-refresh polling.
- FURTKA_DRY_RUN=1 short-circuits the exec for testing.
- archinstall flag names verified against `archinstall --help` in an
archlinux container before committing.
Drive list:
- drives.py now filters via `lsblk … -o NAME,SIZE,TYPE` keeping TYPE=disk,
so the live ISO's own squashfs (loop) and CD-ROM (rom) stop appearing
as install targets.
Boot menu:
- iso/build.sh sed-rebrands "Arch Linux install medium" →
"Furtka Live Installer" across grub/, syslinux/, and efiboot/loader/
entries. Verified zero leftovers against the current releng profile.
Styling:
- static/style.css adopts the website's design tokens (palette,
typography, gate-mark accent), with light + dark via prefers-color-scheme.
- New base.html with header (gate SVG + FURTKA·INSTALLER wordmark + step
indicator) and footer; all install templates extend it.
- Drive picker uses radio cards with score chip; overview uses a summary
table and a destructive "wipe drive" button.
Tests: 17 pass (4 new in test_app.py covering validation + config builders,
2 new in test_drives.py covering the lsblk filter). Ruff clean.
README roadmap updated to mark these done and explicitly defer the
26.0-alpha release until archinstall actually completes end-to-end on a VM.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 10:54:49 +02:00
|
|
|
{% block step_indicator %}<span class="step-indicator">Installing</span>{% endblock %}
|
|
|
|
|
|
|
|
|
|
{% block content %}
|
2026-04-14 18:08:59 +02:00
|
|
|
<h1 id="install-heading">
|
|
|
|
|
{% if progress.status == "done" %}Furtka is ready
|
|
|
|
|
{% elif progress.status == "error" %}Installation hit a snag
|
|
|
|
|
{% else %}Installing Furtka{% endif %}
|
|
|
|
|
</h1>
|
|
|
|
|
<p class="lede" id="install-lede">
|
|
|
|
|
{% if progress.status == "done" %}Installation finished. <strong>Remove the installer USB / eject the ISO</strong>, 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 %}
|
|
|
|
|
</p>
|
|
|
|
|
|
2026-04-14 17:07:57 +02:00
|
|
|
{% if progress.status == "done" %}
|
2026-04-14 18:08:59 +02:00
|
|
|
<form method="post" action="{{ url_for('install_reboot') }}"
|
|
|
|
|
onsubmit="return confirm('Have you removed the installer USB / ejected the ISO? Click OK to reboot.');">
|
|
|
|
|
<div class="actions">
|
|
|
|
|
<button type="submit" class="btn btn-primary">Reboot now</button>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
2026-04-14 17:07:57 +02:00
|
|
|
{% endif %}
|
|
|
|
|
|
|
|
|
|
<div class="progress" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="{{ progress.percent }}">
|
2026-04-14 18:08:59 +02:00
|
|
|
<div id="progress-bar" class="progress-bar{% if progress.status == 'error' %} progress-bar-error{% endif %}{% if progress.status == 'done' %} progress-bar-done{% endif %}" style="width: {{ progress.percent }}%;"></div>
|
2026-04-14 17:07:57 +02:00
|
|
|
</div>
|
2026-04-14 18:08:59 +02:00
|
|
|
<p class="progress-phase"><span id="progress-phase">{{ progress.phase }}</span> · <span id="progress-percent">{{ progress.percent }}</span>%</p>
|
feat: webinstaller writes archinstall config + execs install, styled
Wires the live-ISO wizard from "shows three screens" to "actually invokes
archinstall on the chosen disk", plus first-pass styling so it stops looking
like raw <h1>/<form>.
Webinstaller flow:
- S1 form gains username/password/password2/language with server-side
validation (hostname/username regex, ≥8 char password, match check).
- /install/run writes user_configuration.json + user_credentials.json
(creds 0600) to FURTKA_STATE_DIR (default /tmp/furtka), then execs
`archinstall --config … --creds … --silent` as a backgrounded subprocess.
- /install/log renders the subprocess output via meta-refresh polling.
- FURTKA_DRY_RUN=1 short-circuits the exec for testing.
- archinstall flag names verified against `archinstall --help` in an
archlinux container before committing.
Drive list:
- drives.py now filters via `lsblk … -o NAME,SIZE,TYPE` keeping TYPE=disk,
so the live ISO's own squashfs (loop) and CD-ROM (rom) stop appearing
as install targets.
Boot menu:
- iso/build.sh sed-rebrands "Arch Linux install medium" →
"Furtka Live Installer" across grub/, syslinux/, and efiboot/loader/
entries. Verified zero leftovers against the current releng profile.
Styling:
- static/style.css adopts the website's design tokens (palette,
typography, gate-mark accent), with light + dark via prefers-color-scheme.
- New base.html with header (gate SVG + FURTKA·INSTALLER wordmark + step
indicator) and footer; all install templates extend it.
- Drive picker uses radio cards with score chip; overview uses a summary
table and a destructive "wipe drive" button.
Tests: 17 pass (4 new in test_app.py covering validation + config builders,
2 new in test_drives.py covering the lsblk filter). Ruff clean.
README roadmap updated to mark these done and explicitly defer the
26.0-alpha release until archinstall actually completes end-to-end on a VM.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 10:54:49 +02:00
|
|
|
|
2026-04-14 17:07:57 +02:00
|
|
|
<details class="log-details">
|
|
|
|
|
<summary>Show details</summary>
|
2026-04-14 18:08:59 +02:00
|
|
|
<pre id="install-log" class="log">{{ log or "(waiting for install to start)" }}</pre>
|
2026-04-14 17:07:57 +02:00
|
|
|
</details>
|
2026-04-14 18:08:59 +02:00
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
(function () {
|
|
|
|
|
var initialStatus = {{ progress.status | tojson }};
|
|
|
|
|
if (initialStatus !== 'running') return;
|
|
|
|
|
|
|
|
|
|
var bar = document.getElementById('progress-bar');
|
|
|
|
|
var phaseEl = document.getElementById('progress-phase');
|
|
|
|
|
var percentEl = document.getElementById('progress-percent');
|
|
|
|
|
var logEl = document.getElementById('install-log');
|
|
|
|
|
var headingEl = document.getElementById('install-heading');
|
|
|
|
|
var ledeEl = document.getElementById('install-lede');
|
|
|
|
|
|
|
|
|
|
var HEADINGS = {
|
|
|
|
|
done: 'Furtka is ready',
|
|
|
|
|
error: 'Installation hit a snag',
|
|
|
|
|
};
|
|
|
|
|
var LEDES = {
|
|
|
|
|
done: 'Installation finished. Remove the USB / eject the installer image, then reboot.',
|
|
|
|
|
error: 'Something went wrong. Open the details below and share them so we can help.',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function tick() {
|
|
|
|
|
fetch('{{ url_for("install_log_json") }}', { cache: 'no-store' })
|
|
|
|
|
.then(function (r) { return r.json(); })
|
|
|
|
|
.then(function (data) {
|
|
|
|
|
var p = data.progress;
|
|
|
|
|
bar.style.width = p.percent + '%';
|
|
|
|
|
phaseEl.textContent = p.phase;
|
|
|
|
|
percentEl.textContent = p.percent;
|
|
|
|
|
if (logEl.textContent !== data.log) {
|
|
|
|
|
var atBottom = logEl.scrollTop + logEl.clientHeight >= logEl.scrollHeight - 8;
|
|
|
|
|
logEl.textContent = data.log || '(waiting for install to start)';
|
|
|
|
|
if (atBottom) logEl.scrollTop = logEl.scrollHeight;
|
|
|
|
|
}
|
|
|
|
|
if (p.status === 'done') {
|
|
|
|
|
// Reload so the server-rendered Done state (with the
|
|
|
|
|
// Reboot button) replaces the running-state markup.
|
|
|
|
|
window.location.reload();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (p.status === 'error') {
|
|
|
|
|
bar.classList.add('progress-bar-error');
|
|
|
|
|
headingEl.textContent = HEADINGS.error;
|
|
|
|
|
ledeEl.textContent = LEDES.error;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
setTimeout(tick, 3000);
|
|
|
|
|
})
|
|
|
|
|
.catch(function () { setTimeout(tick, 3000); });
|
|
|
|
|
}
|
|
|
|
|
setTimeout(tick, 3000);
|
|
|
|
|
})();
|
|
|
|
|
</script>
|
feat: webinstaller writes archinstall config + execs install, styled
Wires the live-ISO wizard from "shows three screens" to "actually invokes
archinstall on the chosen disk", plus first-pass styling so it stops looking
like raw <h1>/<form>.
Webinstaller flow:
- S1 form gains username/password/password2/language with server-side
validation (hostname/username regex, ≥8 char password, match check).
- /install/run writes user_configuration.json + user_credentials.json
(creds 0600) to FURTKA_STATE_DIR (default /tmp/furtka), then execs
`archinstall --config … --creds … --silent` as a backgrounded subprocess.
- /install/log renders the subprocess output via meta-refresh polling.
- FURTKA_DRY_RUN=1 short-circuits the exec for testing.
- archinstall flag names verified against `archinstall --help` in an
archlinux container before committing.
Drive list:
- drives.py now filters via `lsblk … -o NAME,SIZE,TYPE` keeping TYPE=disk,
so the live ISO's own squashfs (loop) and CD-ROM (rom) stop appearing
as install targets.
Boot menu:
- iso/build.sh sed-rebrands "Arch Linux install medium" →
"Furtka Live Installer" across grub/, syslinux/, and efiboot/loader/
entries. Verified zero leftovers against the current releng profile.
Styling:
- static/style.css adopts the website's design tokens (palette,
typography, gate-mark accent), with light + dark via prefers-color-scheme.
- New base.html with header (gate SVG + FURTKA·INSTALLER wordmark + step
indicator) and footer; all install templates extend it.
- Drive picker uses radio cards with score chip; overview uses a summary
table and a destructive "wipe drive" button.
Tests: 17 pass (4 new in test_app.py covering validation + config builders,
2 new in test_drives.py covering the lsblk filter). Ruff clean.
README roadmap updated to mark these done and explicitly defer the
26.0-alpha release until archinstall actually completes end-to-end on a VM.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 10:54:49 +02:00
|
|
|
{% endblock %}
|