ansible cleanup

This commit is contained in:
Sergei Poljanski 2025-11-04 14:23:16 +02:00
commit 8ef380bc9b
15 changed files with 163 additions and 420 deletions

58
README.md Normal file
View file

@ -0,0 +1,58 @@
# asxp.io Infrastructure
Infrastructure as Code for asxp.io servers managed via Terraform, Ansible, and Forgejo CI/CD.
## Servers
| Server | Type | vCPU | RAM | Services |
|--------|------|------|-----|----------|
| asxpio-ops | CX22 | 2 | 4GB | traefik, forgejo, grafana, prometheus, loki, static_sites |
| asxpio-services | CX43 | 8 | 16GB | forgejo_runner, immich, minecraft, valheim, factorio, prosody, coturn |
## Directory Structure
- **terraform/** - Cloud infrastructure provisioning (Hetzner Cloud)
- **ansible/** - Server bootstrap and configuration management
- **services/** - Docker Compose files for container orchestration
- **.forgejo/workflows/** - CI/CD pipeline automation (planned)
## Migration TODO
### Phase 0: Preparation
- [x] Terraform infrastructure code
- [x] Ansible inventory and playbooks
- [x] Create S3 buckets (hel1-primary, fsn1-secondary)
- [x] Provision servers via Terraform
- [ ] Backup all services from bare metal
### Phase 1: Core Infrastructure
- [x] Deploy WireGuard VPN on ops-server
- [x] Deploy Traefik reverse proxy
- [ ] Deploy monitoring stack (Grafana, Prometheus, Loki)
### Phase 2: Git & CI/CD
- [x] Migrate Forgejo from bare metal
- [x] Deploy Forgejo Runner on services-server
### Phase 3: Media & Storage
- [x] Upload Immich photos to S3 (135GB)
- [ ] Migrate Immich to services-server
- [ ] Configure S3 geo-replication (hel1 → fsn1)
### Phase 4: Gaming Services
- [ ] Migrate Minecraft (20GB local + 80GB S3 backups)
- [ ] Migrate Valheim (9.5GB)
- [ ] Migrate Factorio (31MB)
### Phase 5: Communication
- [ ] Migrate Prosody XMPP
- [ ] Migrate Turnserver
### Phase 6: Final Services
- [ ] Migrate static sites (asxp.io, czsk.it)
- [ ] Configure automated backups to S3
- [ ] DNS cutover and validation
- [ ] Decommission bare metal (after 30 days)
### Later
- [ ] Setup Terraform to manage DNS

53
ansible/.gitignore vendored
View file

@ -3,62 +3,13 @@
*.log
.ansible/
# Vault password files (NEVER commit these!)
# Vault
vault.yaml
.vault_pass
.vault_password
*vault_password*
vault-password.txt
# Decrypted vault files (NEVER commit these!)
*_vault.yaml.decrypted
vault.yaml.decrypted
*.vault.dec
*.decrypted
# Backup files
*.backup
*.bak
*~
*.swp
*.swo
# WireGuard client configs (may contain private keys)
playbooks/wireguard-configs/**/*.conf
playbooks/wireguard-configs/**/private_key
playbooks/wireguard-configs/**/public_key
# But keep the directory structure
!playbooks/wireguard-configs/.gitkeep
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
# OS files
.DS_Store
Thumbs.db
*.lnk
# Editor files
.vscode/
.idea/
*.sublime-*
# Local testing
test/
tmp/
.tmp/
# SSH control sockets
/tmp/
# Ansible facts cache
*.fact
facts.d/
# Molecule (if using for testing)
.molecule/
.cache/

View file

@ -1,21 +0,0 @@
---
# Shared configuration for all servers
# Docker network for Traefik
traefik_network: traefik
# Forgejo configuration
forgejo_version: "12"
forgejo_domain: git.asxp.io
forgejo_http_port: 3000
forgejo_ssh_port: 2222 # External port (container uses 22)
# Forgejo Runner configuration
forgejo_runner_version: "11"
forgejo_runner_capacity: 1
forgejo_runner_timeout: 3h
forgejo_runner_token: "{{ vault_forgejo_runner_token }}"
# Backup configuration
backup_dest_dir: /opt/forgejo-backup
backup_old_server: asxpio-old

