ilia 69a39e5e5b Add POTE app project support and improve IP conflict detection (#3)
## Summary

This PR adds comprehensive support for deploying the **POTE** application project via Ansible, along with improvements to IP conflict detection and a new app stack provisioning system for Proxmox-managed LXC containers.

## Key Features

### 🆕 New Roles
- **`roles/pote`**: Python/venv deployment role for POTE (PostgreSQL, cron jobs, Alembic migrations)
- **`roles/app_setup`**: Generic app deployment role (Node.js/systemd)
- **`roles/base_os`**: Base OS hardening role

### 🛡️ Safety Improvements
- IP uniqueness validation within projects
- Proxmox-side IP conflict detection
- Enhanced error messages for IP conflicts

### 📦 New Playbooks
- `playbooks/app/site.yml`: End-to-end app stack deployment
- `playbooks/app/provision_vms.yml`: Proxmox guest provisioning
- `playbooks/app/configure_app.yml`: OS + application configuration

## Security
-  All secrets stored in encrypted vault.yml
-  Deploy keys excluded via .gitignore
-  No plaintext secrets committed

## Testing
-  POTE successfully deployed to dev/qa/prod environments
-  All components validated (Git, PostgreSQL, cron, migrations)

Co-authored-by: ilia <ilia@levkin.ca>
Reviewed-on: #3
2026-01-01 11:19:54 -05:00

83 lines
2.4 KiB
YAML

---
# Proxmox QEMU VM provisioning via API (cloud-init).
# This task file preserves the repo's existing VM behavior.
# Break down the Proxmox VM creation to avoid "file name too long" error
- name: Set VM configuration facts
ansible.builtin.set_fact:
vm_scsi_config:
scsi0: "{{ vm_storage }}:{{ vm_disk_size }},format=raw"
vm_net_config:
net0: "virtio,bridge={{ vm_network_bridge }},firewall=1"
vm_ide_config:
ide2: "{{ vm_iso_storage }}:cloudinit,format=qcow2"
vm_ipconfig:
ipconfig0: "{{ vm_ip_config }}"
- name: Create VM on Proxmox
community.general.proxmox_kvm:
# Connection
api_host: "{{ proxmox_host }}"
api_user: "{{ proxmox_user }}"
api_password: "{{ vault_proxmox_password }}"
api_token_id: "{{ proxmox_token_id | default(omit) }}"
api_token_secret: "{{ vault_proxmox_token | default(omit) }}"
# VM identification
vmid: "{{ vm_id }}"
name: "{{ vm_name }}"
node: "{{ proxmox_node }}"
# Hardware specs
memory: "{{ vm_memory }}"
cores: "{{ vm_cores }}"
sockets: "{{ vm_sockets }}"
cpu: "host"
# Storage and network
scsi: "{{ vm_scsi_config }}"
net: "{{ vm_net_config }}"
ide: "{{ vm_ide_config }}"
# Boot and OS
boot: "{{ vm_boot_order }}"
ostype: "{{ vm_os_type }}"
# Cloud-init
ciuser: "{{ vm_ciuser }}"
cipassword: "{{ vault_vm_cipassword | default(omit) }}"
sshkeys: "{{ vm_ssh_keys | join('\n') if vm_ssh_keys else omit }}"
ipconfig: "{{ vm_ipconfig }}"
nameserver: "{{ vm_nameservers }}"
# VM options
agent: "{{ vm_enable_agent | bool }}"
autostart: false
balloon: 0
state: present
register: vm_creation_result
- name: Start VM if requested
community.general.proxmox_kvm:
api_host: "{{ proxmox_host }}"
api_user: "{{ proxmox_user }}"
api_password: "{{ vault_proxmox_password }}"
api_token_id: "{{ proxmox_token_id | default(omit) }}"
api_token_secret: "{{ vault_proxmox_token | default(omit) }}"
vmid: "{{ vm_id }}"
node: "{{ proxmox_node }}"
state: started
when: vm_start_after_create | bool
- name: Display VM creation results
ansible.builtin.debug:
msg: |
VM Created: {{ vm_name }} (ID: {{ vm_id }})
Memory: {{ vm_memory }}MB
Cores: {{ vm_cores }}
Storage: {{ vm_storage }}:{{ vm_disk_size }}
Network: {{ vm_network_bridge }}
Status: {{ vm_creation_result.msg | default('Created') }}