ilia f5e32afd81
Some checks failed
CI / lint-and-test (pull_request) Failing after 1m20s
CI / ansible-validation (pull_request) Successful in 6m40s
CI / secret-scanning (pull_request) Successful in 2m36s
CI / dependency-scan (pull_request) Successful in 6m12s
CI / sast-scan (pull_request) Successful in 6m48s
CI / license-check (pull_request) Successful in 1m16s
CI / vault-check (pull_request) Failing after 6m13s
CI / playbook-test (pull_request) Successful in 6m34s
CI / container-scan (pull_request) Successful in 6m57s
CI / sonar-analysis (pull_request) Failing after 1m10s
CI / workflow-summary (pull_request) Successful in 1m11s
Add POTE app project support and improve IP conflict detection
- Add roles/pote: Python/venv deployment role with PostgreSQL, cron jobs
- Add playbooks/app/: Proxmox app stack provisioning and configuration
- Add roles/app_setup: Generic app deployment role (Node.js/systemd)
- Add roles/base_os: Base OS hardening role
- Enhance roles/proxmox_vm: Split LXC/KVM tasks, improve error handling
- Add IP uniqueness validation: Preflight check for duplicate IPs within projects
- Add Proxmox-side IP conflict detection: Check existing LXC net0 configs
- Update inventories/production/group_vars/all/main.yml: Add pote project config
- Add vault.example.yml: Template for POTE secrets (git key, DB, SMTP)
- Update .gitignore: Exclude deploy keys, backup files, and other secrets
- Update documentation: README, role docs, execution flow guides

Security:
- All secrets stored in encrypted vault.yml (never committed in plaintext)
- Deploy keys excluded via .gitignore
- IP conflict guardrails prevent accidental duplicate IP assignments
2025-12-28 20:52:45 -05:00

299 lines
9.1 KiB
YAML

