infra-ansible

ansible script to ship alpine/ssh/wireguard

git clone https://9o.is/git/infra-ansible.git

commit 0e124ff8430f3a3aab3b2929fb417416efd9a4c2
parent a01c4a9095e27adfe82a91b8fe5bc508ba1461cc
Author: Jul <jul@9o.is>
Date:   Fri, 31 May 2024 17:44:12 +0800

build alpine as host os

Diffstat:
Ahost/alpine.yml | 7+++++++
Mhost/env/000_cross_env_vars | 3+++
Mhost/env/prod/host_vars/server01.qh.is | 4+++-
Mhost/env/test/host_vars/server01.local | 1-
Mhost/readme.md | 2+-
Ahost/roles/alpine/defaults/main.yml | 3+++
Ahost/roles/alpine/handlers/main.yml | 3+++
Ahost/roles/alpine/tasks/build.yml | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahost/roles/alpine/tasks/debian_autoboot.yml | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahost/roles/alpine/tasks/main.yml | 8++++++++
Ahost/roles/alpine/templates/Containerfile.j2 | 30++++++++++++++++++++++++++++++
Ahost/roles/alpine/templates/entrypoint.sh.j2 | 9+++++++++
Ahost/roles/alpine/templates/genapkovl-mkimgoverlay.sh.j2 | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahost/roles/alpine/templates/mkimg.x.sh.j2 | 7+++++++
Dhost/roles/raw-setup/tasks/main.yml | 6------
Mhost/site.yml | 9+--------
16 files changed, 300 insertions(+), 17 deletions(-)