View file

@ -0,0 +1,5 @@
---
# Base paths for all services
# Base directory for all service installations
services_base_path: "/opt"

View file

@ -1,30 +0,0 @@
---
# Service configuration for all hosts
# Centralized service definitions to avoid hardcoding paths and ports
# Base paths for services
services_base_path: "/opt"
# Service-specific paths (derived from base path)
traefik_base_path: "{{ services_base_path }}/traefik"
forgejo_base_path: "{{ services_base_path }}/forgejo"
forgejo_runner_base_path: "{{ services_base_path }}/forgejo-runner"
# Service ports
traefik_http_port: 80
traefik_https_port: 443
traefik_dashboard_port: 8080
forgejo_http_port: 3000
forgejo_ssh_port: 2222 # External SSH port for Git operations
forgejo_internal_ssh_port: 22 # Internal container SSH port
# WireGuard configuration
wireguard_port: 60101
wireguard_interface: "wg0"
# SSH configuration
ssh_port: 22
# Docker configuration
docker_network_name: "asxpio-net"

View file

@ -0,0 +1,38 @@
---
# WireGuard VPN configuration
# Centralized configuration for all WireGuard settings
# WireGuard network interface and port
wireguard_port: 60101
wireguard_interface: "wg0"
# WireGuard server configuration (asxpio-ops)
wireguard_ipv4: 10.20.0.10
wireguard_ipv6: fd69:69:69::1
wireguard_ipv4_network: 10.20.0.0/24
wireguard_ipv6_network: fd69:69:69::/64
# Enable UFW firewall rules (set to false to use iptables PostUp/PostDown)
wireguard_enable_ufw: false
# WireGuard clients
wireguard_clients:
- name: asxpio-services
ipv4: 10.20.0.20
ipv6: fd69:69:69::20
preshared_key: true
persistent_keepalive: 25
- name: laptop
ipv4: 10.20.0.2
ipv6: fd69:69:69::2
preshared_key: true
persistent_keepalive: 25
# DNS servers for VPN clients
wireguard_dns_servers:
- 1.1.1.1
- 1.0.0.1
# Optional: Additional routes for split tunneling
# wireguard_additional_routes:
# - 192.168.1.0/24

View file

@ -0,0 +1,25 @@
---
# Forgejo Git server configuration
# Forgejo version and domain
forgejo_version: "12"
forgejo_domain: git.asxp.io
# Forgejo installation path
forgejo_base_path: "{{ services_base_path }}/forgejo"
# Forgejo ports
forgejo_http_port: 3000
# Forgejo secrets (stored in encrypted vault)
forgejo_secret_key: "{{ vault_forgejo_secret_key }}"
forgejo_internal_token: "{{ vault_forgejo_internal_token }}"
forgejo_jwt_secret: "{{ vault_forgejo_jwt_secret }}"
forgejo_lfs_jwt_secret: "{{ vault_forgejo_lfs_jwt_secret }}"
# Backup configuration
backup_dest_dir: /opt/forgejo-backup
backup_old_server: asxpio-old
# Docker network for Traefik integration
traefik_network: traefik

View file

@ -0,0 +1,11 @@
---
# Traefik reverse proxy configuration
# Traefik installation path
traefik_base_path: "{{ services_base_path }}/traefik"
# Traefik ports
traefik_dashboard_port: 8080
# SSL/TLS configuration
letsencrypt_email: "{{ vault_letsencrypt_email }}"

View file

@ -0,0 +1,11 @@
---
# Forgejo Runner (CI/CD) configuration
# Runner version and settings
forgejo_runner_version: "11"
forgejo_runner_capacity: 1
forgejo_runner_timeout: 3h
forgejo_runner_token: "{{ vault_forgejo_runner_token }}"
# Runner installation path
forgejo_runner_base_path: "{{ services_base_path }}/forgejo-runner"