---
# Common variables for all hosts
timezone: America/Toronto
locale: en_US.UTF-8
ansible_python_interpreter: /usr/bin/python3
# Debug settings
ansible_debug_output: false
# Security settings
fail2ban_bantime: 3600
fail2ban_findtime: 600
fail2ban_maxretry: 3
# Maintenance settings
maintenance_default_serial: "100%" # Default serial execution for maintenance
maintenance_reboot_timeout: 300 # Reboot timeout in seconds
maintenance_pre_reboot_delay: 5 # Delay before reboot in seconds
# Global variables for all hosts
# Tailscale configuration
# Store your actual auth key in vault_tailscale_auth_key using ansible-vault
# Example: ansible-vault create group_vars/all/vault.yml
# vault_tailscale_auth_key: "tskey-auth-your-actual-key-here"
# Default Tailscale settings - these tell the playbook to use your vault key
tailscale_auth_key: "{{ vault_tailscale_auth_key | default('') }}"
tailscale_accept_routes: true
tailscale_accept_dns: true
tailscale_ssh: false
tailscale_hostname: "{{ inventory_hostname }}"
# -----------------------------------------------------------------------------
# Proxmox + modular app projects (LXC-first)
#
# This repo can manage many independent apps ("projects"). Each project defines
# its own dev/qa/prod guests (IPs/VMIDs/branches) under `app_projects`.
#
# Usage examples:
# - Run one project: ansible-playbook -i inventories/production playbooks/app/site.yml -e app_project=projectA
# - Run all projects: ansible-playbook -i inventories/production playbooks/app/site.yml
# -----------------------------------------------------------------------------
# Proxmox API connection (keep secrets in vault)
proxmox_host: "{{ vault_proxmox_host }}"
proxmox_user: "{{ vault_proxmox_user }}"
proxmox_node: "{{ vault_proxmox_node | default('pve') }}"
proxmox_api_port: "{{ vault_proxmox_api_port | default(8006) }}"
# Proxmox commonly uses a self-signed cert; keep validation off by default.
proxmox_validate_certs: false
# Prefer API token auth (store in vault):
# - proxmox_token_id: "ansible@pve!token-name"
# - vault_proxmox_token: "secret"
proxmox_token_id: "{{ vault_proxmox_token_id | default('') }}"
# Default guest type for new projects. (Later you can set to `kvm` per project/env.)
proxmox_guest_type: lxc
# Proxmox LXC defaults (override per project/env as needed)
lxc_ostemplate: "local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst"
lxc_storage: "local-lvm"
lxc_network_bridge: "vmbr0"
lxc_unprivileged: true
lxc_features_list:
- "keyctl=1"
- "nesting=1"
lxc_start_after_create: true
lxc_nameserver: "1.1.1.1 8.8.8.8"
# Base OS / access defaults
appuser_name: appuser
appuser_shell: /bin/bash
appuser_groups:
- sudo
# Store your workstation public key in vault_ssh_public_key
appuser_ssh_public_key: "{{ vault_ssh_public_key }}"
# App defaults (override per project)
app_backend_port: 3001
app_frontend_port: 3000
# Default Node workflow commands (override per project if your app differs)
app_backend_install_cmd: "npm ci"
app_backend_migrate_cmd: "npm run migrate"
app_backend_start_cmd: "npm start"
app_frontend_install_cmd: "npm ci"
app_frontend_build_cmd: "npm run build"
app_frontend_start_cmd: "npm start"
# Projects definition: add as many projects as you want here.
# Each project has envs (dev/qa/prod) defining name/vmid/ip/gateway/branch and
# optional env_vars (dummy placeholders by default).
#
# -----------------------------------------------------------------------------
# Proxmox VMID/CTID ranges (DEDICATED; avoid collisions)
#
# Proxmox IDs are global. Never reuse IDs across unrelated guests.
# Suggested reservation table (edit to your preference):
# - 9000-9099: pote
# - 9100-9199: punimTagFE
# - 9200-9299: punimTagBE
# - 9300-9399: projectA (example)
# -----------------------------------------------------------------------------
app_projects:
projectA:
description: "Example full-stack app (edit repo_url, IPs, secrets)."
repo_url: "git@github.com:example/projectA.git"
components:
backend: true
frontend: true
# Repo is assumed to contain `backend/` and `frontend/` directories.
repo_dest: "/srv/app"
# Optional overrides for this project
backend_port: "{{ app_backend_port }}"
frontend_port: "{{ app_frontend_port }}"
guest_defaults:
guest_type: "{{ proxmox_guest_type }}"
cores: 2
memory_mb: 2048
swap_mb: 512
rootfs_size_gb: 16
deploy:
backend_install_cmd: "{{ app_backend_install_cmd }}"
backend_migrate_cmd: "{{ app_backend_migrate_cmd }}"
backend_start_cmd: "{{ app_backend_start_cmd }}"
frontend_install_cmd: "{{ app_frontend_install_cmd }}"
frontend_build_cmd: "{{ app_frontend_build_cmd }}"
frontend_start_cmd: "{{ app_frontend_start_cmd }}"
envs:
dev:
name: "projectA-dev"
vmid: 9301
ip: "10.0.10.101/24"
gateway: "10.0.10.1"
branch: "dev"
env_vars:
APP_ENV: "dev"
BACKEND_BASE_URL: "http://10.0.10.101:{{ app_backend_port }}"
FRONTEND_BASE_URL: "http://10.0.10.101:{{ app_frontend_port }}"
SECRET_PLACEHOLDER: "change-me"
qa:
name: "projectA-qa"
vmid: 9302
ip: "10.0.10.102/24"
gateway: "10.0.10.1"
branch: "qa"
env_vars:
APP_ENV: "qa"
BACKEND_BASE_URL: "http://10.0.10.102:{{ app_backend_port }}"
FRONTEND_BASE_URL: "http://10.0.10.102:{{ app_frontend_port }}"
SECRET_PLACEHOLDER: "change-me"
prod:
name: "projectA-prod"
vmid: 9303
ip: "10.0.10.103/24"
gateway: "10.0.10.1"
branch: "main"
pote:
description: "POTE (python/venv + cron) project (edit repo_url, IPs, secrets)."
repo_url: "gitea@10.0.30.169:ilia/POTE.git"
# POTE deploys as a user-owned python app (not /srv/app)
repo_dest: "/home/poteapp/pote"
os_user: "poteapp"
components:
backend: false
frontend: false
guest_defaults:
guest_type: "{{ proxmox_guest_type }}"
cores: 2
memory_mb: 2048
swap_mb: 512
rootfs_size_gb: 16
# POTE-specific optional defaults (override per env if needed)
pote_db_host: "localhost"
pote_db_user: "poteuser"
pote_db_name: "potedb"
pote_smtp_host: "mail.levkin.ca"
pote_smtp_port: 587
envs:
dev:
name: "pote-dev"
vmid: 9001
ip: "10.0.10.114/24"
gateway: "10.0.10.1"
branch: "dev"
qa:
name: "pote-qa"
vmid: 9002
ip: "10.0.10.112/24"
gateway: "10.0.10.1"
branch: "qa"
prod:
name: "pote-prod"
vmid: 9003
ip: "10.0.10.113/24"
gateway: "10.0.10.1"
branch: "main"
punimTagFE:
description: "punimTag frontend-only project (edit repo_url, IPs, secrets)."
repo_url: "git@github.com:example/punimTagFE.git"
repo_dest: "/srv/app"
components:
backend: false
frontend: true
guest_defaults:
guest_type: "{{ proxmox_guest_type }}"
cores: 2
memory_mb: 2048
swap_mb: 512
rootfs_size_gb: 16
deploy:
frontend_install_cmd: "{{ app_frontend_install_cmd }}"
frontend_build_cmd: "{{ app_frontend_build_cmd }}"
frontend_start_cmd: "{{ app_frontend_start_cmd }}"
envs:
dev:
name: "punimTagFE-dev"
vmid: 9101
ip: "10.0.10.121/24"
gateway: "10.0.10.1"
branch: "dev"
env_vars:
APP_ENV: "dev"
SECRET_PLACEHOLDER: "change-me"
qa:
name: "punimTagFE-qa"
vmid: 9102
ip: "10.0.10.122/24"
gateway: "10.0.10.1"
branch: "qa"
env_vars:
APP_ENV: "qa"
SECRET_PLACEHOLDER: "change-me"
prod:
name: "punimTagFE-prod"
vmid: 9103
ip: "10.0.10.123/24"
gateway: "10.0.10.1"
branch: "main"
env_vars:
APP_ENV: "prod"
SECRET_PLACEHOLDER: "change-me"
punimTagBE:
description: "punimTag backend-only project (edit repo_url, IPs, secrets)."
repo_url: "git@github.com:example/punimTagBE.git"
repo_dest: "/srv/app"
components:
backend: true
frontend: false
guest_defaults:
guest_type: "{{ proxmox_guest_type }}"
cores: 2
memory_mb: 2048
swap_mb: 512
rootfs_size_gb: 16
deploy:
backend_install_cmd: "{{ app_backend_install_cmd }}"
backend_migrate_cmd: "{{ app_backend_migrate_cmd }}"
backend_start_cmd: "{{ app_backend_start_cmd }}"
envs:
dev:
name: "punimTagBE-dev"
vmid: 9201
ip: "10.0.10.131/24"
gateway: "10.0.10.1"
branch: "dev"
env_vars:
APP_ENV: "dev"
SECRET_PLACEHOLDER: "change-me"
qa:
name: "punimTagBE-qa"
vmid: 9202
ip: "10.0.10.132/24"
gateway: "10.0.10.1"
branch: "qa"
env_vars:
APP_ENV: "qa"
SECRET_PLACEHOLDER: "change-me"
prod:
name: "punimTagBE-prod"
vmid: 9203
ip: "10.0.10.133/24"
gateway: "10.0.10.1"
branch: "main"
env_vars:
APP_ENV: "prod"
SECRET_PLACEHOLDER: "change-me"