mirror of
https://github.com/BluemediaGER/homelab.git
synced 2024-11-09 15:15: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