diff options
author | Lars Wirzenius <liw@liw.fi> | 2022-01-07 12:39:13 +0000 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2022-01-07 12:39:13 +0000 |
commit | a697783d63d8dc410ae0b104f1cf37e4b4d886cf (patch) | |
tree | c0346af742973940684d17daf31a843df352a3cb | |
parent | b2614eb640c624f63189ada4af868069ff395469 (diff) | |
parent | 602680ab9db41e60ffadacae5c9f190c6d105d86 (diff) | |
download | v-i-a697783d63d8dc410ae0b104f1cf37e4b4d886cf.tar.gz |
Merge branch 'install-script' into 'main'
drop gnome
See merge request larswirzenius/v-i!5
-rw-r--r-- | ansible.cfg | 3 | ||||
-rwxr-xr-x | build-installer.sh (renamed from v-i.sh) | 0 | ||||
-rwxr-xr-x | clean-up-disks | 91 | ||||
-rwxr-xr-x | v-i | 296 | ||||
-rwxr-xr-x | x220.sh | 36 | ||||
-rw-r--r-- | x220.vmdb | 118 | ||||
-rw-r--r-- | x220.yml | 12 |
7 files changed, 304 insertions, 252 deletions
diff --git a/ansible.cfg b/ansible.cfg deleted file mode 100644 index 67e1f40..0000000 --- a/ansible.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[defaults] -nocows = 1 -log_path = ansible.log diff --git a/v-i.sh b/build-installer.sh index e1e5084..e1e5084 100755 --- a/v-i.sh +++ b/build-installer.sh diff --git a/clean-up-disks b/clean-up-disks deleted file mode 100755 index 794badf..0000000 --- a/clean-up-disks +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/python3 - -import glob -import os -from subprocess import run - - -def physical_volumes(): - p = run(["pvdisplay", "-C", "--noheadings"], capture_output=True, check=True) - lines = p.stdout.decode().splitlines() - pvs = [] - for line in lines: - words = line.split() - pv = words[0] - vg = words[1] - pvs.append({"pv": pv, "vg": vg}) - return pvs - - -def logical_volumes(): - p = run(["lvdisplay", "-C", "--noheadings"], capture_output=True, check=True) - lines = p.stdout.decode().splitlines() - lvs = [] - for line in lines: - words = line.split() - lv = words[0] - vg = words[1] - path = os.path.realpath(f"/dev/{vg}/{lv}") - lvs.append({"lv": lv, "vg": vg, "path": path}) - return lvs - - -def volume_groups(): - p = run(["vgdisplay", "-C", "--noheadings"], capture_output=True, check=True) - lines = p.stdout.decode().splitlines() - return [line.split()[0] for line in lines if line.strip()] - - -def mount_points(): - mounts = {} - for line in open("/proc/mounts").readlines(): - words = line.split() - dev = os.path.realpath(words[0]) if words[0].startswith("/") else words[0] - mounts[dev] = { - "mount": words[1], - "type": words[2], - } - return mounts - - -def find_mount_points(mounts, dev): - res = [] - if dev in mounts: - root = mounts[dev]["mount"] - for m in mounts.values(): - if m["mount"].startswith(root): - res.append(m) - return res - - -def is_luks(path): - p = run(["cryptsetup", "isLuks", path], check=False) - return p.returncode == 0 - - -mounts = mount_points() -pvs = physical_volumes() -lvs = logical_volumes() -vgs = volume_groups() - -for lv in lvs: - for m in find_mount_points(mounts, lv["path"]): - print("unount", m["mount"]) - run(["umount", m["mount"]]) - -for vg in vgs: - print("vgremove", vg) - run(["vgremove", "--yes", vg], check=True) - -for pv in pvs: - print("pvremove", pv) - run(["pvremove", pv["pv"]], check=True) - if is_luks(pv["pv"]): - print("cryptsetup close", pv["pv"]) - run(["cryptsetup", "close", pv["pv"]], check=True) - else: - print("not LUKS:", pv["pv"]) - -for mapping in glob.glob("/dev/mapper/*"): - if not mapping.endswith("/control"): - run(["cryptsetup", "close", mapping], check=False) @@ -0,0 +1,296 @@ +#!/usr/bin/python3 + +import argparse +import glob +import os +import shutil +import sys +import tempfile +import yaml +from subprocess import run + + +def log(msg): + print("INSTALLER:", msg) + + +def physical_volumes(): + log("list physical volumes") + p = run(["pvdisplay", "-C", "--noheadings"], capture_output=True, check=True) + lines = p.stdout.decode().splitlines() + pvs = [] + for line in lines: + words = line.split() + pv = words[0] + vg = words[1] + pvs.append({"pv": pv, "vg": vg}) + return pvs + + +def logical_volumes(): + log("list logical volumes") + p = run(["lvdisplay", "-C", "--noheadings"], capture_output=True, check=True) + lines = p.stdout.decode().splitlines() + lvs = [] + for line in lines: + words = line.split() + lv = words[0] + vg = words[1] + path = os.path.realpath(f"/dev/{vg}/{lv}") + lvs.append({"lv": lv, "vg": vg, "path": path}) + return lvs + + +def volume_groups(): + log("list volume groups") + p = run(["vgdisplay", "-C", "--noheadings"], capture_output=True, check=True) + lines = p.stdout.decode().splitlines() + return [line.split()[0] for line in lines if line.strip()] + + +def mount_points(): + log("find mount all points") + mounts = {} + for line in open("/proc/mounts").readlines(): + words = line.split() + dev = os.path.realpath(words[0]) if words[0].startswith("/") else words[0] + mounts[dev] = { + "mount": words[1], + "type": words[2], + } + return mounts + + +def find_mount_points(mounts, dev): + log(f"find mount points using {dev}") + res = [] + if dev in mounts: + root = mounts[dev]["mount"] + for m in mounts.values(): + if m["mount"].startswith(root): + res.append(m) + return res + + +def is_luks(path): + log(f"is {path} a LUKS device?") + p = run(["cryptsetup", "isLuks", path], check=False) + return p.returncode == 0 + + +def clean_up_disks(): + log("clean up disks from old installs") + + mounts = mount_points() + pvs = physical_volumes() + lvs = logical_volumes() + vgs = volume_groups() + + for lv in lvs: + for m in find_mount_points(mounts, lv["path"]): + log(f"unmount {m['mount']}") + run(["umount", m["mount"]]) + + for vg in vgs: + log(f"remove volume group {vg}") + run(["vgremove", "--yes", vg], check=True) + + for pv in pvs: + log(f"remove physical volume {pv}") + run(["pvremove", pv["pv"]], check=True) + if is_luks(pv["pv"]): + run(["cryptsetup", "close", pv["pv"]], check=True) + + for mapping in glob.glob("/dev/mapper/*"): + if not mapping.endswith("/control"): + log(f"open LUKS volume {mapping} (just in case it is one)") + run(["cryptsetup", "close", mapping], check=False) + + +def vmdb_spec(cryptsetup_password, playbook): + device = "{{ image }}" + spec = { + "steps": [ + { + "mklabel": "gpt", + "device": device, + }, + { + "mkpart": "primary", + "device": device, + "start": "0%", + "end": "500M", + "tag": "efi", + }, + { + "mkpart": "primary", + "device": device, + "start": "500M", + "end": "1G", + "tag": "boot", + }, + ] + } + + # Set up pv0 for lvm2, either encrypted or cleartext. + if cryptsetup_password: + spec["steps"].extend( + [ + { + "mkpart": "primary", + "device": device, + "start": "1G", + "end": "100%", + "tag": "cryptsetup0", + }, + { + "cryptsetup": "cryptsetup0", + "password": cryptsetup_password, + "name": "pv0", + }, + ] + ) + else: + spec["steps"].extend( + [ + { + "mkpart": "primary", + "device": device, + "start": "1G", + "end": "100%", + "tag": "pv0", + }, + ] + ) + + # Create file systems and install Debian. + spec["steps"].extend( + [ + { + "mkfs": "vfat", + "partition": "efi", + }, + { + "mkfs": "ext2", + "partition": "boot", + }, + { + "vgcreate": "vg0", + "physical": ["pv0"], + }, + { + "lvcreate": "vg0", + "name": "root", + "size": "10G", + }, + { + "mkfs": "ext4", + "partition": "root", + }, + { + "mount": "root", + }, + {"mount": "boot", "dirname": "/boot", "mount-on": "root"}, + { + "mount": "efi", + "dirname": "/boot/efi", + "mount-on": "boot", + }, + { + "virtual-filesystems": "root", + }, + { + "unpack-rootfs": "root", + }, + { + "debootstrap": "bullseye", + "mirror": "http://deb.debian.org/debian", + "target": "root", + "unless": "rootfs_unpacked", + }, + { + "cache-rootfs": "root", + "unless": "rootfs_unpacked", + }, + { + "fstab": "root", + }, + { + "apt": "install", + "packages": ["linux-image-amd64"], + "tag": "root", + }, + { + "apt": "install", + "packages": [ + "console-setup", + "cryptsetup", + "cryptsetup-initramfs", + "dosfstools", + "ifupdown", + "locales-all", + "lvm2", + "psmisc", + "python3", + "ssh", + "strace", + ], + "tag": "root", + }, + { + "grub": "uefi", + "tag": "root", + "efi": "efi", + "quiet": True, + "image-dev": device, + }, + ] + ) + + # If a playbook has been specified, add an ansible step. + if playbook: + spec["steps"].append({"ansible": "root", "playbook": playbook}) + + return spec + + +def main(): + p = argparse.ArgumentParser() + p.add_argument("--verbose", action="store_true") + p.add_argument("--log", default="install.log") + p.add_argument("--cache", default="cache.tar.gz") + p.add_argument("--playbook") + p.add_argument("--luks") + p.add_argument("device") + args = p.parse_args() + + clean_up_disks() + + spec = vmdb_spec(args.luks, args.playbook) + tmp = tempfile.mkdtemp() + specfile = os.path.join(tmp, "spec.yaml") + if args.verbose: + yaml.dump(spec, stream=sys.stdout, indent=4) + with open(specfile, "w") as f: + yaml.dump(spec, stream=f, indent=4) + + log(f"run vmdb2 to install on {args.device}") + run( + [ + "vmdb2", + "--verbose", + f"--rootfs-tarball={args.cache}", + f"--log={args.log}", + f"--image={args.device}", + specfile, + ], + check=True, + ) + + log("cleanup") + shutil.rmtree(tmp) + + log("OK, done") + + +main() diff --git a/x220.sh b/x220.sh deleted file mode 100755 index dcb322d..0000000 --- a/x220.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -vi="$1" -vmdb2="$2" - -gitget() { - local url="$1" - local branch="$2" - local dir="$3" - echo "get $url ($branch)" - if [ ! -e "$dir" ]; then - git clone -b "$branch" "$url" - else - (cd "$dir" && git checkout "$branch" && git pull) - fi -} - -git config --global pull.ff only -gitget git://git.liw.fi/v-i "$vi" v-i -gitget git://git.liw.fi/vmdb2 "$vmdb2" vmdb2 -gitget git://git.liw.fi/ansibleness main ansibleness -gitget git://git.liw.fi/debian-ansible main debian-ansible - -cd v-i -export ANSIBLE_LOG=/root/ansible.log -export ANSIBLE_ROLES_PATH=/root/debian-ansible/roles:/root/ansibleness/ansible/roles - -rm -f /root/x220.log -/root/vmdb2/vmdb2 \ - --verbose \ - --rootfs-tarball /root/rootfs.tar.gz \ - --log /root/x220.log \ - --image /dev/sda \ - x220.vmdb diff --git a/x220.vmdb b/x220.vmdb deleted file mode 100644 index 8d48a77..0000000 --- a/x220.vmdb +++ /dev/null @@ -1,118 +0,0 @@ -# This is a vmdb2 input file that installs Debian onto my Thinkpad -# X220. It has an SSD as sdb. - -steps: - - mklabel: gpt - device: "{{ image }}" - - # EFI partition. This MUST be vfat and cleartext so that UEFI BIOS - # can handle it. - - mkpart: primary - device: "{{ image }}" - start: 0% - end: 500M - tag: efi - - - mkfs: vfat - partition: efi - - # /boot partition. This will be cleartext, because GRUB doesn't seem - # to support LUKS2 yet. - - mkpart: primary - device: "{{ image }}" - start: 500M - end: 1G - tag: boot - - - mkfs: ext2 - partition: boot - - # The physical volume for LVM. This will be encrypted and the - # unlocked, opened variant will be used as the physical volume for - # LVM2. - - mkpart: primary - device: "{{ image }}" - start: 1G - end: 100% - tag: cleartext_pv0 - - - cryptsetup: cleartext_pv0 - password: asdf - name: pv0 - - - vgcreate: vg0 - physical: - - pv0 - - - lvcreate: vg0 - name: root - size: 10G - - - mkfs: ext4 - partition: root - - # Mount the file systems on top of each other. - - mount: root - - - mount: boot - dirname: /boot - mount-on: root - - - mount: efi - dirname: /boot/efi - mount-on: boot - - - virtual-filesystems: root - - # Install Debian. - - - unpack-rootfs: root - - - debootstrap: bullseye - mirror: http://deb.debian.org/debian - target: root - unless: rootfs_unpacked - - - apt: install - packages: - - linux-image-amd64 - tag: root - unless: rootfs_unpacked - - - cache-rootfs: root - unless: rootfs_unpacked - - # Create fstab and crypttab - - fstab: root - - # Install additional packages. These are not in the rootfs tarball, - # while I keep changing this list: it's easier and faster to iterate - # if the rootfs tarball doesn't need to be re-generated from - # scratch. - - apt: install - packages: - - console-setup - - cryptsetup - - cryptsetup-initramfs - - dosfstools - - gdm3 - - gnome - - ifupdown - - locales-all - - lvm2 - - psmisc - - python3 - - ssh - - strace - tag: root - - # Configure the system with Ansible. - - ansible: root - playbook: x220.yml - - # Install GRUB as the bootloader. - - grub: uefi - tag: root - efi: efi - quiet: true - image-dev: "{{ image }}" @@ -3,10 +3,11 @@ - hosts: image roles: - sane_debian_system -# - comfortable-debian-system + - ssd + - comfortable-debian-system - unix_users # - gnome-system -# - intel-wifi + - intel-wifi pre_tasks: @@ -26,7 +27,7 @@ - name: "set root authorized keys" copy: content: | - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPQe6lsTapAxiwhhEeE/ixuK+5N8esCsMWoekQqjtxjP liw personal systems + {{ liw_personal_ssh_pub }} dest: /root/.ssh/authorized_keys owner: root group: root @@ -82,4 +83,7 @@ comment: Lars Wirzenius sudo: yes authorized_keys: | - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDAlECa3tbFGXhB3Zh/4/GhM11THOThVfiuLqqJ2dpWHEClzpKJHpzzwWt7g9z/MMQNMsUJLy+okz+De6hdjjmYJ9kG9Sr3H4YKq6itGQMj7L/cH3WS3ynp0uy0oW3hf932vDZKQ8iy9vczXH+ERYl+4TYae1Jp4Hyf4/2IYxEfuhKctvSvqySST3Qk9JNZ71HFGOWhjH/MmoCLoT1v+HkqmHdYf/GMKGRo3gqCEGgCgNErYYIyKm3OF3dHXK+hyGLE/cZNu6fU5woW3rvtUCFt08Ri2pm0cnXXJn9jQIMxfS5Kkf64svwgzKmPqgX1f4flopYPlsBXduCgzbJvj+lpgauAk/i1A5B01CFa9sI4C6pHZmwk1qxRwN+4IXL2CQt+tDgYC84ZDDd8R7cNyL22a3KhMQmdHtvog1beAa3Ab+J+cafkXXN+Es9f1wQjzk7DiHupmJIVofBvPP+cRcB46rwha6ati8Fa5QkT9rXFNqQsKk7jq8TIi54Bm15OOa0jInGG3TM17b9Ftu2WTJSAaqgBnDfZiInK7HEvC6K/IBljrN3oGagmFZPrAvzw7d6C2/nKFAQtfoMcE5oWVDrJyjsmJ8oaru0E8rwj7mMvyKPgEMnXTGXLWDgEo50+i291m4bkCxVwiOPbPRvdMll1Y8qfBAPT76sY4Ikgcw/2iw== openpgp:0xBBE80E50 + {{ liw_personal_ssh_pub }} + + liw_personal_ssh_pub: | + ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPQe6lsTapAxiwhhEeE/ixuK+5N8esCsMWoekQqjtxjP liw personal systems |