View file

@ -2,66 +2,8 @@
# Host-specific configuration for asxpio-ops
# Operations server: Forgejo, Traefik, WireGuard VPN hub
# ============================================================================
# WireGuard VPN Configuration
# ============================================================================
wireguard_port: 60101
wireguard_interface: wg0
wireguard_ipv4: 10.20.0.10
wireguard_ipv6: fd69:69:69::1
wireguard_ipv4_network: 10.20.0.0/24
wireguard_ipv6_network: fd69:69:69::/64
# Enable UFW firewall rules (set to false to use iptables PostUp/PostDown)
wireguard_enable_ufw: false
# WireGuard clients
wireguard_clients:
- name: asxpio-services
ipv4: 10.20.0.20
ipv6: fd69:69:69::20
preshared_key: true
persistent_keepalive: 25
- name: laptop
ipv4: 10.20.0.2
ipv6: fd69:69:69::2
preshared_key: true
persistent_keepalive: 25
# Optional: DNS servers for clients
wireguard_dns_servers:
- 1.1.1.1
- 1.0.0.1
# Optional: Additional routes for split tunneling
# wireguard_additional_routes:
# - 192.168.1.0/24
# ============================================================================
# SSH Hardening Configuration
# ============================================================================
# Allow public SSH access for Forgejo git operations
ssh_allow_public_git: true
ssh_git_user: git
# ============================================================================
# Forgejo Configuration
# ============================================================================
# Secrets are stored in encrypted vault (group_vars/all/vault.yaml)
forgejo_secret_key: "{{ vault_forgejo_secret_key }}"
forgejo_internal_token: "{{ vault_forgejo_internal_token }}"
forgejo_jwt_secret: "{{ vault_forgejo_jwt_secret }}"
forgejo_lfs_jwt_secret: "{{ vault_forgejo_lfs_jwt_secret }}"
# ============================================================================
# SSL/TLS Configuration
# ============================================================================
letsencrypt_email: "{{ vault_letsencrypt_email }}"
# ============================================================================
# S3FS Configuration
# ============================================================================
# ops server: CX22 with 40GB disk, limit cache to 10GB
# Formula: Total_Disk - Desired_Cache_Size = ensure_diskfree
# 40GB - 10GB = 30GB free
s3fs_ensure_diskfree: 30720 # 30GB free = max 10GB cache
s3fs_ensure_diskfree: 20000 # Total:40GB Keep:20GB free = ~15GB for Cache

View file

@ -2,16 +2,8 @@
# Host-specific configuration for asxpio-services
# Services server: Forgejo Runner, Immich, game servers, XMPP
# ============================================================================
# SSH Hardening Configuration
# ============================================================================
# Restrict SSH to VPC and WireGuard networks only
ssh_allow_public_git: false
# ============================================================================
# S3FS Configuration
# ============================================================================
# services server: CX43 with 160GB disk, limit cache to 80GB
# Formula: Total_Disk - Desired_Cache_Size = ensure_diskfree
# 160GB - 80GB = 80GB free
s3fs_ensure_diskfree: 81920 # 80GB free = max 80GB cache

View file

@ -8,9 +8,10 @@ all:
ansible_python_interpreter: /usr/bin/python3
children:
# Production asxpio infrastructure (excludes legacy servers)
asxpio:
vars:
# Common variables for all asxpio servers
# Common variables for all asxpio production servers
timezone: UTC
locale: en_US.UTF-8
@ -56,9 +57,10 @@ all:
- prosody
- coturn
old_servers:
hosts:
asxpio-old:
ansible_host: asxp.io
server_role: legacy
ansible_user: asxpi
# Legacy servers (standalone, not part of asxpio group)
old_servers:
hosts:
asxpio-old:
ansible_host: asxp.io
server_role: legacy
ansible_user: asxpi

View file

