Some checks failed
CI / lint-and-test (pull_request) Successful in 1m21s
CI / ansible-validation (pull_request) Successful in 9m3s
CI / secret-scanning (pull_request) Successful in 3m19s
CI / dependency-scan (pull_request) Successful in 7m13s
CI / sast-scan (pull_request) Successful in 6m38s
CI / license-check (pull_request) Successful in 1m16s
CI / vault-check (pull_request) Failing after 6m40s
CI / playbook-test (pull_request) Successful in 9m28s
CI / container-scan (pull_request) Successful in 7m59s
CI / sonar-analysis (pull_request) Failing after 1m11s
CI / workflow-summary (pull_request) Successful in 1m11s
- 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
299 lines
9.1 KiB
YAML
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"
|