diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg index 81a5177..18a459a 100644 --- a/ansible/ansible.cfg +++ b/ansible/ansible.cfg @@ -6,4 +6,7 @@ retry_files_enabled = false [ssh_connection] pipelining = true +# Транспорт (ProxyJump, порты, пользователи, ключи) описан в ansible/ssh_config. +# Он подключается через ansible_ssh_common_args в group_vars/all/main.yml, +# где путь вычисляется от inventory_dir и потому не зависит ни от cwd, ни от места клона. ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=accept-new diff --git a/ansible/inventory/group_vars/all/main.yml b/ansible/inventory/group_vars/all/main.yml new file mode 100644 index 0000000..036f18c --- /dev/null +++ b/ansible/inventory/group_vars/all/main.yml @@ -0,0 +1,23 @@ +--- +# Общие переменные для всех управляемых хостов. +# SSH-транспорт (ProxyJump, порты, ключи по хостам) описан в ansible/ssh_config. +# Путь считается от каталога inventory, поэтому работает из любого cwd +# и не ломается при клоне репозитория в другое место. +ansible_ssh_common_args: "-F {{ inventory_dir }}/../ssh_config" + +ansible_python_interpreter: /usr/bin/python3 +ansible_user: ansible +ansible_ssh_private_key_file: ~/.ssh/id_ed25519_homelab_ansible +ansible_become: true + +homelab_lan_cidr: 192.168.1.0/24 +homelab_service_range: 192.168.1.5-192.168.1.40 + +openvpn_network_cidr: 10.78.0.0/30 +openvpn_listen_port: 8443 +openvpn_forwarded_services: + - name: satisfactory + protocol: udp + public_port: 7777 + target_host: 192.168.1.100 + target_port: 7777 diff --git a/ansible/inventory/group_vars/lxc_infra/main.yml b/ansible/inventory/group_vars/lxc_infra/main.yml new file mode 100644 index 0000000..88d8b08 --- /dev/null +++ b/ansible/inventory/group_vars/lxc_infra/main.yml @@ -0,0 +1,6 @@ +--- +# LXC-контейнеры управляются напрямую под root, sudo не требуется. + +ansible_user: root +ansible_become: false +ansible_ssh_private_key_file: ~/.ssh/id_ed25519_homelab diff --git a/ansible/inventory/hosts.yml b/ansible/inventory/hosts.yml index 2c4374c..c7f0074 100644 --- a/ansible/inventory/hosts.yml +++ b/ansible/inventory/hosts.yml @@ -1,20 +1,11 @@ +# Каноничный список хостов HomeLab. +# +# Общие переменные: inventory/group_vars/all/main.yml +# Переменные LXC: inventory/group_vars/lxc_infra/main.yml +# SSH-транспорт: ../ssh_config (подключён через ssh_args в ansible.cfg) +# +# Здесь у хоста остаются только адрес и его индивидуальные факты. all: - vars: - ansible_python_interpreter: /usr/bin/python3 - ansible_user: ansible - ansible_ssh_private_key_file: ~/.ssh/id_ed25519_homelab_ansible - ansible_become: true - homelab_lan_cidr: 192.168.1.0/24 - homelab_service_range: 192.168.1.5-192.168.1.40 - openvpn_network_cidr: 10.78.0.0/30 - openvpn_listen_port: 8443 - openvpn_forwarded_services: - - name: satisfactory - protocol: udp - public_port: 7777 - target_host: 192.168.1.100 - target_port: 7777 - children: homelab: hosts: @@ -29,8 +20,6 @@ all: hosts: cloud-pc: ansible_host: 192.168.1.5 - ansible_ssh_common_args: >- - -o ProxyCommand="ssh -i ~/.ssh/id_ed25519_homelab_ansible -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -p 3422 -W %h:%p ansible@157.22.231.198" expected_lan_ip: 192.168.1.5 storage_mounts: - src: UUID=ae278333-4116-4225-9b95-595496fadd26 @@ -42,128 +31,67 @@ all: mini-pc: ansible_host: 192.168.1.10 - ansible_ssh_common_args: >- - -o ProxyCommand="ssh -i ~/.ssh/id_ed25519_homelab_ansible -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -p 3422 -W %h:%p ansible@157.22.231.198" expected_lan_ip: 192.168.1.10 lxc_infra: hosts: + # Доступны напрямую по LAN (без ProxyJump через ru-vps) pbs: ansible_host: 192.168.1.20 - ansible_user: root - ansible_become: false - ansible_ssh_private_key_file: ~/.ssh/id_ed25519_homelab expected_lan_ip: 192.168.1.20 ovpn-mini: ansible_host: 192.168.1.23 - ansible_user: root - ansible_become: false - ansible_ssh_private_key_file: ~/.ssh/id_ed25519_homelab expected_lan_ip: 192.168.1.23 openvpn_local_ip: 10.78.0.2 openvpn_peer_ip: 10.78.0.1 openvpn_role: gateway + # Остальные LXC — через ru-vps (см. ssh_config) adguard: ansible_host: 192.168.1.28 - ansible_user: root - ansible_become: false - ansible_ssh_private_key_file: ~/.ssh/id_ed25519_homelab - ansible_ssh_common_args: >- - -o ProxyCommand="ssh -i ~/.ssh/id_ed25519_homelab_ansible -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -p 3422 -W %h:%p ansible@157.22.231.198" expected_lan_ip: 192.168.1.28 docker-test: ansible_host: 192.168.1.29 - ansible_user: root - ansible_become: false - ansible_ssh_private_key_file: ~/.ssh/id_ed25519_homelab - ansible_ssh_common_args: >- - -o ProxyCommand="ssh -i ~/.ssh/id_ed25519_homelab_ansible -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -p 3422 -W %h:%p ansible@157.22.231.198" expected_lan_ip: 192.168.1.29 vaultwarden: ansible_host: 192.168.1.24 - ansible_user: root - ansible_become: false - ansible_ssh_private_key_file: ~/.ssh/id_ed25519_homelab - ansible_ssh_common_args: >- - -o ProxyCommand="ssh -i ~/.ssh/id_ed25519_homelab_ansible -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -p 3422 -W %h:%p ansible@157.22.231.198" expected_lan_ip: 192.168.1.24 gitea: ansible_host: 192.168.1.25 - ansible_user: root - ansible_become: false - ansible_ssh_private_key_file: ~/.ssh/id_ed25519_homelab - ansible_ssh_common_args: >- - -o ProxyCommand="ssh -i ~/.ssh/id_ed25519_homelab_ansible -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -p 3422 -W %h:%p ansible@157.22.231.198" expected_lan_ip: 192.168.1.25 memoir-bot: ansible_host: 192.168.1.26 - ansible_user: root - ansible_become: false - ansible_ssh_private_key_file: ~/.ssh/id_ed25519_homelab - ansible_ssh_common_args: >- - -o ProxyCommand="ssh -i ~/.ssh/id_ed25519_homelab_ansible -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -p 3422 -W %h:%p ansible@157.22.231.198" expected_lan_ip: 192.168.1.26 mihomo: ansible_host: 192.168.1.27 - ansible_user: root - ansible_become: false - ansible_ssh_private_key_file: ~/.ssh/id_ed25519_homelab - ansible_ssh_common_args: >- - -o ProxyCommand="ssh -i ~/.ssh/id_ed25519_homelab_ansible -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -p 3422 -W %h:%p ansible@157.22.231.198" expected_lan_ip: 192.168.1.27 monitoring: ansible_host: 192.168.1.30 - ansible_user: root - ansible_become: false - ansible_ssh_private_key_file: ~/.ssh/id_ed25519_homelab - ansible_ssh_common_args: >- - -o ProxyCommand="ssh -i ~/.ssh/id_ed25519_homelab_ansible -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -p 3422 -W %h:%p ansible@157.22.231.198" expected_lan_ip: 192.168.1.30 hermes-ai: ansible_host: 192.168.1.31 - ansible_user: root - ansible_become: false - ansible_ssh_private_key_file: ~/.ssh/id_ed25519_homelab - ansible_ssh_common_args: >- - -o ProxyCommand="ssh -i ~/.ssh/id_ed25519_homelab_ansible -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -p 3422 -W %h:%p ansible@157.22.231.198" expected_lan_ip: 192.168.1.31 bash_config_proxy_http_url: http://192.168.1.27:7890 bash_config_proxy_socks_url: socks5h://192.168.1.27:7890 emergency-bot: ansible_host: 192.168.1.32 - ansible_user: root - ansible_become: false - ansible_ssh_private_key_file: ~/.ssh/id_ed25519_homelab - ansible_ssh_common_args: >- - -o ProxyCommand="ssh -i ~/.ssh/id_ed25519_homelab_ansible -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -p 3422 -W %h:%p ansible@157.22.231.198" expected_lan_ip: 192.168.1.32 grimmory: ansible_host: 192.168.1.34 - ansible_user: root - ansible_become: false - ansible_ssh_private_key_file: ~/.ssh/id_ed25519_homelab - ansible_ssh_common_args: >- - -o ProxyCommand="ssh -i ~/.ssh/id_ed25519_homelab_ansible -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -p 3422 -W %h:%p ansible@157.22.231.198" expected_lan_ip: 192.168.1.34 gyro: ansible_host: 192.168.1.35 - ansible_user: root - ansible_become: false - ansible_ssh_private_key_file: ~/.ssh/id_ed25519_homelab - ansible_ssh_common_args: >- - -o ProxyCommand="ssh -i ~/.ssh/id_ed25519_homelab_ansible -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -p 3422 -W %h:%p ansible@157.22.231.198" expected_lan_ip: 192.168.1.35 monitoring_exporters: diff --git a/ansible/ssh_config b/ansible/ssh_config new file mode 100644 index 0000000..d71f1dc --- /dev/null +++ b/ansible/ssh_config @@ -0,0 +1,106 @@ +# ════════════════════════════════════════════════════════════════════════ +# HomeLab SSH config — единый источник правды по SSH-доступу +# +# Файл управляется репозиторием infras. Правь его здесь, а не в ~/.ssh/. +# +# Как подключить (один раз), первой строкой ~/.ssh/config: +# +# Include /home/ada/Documents/Projects/HomeLab/infras/ansible/ssh_config +# +# После этого из обычного терминала работает: ssh gitea, ssh pbs, ssh cloud-pc +# +# SSH берёт ПЕРВОЕ найденное значение опции, поэтому: +# - Include в начале ~/.ssh/config -> побеждают настройки репозитория; +# - Include в конце ~/.ssh/config -> побеждают личные записи из config.d/* +# (личные vps/cloud-pc/mini-pc/pbs остаются под пользователем ada, +# а LXC-хосты всё равно резолвятся отсюда). +# +# Ansible использует этот же файл: ansible.cfg -> [ssh_connection] ssh_args +# содержит -F <абсолютный путь к этому файлу>. Поэтому каждая запись +# указана и по имени (ssh gitea), и по IP (Ansible ходит по ansible_host). +# ════════════════════════════════════════════════════════════════════════ + +# ── Jump host: публичная VPS ──────────────────────────────────────────── +Host ru-vps vps 157.22.231.198 + HostName 157.22.231.198 + Port 3422 + User ansible + IdentityFile ~/.ssh/id_ed25519_homelab_ansible + +# ── Proxmox VE ноды (через ru-vps) ────────────────────────────────────── +Host cloud-pc 192.168.1.5 + HostName 192.168.1.5 + +Host mini-pc 192.168.1.10 + HostName 192.168.1.10 + +Host cloud-pc mini-pc 192.168.1.5 192.168.1.10 + User ansible + IdentityFile ~/.ssh/id_ed25519_homelab_ansible + ProxyJump ru-vps + +# ── LXC, доступные напрямую по LAN (без ProxyJump) ────────────────────── +Host pbs 192.168.1.20 + HostName 192.168.1.20 + +Host ovpn-mini 192.168.1.23 + HostName 192.168.1.23 + +# ── LXC за jump-хостом ────────────────────────────────────────────────── +Host vaultwarden 192.168.1.24 + HostName 192.168.1.24 + +Host gitea 192.168.1.25 + HostName 192.168.1.25 + +Host memoir-bot 192.168.1.26 + HostName 192.168.1.26 + +Host mihomo 192.168.1.27 + HostName 192.168.1.27 + +Host adguard 192.168.1.28 + HostName 192.168.1.28 + +Host docker-test 192.168.1.29 + HostName 192.168.1.29 + +Host monitoring 192.168.1.30 + HostName 192.168.1.30 + +Host hermes-ai 192.168.1.31 + HostName 192.168.1.31 + +Host emergency-bot 192.168.1.32 + HostName 192.168.1.32 + +Host grimmory 192.168.1.34 + HostName 192.168.1.34 + +Host gyro 192.168.1.35 + HostName 192.168.1.35 + + +# ── Групповые опции. ssh_config не поддерживает перенос строк, поэтому +# списки паттернов длинные: имя хоста (для `ssh gitea`) + IP (Ansible +# подключается по ansible_host). ───────────────────────────────────── + +# ProxyJump только для LXC, до которых нет прямого доступа +Host vaultwarden gitea memoir-bot mihomo adguard docker-test monitoring hermes-ai emergency-bot grimmory gyro 192.168.1.24 192.168.1.25 192.168.1.26 192.168.1.27 192.168.1.28 192.168.1.29 192.168.1.30 192.168.1.31 192.168.1.32 192.168.1.34 192.168.1.35 + ProxyJump ru-vps + +# Все LXC — под root с ключом id_ed25519_homelab +Host pbs ovpn-mini vaultwarden gitea memoir-bot mihomo adguard docker-test monitoring hermes-ai emergency-bot grimmory gyro 192.168.1.20 192.168.1.23 192.168.1.24 192.168.1.25 192.168.1.26 192.168.1.27 192.168.1.28 192.168.1.29 192.168.1.30 192.168.1.31 192.168.1.32 192.168.1.34 192.168.1.35 + User root + IdentityFile ~/.ssh/id_ed25519_homelab + +# Общие опции для хостов HomeLab (намеренно не `Host *`, чтобы не влиять +# на остальные записи ~/.ssh/config пользователя) +Host ru-vps vps cloud-pc mini-pc pbs ovpn-mini vaultwarden gitea memoir-bot mihomo adguard docker-test monitoring hermes-ai emergency-bot grimmory gyro 157.22.231.198 192.168.1.5 192.168.1.10 192.168.1.20 192.168.1.23 192.168.1.24 192.168.1.25 192.168.1.26 192.168.1.27 192.168.1.28 192.168.1.29 192.168.1.30 192.168.1.31 192.168.1.32 192.168.1.34 192.168.1.35 + IdentitiesOnly yes + StrictHostKeyChecking accept-new + ControlMaster auto + ControlPath ~/.ssh/sockets/%C + ControlPersist 60s + ServerAliveInterval 30 + ServerAliveCountMax 3