@ -88,24 +88,8 @@
ansible.builtin.pause:
prompt: "Press ENTER to continue or Ctrl+C to abort"
- name: Common setup verification
hosts: asxpio:!old_servers
become: true
gather_facts: true
vars:
# Force WireGuard IPs for Stage 2 (SSH hardening requires it)
ansible_host: "{{ wireguard_ip }}"
roles:
- role: common
post_tasks:
- name: Display setup status
ansible.builtin.debug:
msg: "Common setup verified on {{ inventory_hostname }}"
- name: Harden SSH configuration
hosts: asxpio:!old_servers
hosts: asxpio
become: true
gather_facts: true
vars:
@ -171,7 +155,7 @@
msg: |
Forgejo deployed successfully on {{ inventory_hostname }}
Web UI: http://{{ asxpio_ops_wireguard_ip }}:{{ forgejo_http_port }}
SSH: ssh://git@{{ asxpio_ops_wireguard_ip }}:{{ forgejo_ssh_port }}
SSH: ssh://git@{{ asxpio_ops_wireguard_ip }}
⚠️ IMPORTANT: Before deploying the runner, you must:
1. Access Forgejo web UI

View file

@ -9,16 +9,12 @@
- forgejo_http_port is defined
- forgejo_http_port | int > 0
- forgejo_http_port | int < 65536
- forgejo_ssh_port is defined
- forgejo_ssh_port | int > 0
- forgejo_ssh_port | int < 65536
- forgejo_domain is defined
- forgejo_domain | length > 0
fail_msg: |
Forgejo role requires:
- forgejo_base_path (installation directory)
- forgejo_http_port (1-65535)
- forgejo_ssh_port (1-65535)
- forgejo_domain (domain name)
success_msg: "Forgejo basic variables validated successfully"

View file

