mirror of
https://github.com/BluemediaGER/homelab.git
synced 2024-11-22 19:05:29 +01:00
Initial commit
This commit is contained in:
commit
50f2a54331
17
README.md
Normal file
17
README.md
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# Homelab automation
|
||||||
|
|
||||||
|
This project contains the ansible and docker based automation of my homelab. The structure is inspired by [Khue Doan's Homelab Project](https://github.com/khuedoan/homelab).
|
||||||
|
The repo is currently work in progress. Nothing is tested yet, so everything could burst into flames at any time :)
|
||||||
|
|
||||||
|
## Hardware
|
||||||
|
|
||||||
|
- 4 × Fujitsu Esprimo Q957:
|
||||||
|
- CPU: `Intel Core i5-7500T @ 2.70 GHz`
|
||||||
|
- RAM: `16 GB`
|
||||||
|
- NVMe SSD: `256 GB`
|
||||||
|
- SATA SSD: `128 GB`
|
||||||
|
- 1 × Raspberry Pi 4 (4 GB)
|
||||||
|
|
||||||
|
## Current features
|
||||||
|
|
||||||
|
- Fully automated bare metal provisioning of Debian Bullseye using PXE and installer preseed files
|
6
metal/README.md
Normal file
6
metal/README.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# Provision hardware
|
||||||
|
|
||||||
|
- 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.
|
4
metal/ansible.cfg
Normal file
4
metal/ansible.cfg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[defaults]
|
||||||
|
host_key_checking=false
|
||||||
|
stdout_callback=debug
|
||||||
|
stderr_callback=debug
|
3
metal/group_variables/all.yml
Normal file
3
metal/group_variables/all.yml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
ansible_user: root
|
||||||
|
ansible_ssh_private_key_file: ~/.ssh/id_rsa
|
||||||
|
ssh_public_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
|
10
metal/install-os.yml
Normal file
10
metal/install-os.yml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
- name: Build PXE environment
|
||||||
|
hosts: localhost
|
||||||
|
roles:
|
||||||
|
- pxe-server
|
||||||
|
|
||||||
|
- name: Provision OS on machines
|
||||||
|
hosts: metal
|
||||||
|
gather_facts: false
|
||||||
|
roles:
|
||||||
|
- wol-wake
|
10
metal/inventories/lab.yml
Normal file
10
metal/inventories/lab.yml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
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'}
|
||||||
|
workers:
|
||||||
|
hosts:
|
||||||
|
lab-mini-4: {ansible_host: 192.168.1.24, mac: '90:1b:0e:f8:e8:af', disk: '/dev/nvme0n1'}
|
11
metal/roles/pxe-server/defaults/main.yml
Normal file
11
metal/roles/pxe-server/defaults/main.yml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
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"
|
2
metal/roles/pxe-server/files/data/os/.gitignore
vendored
Normal file
2
metal/roles/pxe-server/files/data/os/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*
|
||||||
|
!.gitignore
|
2
metal/roles/pxe-server/files/data/preseed/.gitignore
vendored
Normal file
2
metal/roles/pxe-server/files/data/preseed/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*
|
||||||
|
!.gitignore
|
2
metal/roles/pxe-server/files/data/pxe-config/.gitignore
vendored
Normal file
2
metal/roles/pxe-server/files/data/pxe-config/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*
|
||||||
|
!.gitignore
|
2
metal/roles/pxe-server/files/data/source/.gitignore
vendored
Normal file
2
metal/roles/pxe-server/files/data/source/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*
|
||||||
|
!.gitignore
|
7
metal/roles/pxe-server/files/dhcp/Dockerfile
Normal file
7
metal/roles/pxe-server/files/dhcp/Dockerfile
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
RUN apk add dhcp
|
||||||
|
|
||||||
|
RUN touch /var/lib/dhcp/dhcpd.leases
|
||||||
|
|
||||||
|
CMD [ "dhcpd", "-d", "-f", "-cf", "/etc/dhcp/dhcpd.conf" ]
|
22
metal/roles/pxe-server/files/docker-compose.yml
Normal file
22
metal/roles/pxe-server/files/docker-compose.yml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
version: "3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
dhcp:
|
||||||
|
build: ./dhcp
|
||||||
|
volumes:
|
||||||
|
- ./data/pxe-config/dhcpd.conf:/etc/dhcp/dhcpd.conf
|
||||||
|
network_mode: host
|
||||||
|
tftp:
|
||||||
|
build: ./tftp
|
||||||
|
network_mode: host
|
||||||
|
volumes:
|
||||||
|
- ./data/pxe-config/grub.cfg:/var/lib/tftpboot/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
|
11
metal/roles/pxe-server/files/http/default.conf
Normal file
11
metal/roles/pxe-server/files/http/default.conf
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
|
||||||
|
server_name default;
|
||||||
|
|
||||||
|
root /var/www/html;
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
}
|
7
metal/roles/pxe-server/files/tftp/Dockerfile
Normal file
7
metal/roles/pxe-server/files/tftp/Dockerfile
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
RUN apk add busybox tftp-hpa
|
||||||
|
|
||||||
|
ENTRYPOINT [ "/bin/sh", "-c" ]
|
||||||
|
|
||||||
|
CMD [ "busybox syslogd -n -O /dev/stdout & in.tftpd -vvv --foreground --secure /var/lib/tftpboot" ]
|
37
metal/roles/pxe-server/tasks/main.yml
Normal file
37
metal/roles/pxe-server/tasks/main.yml
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
- name: Download boot image
|
||||||
|
get_url:
|
||||||
|
url: "{{ os_download_url }}"
|
||||||
|
dest: "{{ role_path }}/files/data/source/netboot.tar.gz"
|
||||||
|
checksum: "{{ os_download_checksum }}"
|
||||||
|
register: netboot_tar
|
||||||
|
|
||||||
|
- name: Extract boot image
|
||||||
|
unarchive:
|
||||||
|
src: "{{ netboot_tar.dest }}"
|
||||||
|
dest: "{{ role_path }}/files/data/os"
|
||||||
|
|
||||||
|
- name: Generate DHCP config
|
||||||
|
template:
|
||||||
|
src: dhcpd.conf.j2
|
||||||
|
dest: "{{ role_path }}/files/data/pxe-config/dhcpd.conf"
|
||||||
|
mode: 0644
|
||||||
|
|
||||||
|
- name: Generate GRUB config
|
||||||
|
template:
|
||||||
|
src: grub.cfg.j2
|
||||||
|
dest: "{{ role_path }}/files/data/pxe-config/grub.cfg"
|
||||||
|
mode: 0644
|
||||||
|
|
||||||
|
- name: Generate preseed file for each machine
|
||||||
|
template:
|
||||||
|
src: preseed.cfg.j2
|
||||||
|
dest: "{{ role_path }}/files/data/preseed/{{ hostvars[item]['mac'] }}.cfg"
|
||||||
|
mode: 0644
|
||||||
|
loop: "{{ groups['metal'] }}"
|
||||||
|
|
||||||
|
- name: Start PXE stack
|
||||||
|
docker_compose:
|
||||||
|
project_src: "{{ role_path }}/files"
|
||||||
|
state: present
|
||||||
|
restarted: true
|
||||||
|
build: true
|
20
metal/roles/pxe-server/templates/dhcpd.conf.j2
Normal file
20
metal/roles/pxe-server/templates/dhcpd.conf.j2
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
option space pxelinux;
|
||||||
|
option pxelinux.magic code 208 = string;
|
||||||
|
option pxelinux.configfile code 209 = text;
|
||||||
|
option pxelinux.pathprefix code 210 = text;
|
||||||
|
option pxelinux.reboottime code 211 = unsigned integer 32;
|
||||||
|
option architecture-type code 93 = unsigned integer 16;
|
||||||
|
|
||||||
|
subnet {{ subnet }} netmask {{ netmask }} {
|
||||||
|
option routers {{ gateway }};
|
||||||
|
range {{ subnet | ansible.netcommon.ipmath(3) }} {{ subnet | ansible.netcommon.ipmath(254) }};
|
||||||
|
|
||||||
|
class "pxeclients" {
|
||||||
|
match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
|
||||||
|
next-server {{ ansible_default_ipv4.address }};
|
||||||
|
|
||||||
|
if option architecture-type = 00:07 {
|
||||||
|
filename "grubx64.efi";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
metal/roles/pxe-server/templates/grub.cfg.j2
Normal file
10
metal/roles/pxe-server/templates/grub.cfg.j2
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
set timeout=1
|
||||||
|
|
||||||
|
menuentry 'Auto install Debian Bullseye (PXE)' {
|
||||||
|
set background_color=black
|
||||||
|
linux linux \
|
||||||
|
vga=788 \
|
||||||
|
url=http://{{ ansible_default_ipv4.address }}/preseed/${net_default_mac}.conf \
|
||||||
|
--- auto quiet
|
||||||
|
initrd initrd.gz
|
||||||
|
}
|
78
metal/roles/pxe-server/templates/preseed.cfg.j2
Normal file
78
metal/roles/pxe-server/templates/preseed.cfg.j2
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
# For documentation see: https://www.debian.org/releases/stable/example-preseed.txt
|
||||||
|
|
||||||
|
# Set default locale and keyboard layout
|
||||||
|
d-i debian-installer/locale string {{ locale | default('en_US.UTF-8') }}
|
||||||
|
d-i keyboard-configuration/xkb-keymap select {{ keyboard_layout | default('de') }}
|
||||||
|
|
||||||
|
# Set network interface used by default
|
||||||
|
d-i netcfg/choose_interface select auto
|
||||||
|
|
||||||
|
# Static network config
|
||||||
|
d-i netcfg/disable_autoconfig boolean true
|
||||||
|
d-i netcfg/dhcp_failed note
|
||||||
|
d-i netcfg/dhcp_options select Configure network manually
|
||||||
|
|
||||||
|
d-i netcfg/get_ipaddress string {{ hostvars[item]['ansible_host'] }}
|
||||||
|
d-i netcfg/get_netmask string {{ netmask }}
|
||||||
|
d-i netcfg/get_gateway string {{ gateway }}
|
||||||
|
d-i netcfg/get_nameservers string {{ nameserver }}
|
||||||
|
d-i netcfg/confirm_static boolean true
|
||||||
|
|
||||||
|
# These values will be overwritten if set by dhcp, but the entries will get rid of the correscponding questions
|
||||||
|
d-i netcfg/get_hostname string {{ hostvars[item]['inventory_hostname'] | default('unassigned-hostname') }}
|
||||||
|
d-i netcfg/get_domain string {{ domain | default('unassigned-domain') }}
|
||||||
|
|
||||||
|
# Force hostname regarding of value set by dhcp
|
||||||
|
d-i netcfg/hostname string {{ hostvars[item]['inventory_hostname'] | default('unassigned-hostname') }}
|
||||||
|
|
||||||
|
# Load non-free firmware for hardware by default
|
||||||
|
d-i hw-detect/load_firmware boolean true
|
||||||
|
|
||||||
|
# Setup package mirrror
|
||||||
|
d-i mirror/protocol string {{ mirror_proto | default('http') }}
|
||||||
|
d-i mirror/country string manual
|
||||||
|
d-i mirror/http/hostname string {{ mirror | default('deb.debian.org') }}
|
||||||
|
d-i mirror/http/directory string {{ mirror_dir | default('/debian') }}
|
||||||
|
d-i mirror/http/proxy string {{ mirror_proxy | default('') }}
|
||||||
|
|
||||||
|
# Disable root user - normal user (see below) will have sudo permissions
|
||||||
|
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') }}
|
||||||
|
|
||||||
|
# Setup timezone and NTP server
|
||||||
|
d-i clock-setup/utc boolean true
|
||||||
|
d-i time/zone string {{ timezone | default('UTC') }}
|
||||||
|
d-i clock-setup/ntp-server string {{ ntp_server | default('de.pool.ntp.org') }}
|
||||||
|
|
||||||
|
# Autoformat disk
|
||||||
|
d-i partman-auto/disk string {{ hostvars[item]['disk'] | default('/dev/sda') }}
|
||||||
|
d-i partman-auto/method string regular
|
||||||
|
d-i partman-auto/choose_recipe select atomic
|
||||||
|
d-i partman-partitioning/confirm_write_new_label boolean true
|
||||||
|
d-i partman/choose_partition select finish
|
||||||
|
d-i partman/confirm boolean true
|
||||||
|
d-i partman/confirm_nooverwrite boolean true
|
||||||
|
|
||||||
|
# Remove install cd sources from /etc/sources.list
|
||||||
|
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
|
||||||
|
d-i pkgsel/upgrade select safe-upgrade
|
||||||
|
|
||||||
|
# Disable package reporting
|
||||||
|
popularity-contest popularity-contest/participate boolean false
|
||||||
|
|
||||||
|
# Install grub to specified device
|
||||||
|
d-i grub-installer/only_debian boolean true
|
||||||
|
d-i grub-installer/bootdev string {{ hostvars[item]['disk'] | default('/dev/sda') }}
|
||||||
|
|
||||||
|
# Reboot to installed system without confirmation
|
||||||
|
d-i finish-install/reboot_in_progress note
|
8
metal/roles/wol-wake/tasks/main.yml
Normal file
8
metal/roles/wol-wake/tasks/main.yml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
- name: Send magic packets
|
||||||
|
community.general.wakeonlan:
|
||||||
|
mac: "{{ hostvars[inventory_hostname]['mac'] }}"
|
||||||
|
delegate_to: localhost
|
||||||
|
|
||||||
|
- name: Wait for machines to come online with installed OS
|
||||||
|
wait_for_connection:
|
||||||
|
timeout: 600
|
7
scripts/pxe-log.sh
Executable file
7
scripts/pxe-log.sh
Executable file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
docker-compose \
|
||||||
|
--project-directory ./metal/roles/pxe-server/files/ \
|
||||||
|
logs \
|
||||||
|
--f \
|
||||||
|
${@}
|
Loading…
Reference in a new issue