Restructure into one folder per private repo/host, not a flat Docker/ dump
rocky-docker-lxc/, caddy-vm/, monitoring-vm/ (was missing entirely -
Grafana+Loki+Prometheus stack, refreshed and CA mount stripped same as
everything else), and automation/{ansible,automation-vm,iac}/ for the
three repos that live on the automation VM. Hawser is genuinely
deployed on all three of caddy-vm/monitoring-vm/automation-vm so it's
duplicated in each rather than picking one canonical home.
Old Ansible/ and "Infrastrucutre as Code/" content moved under
automation/ansible/old-playbooks and automation/iac/old-content as-is
for now - contents still need refreshing against the current repos and
a per-folder README, that's the next pass.
This commit is contained in:
146 files changed
+101
-84
No files matched your search
@@ -0,0 +1,20 @@
|
||||
Coming Soon...
|
||||
|
||||
A description of how I use a minimal ISO to built out create a base image with defaults configurations which is perfect for its use as a base for creating Proxmox templates from.
|
||||
|
||||
|
||||
|
||||
|
||||
#ROCKY10-CIS
|
||||
cd /mnt/storage/template/iso
|
||||
qm create 5000 --memory 2048 --core 2 --name rocky10-cis --net0 virtio,bridge=vmbr0
|
||||
qm importdisk 5000 packer-rocky10.iso storage --format qcow2
|
||||
qm set 5000 \
|
||||
--scsihw virtio-scsi-pci \
|
||||
--scsi0 storage:5000/vm-5000-disk-0.qcow2,discard=on,ssd=1 \
|
||||
--cpu host \
|
||||
--numa 1 \
|
||||
--balloon 0
|
||||
qm set 5000 --agent enabled=1,freeze-fs-on-backup=1,fstrim_cloned_disks=1
|
||||
qm set 5000 --boot c --bootdisk scsi0
|
||||
qm set 5000 --serial0 socket --vga serial0
|
||||
@@ -0,0 +1 @@
|
||||
SuperSecretPasswordToUnlock.vault_pass.txtFile
|
||||
@@ -0,0 +1,82 @@
|
||||
#version=RHEL10
|
||||
lang en_US.UTF-8
|
||||
keyboard us
|
||||
timezone Europe/Sofia --utc
|
||||
authselect --enablefeatures=with-faillock
|
||||
selinux --enforcing
|
||||
firewall --disabled
|
||||
services --enabled=sshd,qemu-guest-agent
|
||||
firstboot --disable
|
||||
network --bootproto=dhcp --device=link --onboot=on --hostname=rocky10 --activate
|
||||
ignoredisk --only-use=vda
|
||||
rootpw --plaintext thisisatemporarypassword
|
||||
reboot
|
||||
|
||||
# Clear all partitions and create new MBR label
|
||||
clearpart --all --initlabel --drives=vda --disklabel=msdos
|
||||
|
||||
# /boot with ext4
|
||||
part /boot --fstype="ext4" --size=1024 --ondisk=vda --label=BOOT
|
||||
|
||||
# LVM physical volume on rest of disk
|
||||
part pv.01 --fstype="lvmpv" --ondisk=vda --grow --size=1 --label=PV01
|
||||
volgroup rocky pv.01
|
||||
|
||||
# Logical volumes
|
||||
logvol /tmp --fstype=xfs --size=2048 --name=lv_tmp --vgname=rocky --fsoptions="defaults,nodev,nosuid"
|
||||
logvol /home --fstype=xfs --size=2048 --name=lv_home --vgname=rocky --fsoptions="defaults,nodev"
|
||||
logvol /var --fstype=xfs --size=4096 --name=lv_var --vgname=rocky --fsoptions="defaults,nodev"
|
||||
logvol /var/tmp --fstype=xfs --size=1024 --name=lv_vartmp --vgname=rocky --fsoptions="defaults,nodev,nosuid,noexec"
|
||||
logvol /var/log --fstype=xfs --size=2048 --name=lv_varlog --vgname=rocky --fsoptions="defaults,nodev,noexec,nosuid"
|
||||
logvol /var/log/audit --fstype=xfs --size=2048 --name=lv_audit --vgname=rocky --fsoptions="defaults,nodev,noexec,nosuid"
|
||||
logvol / --fstype=xfs --name=lv_root --vgname=rocky --grow --size=512 --fsoptions="defaults"
|
||||
|
||||
# BIOS-compatible bootloader
|
||||
bootloader --location=mbr --boot-drive=vda
|
||||
|
||||
# Repositories
|
||||
repo --name="base" --baseurl=https://download.rockylinux.org/pub/rocky/10/BaseOS/x86_64/os/
|
||||
repo --name="appstream" --baseurl=https://download.rockylinux.org/pub/rocky/10/AppStream/x86_64/os/
|
||||
|
||||
%packages
|
||||
@^minimal-environment
|
||||
openssh-server
|
||||
openssh-clients
|
||||
qemu-guest-agent
|
||||
nano
|
||||
zsh
|
||||
git
|
||||
curl
|
||||
sudo
|
||||
util-linux-user
|
||||
rsync
|
||||
tree
|
||||
nmap-ncat
|
||||
%end
|
||||
|
||||
%post --erroronfail
|
||||
|
||||
# Enable Docker repository
|
||||
dnf install -y epel-release dnf-plugins-core
|
||||
dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
|
||||
|
||||
# Install Docker fastfetch jq
|
||||
dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin fastfetch jq
|
||||
|
||||
# Enable services
|
||||
systemctl enable sshd
|
||||
systemctl enable docker
|
||||
systemctl restart docker
|
||||
systemctl restart sshd
|
||||
|
||||
# Enable password authentication for SSH
|
||||
cat > /etc/ssh/sshd_config.d/99-password-login.conf <<EOF
|
||||
PermitRootLogin yes
|
||||
PasswordAuthentication yes
|
||||
Subsystem sftp /usr/libexec/openssh/sftp-server
|
||||
EOF
|
||||
|
||||
# Optional: enable LVM resize service (if available)
|
||||
systemctl enable resize-lvm.service || true
|
||||
|
||||
%end
|
||||
@@ -0,0 +1,105 @@
|
||||
packer {
|
||||
required_plugins {
|
||||
qemu = {
|
||||
version = ">=1.0.0"
|
||||
source = "github.com/hashicorp/qemu"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
variable "admin_username" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "admin_password_hash" {
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "admin_ssh_key" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "ansible_username" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "ansible_ssh_key" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "iso_url" {
|
||||
type = string
|
||||
default = "https://download.rockylinux.org/pub/rocky/10/isos/x86_64/Rocky-10-latest-x86_64-minimal.iso"
|
||||
}
|
||||
|
||||
variable "iso_checksum" {
|
||||
type = string
|
||||
default = "sha256:de75c2f7cc566ea964017a1e94883913f066c4ebeb1d356964e398ed76cadd12"
|
||||
}
|
||||
|
||||
source "qemu" "rocky10" {
|
||||
iso_url = var.iso_url
|
||||
iso_checksum = var.iso_checksum
|
||||
output_directory = "output-rocky10"
|
||||
shutdown_command = "shutdown -h now"
|
||||
format = "qcow2"
|
||||
disk_size = 20480
|
||||
http_directory = "http"
|
||||
communicator = "ssh"
|
||||
ssh_username = "root"
|
||||
ssh_password = "HaveATemporaryPasswordHere"
|
||||
ssh_timeout = "20m"
|
||||
boot_wait = "20s"
|
||||
boot_command = [
|
||||
"<up><wait>",
|
||||
"e<wait>", # edit boot entry
|
||||
"<down><down><end><wait>", # go to linux line end
|
||||
" inst.ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg",
|
||||
" console=tty0 console=ttyS0,115200n8",
|
||||
" ip=dhcp",
|
||||
"<f10><wait>" # boot with edited entry
|
||||
]
|
||||
|
||||
headless = true
|
||||
qemu_binary = "/usr/bin/qemu-system-x86_64"
|
||||
accelerator = "kvm"
|
||||
cpus = 2
|
||||
memory = 2048
|
||||
|
||||
qemuargs = [
|
||||
["-serial", "file:serial.log"],
|
||||
["-cpu", "host"],
|
||||
["-display", "none"]
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
build {
|
||||
sources = ["source.qemu.rocky10"]
|
||||
|
||||
provisioner "file" {
|
||||
source = "scripts/setup-admin-user.sh"
|
||||
destination = "/tmp/setup-admin-user.sh"
|
||||
}
|
||||
|
||||
provisioner "file" {
|
||||
source = "scripts/setup-ansible-user.sh"
|
||||
destination = "/tmp/setup-ansible-user.sh"
|
||||
}
|
||||
|
||||
# Run setup-admin-user.sh
|
||||
provisioner "shell" {
|
||||
inline = [
|
||||
"chmod +x /tmp/setup-admin-user.sh",
|
||||
"/tmp/setup-admin-user.sh \"${var.admin_username}\" \"${var.admin_password_hash}\" \"${var.admin_ssh_key}\""
|
||||
]
|
||||
}
|
||||
|
||||
provisioner "shell" {
|
||||
inline = [
|
||||
"chmod +x /tmp/setup-ansible-user.sh",
|
||||
"/tmp/setup-ansible-user.sh \"${var.ansible_username}\" \"${var.ansible_ssh_key}\""
|
||||
]
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
USERNAME="$1"
|
||||
HASHED_PASSWORD="$2"
|
||||
SSH_KEY="$3"
|
||||
|
||||
echo "Creating admin user: $USERNAME"
|
||||
|
||||
# --- Install dependencies early
|
||||
if command -v dnf &>/dev/null; then
|
||||
dnf install -y zsh git curl sudo util-linux-user
|
||||
elif command -v apt-get &>/dev/null; then
|
||||
apt-get update
|
||||
apt-get install -y zsh git curl sudo
|
||||
else
|
||||
echo "Unsupported package manager"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Create user if not exists
|
||||
if ! id "$USERNAME" &>/dev/null; then
|
||||
useradd -m -s /bin/zsh "$USERNAME"
|
||||
echo "${USERNAME}:${HASHED_PASSWORD}" | chpasswd -e
|
||||
# Disable forced password change and expiration
|
||||
chage -M 99999 -I -1 -E -1 "$USERNAME"
|
||||
else
|
||||
echo "User $USERNAME already exists, skipping creation"
|
||||
fi
|
||||
|
||||
USER_HOME=$(eval echo "~$USERNAME")
|
||||
|
||||
# --- Create fastfetch config
|
||||
mkdir -p "$USER_HOME/.config/fastfetch"
|
||||
cat <<'EOF' > "$USER_HOME/.config/fastfetch/config.jsonc"
|
||||
{
|
||||
"displayMode": "default",
|
||||
"modules": [
|
||||
"os", "host", "kernel", "uptime", "packages", "shell",
|
||||
"cpu", "memory",
|
||||
{
|
||||
"type": "disk",
|
||||
"folders": ["/", "/home", "/tmp", "/var", "/var/log", "/var/log/audit", "/var/tmp"]
|
||||
},
|
||||
"locale"
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
chown -R "$USERNAME:$USERNAME" "$USER_HOME/.config"
|
||||
chmod -R 700 "$USER_HOME/.config"
|
||||
|
||||
# --- SSH Setup
|
||||
mkdir -p "$USER_HOME/.ssh"
|
||||
echo "$SSH_KEY" > "$USER_HOME/.ssh/authorized_keys"
|
||||
chmod 700 "$USER_HOME/.ssh"
|
||||
chmod 600 "$USER_HOME/.ssh/authorized_keys"
|
||||
chown -R "$USERNAME:$USERNAME" "$USER_HOME/.ssh"
|
||||
|
||||
# --- Groups and Sudo
|
||||
if ! getent group docker >/dev/null; then
|
||||
groupadd docker
|
||||
fi
|
||||
|
||||
if getent group sudo >/dev/null; then
|
||||
usermod -aG sudo,docker "$USERNAME"
|
||||
elif getent group wheel >/dev/null; then
|
||||
usermod -aG wheel,docker "$USERNAME"
|
||||
else
|
||||
echo "No sudo-equivalent group found, skipping"
|
||||
fi
|
||||
|
||||
echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/99_$USERNAME"
|
||||
chmod 440 "/etc/sudoers.d/99_$USERNAME"
|
||||
|
||||
# --- Install Oh My Zsh and config as the user
|
||||
runuser -l "$USERNAME" -c 'export RUNZSH=no CHSH=no KEEP_ZSHRC=yes && \
|
||||
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" --unattended'
|
||||
|
||||
# --- Install autosuggestions plugin
|
||||
runuser -l "$USERNAME" -c "git clone https://github.com/zsh-users/zsh-autosuggestions \
|
||||
~/.oh-my-zsh/custom/plugins/zsh-autosuggestions"
|
||||
|
||||
# --- Generate custom .zshrc
|
||||
cat << 'EOF' > "$USER_HOME/.zshrc"
|
||||
export ZSH="\$HOME/.oh-my-zsh"
|
||||
ZSH_THEME="robbyrussell"
|
||||
plugins=(git zsh-autosuggestions)
|
||||
source \$ZSH/oh-my-zsh.sh
|
||||
|
||||
PS1='%F{51}%n%F{255}@%F{227}%m %F{84}%~%f %F{15}$ '
|
||||
fastfetch
|
||||
EOF
|
||||
|
||||
chown "$USERNAME:$USERNAME" "$USER_HOME/.zshrc"
|
||||
chmod 644 "$USER_HOME/.zshrc"
|
||||
|
||||
# --- Set shell (do this last to avoid breaking script if user shell changes mid-run)
|
||||
chsh -s "$(command -v zsh)" "$USERNAME"
|
||||
|
||||
# --- Deny admin from using Ansible
|
||||
cat <<EOF > /etc/sudoers.d/99_no_ansible_for_admin
|
||||
$USERNAME ALL=(ALL) !/usr/bin/ansible, !/usr/bin/ansible-playbook
|
||||
EOF
|
||||
|
||||
chmod 440 /etc/sudoers.d/99_no_ansible_for_admin
|
||||
|
||||
echo "✅ User $USERNAME configured successfully"
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
USERNAME="$1"
|
||||
SSH_KEY="$2"
|
||||
|
||||
echo "Creating ansible user: $USERNAME"
|
||||
|
||||
# --- Create user if not exists
|
||||
if ! id "$USERNAME" &>/dev/null; then
|
||||
useradd -m "$USERNAME"
|
||||
mkdir -p "/home/$USERNAME/.ssh"
|
||||
echo "$SSH_KEY" > "/home/$USERNAME/.ssh/authorized_keys"
|
||||
chmod 700 "/home/$USERNAME/.ssh"
|
||||
chmod 600 "/home/$USERNAME/.ssh/authorized_keys"
|
||||
chown -R "$USERNAME:$USERNAME" "/home/$USERNAME/.ssh"
|
||||
else
|
||||
echo "User $USERNAME already exists, skipping creation"
|
||||
fi
|
||||
|
||||
# --- Harden the ansible user
|
||||
|
||||
# Disable password (no password login)
|
||||
passwd -d "$USERNAME"
|
||||
passwd -l "$USERNAME"
|
||||
|
||||
# Allow full passwordless sudo (needed for playbook tasks)
|
||||
cat <<EOF > "/etc/sudoers.d/99_${USERNAME}"
|
||||
${USERNAME} ALL=(ALL) NOPASSWD: ALL
|
||||
EOF
|
||||
chmod 0440 "/etc/sudoers.d/99_${USERNAME}"
|
||||
|
||||
echo "✅ User $USERNAME hardened for automation-only access"
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
VAULT_FILE=".vault_pass.txt"
|
||||
VARS_FILE="terraform.pkrvar.hcl"
|
||||
PACKER_TEMPLATE="packer.pkr.hcl"
|
||||
|
||||
# Check if vault password file exists
|
||||
if [[ ! -f "$VAULT_FILE" ]]; then
|
||||
echo "❌ Vault password file '$VAULT_FILE' not found."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Decrypt the vars file temporarily
|
||||
echo "🔓 Decrypting $VARS_FILE..."
|
||||
ansible-vault decrypt "$VARS_FILE" --vault-password-file "$VAULT_FILE"
|
||||
|
||||
# Run packer build
|
||||
echo "🏗️ Running Packer build..."
|
||||
packer build -var-file="$VARS_FILE" "$PACKER_TEMPLATE"
|
||||
|
||||
# Re-encrypt the vars file
|
||||
echo "🔒 Re-encrypting $VARS_FILE..."
|
||||
ansible-vault encrypt "$VARS_FILE" --vault-password-file "$VAULT_FILE"
|
||||
|
||||
echo "✅ Done!"
|
||||
@@ -0,0 +1,27 @@
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
37323332646365326338303234343138326439366364323631663634653136363935363865636334
|
||||
6534666264666666326235393861356362353932633630390a366334646166623237623233663763
|
||||
32323438646339353263366361323632646433643134663666616631316262363539373330633536
|
||||
3966623765323965650a613664306466353931643234333837376237303131643932306563346532
|
||||
65363634643964613936376661386639303431623534373464636638333238626130316664663666
|
||||
33356661313632366531646564366465366530663366326135326133313662323939393566653333
|
||||
62393839316330303164646131393162373138613764303864616562666130663035323864383031
|
||||
31303536346332393164306162343062616436303138643138653734633630666462633565326234
|
||||
66636562663165333863373563373535666533396334363865303237373331633761633838653961
|
||||
38383634326530333531656438346238336133613636356238653264303137333839313233656339
|
||||
38323730626234643963636662326663353737346332366263373139353962663239663363623736
|
||||
38656434386261316136323130646235666139643131313132396536393234373263323735336631
|
||||
37623537613164346663363138343238386362646533343837363165353539636539323434393839
|
||||
32323633636534623738356338336561653033633939366537653662643430396364383033343663
|
||||
37306666353432643636353464333362343162306435363236623866366639663339363339353736
|
||||
64663332386662353864303634653539323831396136383565363462316638613530623236623038
|
||||
63613262393035303730376164656239646336343133363931613136393362383734363235336637
|
||||
34613830633136636130303737636339306332393062656538616133393638613564326534336233
|
||||
35623764366232366538363464383334386539333963373066373065323466313033663735626466
|
||||
30366430323565333365343036343566663133316236663431393335353930323731633934346636
|
||||
38653039653930356633666336333365663833316635353866313965653632363365303165393538
|
||||
30666431663838633434363637656365613133323834343630383133396435333061373832633361
|
||||
30393730653963303933303934626562373663623265356562376633366238323563623462343162
|
||||
32626164663630393831316136303835613362663534383938353965366538653838343539663263
|
||||
65663833343834356137366263623331373236323065376536633237613030346135663563333763
|
||||
6539613565366337613162366434373430643634393665326666
|
||||
@@ -0,0 +1,15 @@
|
||||
variable "admin_username" {
|
||||
default = "admin"
|
||||
}
|
||||
|
||||
variable "admin_password_hash" {
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "admin_ssh_key" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "ansible_username" {}
|
||||
variable "ansible_ssh_key" {}
|
||||
Reference in new issue
Block a user