feat(archiso): embed every installer script at /installer, with an offline repo snapshot
The ISO carried only the three entry scripts launch.sh dispatches to;
tui-install.sh, its modules/ and the desktopenvs/ configs it deploys existed
solely inside the repo the installer clones at run time. A live environment
without working networking therefore ran the whole install and only failed at
the very last step, on a missing /home/<user>/Dotfiles/setup/tui-install.sh.
build.sh now embeds the entire setup/ tree at /installer (so every installer
script is on the ISO), plus a full repo snapshot — .git included, so a seeded
checkout is a real repo — at /installer/dotfiles. launch.sh moves there too
and the overlay/motd/docs follow; profiledef's file_permissions list is
repointed, which matters because mkarchiso hard-errors on an entry whose path
does not exist.
Tree resolution in both installers is now: an existing checkout, else a fresh
clone (online installs still get what is newest), else the ISO snapshot. Each
candidate is accepted only if it actually contains setup/tui-install.sh — the
old check was a bare `-d .git`, which any leftover or half-finished checkout
satisfied.
Sudo can no longer stop the install to ask for a password:
- before the chroot hands over to the TUI, the temporary NOPASSWD drop-in is
proven with `sudo -n true` and `sudo -n -v` (both forms modules rely on).
A rule that didn't apply now skips the TUI instead of stalling forever on a
hidden prompt, and the drop-in is removed on that path too rather than
being left behind as permanent passwordless sudo;
- tui-install.sh's root sudo shim moves to the top of the file, ahead of the
require_jq() bootstrap that shells out through sudo, so running it as root
straight from /installer never needs a real sudo binary.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
main
parent
72e0fa8edc
commit
96f15c82af
|
|
@ -54,7 +54,7 @@ Build artefacts land in `~/m-archy-out/` by default. Override with the `OUT_DIR`
|
|||
2. Applies the M-Archy overlay (`setup/archiso/overlay/`)
|
||||
3. Replaces `profiledef.sh` with the M-Archy version
|
||||
4. Adds extra packages from `packages.extra`
|
||||
5. Embeds both installer scripts (`arch-autoinstall.sh`, `archbaseos-guided-install.sh`) into `/root/installer/`
|
||||
5. Embeds the whole `setup/` tree into `/installer/` (every installer script, including `tui-install.sh` and its `modules/`), plus a full repo snapshot at `/installer/dotfiles/`
|
||||
6. If `--preconf`: copies the answerfile to `/answerfile.json` in the ISO's airootfs
|
||||
7. Runs `mkarchiso` to produce the final `.iso`
|
||||
|
||||
|
|
@ -94,7 +94,7 @@ install-arch guided # guided interactive install
|
|||
install-arch auto # automated mode (reads /answerfile.json)
|
||||
```
|
||||
|
||||
### `/root/launch.sh`
|
||||
### `/installer/launch.sh`
|
||||
|
||||
Internal dispatcher used by `install-arch`. After keymap selection, it prompts for one of two actions:
|
||||
|
||||
|
|
@ -188,8 +188,10 @@ For multi-machine deployments, the `hostname` field in the answerfile is combine
|
|||
setup/archiso/overlay/
|
||||
├── airootfs/
|
||||
│ ├── etc/motd # Welcome message
|
||||
│ ├── root/
|
||||
│ ├── installer/
|
||||
│ │ └── launch.sh # Installer entry point
|
||||
│ ├── root/
|
||||
│ │ └── .automated_script.sh # Login hook → /installer/launch.sh
|
||||
│ └── usr/local/bin/
|
||||
│ └── install-arch # User-facing CLI command
|
||||
├── packages.extra # Additional live-system packages
|
||||
|
|
@ -198,11 +200,21 @@ setup/archiso/overlay/
|
|||
|
||||
The `build.sh` script also adds at build time:
|
||||
```
|
||||
airootfs/root/installer/
|
||||
airootfs/installer/ # the whole setup/ tree
|
||||
├── archbaseos-guided-install.sh
|
||||
├── arch-autoinstall.sh
|
||||
└── archbaseos-guided-install.sh
|
||||
├── reset-arch.sh
|
||||
├── tui-install.sh
|
||||
├── modules/ # every DE/app/service module
|
||||
└── dotfiles/ # full repo snapshot (incl. .git)
|
||||
```
|
||||
|
||||
Nothing the installer runs depends on network access any more: the guided and
|
||||
automated installers still clone the repo when they can (so an online install
|
||||
gets whatever is newest), but fall back to `/installer/dotfiles` when the clone
|
||||
fails, and both verify the resulting tree actually contains
|
||||
`setup/tui-install.sh` before they promise to run it.
|
||||
|
||||
---
|
||||
|
||||
## Writing the ISO to USB
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ Two scripts install Arch Linux itself (before the dotfiles step):
|
|||
Interactive, dialog-based. Prompts for each setting with sensible defaults. Good for hands-on installs where you want to review each option.
|
||||
|
||||
```bash
|
||||
bash ~/installer/archbaseos-guided-install.sh
|
||||
bash /installer/archbaseos-guided-install.sh
|
||||
```
|
||||
|
||||
### Auto Installer (`arch-autoinstall.sh`)
|
||||
|
|
@ -150,7 +150,7 @@ bash ~/installer/archbaseos-guided-install.sh
|
|||
Reads all settings from `/answerfile.json` if present; falls back to prompts for anything missing.
|
||||
|
||||
```bash
|
||||
bash ~/installer/arch-autoinstall.sh
|
||||
bash /installer/arch-autoinstall.sh
|
||||
```
|
||||
|
||||
Both installers perform the same steps:
|
||||
|
|
|
|||
|
|
@ -584,38 +584,64 @@ fi
|
|||
export HOSTNAME USERNAME USERPASS ROOT_PART KERNEL FIDO_ROOT FIDO_USER ENCRYPT_DISK KEYMAP RUN_TUI CLONE_SKEL_DOTFILES
|
||||
|
||||
############################################
|
||||
# DOTFILES CLONE (live environment, with retry)
|
||||
# DOTFILES TREE (existing checkout → clone → ISO snapshot)
|
||||
############################################
|
||||
# The live ISO only embeds the top-level installer scripts (see build.sh) —
|
||||
# tui-install.sh, its modules/, and desktopenvs/ configs exist only inside the
|
||||
# full repo. Clone it ONCE into the live environment whenever either RUN_TUI
|
||||
# or CLONE_SKEL_DOTFILES is YES, so both consumers below (the skel copy, and
|
||||
# the fallback copy straight into the new user's home when skel is skipped
|
||||
# but the TUI still needs to run) are served from one clone instead of each
|
||||
# needing its own network fetch — and so a bare install genuinely fetches
|
||||
# nothing at all. Done here (outside the chroot) because a clone made inside
|
||||
# the chroot heredoc lives only under /mnt and can't be reused for the skel
|
||||
# copy that must happen before useradd -m runs inside that same heredoc.
|
||||
# The ISO embeds every installer script under /installer and a full repo
|
||||
# snapshot under /installer/dotfiles (see setup/tools/build.sh), so this step
|
||||
# is only about picking the best copy available, in order:
|
||||
# 1. a checkout already sitting in the live environment (a re-run),
|
||||
# 2. a fresh clone, so an install with working networking gets what is newest,
|
||||
# 3. the ISO's own snapshot, so an offline install still gets a full tree.
|
||||
# Resolved ONCE, whenever either RUN_TUI or CLONE_SKEL_DOTFILES is YES, so both
|
||||
# consumers below (the skel copy, and the fallback copy straight into the new
|
||||
# user's home when skel is skipped but the TUI still needs to run) are served
|
||||
# from it — and so a bare install genuinely fetches nothing at all.
|
||||
# Done here (outside the chroot) because a tree materialised inside the chroot
|
||||
# heredoc lives only under /mnt and can't be reused for the skel copy that must
|
||||
# happen before useradd -m runs inside that same heredoc.
|
||||
LIVE_DOTFILES_DIR="$HOME/Dotfiles"
|
||||
if [[ "${CLONE_SKEL_DOTFILES^^}" == "YES" || "${RUN_TUI^^}" == "YES" ]]; then
|
||||
echo "Cloning dotfiles into the live environment ($LIVE_DOTFILES_DIR)..."
|
||||
_clone_ok=false
|
||||
while ! $_clone_ok; do
|
||||
if [[ -d "$LIVE_DOTFILES_DIR/.git" ]]; then
|
||||
_clone_ok=true
|
||||
elif git clone https://git.abdelbaki.eu/The_miro/Dotfiles.git "$LIVE_DOTFILES_DIR"; then
|
||||
_clone_ok=true
|
||||
else
|
||||
if $AF_MODE; then
|
||||
echo "Warning: dotfiles clone failed — continuing without dotfiles."
|
||||
RUN_TUI="NO"; CLONE_SKEL_DOTFILES="NO"
|
||||
_clone_ok=true
|
||||
else
|
||||
# Snapshot embedded by setup/tools/build.sh. Overridable so the scripts can be
|
||||
# run from a checkout on a normal system, not just from the ISO.
|
||||
ISO_DOTFILES="${ISO_DOTFILES:-/installer/dotfiles}"
|
||||
|
||||
# A tree is only usable if the script the chroot step actually runs is in it.
|
||||
# The old check was `-d $LIVE_DOTFILES_DIR/.git`, which a leftover or half-
|
||||
# finished checkout satisfies — the install then went all the way to the last
|
||||
# step before failing on a missing tui-install.sh.
|
||||
_dotfiles_tree_ok() { [[ -f "$1/setup/tui-install.sh" ]]; }
|
||||
|
||||
_clone_dotfiles() {
|
||||
local url="https://git.abdelbaki.eu/The_miro/Dotfiles.git"
|
||||
while :; do
|
||||
rm -rf "$LIVE_DOTFILES_DIR"
|
||||
if git clone "$url" "$LIVE_DOTFILES_DIR" && _dotfiles_tree_ok "$LIVE_DOTFILES_DIR"; then
|
||||
return 0
|
||||
fi
|
||||
# Unattended, or the ISO carries a snapshot we can fall back to: don't
|
||||
# sit at a prompt nobody is going to answer.
|
||||
if $AF_MODE; then return 1; fi
|
||||
if _dotfiles_tree_ok "$ISO_DOTFILES"; then return 1; fi
|
||||
read -rp "Clone failed — retry? [y/N]: " _retry
|
||||
[[ "${_retry,,}" == "y" ]] || { echo "Skipping dotfiles — clone manually after first boot."; RUN_TUI="NO"; CLONE_SKEL_DOTFILES="NO"; _clone_ok=true; }
|
||||
fi
|
||||
fi
|
||||
if [[ "${_retry,,}" != "y" ]]; then return 1; fi
|
||||
done
|
||||
}
|
||||
|
||||
if [[ "${CLONE_SKEL_DOTFILES^^}" == "YES" || "${RUN_TUI^^}" == "YES" ]]; then
|
||||
if _dotfiles_tree_ok "$LIVE_DOTFILES_DIR"; then
|
||||
echo "Using the dotfiles checkout already present at $LIVE_DOTFILES_DIR."
|
||||
else
|
||||
echo "Cloning dotfiles into the live environment ($LIVE_DOTFILES_DIR)..."
|
||||
if ! _clone_dotfiles && _dotfiles_tree_ok "$ISO_DOTFILES"; then
|
||||
echo "Clone unavailable — using the snapshot embedded in the ISO ($ISO_DOTFILES)."
|
||||
rm -rf "$LIVE_DOTFILES_DIR"
|
||||
cp -r "$ISO_DOTFILES" "$LIVE_DOTFILES_DIR"
|
||||
fi
|
||||
fi
|
||||
if ! _dotfiles_tree_ok "$LIVE_DOTFILES_DIR"; then
|
||||
echo "Warning: no usable dotfiles tree (no clone, no ISO snapshot) — continuing without dotfiles."
|
||||
echo " Clone manually after first boot: git clone https://git.abdelbaki.eu/The_miro/Dotfiles.git ~/Dotfiles"
|
||||
RUN_TUI="NO"; CLONE_SKEL_DOTFILES="NO"
|
||||
fi
|
||||
fi
|
||||
|
||||
############################################
|
||||
|
|
@ -823,6 +849,39 @@ if [[ "${RUN_TUI^^}" == "YES" ]]; then
|
|||
| arch-chroot /mnt tee /etc/sudoers.d/99-setup-nopasswd > /dev/null
|
||||
arch-chroot /mnt chmod 0440 /etc/sudoers.d/99-setup-nopasswd
|
||||
|
||||
# Never hand control to a script that isn't there: without this the install
|
||||
# ran to completion and only then reported a missing tui-install.sh.
|
||||
if [[ ! -f "/mnt/home/${USERNAME}/Dotfiles/setup/tui-install.sh" ]]; then
|
||||
echo "Warning: /home/${USERNAME}/Dotfiles/setup/tui-install.sh is missing — skipping the dotfiles TUI."
|
||||
_DO_TUI="NO"
|
||||
fi
|
||||
|
||||
# Prove the drop-in above actually took effect before the TUI starts. `-n`
|
||||
# makes sudo fail rather than prompt, so a rule that didn't apply surfaces
|
||||
# here as a clean skip instead of a hidden "[sudo] password for ..." prompt
|
||||
# that stalls the install forever — nobody is watching an unattended one.
|
||||
# Both forms are tested: modules call plain `sudo <cmd>` (NOPASSWD rule) and
|
||||
# third-party installers call `sudo -v` (the !authenticate default).
|
||||
if [[ "${_DO_TUI^^}" == "YES" ]] \
|
||||
&& ! arch-chroot /mnt runuser -u "${USERNAME}" -- sudo -n true 2>/dev/null; then
|
||||
echo "Warning: passwordless sudo for ${USERNAME} is not in effect — skipping the TUI rather than stalling on a password prompt."
|
||||
_DO_TUI="NO"
|
||||
fi
|
||||
if [[ "${_DO_TUI^^}" == "YES" ]] \
|
||||
&& ! arch-chroot /mnt runuser -u "${USERNAME}" -- sudo -n -v 2>/dev/null; then
|
||||
echo "Warning: 'sudo -v' still demands a password for ${USERNAME} — skipping the TUI rather than stalling on a password prompt."
|
||||
_DO_TUI="NO"
|
||||
fi
|
||||
|
||||
# Skipping here means the run below never happens, so the drop-in never
|
||||
# reaches its usual post-run removal — take it back out now rather than
|
||||
# leaving the installed system with permanent passwordless sudo.
|
||||
if [[ "${_DO_TUI^^}" != "YES" ]]; then
|
||||
arch-chroot /mnt rm -f /etc/sudoers.d/99-setup-nopasswd
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "${_DO_TUI^^}" == "YES" ]]; then
|
||||
echo "Running tui-install.sh as ${USERNAME} inside chroot..."
|
||||
# `runuser -u` switches to the unprivileged user inside the chroot so that
|
||||
# AUR helpers and dotfiles are owned/built by the correct UID.
|
||||
|
|
|
|||
|
|
@ -560,36 +560,61 @@ if $AF_MODE; then
|
|||
fi
|
||||
|
||||
############################################
|
||||
# DOTFILES CLONE (live environment, with retry)
|
||||
# DOTFILES TREE (existing checkout → clone → ISO snapshot)
|
||||
############################################
|
||||
# The live ISO only embeds the top-level installer scripts (see build.sh) —
|
||||
# tui-install.sh, its modules/, and desktopenvs/ configs exist only inside the
|
||||
# full repo. Clone it ONCE into the live environment whenever either RUN_TUI
|
||||
# or CLONE_SKEL_DOTFILES is YES, so both consumers below (the skel copy, and
|
||||
# the fallback copy straight into the new user's home when skel is skipped
|
||||
# but the TUI still needs to run) are served from one clone instead of each
|
||||
# needing its own network fetch — and so a bare install genuinely fetches
|
||||
# nothing at all.
|
||||
# The ISO embeds every installer script under /installer and a full repo
|
||||
# snapshot under /installer/dotfiles (see setup/tools/build.sh), so this step
|
||||
# is only about picking the best copy available, in order:
|
||||
# 1. a checkout already sitting in the live environment (a re-run),
|
||||
# 2. a fresh clone, so an install with working networking gets what is newest,
|
||||
# 3. the ISO's own snapshot, so an offline install still gets a full tree.
|
||||
# Resolved ONCE, whenever either RUN_TUI or CLONE_SKEL_DOTFILES is YES, so both
|
||||
# consumers below (the skel copy, and the fallback copy straight into the new
|
||||
# user's home when skel is skipped but the TUI still needs to run) are served
|
||||
# from it — and so a bare install genuinely fetches nothing at all.
|
||||
LIVE_DOTFILES_DIR="$HOME/Dotfiles"
|
||||
if [[ "${CLONE_SKEL_DOTFILES^^}" == "YES" || "${RUN_TUI^^}" == "YES" ]]; then
|
||||
echo "Cloning dotfiles into the live environment ($LIVE_DOTFILES_DIR)..."
|
||||
_clone_ok=false
|
||||
while ! $_clone_ok; do
|
||||
if [[ -d "$LIVE_DOTFILES_DIR/.git" ]]; then
|
||||
_clone_ok=true
|
||||
elif git clone https://git.abdelbaki.eu/The_miro/Dotfiles.git "$LIVE_DOTFILES_DIR"; then
|
||||
_clone_ok=true
|
||||
else
|
||||
if $AF_MODE; then
|
||||
echo "Warning: dotfiles clone failed — continuing without dotfiles."
|
||||
RUN_TUI="NO"; CLONE_SKEL_DOTFILES="NO"
|
||||
_clone_ok=true
|
||||
else
|
||||
# Snapshot embedded by setup/tools/build.sh. Overridable so the scripts can be
|
||||
# run from a checkout on a normal system, not just from the ISO.
|
||||
ISO_DOTFILES="${ISO_DOTFILES:-/installer/dotfiles}"
|
||||
|
||||
# A tree is only usable if the script the chroot step actually runs is in it.
|
||||
# The old check was `-d $LIVE_DOTFILES_DIR/.git`, which a leftover or half-
|
||||
# finished checkout satisfies — the install then went all the way to the last
|
||||
# step before failing on a missing tui-install.sh.
|
||||
_dotfiles_tree_ok() { [[ -f "$1/setup/tui-install.sh" ]]; }
|
||||
|
||||
_clone_dotfiles() {
|
||||
local url="https://git.abdelbaki.eu/The_miro/Dotfiles.git"
|
||||
while :; do
|
||||
rm -rf "$LIVE_DOTFILES_DIR"
|
||||
if git clone "$url" "$LIVE_DOTFILES_DIR" && _dotfiles_tree_ok "$LIVE_DOTFILES_DIR"; then
|
||||
return 0
|
||||
fi
|
||||
# Unattended, or the ISO carries a snapshot we can fall back to: don't
|
||||
# sit at a prompt nobody is going to answer.
|
||||
if $AF_MODE; then return 1; fi
|
||||
if _dotfiles_tree_ok "$ISO_DOTFILES"; then return 1; fi
|
||||
read -rp "Clone failed — retry? [y/N]: " _retry
|
||||
[[ "${_retry,,}" == "y" ]] || { echo "Skipping dotfiles — clone manually after first boot."; RUN_TUI="NO"; CLONE_SKEL_DOTFILES="NO"; _clone_ok=true; }
|
||||
fi
|
||||
fi
|
||||
if [[ "${_retry,,}" != "y" ]]; then return 1; fi
|
||||
done
|
||||
}
|
||||
|
||||
if [[ "${CLONE_SKEL_DOTFILES^^}" == "YES" || "${RUN_TUI^^}" == "YES" ]]; then
|
||||
if _dotfiles_tree_ok "$LIVE_DOTFILES_DIR"; then
|
||||
echo "Using the dotfiles checkout already present at $LIVE_DOTFILES_DIR."
|
||||
else
|
||||
echo "Cloning dotfiles into the live environment ($LIVE_DOTFILES_DIR)..."
|
||||
if ! _clone_dotfiles && _dotfiles_tree_ok "$ISO_DOTFILES"; then
|
||||
echo "Clone unavailable — using the snapshot embedded in the ISO ($ISO_DOTFILES)."
|
||||
rm -rf "$LIVE_DOTFILES_DIR"
|
||||
cp -r "$ISO_DOTFILES" "$LIVE_DOTFILES_DIR"
|
||||
fi
|
||||
fi
|
||||
if ! _dotfiles_tree_ok "$LIVE_DOTFILES_DIR"; then
|
||||
echo "Warning: no usable dotfiles tree (no clone, no ISO snapshot) — continuing without dotfiles."
|
||||
echo " Clone manually after first boot: git clone https://git.abdelbaki.eu/The_miro/Dotfiles.git ~/Dotfiles"
|
||||
RUN_TUI="NO"; CLONE_SKEL_DOTFILES="NO"
|
||||
fi
|
||||
fi
|
||||
|
||||
############################################
|
||||
|
|
@ -793,6 +818,39 @@ if [[ "${_DO_TUI^^}" == "YES" ]]; then
|
|||
| arch-chroot /mnt tee /etc/sudoers.d/99-setup-nopasswd > /dev/null
|
||||
arch-chroot /mnt chmod 0440 /etc/sudoers.d/99-setup-nopasswd
|
||||
|
||||
# Never hand control to a script that isn't there: without this the install
|
||||
# ran to completion and only then reported a missing tui-install.sh.
|
||||
if [[ ! -f "/mnt/home/${USERNAME}/Dotfiles/setup/tui-install.sh" ]]; then
|
||||
echo "Warning: /home/${USERNAME}/Dotfiles/setup/tui-install.sh is missing — skipping the dotfiles TUI."
|
||||
_DO_TUI="NO"
|
||||
fi
|
||||
|
||||
# Prove the drop-in above actually took effect before the TUI starts. `-n`
|
||||
# makes sudo fail rather than prompt, so a rule that didn't apply surfaces
|
||||
# here as a clean skip instead of a hidden "[sudo] password for ..." prompt
|
||||
# that stalls the install forever — nobody is watching an unattended one.
|
||||
# Both forms are tested: modules call plain `sudo <cmd>` (NOPASSWD rule) and
|
||||
# third-party installers call `sudo -v` (the !authenticate default).
|
||||
if [[ "${_DO_TUI^^}" == "YES" ]] \
|
||||
&& ! arch-chroot /mnt runuser -u "${USERNAME}" -- sudo -n true 2>/dev/null; then
|
||||
echo "Warning: passwordless sudo for ${USERNAME} is not in effect — skipping the TUI rather than stalling on a password prompt."
|
||||
_DO_TUI="NO"
|
||||
fi
|
||||
if [[ "${_DO_TUI^^}" == "YES" ]] \
|
||||
&& ! arch-chroot /mnt runuser -u "${USERNAME}" -- sudo -n -v 2>/dev/null; then
|
||||
echo "Warning: 'sudo -v' still demands a password for ${USERNAME} — skipping the TUI rather than stalling on a password prompt."
|
||||
_DO_TUI="NO"
|
||||
fi
|
||||
|
||||
# Skipping here means the run below never happens, so the drop-in never
|
||||
# reaches its usual post-run removal — take it back out now rather than
|
||||
# leaving the installed system with permanent passwordless sudo.
|
||||
if [[ "${_DO_TUI^^}" != "YES" ]]; then
|
||||
arch-chroot /mnt rm -f /etc/sudoers.d/99-setup-nopasswd
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "${_DO_TUI^^}" == "YES" ]]; then
|
||||
echo "Running tui-install.sh as ${USERNAME} inside chroot..."
|
||||
# `runuser -u` switches to the unprivileged user inside the chroot so that
|
||||
# AUR helpers and dotfiles are owned/built by the correct UID.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
install-arch guided installer (manual mode)
|
||||
install-arch auto automated installer (requires answerfile)
|
||||
|
||||
Scripts are also at: ~/installer/
|
||||
Scripts are also at: /installer/
|
||||
|
||||
Dotfiles: https://git.abdelbaki.eu/The_miro/Dotfiles
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
INSTALLER_DIR="$HOME/installer"
|
||||
# Every installer script (this dispatcher, the guided/automated installers,
|
||||
# tui-install.sh and its modules/) lives under /installer on the live ISO —
|
||||
# see setup/tools/build.sh, which embeds the whole setup/ tree there.
|
||||
INSTALLER_DIR="${INSTALLER_DIR:-/installer}"
|
||||
|
||||
############################################
|
||||
# Keyboard layout (live environment)
|
||||
|
|
@ -40,9 +40,9 @@ ANSWERFILE="/answerfile.json"
|
|||
if [[ -f "$ANSWERFILE" ]]; then
|
||||
# Automated mode: pass "auto" as the first arg and the answerfile path as
|
||||
# the second. launch.sh will forward these to arch-autoinstall.sh.
|
||||
exec /root/launch.sh auto "$ANSWERFILE"
|
||||
exec /installer/launch.sh auto "$ANSWERFILE"
|
||||
else
|
||||
# Guided mode: start the interactive installer. The user will be prompted
|
||||
# for keyboard layout and installation action before anything happens.
|
||||
exec /root/launch.sh guided
|
||||
exec /installer/launch.sh guided
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
exec /root/launch.sh "$@"
|
||||
exec /installer/launch.sh "$@"
|
||||
|
|
|
|||
|
|
@ -19,8 +19,15 @@ file_permissions=(
|
|||
["/root"]="0:0:750"
|
||||
["/root/.automated_script.sh"]="0:0:755"
|
||||
["/root/.zlogin"]="0:0:644"
|
||||
["/root/launch.sh"]="0:0:755"
|
||||
["/root/installer/archbaseos-guided-install.sh"]="0:0:755"
|
||||
["/root/installer/arch-autoinstall.sh"]="0:0:755"
|
||||
# /installer holds every installer script (build.sh embeds the whole setup/
|
||||
# tree there, plus a full repo snapshot at /installer/dotfiles). Only the
|
||||
# entry points need an explicit mode here — build.sh chmods the rest, and
|
||||
# everything below them is invoked as `bash <script>` anyway.
|
||||
["/installer"]="0:0:755"
|
||||
["/installer/launch.sh"]="0:0:755"
|
||||
["/installer/archbaseos-guided-install.sh"]="0:0:755"
|
||||
["/installer/arch-autoinstall.sh"]="0:0:755"
|
||||
["/installer/reset-arch.sh"]="0:0:755"
|
||||
["/installer/tui-install.sh"]="0:0:755"
|
||||
["/usr/local/bin/install-arch"]="0:0:755"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
# Logo resolution order:
|
||||
# 1. $PLYMOUTH_LOGO_SRC env var — caller-supplied custom image (PNG or SVG)
|
||||
# 2. $DOTFILES_DIR/resources/bg-skull.svg — repo copy, always present
|
||||
# 3. /root/installer/resources/bg-skull.svg — archiso embedded copy
|
||||
# 3. /installer/dotfiles/resources/bg-skull.svg — archiso embedded snapshot
|
||||
#
|
||||
# PNG inputs are used directly; SVG inputs are converted via rsvg-convert.
|
||||
#
|
||||
|
|
@ -40,7 +40,7 @@ LOGO_SRC="${PLYMOUTH_LOGO_SRC:-}"
|
|||
if [[ -z "$LOGO_SRC" ]]; then
|
||||
for _candidate in \
|
||||
"$DOTFILES_DIR/resources/bg-skull.svg" \
|
||||
"/root/installer/resources/bg-skull.svg"
|
||||
"/installer/dotfiles/resources/bg-skull.svg"
|
||||
do
|
||||
if [[ -f "$_candidate" ]]; then
|
||||
LOGO_SRC="$_candidate"
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@
|
|||
# 3. Copy the upstream releng profile to a working directory.
|
||||
# 4. Apply the M-Archy overlay (custom scripts, profiledef, mkinitcpio config).
|
||||
# 5. Merge extra packages (packages.extra) into the releng package list.
|
||||
# 6. Embed the installer shell scripts into the ISO's /root/installer/.
|
||||
# 6. Embed the whole setup/ tree into the ISO's /installer/, plus a full repo
|
||||
# snapshot at /installer/dotfiles/ so installs work with no network.
|
||||
# 7. Optionally embed an answerfile.json for automated installs.
|
||||
# 8. Run mkarchiso to produce the final .iso and netboot tarball.
|
||||
# 9. Optionally write an iPXE chainload script for netboot.xyz / WDS.
|
||||
|
|
@ -184,33 +185,37 @@ while IFS= read -r pkg || [[ -n "$pkg" ]]; do
|
|||
grep -qxF "$pkg" "$PROFILE/packages.x86_64" || echo "$pkg" >> "$PROFILE/packages.x86_64"
|
||||
done < "$OVERLAY_DIR/packages.extra"
|
||||
|
||||
# ── Embed installer scripts ────────────────────────────────────────────────────
|
||||
# These three scripts live in the main setup/ directory of the dotfiles repo
|
||||
# and implement the actual Arch Linux installation logic. They are placed in
|
||||
# /root/installer/ on the live ISO so the auto-launch scripts can find them.
|
||||
echo "Embedding installer scripts..."
|
||||
mkdir -p "$PROFILE/airootfs/root/installer"
|
||||
# Guided interactive installer — walks the user through partitioning, locale, etc.
|
||||
cp "$DOTFILES_DIR/setup/archbaseos-guided-install.sh" "$PROFILE/airootfs/root/installer/"
|
||||
# Automated unattended installer — reads /answerfile.json and installs silently.
|
||||
cp "$DOTFILES_DIR/setup/arch-autoinstall.sh" "$PROFILE/airootfs/root/installer/"
|
||||
# Reset script — wipes and reinstalls the system while preserving /home.
|
||||
cp "$DOTFILES_DIR/setup/reset-arch.sh" "$PROFILE/airootfs/root/installer/"
|
||||
# ── Embed the installer scripts (the whole setup/ tree) ───────────────────────
|
||||
# EVERY installer script goes into /installer on the live ISO, not just the
|
||||
# three entry points launch.sh dispatches to. tui-install.sh and its modules/
|
||||
# used to exist only inside the repo the installer clones at run time, so a live
|
||||
# environment with no network — or a briefly unreachable Gitea — got all the way
|
||||
# to "Running tui-install.sh ..." and then died on a missing file. Logs that
|
||||
# happen to be committed under setup/ are skipped: build junk, not installer code.
|
||||
echo "Embedding installer scripts (setup/ → /installer)..."
|
||||
mkdir -p "$PROFILE/airootfs/installer"
|
||||
tar -C "$DOTFILES_DIR/setup" --exclude='*.log' -cf - . \
|
||||
| tar -C "$PROFILE/airootfs/installer" -xf -
|
||||
|
||||
echo "Embedding resources (branding assets used by post-install modules)..."
|
||||
# resources/ contains shared assets (SVGs, etc.) referenced by installer modules
|
||||
# such as the Plymouth splash logo. Embedding them here means the ISO carries
|
||||
# everything needed so post-install steps never require the user to supply files.
|
||||
mkdir -p "$PROFILE/airootfs/root/installer/resources"
|
||||
cp -r "$DOTFILES_DIR/resources/." "$PROFILE/airootfs/root/installer/resources/"
|
||||
# ── Embed a full snapshot of the repo ─────────────────────────────────────────
|
||||
# The installer scripts alone still aren't a complete offline install: the TUI
|
||||
# deploys desktopenvs/ configs, colors.conf, resources/ and friends out of the
|
||||
# repo. Ship the whole thing (~31 MB, and mksquashfs deduplicates the setup/
|
||||
# copy above) so the installers can seed ~/Dotfiles from the ISO whenever the
|
||||
# clone can't run. .git is included on purpose — a seeded checkout is then a
|
||||
# real repo that can `git pull` later, exactly like a cloned one.
|
||||
echo "Embedding dotfiles snapshot (/installer/dotfiles)..."
|
||||
mkdir -p "$PROFILE/airootfs/installer/dotfiles"
|
||||
tar -C "$DOTFILES_DIR" --exclude='*.log' -cf - . \
|
||||
| tar -C "$PROFILE/airootfs/installer/dotfiles" -xf -
|
||||
|
||||
# Make all scripts executable. The archiso tool preserves these bits in the
|
||||
# Make the scripts executable. The archiso tool preserves these bits in the
|
||||
# squashfs, so they will be executable on the live system too.
|
||||
chmod 755 \
|
||||
"$PROFILE/airootfs/root/launch.sh" \
|
||||
"$PROFILE/airootfs/installer/launch.sh" \
|
||||
"$PROFILE/airootfs/root/.automated_script.sh" \
|
||||
"$PROFILE/airootfs/usr/local/bin/install-arch" \
|
||||
"$PROFILE/airootfs/root/installer/"*.sh
|
||||
"$PROFILE/airootfs/usr/local/bin/install-arch"
|
||||
find "$PROFILE/airootfs/installer" -name '*.sh' -exec chmod 755 {} +
|
||||
|
||||
# ── Embed answerfile (--preconf) ───────────────────────────────────────────────
|
||||
# An answerfile baked into the ISO lets machines boot and install completely
|
||||
|
|
|
|||
|
|
@ -23,6 +23,22 @@ TMP_D="$(mktemp -d)"
|
|||
# '|| true' ensures the trap never returns a non-zero code, which would mask the real exit status.
|
||||
trap 'rm -rf "$TMP_D"; tput reset 2>/dev/null || stty sane 2>/dev/null || true' EXIT INT TERM HUP
|
||||
|
||||
# ── sudo shim (root contexts) ─────────────────────────────────────────────────
|
||||
# Module scripts call `sudo` for privileged work. When this script is already
|
||||
# running as root — an archiso chroot, or a run straight out of /installer on
|
||||
# the live ISO — there may be no sudo binary at all, and there is certainly
|
||||
# nothing to authenticate against. Shim it as a plain passthrough so nothing
|
||||
# ever stops to ask for a password. Installed this early (rather than in the
|
||||
# preflight section further down) because require_jq() below already shells out
|
||||
# through sudo.
|
||||
if [[ $EUID -eq 0 ]]; then
|
||||
mkdir -p "$TMP_D/bin"
|
||||
printf '#!/bin/bash\nexec "$@"\n' > "$TMP_D/bin/sudo"
|
||||
chmod +x "$TMP_D/bin/sudo"
|
||||
# Prepend to PATH so this shim takes precedence over any real sudo.
|
||||
export PATH="$TMP_D/bin:$PATH"
|
||||
fi
|
||||
|
||||
# Allow the caller to inject a different answerfile path via the ANSWERFILE env var.
|
||||
# The default /answerfile.json is a conventional location for CI/PXE boot images.
|
||||
ANSWERFILE="${ANSWERFILE:-/answerfile.json}"
|
||||
|
|
@ -455,17 +471,7 @@ load_answerfile() {
|
|||
}
|
||||
|
||||
# ── Preflight ─────────────────────────────────────────────────────────────────
|
||||
if [[ $EUID -eq 0 ]]; then
|
||||
# Root context (e.g. archiso chroot): shim sudo as a passthrough
|
||||
# Module scripts call 'sudo' for privilege operations; when we are already root
|
||||
# there is no sudo binary (or it may be absent), so inject a fake one that is
|
||||
# just 'exec "$@"' — transparently forwarding all arguments.
|
||||
mkdir -p "$TMP_D/bin"
|
||||
printf '#!/bin/bash\nexec "$@"\n' > "$TMP_D/bin/sudo"
|
||||
chmod +x "$TMP_D/bin/sudo"
|
||||
# Prepend to PATH so this shim takes precedence over any real sudo.
|
||||
export PATH="$TMP_D/bin:$PATH"
|
||||
fi
|
||||
# (the root sudo shim lives at the top of this file — require_jq() needs it)
|
||||
# Hard guard: pacman is the package manager used by every module; without it
|
||||
# the installer cannot function on this OS.
|
||||
command -v pacman &>/dev/null || die "pacman not found — Arch Linux required."
|
||||
|
|
|
|||
Loading…
Reference in New Issue