diff --git a/host/alpine.yml b/host/alpine.yml @@ -0,0 +1,7 @@ +--- +- name: Build Alpine + hosts: servers + gather_facts: false + roles: + - alpine + diff --git a/host/env/000_cross_env_vars b/host/env/000_cross_env_vars @@ -1,3 +1,6 @@ +alpine_version: 3.19 +static_interface: eth0 +debian_preinstalled: false wireguard_port: 62620 ssh_authorized_key: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN4zNrHVit/S7gU3qW2IbSP8jtUpGSP3tb+z/PBSXD66 jul@9o.is diff --git a/host/env/prod/host_vars/server01.qh.is b/host/env/prod/host_vars/server01.qh.is @@ -1,4 +1,6 @@ -static_interface: ens3 +debian_preinstalled: true +debian_net_interface: ens3 + static_ip: 89.147.110.9 static_subnet: 255.255.255.0 static_gateway: 89.147.110.1 diff --git a/host/env/test/host_vars/server01.local b/host/env/test/host_vars/server01.local @@ -1,4 +1,3 @@ -static_interface: enX0 static_ip: 10.137.0.5 static_subnet: 255.255.255.255 static_gateway: 10.137.0.39 diff --git a/host/readme.md b/host/readme.md @@ -1,7 +1,7 @@ ### Installation ``` -ansible-playbook site.yml --tags raw-setup --user root +ansible-playbook alpine.yml --user root ansible-playbook site.yml --user root ``` diff --git a/host/roles/alpine/defaults/main.yml b/host/roles/alpine/defaults/main.yml @@ -0,0 +1,3 @@ +alpine_output: .output/alpine/{{ inventory_hostname }} +alpine_iso_dir: '{{ alpine_output }}/iso' +alpine_iso: '{{ alpine_iso_dir }}/alpine-x-{{ inventory_hostname }}-x86_64.iso' diff --git a/host/roles/alpine/handlers/main.yml b/host/roles/alpine/handlers/main.yml @@ -0,0 +1,3 @@ +--- +- name: update grub + command: update-grub2 diff --git a/host/roles/alpine/tasks/build.yml b/host/roles/alpine/tasks/build.yml @@ -0,0 +1,88 @@ + +--- +- name: create iso directory + become: false + delegate_to: localhost + file: + path: '{{ alpine_output }}/iso' + mode: '0700' + state: directory + +- name: add Containerfile + become: false + delegate_to: localhost + template: + src: Containerfile.j2 + dest: '{{ alpine_output }}/Containerfile' + mode: '0600' + +- name: add entrypoint.sh + become: false + delegate_to: localhost + template: + src: entrypoint.sh.j2 + dest: '{{ alpine_output }}/entrypoint.sh' + mode: '0755' + +- name: add mkimg.x.sh + become: false + delegate_to: localhost + template: + src: mkimg.x.sh.j2 + dest: '{{ alpine_output }}/mkimg.x.sh' + mode: '0755' + +- name: add genapkovl-mkimgoverlay.sh + become: false + delegate_to: localhost + template: + src: genapkovl-mkimgoverlay.sh.j2 + dest: '{{ alpine_output }}/genapkovl-mkimgoverlay.sh' + mode: '0755' + +- name: build alpine-builder + become: false + delegate_to: localhost + podman_image: + name: alpine-builder + path: '{{ alpine_output }}' + force: true + register: alpine_builder + +- name: check alpine iso + become: false + delegate_to: localhost + stat: + path: '{{ alpine_iso }}' + register: iso_file + +- name: build alpine iso + become: false + delegate_to: localhost + containers.podman.podman_container: + name: 'alpine-builder-{{ inventory_hostname }}' + image: alpine-builder + rm: true + detach: false + volume: + - '{{ alpine_iso_dir }}:/iso' + when: not iso_file.stat.exists or alpine_builder.changed + register: iso_build + +- name: fix ownership of iso directory + delegate_to: localhost + file: + path: '{{ alpine_iso_dir }}' + state: directory + recurse: true + owner: user + group: user + +- name: show next steps + debug: + msg: + - 'ISO is ready for manual installation.' + - '1) Mount iso {{ playbook_dir }}/{{ alpine_iso }}' + - '2) Run setup-disk' + when: not debian_preinstalled and iso_build.changed + diff --git a/host/roles/alpine/tasks/debian_autoboot.yml b/host/roles/alpine/tasks/debian_autoboot.yml @@ -0,0 +1,52 @@ +--- +- name: Set mtu to {{ static_mtu }} + raw: apt install -y iproute2 && ip link set {{ debian_net_interface }} mtu {{ static_mtu }} + +- name: Reset ssh connection to apply mtu change + become: false + delegate_to: localhost + command: rm -rf ~/.ansible/cp + +- name: upload alpine iso + copy: + src: '{{ alpine_iso }}' + dest: /alpine.iso + owner: root + group: root + mode: '0644' + register: iso_upload + +- name: create grub menuentry + blockinfile: + dest: /etc/grub.d/40_custom + block: | + menuentry "Alpine Linux" --id alpine-linux { + loopback loop /alpine.iso + linux (loop)/boot/vmlinuz-virt + initrd (loop)/boot/initramfs-virt + } + notify: update grub + +- name: set grub default + lineinfile: + path: /etc/default/grub + regexp: '^GRUB_DEFAULT=' + line: GRUB_DEFAULT=alpine-linux + notify: update grub + +- name: show next steps (with grub) + debug: + msg: + - 'ISO is ready for manual installation.' + - '1) Reboot machine' + - '2) In rescue mode, load the iso in memory and continue boot.' + - 'mount /dev/vda1 /media/vda1' + - 'cp /media/vda1/alpine.iso /dev/shm' + - 'umount /dev/vda1' + - 'mount -o loop -t iso9660 /dev/shm/alpine.iso /media/cdrom' + - 'exit' + - '3) Load apkovl if it is missing:' + - 'tar xCf / {{ inventory_hostname }}.apkovl.tar.gz' + - '4) Run setup-disk' + when: iso_upload.changed + diff --git a/host/roles/alpine/tasks/main.yml b/host/roles/alpine/tasks/main.yml @@ -0,0 +1,8 @@ +--- +- name: Build Alpine ISO + import_tasks: build.yml + +- name: Autoboot ISO on Debian + import_tasks: debian_autoboot.yml + when: debian_preinstalled + diff --git a/host/roles/alpine/templates/Containerfile.j2 b/host/roles/alpine/templates/Containerfile.j2 @@ -0,0 +1,30 @@ +FROM docker.io/library/alpine:{{ alpine_version }} + +RUN apk update +RUN apk add \ + alpine-sdk \ + alpine-conf \ + syslinux \ + xorriso \ + squashfs-tools \ + grub \ + grub-efi \ + mtools \ + dosfstools \ + doas + +RUN adduser build -u 1000 -s /bin/sh -D -G abuild; \ + echo "permit nopass :abuild" > /etc/doas.d/doas.conf + +USER build +WORKDIR /home/build + +RUN abuild-keygen -a -i -n; \ + git clone --depth=1 https://gitlab.alpinelinux.org/alpine/aports.git + +COPY mkimg.x.sh aports/scripts +COPY genapkovl-mkimgoverlay.sh aports/scripts +COPY entrypoint.sh /entrypoint.sh + +VOLUME /iso +ENTRYPOINT /entrypoint.sh diff --git a/host/roles/alpine/templates/entrypoint.sh.j2 b/host/roles/alpine/templates/entrypoint.sh.j2 @@ -0,0 +1,9 @@ +#!/bin/sh +doas chown -R build:abuild /iso +aports/scripts/mkimage.sh \ + --outdir /iso \ + --tag {{ inventory_hostname }} \ + --arch x86_64 \ + --profile x \ + --repository https://dl-cdn.alpinelinux.org/alpine/v{{ alpine_version }}/main + diff --git a/host/roles/alpine/templates/genapkovl-mkimgoverlay.sh.j2 b/host/roles/alpine/templates/genapkovl-mkimgoverlay.sh.j2 @@ -0,0 +1,85 @@ +#!/bin/sh -e + +HOSTNAME="{{ inventory_hostname }}" + +cleanup() { + rm -rf "$tmp" +} + +makefile() { + OWNER="$1" + PERMS="$2" + FILENAME="$3" + cat > "$FILENAME" + chown "$OWNER" "$FILENAME" + chmod "$PERMS" "$FILENAME" +} + +rc_add() { + mkdir -p "$tmp"/etc/runlevels/"$2" + ln -sf /etc/init.d/"$1" "$tmp"/etc/runlevels/"$2"/"$1" +} + +tmp="$(mktemp -d)" +trap cleanup EXIT + +mkdir -p "$tmp"/etc + +makefile root:root 0644 "$tmp"/etc/hostname <<EOF +$HOSTNAME +EOF + +mkdir -p "$tmp"/etc/network + +makefile root:root 0644 "$tmp"/etc/network/interfaces <<EOF +auto lo +iface lo inet loopback + +auto {{ static_interface }} +iface {{ static_interface }} inet static + address {{ static_ip }} + netmask {{ static_subnet }} + gateway {{ static_gateway }} + mtu {{ static_mtu }} +EOF + +makefile root:root 0644 "$tmp"/etc/resolv.conf <<EOF +nameserver {{ static_nameservers[0] }} +nameserver {{ static_nameservers[1] }} +EOF + +mkdir -p "$tmp"/etc/apk + +makefile root:root 0644 "$tmp"/etc/apk/world <<EOF +alpine-base +openssh +python3 +EOF + +mkdir -p "$tmp"/etc/ssh + +makefile root:root 0644 "$tmp"/etc/ssh/sshd_config <<EOF +AuthorizedKeysFile /etc/ssh/authorized_keys +Subsystem sftp internal-sftp +EOF + +makefile root:root 0644 "$tmp"/etc/ssh/authorized_keys <<EOF +{{ ssh_authorized_key }} +EOF + +rc_add devfs sysinit +rc_add dmesg sysinit +rc_add mdev sysinit +rc_add hwclock boot +rc_add modules boot +rc_add sysctl boot +rc_add hostname boot +rc_add bootmisc boot +rc_add syslog boot +rc_add networking boot +rc_add sshd default +rc_add mount-ro shutdown +rc_add killprocs shutdown +rc_add savecache shutdown + +tar -c -C "$tmp" etc | gzip -9n > $HOSTNAME.apkovl.tar.gz diff --git a/host/roles/alpine/templates/mkimg.x.sh.j2 b/host/roles/alpine/templates/mkimg.x.sh.j2 @@ -0,0 +1,7 @@ +profile_x() { + profile_virt + profile_abbrev="x" + title="Custom Virtual" + apks="$apks syslinux grub-efi acct linux-virt python3" + apkovl="aports/scripts/genapkovl-mkimgoverlay.sh" +} diff --git a/host/roles/raw-setup/tasks/main.yml b/host/roles/raw-setup/tasks/main.yml @@ -1,6 +0,0 @@ ---- -- name: Set MTU to {{ static_mtu }} - raw: apt install -y iproute2 && ip link set {{ static_interface }} mtu {{ static_mtu }} - -- name: Install Python - raw: apt install -y python3 diff --git a/host/site.yml b/host/site.yml @@ -1,12 +1,5 @@ --- -- name: Raw Setup - hosts: servers - gather_facts: false - tags: raw-setup - roles: - - raw-setup - -- name: Create Services +- name: Set Up Host Services hosts: servers roles: - role: setup