@ -1,221 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Ansible Vault Setup Script
# This script helps you set up encrypted secrets for the Ansible infrastructure
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ANSIBLE_DIR="$(dirname "$SCRIPT_DIR")"
VAULT_FILE="$ANSIBLE_DIR/inventory/group_vars/all/vault.yaml"
VAULT_PASS_FILE="$ANSIBLE_DIR/.vault_pass"
echo "========================================"
echo "Ansible Vault Setup"
echo "========================================"
echo ""
# Check if ansible-vault is available
if ! command -v ansible-vault &> /dev/null; then
echo "❌ Error: ansible-vault command not found"
echo " Please install Ansible first: pip install ansible"
exit 1
fi
# Function to generate secrets
generate_secrets() {
echo "Generating new Forgejo secrets..."
echo ""
echo "SECRET_KEY (64 chars hex):"
openssl rand -hex 32
echo ""
echo "JWT_SECRET (base64):"
openssl rand -base64 32
echo ""
echo "LFS_JWT_SECRET (base64):"
openssl rand -base64 32
echo ""
echo "Copy these values to your vault.yaml file"
echo ""
}
# Function to create vault password file
create_vault_password() {
if [ -f "$VAULT_PASS_FILE" ]; then
echo "⚠️ Vault password file already exists: $VAULT_PASS_FILE"
read -p "Overwrite? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Skipping vault password creation"
return
fi
fi
echo "Creating vault password file..."
read -sp "Enter vault password: " password
echo ""
read -sp "Confirm password: " password2
echo ""
if [ "$password" != "$password2" ]; then
echo "❌ Passwords don't match"
exit 1
fi
echo "$password" > "$VAULT_PASS_FILE"
chmod 600 "$VAULT_PASS_FILE"
echo "✅ Vault password saved to: $VAULT_PASS_FILE"
echo " (This file is git-ignored)"
echo ""
}
# Function to encrypt vault
encrypt_vault() {
if [ ! -f "$VAULT_FILE" ]; then
echo "❌ Vault file not found: $VAULT_FILE"
echo " Please create it first from the template"
exit 1
fi
# Check if already encrypted
if head -n1 "$VAULT_FILE" | grep -q "ANSIBLE_VAULT"; then
echo "⚠️ Vault file is already encrypted"
return
fi
if [ ! -f "$VAULT_PASS_FILE" ]; then
echo "❌ Vault password file not found: $VAULT_PASS_FILE"
echo " Run: $0 create-password"
exit 1
fi
echo "Encrypting vault file..."
ansible-vault encrypt "$VAULT_FILE" --vault-password-file="$VAULT_PASS_FILE" --encrypt-vault-id default
echo "✅ Vault encrypted successfully"
echo ""
}
# Function to decrypt vault
decrypt_vault() {
if [ ! -f "$VAULT_FILE" ]; then
echo "❌ Vault file not found: $VAULT_FILE"
exit 1
fi
# Check if encrypted
if ! head -n1 "$VAULT_FILE" | grep -q "ANSIBLE_VAULT"; then
echo "⚠️ Vault file is not encrypted"
return
fi
if [ ! -f "$VAULT_PASS_FILE" ]; then
echo "❌ Vault password file not found: $VAULT_PASS_FILE"
exit 1
fi
echo "Decrypting vault file..."
ansible-vault decrypt "$VAULT_FILE" --vault-password-file="$VAULT_PASS_FILE"
echo "✅ Vault decrypted successfully"
echo "⚠️ Remember to re-encrypt before committing!"
echo ""
}
# Function to edit vault
edit_vault() {
if [ ! -f "$VAULT_FILE" ]; then
echo "❌ Vault file not found: $VAULT_FILE"
exit 1
fi
if [ ! -f "$VAULT_PASS_FILE" ]; then
echo "❌ Vault password file not found: $VAULT_PASS_FILE"
echo " Run: $0 create-password"
exit 1
fi
echo "Opening vault for editing..."
ansible-vault edit "$VAULT_FILE" --vault-password-file="$VAULT_PASS_FILE"
}
# Function to view vault
view_vault() {
if [ ! -f "$VAULT_FILE" ]; then
echo "❌ Vault file not found: $VAULT_FILE"
exit 1
fi
if [ ! -f "$VAULT_PASS_FILE" ]; then
echo "❌ Vault password file not found: $VAULT_PASS_FILE"
exit 1
fi
ansible-vault view "$VAULT_FILE" --vault-password-file="$VAULT_PASS_FILE"
}
# Function to check vault status
check_status() {
echo "Vault Status:"
echo "-------------"
if [ -f "$VAULT_PASS_FILE" ]; then
echo "✅ Vault password file exists: $VAULT_PASS_FILE"
else
echo "❌ Vault password file not found: $VAULT_PASS_FILE"
fi
if [ -f "$VAULT_FILE" ]; then
if head -n1 "$VAULT_FILE" | grep -q "ANSIBLE_VAULT"; then
echo "✅ Vault file is encrypted: $VAULT_FILE"
else
echo "⚠️ Vault file exists but is NOT encrypted: $VAULT_FILE"
echo " Run: $0 encrypt"
fi
else
echo "❌ Vault file not found: $VAULT_FILE"
fi
echo ""
}
# Main menu
case "${1:-}" in
generate-secrets)
generate_secrets
;;
create-password)
create_vault_password
;;
encrypt)
encrypt_vault
;;
decrypt)
decrypt_vault
;;
edit)
edit_vault
;;
view)
view_vault
;;
status)
check_status
;;
*)
echo "Usage: $0 {generate-secrets|create-password|encrypt|decrypt|edit|view|status}"
echo ""
echo "Commands:"
echo " generate-secrets - Generate new Forgejo secrets"
echo " create-password - Create vault password file (.vault_pass)"
echo " encrypt - Encrypt vault.yaml"
echo " decrypt - Decrypt vault.yaml (use carefully!)"
echo " edit - Edit encrypted vault"
echo " view - View encrypted vault contents"
echo " status - Check vault status"
echo ""
echo "Quick setup:"
echo " 1. $0 generate-secrets # Generate new secrets"
echo " 2. Edit vault.yaml with your secrets"
echo " 3. $0 create-password # Create password file"
echo " 4. $0 encrypt # Encrypt vault"
echo ""
exit 1
;;
esac