home lab init
This commit is contained in:
commit
7278922625
65 changed files with 27336 additions and 0 deletions
3
ansible/README.me
Normal file
3
ansible/README.me
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
ansible-playbook -i inventory.yml books/bootstrap/bootstrap-proxmox.yml
|
||||
|
||||
ansible-playbook -i inventory.yml books/upload-nix-image.yml
|
||||
3
ansible/ansible.cfg
Normal file
3
ansible/ansible.cfg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[defaults]
|
||||
roles_path = ./roles
|
||||
inventory = ./inventory.yml
|
||||
40
ansible/books/bootstrap/bootstrap-proxmox.yml
Normal file
40
ansible/books/bootstrap/bootstrap-proxmox.yml
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
- name: Bootstrap Proxmox Server
|
||||
hosts: proxmox
|
||||
become: true
|
||||
|
||||
pre_tasks:
|
||||
- name: Remove enterprise repository
|
||||
ansible.builtin.apt_repository:
|
||||
update_cache: false
|
||||
repo: deb https://enterprise.proxmox.com/debian/pve bookworm pve-enterprise
|
||||
state: absent
|
||||
- name: Remove enterprise pbs repository
|
||||
ansible.builtin.apt_repository:
|
||||
update_cache: false
|
||||
repo: deb https://enterprise.proxmox.com/debian/pbs bookworm InRelease
|
||||
state: absent
|
||||
- name: Remove enterprise ceph repository
|
||||
ansible.builtin.apt_repository:
|
||||
update_cache: false
|
||||
repo: deb https://enterprise.proxmox.com/debian/ceph-quincy bookworm enterprise
|
||||
state: absent
|
||||
- name: Add community repository
|
||||
ansible.builtin.apt_repository:
|
||||
update_cache: true
|
||||
repo: deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription
|
||||
state: present
|
||||
|
||||
tasks:
|
||||
- name: Ensure ethtool offload post-up is present for eno1
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/network/interfaces
|
||||
line: "\tpost-up ethtool -K eno2 tso off gso off"
|
||||
insertafter: "^iface eno2 inet manual"
|
||||
state: present
|
||||
backup: yes
|
||||
|
||||
- import_tasks: ../tasks/packages.yml
|
||||
# - import_tasks: ../tasks/locale.yml
|
||||
# - import_tasks: ../tasks/keyboard.yml
|
||||
# - import_tasks: ../tasks/users.yml
|
||||
# - import_tasks: ../tasks/ssh.yml
|
||||
82
ansible/books/clone-template.yml
Normal file
82
ansible/books/clone-template.yml
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
- name: Clone VM from Template
|
||||
hosts: proxmox
|
||||
become: true
|
||||
vars_prompt:
|
||||
- name: "template_vmid"
|
||||
prompt: "Enter VMID for the template"
|
||||
private: no
|
||||
default: "9000"
|
||||
|
||||
- name: "new_vmid"
|
||||
prompt: "Enter the new VMID"
|
||||
private: no
|
||||
default: "9001"
|
||||
|
||||
- name: "new_name"
|
||||
prompt: "Enter name for the new VM"
|
||||
private: no
|
||||
default: "nixos-clone"
|
||||
|
||||
vars:
|
||||
storage: "local-lvm"
|
||||
|
||||
tasks:
|
||||
- name: Clone the template
|
||||
ansible.builtin.command: >
|
||||
qm clone {{ template_vmid }} {{ new_vmid }} --name {{ new_name }}
|
||||
|
||||
- name: Resize disk to 10G
|
||||
ansible.builtin.command: >
|
||||
qm resize {{ new_vmid }} virtio0 +5G
|
||||
|
||||
- name: Set cloud-init params
|
||||
ansible.builtin.command: >
|
||||
qm set {{ new_vmid }}
|
||||
--ciuser root
|
||||
--cipassword root
|
||||
--sshkey /root/.ssh/id_rsa.pub
|
||||
--ipconfig0 ip=dhcp
|
||||
|
||||
- name: Start the new VM
|
||||
ansible.builtin.command: >
|
||||
qm start {{ new_vmid }}
|
||||
|
||||
- name: Wait for QEMU Guest Agent to come online
|
||||
retries: 20
|
||||
delay: 5
|
||||
ansible.builtin.shell: |
|
||||
qm guest exec {{ new_vmid }} -- true
|
||||
register: qga_check
|
||||
until: qga_check.rc == 0
|
||||
|
||||
- name: Get IP addresses via QEMU Guest Agent
|
||||
ansible.builtin.shell: |
|
||||
qm guest cmd {{ new_vmid }} network-get-interfaces
|
||||
register: qga_json
|
||||
failed_when: qga_json.rc != 0
|
||||
|
||||
- name: Parse out eth0’s IPv4 address
|
||||
ansible.builtin.set_fact:
|
||||
vm_ipv4: >-
|
||||
{{
|
||||
(
|
||||
qga_json.stdout
|
||||
| from_json
|
||||
| selectattr('name','equalto','eth0')
|
||||
| map(attribute='ip-addresses')
|
||||
| first
|
||||
| selectattr('ip-address-type','equalto','ipv4')
|
||||
| map(attribute='ip-address')
|
||||
| first
|
||||
)
|
||||
}}
|
||||
|
||||
- name: Show the VM’s IP
|
||||
ansible.builtin.debug:
|
||||
msg: "VM {{ new_vmid }} ({{ new_name }}) reports IPv4: {{ vm_ipv4 }}"
|
||||
|
||||
# - name: Add new VM’s IP to in-memory inventory (for later tasks)
|
||||
# ansible.builtin.add_host:
|
||||
# name: "nixos-{{ new_vmid }}"
|
||||
# ansible_host: "{{ vm_ipv4 }}"
|
||||
# ansible_user: root
|
||||
81
ansible/books/create-template.yml
Normal file
81
ansible/books/create-template.yml
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
- name: Build and Upload NixOS Image, Restore and Convert to Template
|
||||
hosts: nodes
|
||||
gather_facts: false
|
||||
|
||||
vars:
|
||||
flake_name: "{{ flake | default('base') }}"
|
||||
image_dir: "{{ playbook_dir }}/../../nixos"
|
||||
result_path: "{{ image_dir }}/result"
|
||||
dest_dir: "/var/lib/vz/dump/"
|
||||
|
||||
tasks:
|
||||
- name: Build NixOS base image
|
||||
ansible.builtin.shell: nix build .#{{ flake_name }}
|
||||
args:
|
||||
chdir: "{{ image_dir }}"
|
||||
register: build_result
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Get built image file
|
||||
ansible.builtin.find:
|
||||
paths: "{{ result_path }}"
|
||||
patterns: "*.vma.zst"
|
||||
register: built_image
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Fail if no image was built
|
||||
ansible.builtin.fail:
|
||||
msg: "No image file found in result/"
|
||||
when: built_image.files | length == 0
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Set fact for built image path
|
||||
ansible.builtin.set_fact:
|
||||
local_image_path: "{{ built_image.files[0].path | realpath }}"
|
||||
image_filename: "{{ built_image.files[0].path | basename }}"
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Copy image to Proxmox
|
||||
ansible.builtin.copy:
|
||||
src: "{{ local_image_path }}"
|
||||
dest: "{{ dest_dir }}"
|
||||
|
||||
- name: Remove local build result
|
||||
ansible.builtin.file:
|
||||
path: "{{ result_path }}"
|
||||
state: absent
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Restore and Convert to Template on Proxmox
|
||||
hosts: nodes
|
||||
become: true
|
||||
|
||||
vars_prompt:
|
||||
- name: "vmid"
|
||||
prompt: "Enter VMID for the template"
|
||||
private: no
|
||||
default: "9000"
|
||||
|
||||
- name: "vmname"
|
||||
prompt: "Enter name for the Proxmox template"
|
||||
private: no
|
||||
default: "nixos-base"
|
||||
|
||||
vars:
|
||||
image_path: "/var/lib/vz/dump/{{ image_filename }}"
|
||||
cpu_cores: 2
|
||||
memory_mb: 2048
|
||||
|
||||
tasks:
|
||||
- name: Restore VM from image
|
||||
ansible.builtin.command: >
|
||||
qmrestore {{ image_path }} {{ vmid }} --unique true
|
||||
args:
|
||||
creates: "/etc/pve/qemu-server/{{ vmid }}.conf"
|
||||
|
||||
- name: Set name, CPU and memory
|
||||
ansible.builtin.command: >
|
||||
qm set {{ vmid }} --cores {{ cpu_cores }} --memory {{ memory_mb }} --name {{ vmname }}
|
||||
|
||||
- name: Convert VM to template
|
||||
ansible.builtin.command: qm template {{ vmid }}
|
||||
13
ansible/books/installers/install-nix.yml
Normal file
13
ansible/books/installers/install-nix.yml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
- name: Install Nix (multi-user mode)
|
||||
ansible.builtin.shell: |
|
||||
if [ ! -x /nix/var/nix/profiles/default/bin/nix ]; then
|
||||
curl -L https://nixos.org/nix/install | bash -s -- --daemon
|
||||
fi
|
||||
args:
|
||||
creates: /nix
|
||||
|
||||
- name: Enable flakes in nix config
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/nix/nix.conf
|
||||
content: |
|
||||
experimental-features = nix-command flakes
|
||||
25
ansible/books/installers/uninstall-nix.yml
Normal file
25
ansible/books/installers/uninstall-nix.yml
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
- name: Stop nix-daemon service
|
||||
ansible.builtin.systemd:
|
||||
name: nix-daemon.service
|
||||
state: stopped
|
||||
enabled: no
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Remove /nix directory
|
||||
ansible.builtin.file:
|
||||
path: /nix
|
||||
state: absent
|
||||
|
||||
- name: Remove nix entries from root's shell config
|
||||
ansible.builtin.lineinfile:
|
||||
path: /root/.bashrc
|
||||
regexp: "^.*nix.*$"
|
||||
state: absent
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Remove nix entries from root's shell profile
|
||||
ansible.builtin.lineinfile:
|
||||
path: /root/.profile
|
||||
regexp: "^.*nix.*$"
|
||||
state: absent
|
||||
ignore_errors: yes
|
||||
17
ansible/books/nas/nfs-data-volume.yml
Normal file
17
ansible/books/nas/nfs-data-volume.yml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
- name: Ensure NFS subfolders exist on NAS
|
||||
hosts: nas
|
||||
become: true
|
||||
tasks:
|
||||
- name: Ensure /volume1/data exists
|
||||
file:
|
||||
path: /volume1/data
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Ensure /volume1/data/forgejo exists
|
||||
file:
|
||||
path: /volume1/data/forgejo
|
||||
state: directory
|
||||
owner: 992
|
||||
group: 990
|
||||
mode: "0770"
|
||||
2
ansible/books/tasks/keyboard.yml
Normal file
2
ansible/books/tasks/keyboard.yml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
- name: Set keyboard layout
|
||||
ansible.builtin.command: localectl set-keymap dk
|
||||
10
ansible/books/tasks/locale.yml
Normal file
10
ansible/books/tasks/locale.yml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
- name: Ensure locale is set
|
||||
ansible.builtin.locale_gen:
|
||||
name: "en_DK.UTF-8"
|
||||
state: present
|
||||
|
||||
- name: Set system locale
|
||||
ansible.builtin.command: localectl set-locale LANG=en_DK.UTF-8
|
||||
|
||||
- name: Set timezone
|
||||
ansible.builtin.command: timedatectl set-timezone Europe/Copenhagen
|
||||
8
ansible/books/tasks/packages.yml
Normal file
8
ansible/books/tasks/packages.yml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
- name: Install required packages
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- python3
|
||||
- curl
|
||||
- git
|
||||
state: present
|
||||
update_cache: yes
|
||||
14
ansible/books/tasks/ssh.yml
Normal file
14
ansible/books/tasks/ssh.yml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
- name: Ensure user plasmagoat exists
|
||||
ansible.builtin.user:
|
||||
name: plasmagoat
|
||||
groups: wheel,docker,networkmanager
|
||||
shell: /usr/bin/zsh
|
||||
state: present
|
||||
|
||||
- name: Set authorized SSH keys for plasmagoat
|
||||
ansible.posix.authorized_key:
|
||||
user: plasmagoat
|
||||
key: "{{ item }}"
|
||||
loop:
|
||||
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCeg/n/..."
|
||||
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICUP7m8jZJ..."
|
||||
16
ansible/books/tasks/users.yml
Normal file
16
ansible/books/tasks/users.yml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
- name: Disable PasswordAuthentication in sshd_config
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: "^PasswordAuthentication"
|
||||
line: "PasswordAuthentication no"
|
||||
|
||||
- name: Disable KbdInteractiveAuthentication in sshd_config
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: "^KbdInteractiveAuthentication"
|
||||
line: "KbdInteractiveAuthentication no"
|
||||
|
||||
- name: Restart sshd to apply changes
|
||||
ansible.builtin.service:
|
||||
name: ssh
|
||||
state: restarted
|
||||
8
ansible/books/upgrade.yml
Normal file
8
ansible/books/upgrade.yml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
- name: Upgrade
|
||||
hosts: nodes
|
||||
tasks:
|
||||
- name: Upgrade
|
||||
tags: upgrade
|
||||
ansible.builtin.apt:
|
||||
upgrade: dist
|
||||
6
ansible/books/upload-age-key.yml
Normal file
6
ansible/books/upload-age-key.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
- name: Deploy and bootstrap mailer VM
|
||||
hosts: mailer
|
||||
become: true
|
||||
|
||||
roles:
|
||||
- common
|
||||
26
ansible/books/upload-nix-image.yml
Normal file
26
ansible/books/upload-nix-image.yml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
- name: Build and Upload NixOS Image
|
||||
hosts: nodes
|
||||
vars:
|
||||
current_date: "{{ ansible_date_time.date }}"
|
||||
flake_name: "{{ flake | default('proxmox') }}"
|
||||
tasks:
|
||||
- name: create iso
|
||||
ansible.builtin.shell: nix build .#{{ flake_name }}
|
||||
args:
|
||||
chdir: "{{ playbook_dir }}/../../nixos/nixos-base-image"
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
|
||||
- name: copy the backup
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item }}"
|
||||
dest: "/var/lib/vz/dump/"
|
||||
with_fileglob:
|
||||
- "{{ playbook_dir }}/../../nixos/nixos-base-image/result/*.zst"
|
||||
|
||||
- name: remove build result
|
||||
ansible.builtin.file:
|
||||
path: "{{ playbook_dir }}/../../nixos/nixos-base-image/result"
|
||||
state: absent
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
28
ansible/inventory.yml
Normal file
28
ansible/inventory.yml
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
nodes:
|
||||
hosts:
|
||||
proxmox-01:
|
||||
ansible_host: 192.168.1.205
|
||||
ansible_user: root
|
||||
ansible_ssh_private_key_file: ~/.ssh/id_ed25519
|
||||
|
||||
vms:
|
||||
hosts:
|
||||
mailer:
|
||||
ansible_host: 192.168.1.36
|
||||
ansible_user: plasmagoat
|
||||
|
||||
nas:
|
||||
hosts:
|
||||
nas-01:
|
||||
ansible_host: 192.168.1.226
|
||||
ansible_user: plasmagoat
|
||||
ansible_ssh_private_key_file: ~/.ssh/id_ed25519
|
||||
|
||||
proxmox:
|
||||
hosts:
|
||||
proxmox-01:
|
||||
# vms:
|
||||
# hosts:
|
||||
# tailgate:
|
||||
# ansible_user: example
|
||||
# ansible_host: example.example.ts.net
|
||||
1
ansible/roles/common/files/.gitignore
vendored
Normal file
1
ansible/roles/common/files/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
*.key
|
||||
15
ansible/roles/common/tasks/main.yml
Normal file
15
ansible/roles/common/tasks/main.yml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
- name: Ensure /etc/sops exists
|
||||
file:
|
||||
path: /etc/sops
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0700"
|
||||
|
||||
- name: Upload age key
|
||||
copy:
|
||||
src: files/age.key
|
||||
dest: /etc/sops/age.key
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
Loading…
Add table
Add a link
Reference in a new issue