Added proxmox-vm and static tagging of docker images
Signed-off-by: Tuan-Dat Tran <tuan-dat.tran@tudattr.dev>
This commit is contained in:
@@ -15,7 +15,7 @@ services:
|
||||
vm:
|
||||
- docker-host00
|
||||
container_name: syncthing
|
||||
image: syncthing/syncthing
|
||||
image: syncthing/syncthing:1.29
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- name: "Data"
|
||||
@@ -42,7 +42,7 @@ services:
|
||||
vm:
|
||||
- docker-host00
|
||||
container_name: kuma
|
||||
image: louislam/uptime-kuma:1
|
||||
image: louislam/uptime-kuma:1.23.16
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- name: "Data"
|
||||
@@ -60,7 +60,7 @@ services:
|
||||
vm:
|
||||
- docker-host00
|
||||
container_name: plex
|
||||
image: lscr.io/linuxserver/plex:latest
|
||||
image: lscr.io/linuxserver/plex:1.41.5
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- name: "Configuration"
|
||||
@@ -113,7 +113,7 @@ services:
|
||||
vm:
|
||||
- docker-host01
|
||||
container_name: jellyfin
|
||||
image: jellyfin/jellyfin
|
||||
image: jellyfin/jellyfin:10.10
|
||||
restart: "unless-stopped"
|
||||
volumes:
|
||||
- name: "Configuration"
|
||||
@@ -171,7 +171,7 @@ services:
|
||||
vm:
|
||||
- docker-host00
|
||||
container_name: ddns-updater
|
||||
image: ghcr.io/qdm12/ddns-updater
|
||||
image: qmcgaw/ddns-updater:2
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- name: "Configuration"
|
||||
@@ -185,7 +185,7 @@ services:
|
||||
vm:
|
||||
- docker-host00
|
||||
container_name: sonarr
|
||||
image: lscr.io/linuxserver/sonarr:latest
|
||||
image: linuxserver/sonarr:4.0.14
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- name: "Configuration"
|
||||
@@ -209,7 +209,7 @@ services:
|
||||
vm:
|
||||
- docker-host00
|
||||
container_name: radarr
|
||||
image: lscr.io/linuxserver/radarr:latest
|
||||
image: linuxserver/radarr:5.21.1
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- name: "Configuration"
|
||||
@@ -233,7 +233,7 @@ services:
|
||||
vm:
|
||||
- docker-host00
|
||||
container_name: lidarr
|
||||
image: lscr.io/linuxserver/lidarr:latest
|
||||
image: linuxserver/lidarr:2.10.3
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- name: "Configuration"
|
||||
@@ -257,7 +257,7 @@ services:
|
||||
vm:
|
||||
- docker-host00
|
||||
container_name: prowlarr
|
||||
image: lscr.io/linuxserver/prowlarr:latest
|
||||
image: linuxserver/prowlarr:1.32.2
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- name: "Configuration"
|
||||
@@ -275,7 +275,7 @@ services:
|
||||
vm:
|
||||
- docker-host00
|
||||
container_name: paperless
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:2.14
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- paperless-postgres
|
||||
@@ -311,7 +311,7 @@ services:
|
||||
vm:
|
||||
- docker-host00
|
||||
container_name: stirling
|
||||
image: frooodle/s-pdf:latest
|
||||
image: frooodle/s-pdf:0.45.0
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- name: "http"
|
||||
@@ -321,7 +321,7 @@ services:
|
||||
vm:
|
||||
- docker-host01
|
||||
container_name: gitea
|
||||
image: gitea/gitea:1.23.1-rootless
|
||||
image: gitea/gitea:1.23-rootless
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- name: "Configuration"
|
||||
@@ -350,7 +350,7 @@ services:
|
||||
vm:
|
||||
- docker-host00
|
||||
container_name: changedetection
|
||||
image: dgtlmoon/changedetection.io
|
||||
image: dgtlmoon/changedetection.io:0.49
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- name: "Data"
|
||||
@@ -364,7 +364,7 @@ services:
|
||||
vm:
|
||||
- docker-host00
|
||||
container_name: gluetun
|
||||
image: qmcgaw/gluetun
|
||||
image: qmcgaw/gluetun:v3.40
|
||||
restart: unless-stopped
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
@@ -423,7 +423,7 @@ services:
|
||||
vm:
|
||||
- docker-host00
|
||||
container_name: qbit
|
||||
image: qbittorrentofficial/qbittorrent-nox
|
||||
image: qbittorrentofficial/qbittorrent-nox:5.0.4-1
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- gluetun
|
||||
@@ -449,9 +449,8 @@ services:
|
||||
vm:
|
||||
- docker-host00
|
||||
- docker-host01
|
||||
- docker-host02
|
||||
container_name: cadvisor
|
||||
image: gcr.io/cadvisor/cadvisor:latest
|
||||
image: gcr.io/cadvisor/cadvisor:v0.52.1
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- name: ""
|
||||
@@ -470,6 +469,28 @@ services:
|
||||
- name: "Docker"
|
||||
internal: /var/lib/docker:ro
|
||||
external: /var/lib/docker
|
||||
# - name: anubis
|
||||
# vm:
|
||||
# - docker-host00
|
||||
# - docker-host01
|
||||
# container_name: anubis
|
||||
# image: ghcr.io/techarohq/anubis:v1.15.2
|
||||
# restart: unless-stopped
|
||||
# ports:
|
||||
# - name: ""
|
||||
# internal: 8080
|
||||
# external: 8080
|
||||
# volumes:
|
||||
# - name: ""
|
||||
# internal: "/data/cfg/botPolicy.json:ro"
|
||||
# external: "./botPolicy.json"
|
||||
# environment:
|
||||
# - BIND=":8080"
|
||||
# - DIFFICULTY="5"
|
||||
# - METRICS_BIND=":9090"
|
||||
# - SERVE_ROBOTS_TXT="true"
|
||||
# - TARGET="http://{{ hostvars[docker-lb].host.ip }}"
|
||||
# - POLICY_FNAME="/data/cfg/botPolicy.json"
|
||||
# - name: template
|
||||
# vm:
|
||||
# -
|
||||
|
||||
8
group_vars/proxmox/secrets_vm.yml
Normal file
8
group_vars/proxmox/secrets_vm.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
65336233643939653766663539646638346437653862656539666366353630376231353866336439
|
||||
3661363464343138333038633464646361616161376662610a303266333539306563393464613238
|
||||
36356264633564653265653632323664653133646261656234643235303165393666663539333938
|
||||
3665373736323262650a376564663737666339356666393934653234386234306334633864626130
|
||||
62663831633836373666303365643539336435393165343461346666636463653564343065653962
|
||||
62653163366663386234383462613837316166633735383862646238303263376464366564623631
|
||||
383264383961333035653539313266663463
|
||||
@@ -4,10 +4,19 @@ proxmox_api_password: "{{ vault.pve.aya01.root.sudo }}"
|
||||
|
||||
proxmox_vms:
|
||||
- name: "test-vm-00"
|
||||
hostname: "test-vm-00"
|
||||
node:
|
||||
- "aya01"
|
||||
ostemplate: ""
|
||||
node: "inko"
|
||||
vmid: 950
|
||||
cores: 2
|
||||
cpu: "x86-64-v2-AES"
|
||||
memory: 8192 # in MiB
|
||||
net:
|
||||
net0: "virtio,bridge=vmbr0,firewall=1"
|
||||
scsi:
|
||||
scsi0: "proxmox:64,format=qcow2"
|
||||
scsihw: "virtio-scsi-single"
|
||||
ostype: "l26"
|
||||
sshkeys: "{{ pubkey }}"
|
||||
ciuser: "{{ user }}"
|
||||
|
||||
proxmox_lxcs:
|
||||
- name: "test-lxc-00"
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
vars_files:
|
||||
- secrets.yml
|
||||
roles:
|
||||
- role: proxmox_vm
|
||||
- role: proxmox
|
||||
tags:
|
||||
- proxmox_vm
|
||||
- proxmox
|
||||
vars:
|
||||
action: provision
|
||||
|
||||
@@ -19,7 +19,7 @@ k3s-loadbalancer
|
||||
k3s-agent[00:02]
|
||||
k3s-server[00:02]
|
||||
k3s-longhorn[00:02]
|
||||
docker-host[00:02]
|
||||
docker-host[00:01]
|
||||
|
||||
[k3s_nodes]
|
||||
k3s-server[00:02]
|
||||
@@ -27,7 +27,7 @@ k3s-agent[00:02]
|
||||
k3s-longhorn[00:02]
|
||||
|
||||
[docker]
|
||||
docker-host[00:02]
|
||||
docker-host[00:01]
|
||||
docker-lb
|
||||
|
||||
[vps]
|
||||
@@ -49,7 +49,7 @@ k3s-postgres
|
||||
k3s-loadbalancer
|
||||
|
||||
[docker_host]
|
||||
docker-host[00:02]
|
||||
docker-host[00:01]
|
||||
|
||||
[docker_lb]
|
||||
docker-lb
|
||||
|
||||
@@ -8,4 +8,8 @@
|
||||
- name: Restart compose
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ docker.directories.compose }}"
|
||||
state: restarted
|
||||
state: present
|
||||
retries: 3
|
||||
delay: 5
|
||||
register: result
|
||||
until: result.rc == 0
|
||||
|
||||
83
roles/proxmox/files/check_proxmox_vm.sh
Executable file
83
roles/proxmox/files/check_proxmox_vm.sh
Executable file
@@ -0,0 +1,83 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Configuration
|
||||
VM_ID=303
|
||||
TARGET_IP="192.168.20.36" # Replace with the IP of your VM
|
||||
PORT=22
|
||||
CHECK_INTERVAL=300 # 5 minutes in seconds
|
||||
LOG_FILE="/var/log/vm_monitor.log"
|
||||
|
||||
# Function to log messages
|
||||
log_message() {
|
||||
echo "$(date): $1" | tee -a $LOG_FILE
|
||||
}
|
||||
|
||||
# Check if running on a Proxmox host
|
||||
if ! command -v qm &>/dev/null; then
|
||||
log_message "qm command not found. This script must run on a Proxmox host."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to check port
|
||||
check_port() {
|
||||
# Try nc first if available
|
||||
if command -v nc &>/dev/null; then
|
||||
if nc -z -w 5 $TARGET_IP $PORT 2>/dev/null; then
|
||||
return 0 # Port is open
|
||||
else
|
||||
return 1 # Port is closed
|
||||
fi
|
||||
# Fall back to nmap if nc is not available
|
||||
elif command -v nmap &>/dev/null; then
|
||||
if nmap -p $PORT $TARGET_IP | grep -q "$PORT/tcp.*open"; then
|
||||
return 0 # Port is open
|
||||
else
|
||||
return 1 # Port is closed
|
||||
fi
|
||||
else
|
||||
log_message "Neither nc nor nmap found. Please install one of them."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to restart the VM
|
||||
restart_vm() {
|
||||
log_message "Port $PORT is not reachable. Restarting VM $VM_ID..."
|
||||
|
||||
# Stop the VM
|
||||
qm stop $VM_ID
|
||||
if [ $? -ne 0 ]; then
|
||||
log_message "Failed to stop VM $VM_ID. Trying force stop..."
|
||||
qm stop $VM_ID --force
|
||||
fi
|
||||
|
||||
# Wait for VM to fully stop
|
||||
log_message "Waiting for VM to stop..."
|
||||
sleep 10
|
||||
|
||||
# Start the VM
|
||||
qm start $VM_ID
|
||||
if [ $? -ne 0 ]; then
|
||||
log_message "Failed to start VM $VM_ID. Manual intervention required."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_message "VM $VM_ID has been restarted."
|
||||
}
|
||||
|
||||
# Main loop
|
||||
log_message "Starting monitoring of VM $VM_ID on port $PORT..."
|
||||
log_message "Press Ctrl+C to exit."
|
||||
|
||||
while true; do
|
||||
# Check if port 22 is open
|
||||
if ! check_port; then
|
||||
restart_vm
|
||||
else
|
||||
log_message "Port $PORT is reachable. VM is running normally."
|
||||
fi
|
||||
|
||||
# Wait for the next check
|
||||
log_message "Sleeping for $CHECK_INTERVAL seconds..."
|
||||
sleep $CHECK_INTERVAL
|
||||
done
|
||||
0
roles/proxmox/tasks/01_setup_user.yml
Normal file
0
roles/proxmox/tasks/01_setup_user.yml
Normal file
33
roles/proxmox/tasks/10_create_secrets.yml
Normal file
33
roles/proxmox/tasks/10_create_secrets.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
- name: Ensure Vault file exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ proxmox_vault_file }}"
|
||||
state: touch
|
||||
mode: "0600"
|
||||
|
||||
- name: Decrypt vm vault file
|
||||
ansible.builtin.shell: cd ../; ansible-vault decrypt "./playbooks/{{ proxmox_vault_file }}"
|
||||
ignore_errors: true
|
||||
no_log: true
|
||||
|
||||
- name: Load existing vault content
|
||||
ansible.builtin.slurp:
|
||||
src: "{{ proxmox_vault_file }}"
|
||||
register: vault_content
|
||||
no_log: true
|
||||
|
||||
- name: Parse vault content as YAML
|
||||
ansible.builtin.set_fact:
|
||||
vault_data: "{{ (vault_content['content'] | b64decode | from_yaml) if (vault_content['content'] | length > 0) else {} }}"
|
||||
no_log: true
|
||||
|
||||
- name: Update Vault data
|
||||
ansible.builtin.include_tasks: 15_create_secret.yml
|
||||
loop: "{{ proxmox_vms | map(attribute='name') }}"
|
||||
loop_control:
|
||||
loop_var: "vm_name"
|
||||
|
||||
- name: Encrypt vm vault file
|
||||
ansible.builtin.shell: cd ../; ansible-vault encrypt "./playbooks/{{ proxmox_vault_file }}"
|
||||
ignore_errors: true
|
||||
no_log: true
|
||||
26
roles/proxmox/tasks/15_create_secret.yml
Normal file
26
roles/proxmox/tasks/15_create_secret.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
- name: Setup secret name
|
||||
ansible.builtin.set_fact:
|
||||
vm_name_secret: "{{ proxmox_secrets_prefix }}_{{ vm_name | replace('-','_') }}"
|
||||
|
||||
- name: Check if variable is in vault
|
||||
ansible.builtin.set_fact:
|
||||
variable_exists: "{{ vm_name_secret in vault_data }}"
|
||||
|
||||
- name: Set new secret
|
||||
ansible.builtin.set_fact:
|
||||
cipassword: "{{ lookup('password', '/dev/null length=32 chars=ascii_letters,digits') }}"
|
||||
when: not variable_exists
|
||||
|
||||
- name: Set new secret
|
||||
ansible.builtin.set_fact:
|
||||
new_vault_data: "{{ vault_data | combine({ vm_name_secret: cipassword }) }}"
|
||||
when: not variable_exists
|
||||
|
||||
- name: Write updated Vault content to file (temporary plaintext)
|
||||
ansible.builtin.copy:
|
||||
content: "{{ new_vault_data | to_nice_yaml }}"
|
||||
dest: "{{ proxmox_vault_file }}"
|
||||
mode: "0600"
|
||||
when: not variable_exists
|
||||
no_log: true
|
||||
11
roles/proxmox/tasks/50_create_vms.yml
Normal file
11
roles/proxmox/tasks/50_create_vms.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Load vault variables
|
||||
ansible.builtin.include_vars:
|
||||
file: "{{ proxmox_vault_file }}"
|
||||
name: vm_secrets
|
||||
|
||||
- name: Create vms
|
||||
ansible.builtin.include_tasks: 55_create_vm.yml
|
||||
loop: "{{ proxmox_vms }}"
|
||||
loop_control:
|
||||
loop_var: "vm"
|
||||
34
roles/proxmox/tasks/55_create_vm.yml
Normal file
34
roles/proxmox/tasks/55_create_vm.yml
Normal file
@@ -0,0 +1,34 @@
|
||||
- name: Create VM
|
||||
community.general.proxmox_kvm:
|
||||
api_user: root@pam
|
||||
api_password: "{{ vault.pve.aya01.root.sudo }}"
|
||||
api_host: "192.168.20.12"
|
||||
name: "{{ vm.name }}"
|
||||
vmid: "{{ vm.vmid }}"
|
||||
node: "{{ vm.node }}"
|
||||
cpu: "{{ vm.cpu }}"
|
||||
cores: "{{ vm.cores }}"
|
||||
memory: "{{ vm.memory }}"
|
||||
net: "{{ vm.net }}"
|
||||
scsi: "{{ vm.scsi }}"
|
||||
scsihw: "{{ vm.scsihw }}"
|
||||
ostype: "{{ vm.ostype }}"
|
||||
sshkeys: "{{ vm.sshkeys }}"
|
||||
tags: "{{ proxmox_tags }}"
|
||||
ciuser: "{{ vm.ciuser }}"
|
||||
cipassword: "{{ vm_secrets[proxmox_secrets_prefix + '_' + vm.name.replace('-', '_')] }}"
|
||||
ide:
|
||||
ide2: "proxmox:cloudinit,format=qcow2"
|
||||
register: temp
|
||||
|
||||
- name: Debug temp
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ temp }}"
|
||||
|
||||
- name: Set mac
|
||||
ansible.builtin.set_fact:
|
||||
mac: "{{ temp.mac }}"
|
||||
|
||||
- name: debug mac
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ mac }}"
|
||||
11
roles/proxmox/tasks/60_create_container.yml
Normal file
11
roles/proxmox/tasks/60_create_container.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Load vault variables
|
||||
ansible.builtin.include_vars:
|
||||
file: "{{ proxmox_vault_file }}"
|
||||
name: vm_secrets
|
||||
|
||||
- name: Create vms
|
||||
ansible.builtin.include_tasks: 65_create_container.yml
|
||||
loop: "{{ proxmox_lxcs }}"
|
||||
loop_control:
|
||||
loop_var: "container"
|
||||
4
roles/proxmox/tasks/65_create_containers.yml
Normal file
4
roles/proxmox/tasks/65_create_containers.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
- name: Create Container
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ container.name }}"
|
||||
6
roles/proxmox/tasks/90-download-image.yml
Normal file
6
roles/proxmox/tasks/90-download-image.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: Download Debian Image
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ proxmox_debian_image_url }}"
|
||||
dest: "{{ proxmox_image_path }}"
|
||||
mode: "0644"
|
||||
12
roles/proxmox/tasks/main.yml
Normal file
12
roles/proxmox/tasks/main.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
- name: Setup user
|
||||
ansible.builtin.include_tasks: 01_setup_user.yml
|
||||
|
||||
- name: Create VM vault
|
||||
ansible.builtin.include_tasks: 10_create_secrets.yml
|
||||
|
||||
- name: Create VMs
|
||||
ansible.builtin.include_tasks: 50_create_vms.yml
|
||||
|
||||
- name: Create LXC containers
|
||||
ansible.builtin.include_tasks: 60_create_containers.yml
|
||||
10
roles/proxmox/vars/main.yml
Normal file
10
roles/proxmox/vars/main.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
author: tuan-dat.tran@tudattr.dev
|
||||
creator: ansible
|
||||
|
||||
proxmox_vault_file: ../group_vars/proxmox/secrets_vm.yml
|
||||
proxmox_secrets_prefix: secrets_vm
|
||||
proxmox_debian_image_url: https://cdimage.debian.org/images/cloud/bookworm/20250316-2053/debian-12-genericcloud-amd64-20250316-2053.qcow2
|
||||
proxmox_image_path: /opt/template/iso/
|
||||
|
||||
proxmox_tags:
|
||||
- "{{ creator }}"
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
# - name: Create VM
|
||||
# community.general.proxmox:
|
||||
# api_host: "{{ api_host }}"
|
||||
# api_user: "{{ api_user }}"
|
||||
# api_password: "{{ vault.proxmox.api_password }}"
|
||||
# node: "{{ }}"
|
||||
@@ -1,11 +0,0 @@
|
||||
---
|
||||
- name: List existing nodes
|
||||
community.general.proxmox_node_info:
|
||||
api_host: "{{ proxmox_api_host }}"
|
||||
api_user: "{{ proxmox_api_user }}@pam"
|
||||
api_password: "{{ proxmox_api_password }}"
|
||||
register: proxmox_nodes
|
||||
|
||||
- name: Print info
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ proxmox_nodes }}"
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
- name: Get info
|
||||
ansible.builtin.include_tasks: get_info.yml
|
||||
# - name: Create vm
|
||||
# ansible.builtin.include_tasks: create_vm.yml
|
||||
Reference in New Issue
Block a user