diff --git a/metal/README.md b/metal/README.md index 9100205..566fced 100644 --- a/metal/README.md +++ b/metal/README.md @@ -3,4 +3,5 @@ - Download and extract Debian Bullseye netboot installer from the official repository. - Render config files (PXE config, GRUB config, preseed files etc.) from their corresponding [templates](./roles/pxe-server/templates). - Spin up an PXE environment (DHCP, TFTP and HTTP server) using Docker compose. -- Wake machines using WoL to install the OS via PXE. Machines will auto reboot into the finished preseeded OS after the installation is complete. \ No newline at end of file +- Wake machines using WoL to install the OS via PXE. Machines will auto reboot into the finished preseeded OS after the installation is complete. +- Tear down the docker compose project for PXE. \ No newline at end of file diff --git a/metal/group_variables/all.yml b/metal/group_variables/all.yml deleted file mode 100644 index 5de0838..0000000 --- a/metal/group_variables/all.yml +++ /dev/null @@ -1,3 +0,0 @@ -ansible_user: root -ansible_ssh_private_key_file: ~/.ssh/id_rsa -ssh_public_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" \ No newline at end of file diff --git a/metal/group_vars/all/.gitignore b/metal/group_vars/all/.gitignore new file mode 100644 index 0000000..74a72fb --- /dev/null +++ b/metal/group_vars/all/.gitignore @@ -0,0 +1 @@ +vault.yml \ No newline at end of file diff --git a/metal/group_vars/all/all.yml b/metal/group_vars/all/all.yml new file mode 100644 index 0000000..1c9fb20 --- /dev/null +++ b/metal/group_vars/all/all.yml @@ -0,0 +1,14 @@ +ansible_ssh_private_key_file: ~/.ssh/id_rsa +ssh_public_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" + +# Network config +subnet: "192.168.6.0" +netmask: "255.255.255.0" +gateway: "192.168.6.1" +nameserver: "192.168.6.1" +domain: "lab.bluemedia.dev" + +# User config from vault +user_fullname: "{{ vault_user_fullname }}" +ansible_user: "{{ vault_ansible_user }}" +ansible_become_password: "{{ vault_ansible_become_password }}" \ No newline at end of file diff --git a/metal/group_vars/all/vault.tmpl b/metal/group_vars/all/vault.tmpl new file mode 100644 index 0000000..cca0744 --- /dev/null +++ b/metal/group_vars/all/vault.tmpl @@ -0,0 +1,4 @@ +# Copy this file to vault.yml, change the values below and encrypt it using ansible-vault. +vault_user_fullname: "Lab User" +vault_ansible_user: lab +vault_ansible_become_password: "insecure" # Become password will also be the users password. \ No newline at end of file diff --git a/metal/install-os.yml b/metal/install-os.yml index d61cf0c..5e8f7c7 100644 --- a/metal/install-os.yml +++ b/metal/install-os.yml @@ -7,4 +7,10 @@ hosts: metal gather_facts: false roles: - - wol-wake \ No newline at end of file + - wol-wake + +- name: Tear down PXE stack + hosts: localhost + gather_facts: false + roles: + - pxe-teardown \ No newline at end of file diff --git a/metal/inventories/lab.yml b/metal/inventories/lab.yml index 8ec9dfd..b687f01 100644 --- a/metal/inventories/lab.yml +++ b/metal/inventories/lab.yml @@ -2,9 +2,9 @@ metal: children: masters: hosts: - lab-mini-1: {ansible_host: 192.168.1.21, mac: '4c:52:62:1c:bf:6c', disk: '/dev/nvme0n1'} - lab-mini-2: {ansible_host: 192.168.1.22, mac: '4c:52:62:0f:09:6d', disk: '/dev/nvme0n1'} - lab-mini-3: {ansible_host: 192.168.1.23, mac: '4c:52:62:0f:0a:23', disk: '/dev/nvme0n1'} + lab-mini-1: {ansible_host: 192.168.6.21, mac: '4c:52:62:1c:bf:6c', disk: '/dev/nvme0n1'} + lab-mini-2: {ansible_host: 192.168.6.22, mac: '4c:52:62:0f:09:6d', disk: '/dev/nvme0n1'} + lab-mini-3: {ansible_host: 192.168.6.23, mac: '4c:52:62:0f:0a:23', disk: '/dev/nvme0n1'} workers: hosts: - lab-mini-4: {ansible_host: 192.168.1.24, mac: '90:1b:0e:f8:e8:af', disk: '/dev/nvme0n1'} \ No newline at end of file + lab-mini-4: {ansible_host: 192.168.6.24, mac: '90:1b:0e:f8:e8:af', disk: '/dev/nvme0n1'} \ No newline at end of file diff --git a/metal/roles/pxe-server/defaults/main.yml b/metal/roles/pxe-server/defaults/main.yml index 839ab30..b152d8d 100644 --- a/metal/roles/pxe-server/defaults/main.yml +++ b/metal/roles/pxe-server/defaults/main.yml @@ -1,11 +1,2 @@ os_download_url: "https://deb.debian.org/debian/dists/bullseye/main/installer-amd64/current/images/netboot/netboot.tar.gz" -os_download_checksum: "sha256:ec3b71964457f30a57061ea758c12394bf2b792b461c697e61cc2d47053c5878" - -user_fullname: "Lab User" -username: "lab" -domain: "lab.bluemedia.dev" - -subnet: "192.168.6.0" -netmask: "255.255.255.0" -gateway: "192.168.6.1" -nameserver: "192.168.6.1" \ No newline at end of file +os_download_checksum: "sha256:ec3b71964457f30a57061ea758c12394bf2b792b461c697e61cc2d47053c5878" \ No newline at end of file diff --git a/metal/roles/pxe-server/files/docker-compose.yml b/metal/roles/pxe-server/files/docker-compose.yml index de4915e..c7ef0db 100644 --- a/metal/roles/pxe-server/files/docker-compose.yml +++ b/metal/roles/pxe-server/files/docker-compose.yml @@ -10,13 +10,15 @@ services: build: ./tftp network_mode: host volumes: - - ./data/pxe-config/grub.cfg:/var/lib/tftpboot/grub.cfg + - ./data/os/debian-installer/amd64/grub:/var/lib/tftpboot/debian-installer/amd64/grub + - ./data/pxe-config/grub.cfg:/var/lib/tftpboot/debian-installer/amd64/grub/grub.cfg - ./data/os/debian-installer/amd64/grubx64.efi:/var/lib/tftpboot/grubx64.efi - ./data/os/debian-installer/amd64/initrd.gz:/var/lib/tftpboot/initrd.gz - ./data/os/debian-installer/amd64/linux:/var/lib/tftpboot/linux - http: - image: nginx:latest - network_mode: host - volumes: - - ./data/os:/usr/share/nginx/html/os:ro - - ./data/preseed:/usr/share/nginx/html/preseed:ro \ No newline at end of file + - ./data/preseed:/var/lib/tftpboot/preseed + #http: + # image: nginx:latest + # network_mode: host + # volumes: + # - ./data/os:/usr/share/nginx/html/os:ro + # - ./data/preseed:/usr/share/nginx/html/preseed:ro \ No newline at end of file diff --git a/metal/roles/pxe-server/tasks/main.yml b/metal/roles/pxe-server/tasks/main.yml index df99c1c..8881633 100644 --- a/metal/roles/pxe-server/tasks/main.yml +++ b/metal/roles/pxe-server/tasks/main.yml @@ -32,6 +32,7 @@ - name: Start PXE stack docker_compose: project_src: "{{ role_path }}/files" + project_name: "pxe" state: present restarted: true build: true \ No newline at end of file diff --git a/metal/roles/pxe-server/templates/dhcpd.conf.j2 b/metal/roles/pxe-server/templates/dhcpd.conf.j2 index 31ff00d..5a87f14 100644 --- a/metal/roles/pxe-server/templates/dhcpd.conf.j2 +++ b/metal/roles/pxe-server/templates/dhcpd.conf.j2 @@ -5,8 +5,17 @@ option pxelinux.pathprefix code 210 = text; option pxelinux.reboottime code 211 = unsigned integer 32; option architecture-type code 93 = unsigned integer 16; +{% for item in groups['metal'] %} +host {{ hostvars[item]['inventory_hostname'] }} { + hardware ethernet {{ hostvars[item]['mac'] }}; + option host-name "{{ hostvars[item]['inventory_hostname'] }}"; +} +{% endfor %} + subnet {{ subnet }} netmask {{ netmask }} { option routers {{ gateway }}; + option domain-name-servers {{ nameserver }}; + option domain-name "{{ domain }}"; range {{ subnet | ansible.utils.ipmath(3) }} {{ subnet | ansible.utils.ipmath(254) }}; class "pxeclients" { diff --git a/metal/roles/pxe-server/templates/grub.cfg.j2 b/metal/roles/pxe-server/templates/grub.cfg.j2 index 7e42213..d8851d1 100644 --- a/metal/roles/pxe-server/templates/grub.cfg.j2 +++ b/metal/roles/pxe-server/templates/grub.cfg.j2 @@ -2,9 +2,13 @@ set timeout=1 menuentry 'Auto install Debian Bullseye (PXE)' { set background_color=black + set linux linux \ vga=788 \ - url=http://{{ ansible_default_ipv4.address }}/preseed/${net_default_mac}.conf \ - --- auto quiet + auto=true \ + url=tftp://{{ ansible_default_ipv4.address }}/preseed/${net_default_mac}.cfg \ + priority=critical \ + ipv6.disable=1 \ + --- quiet initrd initrd.gz } \ No newline at end of file diff --git a/metal/roles/pxe-server/templates/preseed.cfg.j2 b/metal/roles/pxe-server/templates/preseed.cfg.j2 index b662a3d..5d7c4cd 100644 --- a/metal/roles/pxe-server/templates/preseed.cfg.j2 +++ b/metal/roles/pxe-server/templates/preseed.cfg.j2 @@ -1,3 +1,4 @@ +#_preseed_V1 # For documentation see: https://www.debian.org/releases/stable/example-preseed.txt # Set default locale and keyboard layout @@ -7,6 +8,9 @@ d-i keyboard-configuration/xkb-keymap select {{ keyboard_layout | default('de') # Set network interface used by default d-i netcfg/choose_interface select auto +# Work around the problem that the network configuration is not applied, because the preseed file is loaded after it already completed. So we just run the network configuration again! :D +d-i preseed/early_command string kill-all-dhcp; netcfg + # Static network config d-i netcfg/disable_autoconfig boolean true d-i netcfg/dhcp_failed note @@ -40,9 +44,9 @@ d-i passwd/root-login boolean false # Create new user d-i passwd/user-fullname string {{ user_fullname | default('Debian User') }} -d-i passwd/username string {{ username | default('debian') }} -d-i passwd/user-password password {{ password | default('insecure') }} -d-i passwd/user-password-again password {{ password | default('insecure') }} +d-i passwd/username string {{ ansible_user | default('debian') }} +d-i passwd/user-password password {{ ansible_become_password | default('insecure') }} +d-i passwd/user-password-again password {{ ansible_become_password | default('insecure') }} # Setup timezone and NTP server d-i clock-setup/utc boolean true @@ -63,8 +67,7 @@ d-i apt-setup/cdrom/set-first boolean false d-i apt-setup/disable-cdrom-entries boolean true # Install openssh-server and basic system tools -d-i pkgsel/run_tasksel boolean false -d-i pkgsel/include string openssh-server build-essential +tasksel tasksel/first multiselect standard, ssh-server d-i pkgsel/upgrade select safe-upgrade # Disable package reporting @@ -74,5 +77,15 @@ popularity-contest popularity-contest/participate boolean false d-i grub-installer/only_debian boolean true d-i grub-installer/bootdev string {{ hostvars[item]['disk'] | default('/dev/sda') }} +# Configure openssh-server. Include public key, disable root login and passord based login. +d-i preseed/late_command string in-target mkdir -p /home/{{ ansible_user | default('debian') }}/.ssh/ ; \ + in-target /bin/sh -c 'echo "{{ ssh_public_key }}" >> /home/{{ ansible_user | default('debian') }}/.ssh/authorized_keys' ; \ + in-target chmod -R 700 /home/{{ ansible_user | default('debian') }}/.ssh/ ; \ + in-target chown -R {{ ansible_user | default('debian') }}:{{ ansible_user | default('debian') }} /home/{{ ansible_user | default('debian') }}/.ssh/ ; \ + in-target grep -q '^PermitRootLogin ' /etc/ssh/sshd_config || in-target sh -c 'echo "PermitRootLogin no" >> /etc/ssh/sshd_config' ; \ + in-target sed 's/^PermitRootLogin .*/PermitRootLogin no/' -i /etc/ssh/sshd_config ; \ + in-target grep -q '^PasswordAuthentication ' /etc/ssh/sshd_config || in-target sh -c 'echo "PasswordAuthentication no" >> /etc/ssh/sshd_config' ; \ + in-target sed 's/^PasswordAuthentication .*/PasswordAuthentication no/' -i /etc/ssh/sshd_config + # Reboot to installed system without confirmation d-i finish-install/reboot_in_progress note \ No newline at end of file diff --git a/metal/roles/pxe-teardown/tasks/main.yml b/metal/roles/pxe-teardown/tasks/main.yml new file mode 100644 index 0000000..aea2810 --- /dev/null +++ b/metal/roles/pxe-teardown/tasks/main.yml @@ -0,0 +1,5 @@ +- name: Tear down PXE stack + docker_compose: + project_name: "pxe" + project_src: "{{ playbook_dir }}/roles/pxe-server/files/" + state: absent \ No newline at end of file diff --git a/scripts/pxe-log.sh b/scripts/pxe-log.sh index b99425b..d2ded7e 100755 --- a/scripts/pxe-log.sh +++ b/scripts/pxe-log.sh @@ -1,7 +1,7 @@ #!/bin/bash -docker-compose \ - --project-directory ./metal/roles/pxe-server/files/ \ +docker compose \ + --project-name pxe \ logs \ - --f \ + --follow \ ${@} \ No newline at end of file diff --git a/scripts/pxe-teardown.sh b/scripts/pxe-teardown.sh deleted file mode 100755 index efbfbf4..0000000 --- a/scripts/pxe-teardown.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -docker compose --project-directory metal/roles/pxe-server/files/ down \ No newline at end of file