Adding recovery for debian desktop
This commit is contained in:
parent
f121910cba
commit
a69966c457
|
|
@ -3,9 +3,11 @@
|
|||
*.tfstate.backup
|
||||
.terraform/
|
||||
.lab/
|
||||
bootstrap/host/inventory/
|
||||
|
||||
# Ignore local archive dumps and backups
|
||||
*.tar
|
||||
*.tar.gz
|
||||
*.zip
|
||||
infra/gitea/data/
|
||||
|
||||
|
|
|
|||
15
README.md
15
README.md
|
|
@ -92,6 +92,21 @@ On the Debian host:
|
|||
- SSH access to the OCI edge host
|
||||
- enough persistent storage for `/var/openebs/local` and `/var/lib/docker`
|
||||
|
||||
After a clean Debian reinstall, bootstrap the host package set and desktop
|
||||
configuration first:
|
||||
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y git ansible sudo
|
||||
git clone <repo-url> /home/jv/my-homelab-configs
|
||||
cd /home/jv/my-homelab-configs
|
||||
ansible-playbook -K -i bootstrap/host/inventory.ini bootstrap/host/playbook.yml
|
||||
```
|
||||
|
||||
If you kept the private app-config archive generated from the old Debian host,
|
||||
pass its generated `ansible-vars.yml` with `-e @/path/to/ansible-vars.yml`.
|
||||
Details are in `bootstrap/host/README.md`.
|
||||
|
||||
The default kubeconfig path is `/home/jv/.kube/config`. Override it with
|
||||
`KUBECONFIG_PATH` or `TF_VAR_kubeconfig_path` when needed.
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
# Debian Host Bootstrap
|
||||
|
||||
This layer restores the Debian control-plane and personal desktop package set
|
||||
before the OpenTofu/Kubernetes bootstrap runs.
|
||||
|
||||
Fresh Debian recovery path:
|
||||
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y git ansible sudo
|
||||
sudo usermod -aG sudo jv
|
||||
git clone <repo-url> /home/jv/my-homelab-configs
|
||||
cd /home/jv/my-homelab-configs
|
||||
ansible-playbook -K -i bootstrap/host/inventory.ini bootstrap/host/playbook.yml
|
||||
./lab.sh up
|
||||
```
|
||||
|
||||
To also restore captured application behavior/configuration, keep the generated
|
||||
`home-configs.tar.gz` outside Git and pass the generated vars file:
|
||||
|
||||
```bash
|
||||
ansible-playbook -K -i bootstrap/host/inventory.ini bootstrap/host/playbook.yml \
|
||||
-e @/path/to/debian-pc-ansible-inventory/ansible-vars.yml
|
||||
```
|
||||
|
||||
The playbook:
|
||||
|
||||
- configures apt repositories for Docker, Kubernetes, Helm, OpenTofu, and Brave
|
||||
- installs the captured Debian package set, filtering packages unavailable on
|
||||
the current Debian release
|
||||
- installs Zoom from the upstream `.deb` when requested on amd64
|
||||
- adds `jv` to expected local groups
|
||||
- enables core services such as Docker, containerd, kubelet, ssh, cron, and
|
||||
Bluetooth when installed
|
||||
- creates homelab persistence directories used by `lab.sh up`
|
||||
- optionally extracts the captured user config archive into `/home/jv`
|
||||
|
||||
Secrets and active sessions are intentionally not stored in this repo. Keep
|
||||
SSH keys, kubeconfigs, SOPS keys, Docker auth, and browser session/password data
|
||||
in a separate encrypted backup if you want them restored.
|
||||
|
|
@ -0,0 +1,253 @@
|
|||
---
|
||||
debian_pc_user: jv
|
||||
debian_pc_user_home: "/home/{{ debian_pc_user }}"
|
||||
debian_pc_kubernetes_minor_version: v1.36
|
||||
debian_pc_enable_passwordless_sudo: true
|
||||
|
||||
debian_pc_persistent_directories:
|
||||
- /var/openebs/local/registry
|
||||
- /var/lib/docker
|
||||
- "/home/{{ debian_pc_user }}/git-server"
|
||||
- "/home/{{ debian_pc_user }}/backups/gitea"
|
||||
- "/home/{{ debian_pc_user }}/backups/gitea-restore-drills"
|
||||
|
||||
debian_pc_user_groups:
|
||||
- sudo
|
||||
- docker
|
||||
- audio
|
||||
- bluetooth
|
||||
- video
|
||||
- plugdev
|
||||
|
||||
debian_pc_enable_services:
|
||||
- ssh
|
||||
- cron
|
||||
- docker
|
||||
- containerd
|
||||
- kubelet
|
||||
- bluetooth
|
||||
|
||||
debian_pc_hold_packages:
|
||||
- containerd.io
|
||||
- kubeadm
|
||||
- kubectl
|
||||
- kubelet
|
||||
|
||||
debian_pc_base_packages:
|
||||
- apt-transport-https
|
||||
- bash-completion
|
||||
- ca-certificates
|
||||
- curl
|
||||
- git
|
||||
- gnupg
|
||||
- gpg
|
||||
- python3
|
||||
- python3-apt
|
||||
- rsync
|
||||
- sudo
|
||||
- tar
|
||||
- unzip
|
||||
- wget
|
||||
- zip
|
||||
|
||||
# Captured from the Debian PC manual package inventory. The playbook filters
|
||||
# packages that are unavailable for the current Debian release after adding the
|
||||
# third-party repositories, so this list can remain faithful to the source host.
|
||||
debian_pc_apt_manual_packages:
|
||||
- adduser
|
||||
- amd64-microcode
|
||||
- ansible
|
||||
- apt
|
||||
- apt-listchanges
|
||||
- apt-transport-https
|
||||
- apt-utils
|
||||
- aria2
|
||||
- base-files
|
||||
- base-passwd
|
||||
- bash
|
||||
- bash-completion
|
||||
- bind9-dnsutils
|
||||
- bind9-host
|
||||
- blueman
|
||||
- bluez
|
||||
- bluez-tools
|
||||
- brave-browser
|
||||
- bsdutils
|
||||
- busybox
|
||||
- bzip2
|
||||
- ca-certificates
|
||||
- chafa
|
||||
- chromium
|
||||
- conky-all
|
||||
- console-setup
|
||||
- containerd.io
|
||||
- containernetworking-plugins
|
||||
- coreutils
|
||||
- cpio
|
||||
- cron
|
||||
- cron-daemon-common
|
||||
- curl
|
||||
- dash
|
||||
- dbus
|
||||
- debconf
|
||||
- debconf-i18n
|
||||
- debian-archive-keyring
|
||||
- debian-faq
|
||||
- debianutils
|
||||
- dhcpcd-base
|
||||
- diffutils
|
||||
- direnv
|
||||
- dmidecode
|
||||
- dnsmasq
|
||||
- doc-debian
|
||||
- docker-buildx-plugin
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- docker-ce-rootless-extras
|
||||
- docker-compose-plugin
|
||||
- docker-model-plugin
|
||||
- dosfstools
|
||||
- dpkg
|
||||
- e2fsprogs
|
||||
- fdisk
|
||||
- file
|
||||
- findutils
|
||||
- firmware-amd-graphics
|
||||
- firmware-realtek
|
||||
- firmware-sof-signed
|
||||
- gcc-14-base
|
||||
- geany
|
||||
- geany-plugins
|
||||
- gettext-base
|
||||
- git
|
||||
- gnumeric
|
||||
- gnupg
|
||||
- gparted
|
||||
- gpg
|
||||
- grep
|
||||
- groff-base
|
||||
- grub-common
|
||||
- grub-efi-amd64
|
||||
- gzip
|
||||
- haveged
|
||||
- helm
|
||||
- hostname
|
||||
- i3
|
||||
- ifupdown
|
||||
- imagemagick
|
||||
- inetutils-telnet
|
||||
- init
|
||||
- initramfs-tools
|
||||
- init-system-helpers
|
||||
- installation-report
|
||||
- iproute2
|
||||
- iputils-ping
|
||||
- keyboard-configuration
|
||||
- kitty
|
||||
- kmod
|
||||
- krb5-locales
|
||||
- kubeadm
|
||||
- kubectl
|
||||
- kubelet
|
||||
- laptop-detect
|
||||
- less
|
||||
- linux-image-amd64
|
||||
- linux-sysctl-defaults
|
||||
- locales
|
||||
- login
|
||||
- login.defs
|
||||
- logrotate
|
||||
- logsave
|
||||
- lsof
|
||||
- lvm2
|
||||
- man-db
|
||||
- manpages
|
||||
- mawk
|
||||
- mcomix
|
||||
- media-types
|
||||
- mount
|
||||
- mplayer
|
||||
- nano
|
||||
- ncurses-base
|
||||
- ncurses-bin
|
||||
- ncurses-term
|
||||
- netbase
|
||||
- netcat-traditional
|
||||
- nfs-common
|
||||
- nftables
|
||||
- nginx
|
||||
- nodejs
|
||||
- openbox
|
||||
- open-iscsi
|
||||
- openssh-client
|
||||
- openssl-provider-legacy
|
||||
- os-prober
|
||||
- parted
|
||||
- passwd
|
||||
- pavucontrol
|
||||
- pciutils
|
||||
- perl
|
||||
- perl-base
|
||||
- pipx
|
||||
- procps
|
||||
- psmisc
|
||||
- pulseaudio-module-bluetooth
|
||||
- qcomicbook
|
||||
- readline-common
|
||||
- reportbug
|
||||
- rocminfo
|
||||
- rsync
|
||||
- screen
|
||||
- sed
|
||||
- sensible-utils
|
||||
- shellcheck
|
||||
- shim-signed
|
||||
- smplayer
|
||||
- sqv
|
||||
- sudo
|
||||
- synapse
|
||||
- systemd
|
||||
- systemd-sysv
|
||||
- systemd-timesyncd
|
||||
- sysvinit-utils
|
||||
- tar
|
||||
- task-english
|
||||
- task-laptop
|
||||
- tasksel
|
||||
- task-ssh-server
|
||||
- tcpdump
|
||||
- thefuck
|
||||
- tilda
|
||||
- tmux
|
||||
- tofu
|
||||
- traceroute
|
||||
- transmission
|
||||
- tree
|
||||
- tzdata
|
||||
- ucf
|
||||
- udev
|
||||
- unzip
|
||||
- usbutils
|
||||
- util-linux
|
||||
- util-linux-extra
|
||||
- vim
|
||||
- vim-common
|
||||
- vim-tiny
|
||||
- virtualenvwrapper
|
||||
- vlc
|
||||
- wamerican
|
||||
- wget
|
||||
- whiptail
|
||||
- wmctrl
|
||||
- wtmpdb
|
||||
- xlsx2csv
|
||||
- xorg
|
||||
- xz-utils
|
||||
- zip
|
||||
- zlib1g
|
||||
- zoom
|
||||
- zstd
|
||||
|
||||
debian_pc_config_archive: ""
|
||||
debian_pc_restore_configs: true
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
[debian_pc]
|
||||
localhost ansible_connection=local
|
||||
|
||||
|
|
@ -0,0 +1,242 @@
|
|||
---
|
||||
- name: Restore Debian homelab control-plane and desktop host
|
||||
hosts: debian_pc
|
||||
become: true
|
||||
gather_facts: true
|
||||
|
||||
pre_tasks:
|
||||
- name: Require Debian
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- ansible_facts.os_family == "Debian"
|
||||
- ansible_facts.distribution == "Debian"
|
||||
fail_msg: "This host bootstrap is intentionally scoped to Debian."
|
||||
|
||||
- name: Install apt prerequisites
|
||||
ansible.builtin.apt:
|
||||
name: "{{ debian_pc_base_packages }}"
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Ensure apt keyring directory exists
|
||||
ansible.builtin.file:
|
||||
path: /etc/apt/keyrings
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
tasks:
|
||||
- name: Add Docker apt key
|
||||
ansible.builtin.get_url:
|
||||
url: https://download.docker.com/linux/debian/gpg
|
||||
dest: /etc/apt/keyrings/docker.asc
|
||||
mode: "0644"
|
||||
|
||||
- name: Add Docker apt source
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/apt/sources.list.d/docker.sources
|
||||
mode: "0644"
|
||||
content: |
|
||||
Types: deb
|
||||
URIs: https://download.docker.com/linux/debian
|
||||
Suites: {{ ansible_facts.distribution_release }}
|
||||
Components: stable
|
||||
Architectures: {{ ansible_facts.architecture | regex_replace('x86_64', 'amd64') | regex_replace('aarch64', 'arm64') }}
|
||||
Signed-By: /etc/apt/keyrings/docker.asc
|
||||
|
||||
- name: Add Kubernetes apt key
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
curl -fsSL "https://pkgs.k8s.io/core:/stable:/{{ debian_pc_kubernetes_minor_version }}/deb/Release.key" |
|
||||
gpg --dearmor >/etc/apt/keyrings/kubernetes-apt-keyring.gpg
|
||||
chmod 0644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg
|
||||
args:
|
||||
executable: /bin/bash
|
||||
creates: /etc/apt/keyrings/kubernetes-apt-keyring.gpg
|
||||
|
||||
- name: Add Kubernetes apt source
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/apt/sources.list.d/kubernetes.list
|
||||
mode: "0644"
|
||||
content: |
|
||||
deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/{{ debian_pc_kubernetes_minor_version }}/deb/ /
|
||||
|
||||
- name: Add Helm apt key
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
curl -fsSL https://baltocdn.com/helm/signing.asc |
|
||||
gpg --dearmor >/etc/apt/keyrings/helm.gpg
|
||||
chmod 0644 /etc/apt/keyrings/helm.gpg
|
||||
args:
|
||||
executable: /bin/bash
|
||||
creates: /etc/apt/keyrings/helm.gpg
|
||||
|
||||
- name: Add Helm apt source
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/apt/sources.list.d/helm-stable-debian.list
|
||||
mode: "0644"
|
||||
content: |
|
||||
deb [arch={{ ansible_facts.architecture | regex_replace('x86_64', 'amd64') | regex_replace('aarch64', 'arm64') }} signed-by=/etc/apt/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main
|
||||
|
||||
- name: Add OpenTofu apt keys
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
curl -fsSL https://get.opentofu.org/opentofu.gpg >/etc/apt/keyrings/opentofu.gpg
|
||||
curl -fsSL https://packages.opentofu.org/opentofu/tofu/gpgkey |
|
||||
gpg --dearmor >/etc/apt/keyrings/opentofu-repo.gpg
|
||||
chmod 0644 /etc/apt/keyrings/opentofu.gpg /etc/apt/keyrings/opentofu-repo.gpg
|
||||
args:
|
||||
executable: /bin/bash
|
||||
creates: /etc/apt/keyrings/opentofu-repo.gpg
|
||||
|
||||
- name: Add OpenTofu apt source
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/apt/sources.list.d/opentofu.list
|
||||
mode: "0644"
|
||||
content: |
|
||||
deb [signed-by=/etc/apt/keyrings/opentofu.gpg,/etc/apt/keyrings/opentofu-repo.gpg] https://packages.opentofu.org/opentofu/tofu/any/ any main
|
||||
|
||||
- name: Add Brave apt key
|
||||
ansible.builtin.get_url:
|
||||
url: https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg
|
||||
dest: /etc/apt/keyrings/brave-browser-archive-keyring.gpg
|
||||
mode: "0644"
|
||||
|
||||
- name: Add Brave apt source
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/apt/sources.list.d/brave-browser-release.sources
|
||||
mode: "0644"
|
||||
content: |
|
||||
Types: deb
|
||||
URIs: https://brave-browser-apt-release.s3.brave.com/
|
||||
Suites: stable
|
||||
Components: main
|
||||
Architectures: amd64 arm64
|
||||
Signed-By: /etc/apt/keyrings/brave-browser-archive-keyring.gpg
|
||||
|
||||
- name: Refresh apt cache after repository setup
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
|
||||
- name: Write desired package list for availability filtering
|
||||
ansible.builtin.copy:
|
||||
dest: /tmp/homelab-debian-pc-desired-packages.txt
|
||||
mode: "0644"
|
||||
content: |
|
||||
{% for package in (debian_pc_base_packages + debian_pc_apt_manual_packages) | unique | sort %}
|
||||
{{ package }}
|
||||
{% endfor %}
|
||||
|
||||
- name: Filter packages available to apt
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
while IFS= read -r package; do
|
||||
[ -n "$package" ] || continue
|
||||
if apt-cache policy "$package" | awk '/Candidate:/ && $2 != "(none)" { found = 1 } END { exit found ? 0 : 1 }'; then
|
||||
printf '%s\n' "$package"
|
||||
fi
|
||||
done </tmp/homelab-debian-pc-desired-packages.txt
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: debian_pc_installable_packages_result
|
||||
changed_when: false
|
||||
|
||||
- name: Track installable package list
|
||||
ansible.builtin.set_fact:
|
||||
debian_pc_installable_packages: "{{ debian_pc_installable_packages_result.stdout_lines | default([]) }}"
|
||||
|
||||
- name: Install available Debian PC packages
|
||||
ansible.builtin.apt:
|
||||
name: "{{ debian_pc_installable_packages }}"
|
||||
state: present
|
||||
when: debian_pc_installable_packages | length > 0
|
||||
|
||||
- name: Install Zoom from upstream deb when requested on amd64
|
||||
ansible.builtin.apt:
|
||||
deb: https://zoom.us/client/latest/zoom_amd64.deb
|
||||
state: present
|
||||
when:
|
||||
- "'zoom' in debian_pc_apt_manual_packages"
|
||||
- ansible_facts.architecture == "x86_64"
|
||||
|
||||
- name: Hold Kubernetes and runtime packages
|
||||
ansible.builtin.dpkg_selections:
|
||||
name: "{{ item }}"
|
||||
selection: hold
|
||||
loop: "{{ debian_pc_hold_packages }}"
|
||||
failed_when: false
|
||||
|
||||
- name: Ensure expected local groups exist
|
||||
ansible.builtin.group:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
loop: "{{ debian_pc_user_groups }}"
|
||||
|
||||
- name: Ensure user supplementary groups
|
||||
ansible.builtin.user:
|
||||
name: "{{ debian_pc_user }}"
|
||||
groups: "{{ debian_pc_user_groups }}"
|
||||
append: true
|
||||
|
||||
- name: Allow passwordless sudo for homelab automation
|
||||
ansible.builtin.copy:
|
||||
dest: "/etc/sudoers.d/90-homelab-{{ debian_pc_user }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0440"
|
||||
validate: "visudo -cf %s"
|
||||
content: |
|
||||
{{ debian_pc_user }} ALL=(ALL) NOPASSWD:ALL
|
||||
when: debian_pc_enable_passwordless_sudo | bool
|
||||
|
||||
- name: Ensure persistent homelab directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
owner: "{{ debian_pc_user if item.startswith(debian_pc_user_home) else 'root' }}"
|
||||
group: "{{ debian_pc_user if item.startswith(debian_pc_user_home) else 'root' }}"
|
||||
mode: "{{ '0755' if item.startswith(debian_pc_user_home) else '0775' }}"
|
||||
loop: "{{ debian_pc_persistent_directories }}"
|
||||
|
||||
- name: Enable expected services when installed
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ item }}"
|
||||
enabled: true
|
||||
state: started
|
||||
loop: "{{ debian_pc_enable_services }}"
|
||||
failed_when: false
|
||||
|
||||
- name: Check whether config archive is present
|
||||
ansible.builtin.stat:
|
||||
path: "{{ debian_pc_config_archive }}"
|
||||
register: debian_pc_config_archive_stat
|
||||
when:
|
||||
- debian_pc_restore_configs | bool
|
||||
- debian_pc_config_archive | length > 0
|
||||
|
||||
- name: Restore captured home application configs
|
||||
ansible.builtin.unarchive:
|
||||
src: "{{ debian_pc_config_archive }}"
|
||||
dest: "{{ debian_pc_user_home }}"
|
||||
remote_src: true
|
||||
owner: "{{ debian_pc_user }}"
|
||||
group: "{{ debian_pc_user }}"
|
||||
when:
|
||||
- debian_pc_restore_configs | bool
|
||||
- debian_pc_config_archive | length > 0
|
||||
- debian_pc_config_archive_stat.stat.exists | default(false)
|
||||
|
||||
- name: Report packages skipped because apt has no candidate
|
||||
ansible.builtin.shell: |
|
||||
set -euo pipefail
|
||||
comm -23 \
|
||||
<(sort -u /tmp/homelab-debian-pc-desired-packages.txt) \
|
||||
<(printf '%s\n' {{ debian_pc_installable_packages | map('quote') | join(' ') }} | sort -u)
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: debian_pc_skipped_packages_result
|
||||
changed_when: false
|
||||
|
||||
- name: Show skipped packages
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ debian_pc_skipped_packages_result.stdout_lines }}"
|
||||
when: debian_pc_skipped_packages_result.stdout_lines | length > 0
|
||||
Loading…
Reference in New Issue