From 8ef380bc9b6c5a3a436080ba805bf85faf567605 Mon Sep 17 00:00:00 2001 From: Sergei Poljanski Date: Tue, 4 Nov 2025 14:23:16 +0200 Subject: [PATCH] ansible cleanup --- README.md | 58 +++++ ansible/.gitignore | 53 +---- ansible/inventory/group_vars/all/main.yaml | 21 -- ansible/inventory/group_vars/all/paths.yaml | 5 + .../inventory/group_vars/all/services.yaml | 30 --- .../inventory/group_vars/all/wireguard.yaml | 38 +++ .../group_vars/ops_servers/forgejo.yaml | 25 ++ .../group_vars/ops_servers/traefik.yaml | 11 + .../services_servers/forgejo_runner.yaml | 11 + ansible/inventory/host_vars/asxpio-ops.yaml | 60 +---- .../inventory/host_vars/asxpio-services.yaml | 10 +- ansible/inventory/hosts.yaml | 16 +- ansible/playbooks/02-full-deployment.yaml | 20 +- ansible/roles/forgejo/tasks/validate.yaml | 4 - ansible/scripts/setup-vault.sh | 221 ------------------ 15 files changed, 163 insertions(+), 420 deletions(-) create mode 100644 README.md delete mode 100644 ansible/inventory/group_vars/all/main.yaml create mode 100644 ansible/inventory/group_vars/all/paths.yaml delete mode 100644 ansible/inventory/group_vars/all/services.yaml create mode 100644 ansible/inventory/group_vars/all/wireguard.yaml create mode 100644 ansible/inventory/group_vars/ops_servers/forgejo.yaml create mode 100644 ansible/inventory/group_vars/ops_servers/traefik.yaml create mode 100644 ansible/inventory/group_vars/services_servers/forgejo_runner.yaml delete mode 100755 ansible/scripts/setup-vault.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..cdbeac9 --- /dev/null +++ b/README.md @@ -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 diff --git a/ansible/.gitignore b/ansible/.gitignore index 9bec0f3..8d51cab 100644 --- a/ansible/.gitignore +++ b/ansible/.gitignore @@ -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/ diff --git a/ansible/inventory/group_vars/all/main.yaml b/ansible/inventory/group_vars/all/main.yaml deleted file mode 100644 index 335db14..0000000 --- a/ansible/inventory/group_vars/all/main.yaml +++ /dev/null @@ -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 diff --git a/ansible/inventory/group_vars/all/paths.yaml b/ansible/inventory/group_vars/all/paths.yaml new file mode 100644 index 0000000..9410d1a --- /dev/null +++ b/ansible/inventory/group_vars/all/paths.yaml @@ -0,0 +1,5 @@ +--- +# Base paths for all services + +# Base directory for all service installations +services_base_path: "/opt" diff --git a/ansible/inventory/group_vars/all/services.yaml b/ansible/inventory/group_vars/all/services.yaml deleted file mode 100644 index ab9b357..0000000 --- a/ansible/inventory/group_vars/all/services.yaml +++ /dev/null @@ -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" diff --git a/ansible/inventory/group_vars/all/wireguard.yaml b/ansible/inventory/group_vars/all/wireguard.yaml new file mode 100644 index 0000000..f24c1a9 --- /dev/null +++ b/ansible/inventory/group_vars/all/wireguard.yaml @@ -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 diff --git a/ansible/inventory/group_vars/ops_servers/forgejo.yaml b/ansible/inventory/group_vars/ops_servers/forgejo.yaml new file mode 100644 index 0000000..8c2bd4c --- /dev/null +++ b/ansible/inventory/group_vars/ops_servers/forgejo.yaml @@ -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 diff --git a/ansible/inventory/group_vars/ops_servers/traefik.yaml b/ansible/inventory/group_vars/ops_servers/traefik.yaml new file mode 100644 index 0000000..45f6340 --- /dev/null +++ b/ansible/inventory/group_vars/ops_servers/traefik.yaml @@ -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 }}" diff --git a/ansible/inventory/group_vars/services_servers/forgejo_runner.yaml b/ansible/inventory/group_vars/services_servers/forgejo_runner.yaml new file mode 100644 index 0000000..4b78089 --- /dev/null +++ b/ansible/inventory/group_vars/services_servers/forgejo_runner.yaml @@ -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" diff --git a/ansible/inventory/host_vars/asxpio-ops.yaml b/ansible/inventory/host_vars/asxpio-ops.yaml index db5fdc0..1f0feb3 100644 --- a/ansible/inventory/host_vars/asxpio-ops.yaml +++ b/ansible/inventory/host_vars/asxpio-ops.yaml @@ -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 diff --git a/ansible/inventory/host_vars/asxpio-services.yaml b/ansible/inventory/host_vars/asxpio-services.yaml index 120fa57..e555e4c 100644 --- a/ansible/inventory/host_vars/asxpio-services.yaml +++ b/ansible/inventory/host_vars/asxpio-services.yaml @@ -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 diff --git a/ansible/inventory/hosts.yaml b/ansible/inventory/hosts.yaml index bd949e2..6b4907d 100644 --- a/ansible/inventory/hosts.yaml +++ b/ansible/inventory/hosts.yaml @@ -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 diff --git a/ansible/playbooks/02-full-deployment.yaml b/ansible/playbooks/02-full-deployment.yaml index b25f182..1d506b2 100644 --- a/ansible/playbooks/02-full-deployment.yaml +++ b/ansible/playbooks/02-full-deployment.yaml @@ -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 diff --git a/ansible/roles/forgejo/tasks/validate.yaml b/ansible/roles/forgejo/tasks/validate.yaml index 1b08a6b..7c9b883 100644 --- a/ansible/roles/forgejo/tasks/validate.yaml +++ b/ansible/roles/forgejo/tasks/validate.yaml @@ -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" diff --git a/ansible/scripts/setup-vault.sh b/ansible/scripts/setup-vault.sh deleted file mode 100755 index 0e07992..0000000 --- a/ansible/scripts/setup-vault.sh +++ /dev/null @@ -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