diff --git a/.gitignore b/.gitignore index 97573fb..2060c5f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,7 @@ *.env !*.env.example passwd +.venv/ +ansible/.venv/ +ansible/collections/ +ansible/generated/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..f15f4a7 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# HomeLab Infrastructure + +Active HomeLab infrastructure is managed through Ansible. + +## Active Files + +- `ansible/` — current control plane. +- `ansible/inventory/hosts.yml` — inventory and host facts. +- `ansible/playbooks/check.yml` — safe connectivity/facts check. + +## Archive + +Historical pre-Proxmox material is kept under: + +```text +archive/2026-07-proxmox-migration/ +``` + +It contains old NixOS configs, Docker Compose service definitions, Gitea workflows, deploy scripts and old Ansible bootstrap playbooks. + +## Basic Check + +```bash +cd ansible +ansible-playbook playbooks/check.yml +``` diff --git a/ansible/.env.example b/ansible/.env.example new file mode 100644 index 0000000..0ac6361 --- /dev/null +++ b/ansible/.env.example @@ -0,0 +1,8 @@ +export PROXMOX_HOST=192.168.1.10 +export PROXMOX_USER='ansible@pve' +export PROXMOX_TOKEN_ID='homelab' +export PROXMOX_TOKEN_SECRET='replace-me' +export PROXMOX_VALIDATE_CERTS=false + +# Override if the downloaded template name differs. +export PVE_LXC_OSTEMPLATE='local:vztmpl/debian-13-standard_13.1-2_amd64.tar.zst' diff --git a/ansible/README.md b/ansible/README.md new file mode 100644 index 0000000..17c5f7d --- /dev/null +++ b/ansible/README.md @@ -0,0 +1,82 @@ +# HomeLab Ansible + +Ansible is the control plane for HomeLab infrastructure changes. + +## Contract + +- The operator keeps passwords, SSH access and network reachability working. +- The agent changes infrastructure only through inventory, roles and playbooks in this directory. +- Manual server changes are allowed only for break-glass recovery; afterwards they must be captured in Ansible. +- Secrets stay outside git. Use `.env`, vault files or local prompt input, not committed variables. + +## Layout + +- `inventory/hosts.yml` — canonical host list and host-specific facts. +- `playbooks/` — entry points for tasks. +- `roles/` — reusable configuration units. + +## Current Groups + +- `ru-vps` — public VPS, JumpHost, qdevice, ZeroTier member. +- `pve_nodes` — Proxmox hosts: `cloud-pc`, `mini-pc`. +- `lxc_infra` — infrastructure LXC containers: `pbs`, `zt-cloud`, `zt-mini`. +- `vpn_openvpn` — OpenVPN transport hosts: `ru-vps`, `wg-mini`. +- `shell_hosts` — hosts with unified bash config: `ru-vps`, `cloud-pc`, `mini-pc`. +- `servers` — all managed hosts. + +## First Checks + +Install control-node dependencies locally: + +```bash +python3 -m venv .venv +. .venv/bin/activate +pip install -r requirements.txt +ansible-galaxy collection install -r requirements.yml -p collections +``` + +Run from `ansible/`: + +```bash +ansible-playbook playbooks/check.yml +``` + +For Proxmox API playbooks, create ignored `.env` from `.env.example` and load it: + +```bash +cp .env.example .env +. ./.env +.venv/bin/ansible-playbook playbooks/pve-wg-mini.yml +``` + +Or bootstrap the token from `mini-pc` with sudo: + +```bash +.venv/bin/ansible-playbook playbooks/bootstrap-pve-api-token.yml -K +``` + +OpenVPN transport: + +```bash +.venv/bin/ansible-playbook playbooks/openvpn-vps-mini.yml -K +.venv/bin/ansible-playbook playbooks/openvpn-check.yml +``` + +Bootstrap the Ansible service account on shell hosts: + +```bash +.venv/bin/ansible-playbook -i inventory/hosts.yml playbooks/bootstrap-ansible-user.yml -K +``` + +When a task needs privilege escalation: + +```bash +ansible-playbook playbooks/.yml -K +``` + +## Workflow + +1. Describe the desired infrastructure change. +2. Add or update a role/playbook. +3. Run the smallest safe check or playbook. +4. Document non-obvious decisions in the project notes. diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg index 5cc1c20..81a5177 100644 --- a/ansible/ansible.cfg +++ b/ansible/ansible.cfg @@ -1,6 +1,9 @@ [defaults] inventory = inventory/hosts.yml +roles_path = roles +collections_path = collections +retry_files_enabled = false [ssh_connection] pipelining = true -ssh_args = -o ControlMaster=auto -o ControlPersist=60s +ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=accept-new diff --git a/ansible/inventory/hosts.yml b/ansible/inventory/hosts.yml index be29106..f1b4c6b 100644 --- a/ansible/inventory/hosts.yml +++ b/ansible/inventory/hosts.yml @@ -1,18 +1,30 @@ all: vars: ansible_python_interpreter: /usr/bin/python3 - ansible_user: ada + 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 + homelab_zerotier_network_id: 743993800fa5a34c + openvpn_network_cidr: 10.78.0.0/30 + openvpn_listen_port: 8443 children: - servers: + homelab: hosts: ru-vps: ansible_host: vps + openvpn_local_ip: 10.78.0.1 + openvpn_peer_ip: 10.78.0.2 + openvpn_role: server + pve_nodes: + hosts: cloud-pc: - ansible_host: 10.122.62.51 - # ansible_host: 192.168.1.5 - ansible_ssh_common_args: '-J vps' + 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 @@ -21,11 +33,71 @@ all: - src: UUID=940a9a4e-10cf-4380-9d22-a71549066561 path: /mnt/backup fstype: ext4 - - src: UUID=89024d30-1ab6-4b2e-b23b-62837455b24a - path: /opt/samba - fstype: ext4 mini-pc: - ansible_host: 10.122.62.95 - ansible_ssh_common_args: '-J vps' + 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: + pbs: + ansible_host: 192.168.1.20 + expected_lan_ip: 192.168.1.20 + + zt-cloud: + ansible_host: 192.168.1.21 + expected_lan_ip: 192.168.1.21 + zerotier_ip: 10.122.62.206 + zerotier_node_id: c606e6d181 + + zt-mini: + ansible_host: 192.168.1.22 + expected_lan_ip: 192.168.1.22 + zerotier_ip: 10.122.62.213 + zerotier_node_id: 022ac284e1 + + wg-mini: + ansible_host: 192.168.1.23 + ansible_user: root + 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 + + 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 + + vpn_openvpn: + hosts: + ru-vps: + wg-mini: + + shell_hosts: + hosts: + ru-vps: + cloud-pc: + mini-pc: + + servers: + children: + homelab: + pve_nodes: + lxc_infra: diff --git a/ansible/playbooks/bash-config.yml b/ansible/playbooks/bash-config.yml new file mode 100644 index 0000000..514570e --- /dev/null +++ b/ansible/playbooks/bash-config.yml @@ -0,0 +1,6 @@ +- name: Configure unified bash profile + hosts: shell_hosts + gather_facts: true + become: true + roles: + - bash_config diff --git a/ansible/playbooks/bootstrap-ansible-user.yml b/ansible/playbooks/bootstrap-ansible-user.yml new file mode 100644 index 0000000..b466f70 --- /dev/null +++ b/ansible/playbooks/bootstrap-ansible-user.yml @@ -0,0 +1,38 @@ +- name: Bootstrap Ansible service account + hosts: shell_hosts + gather_facts: true + become: true + vars: + ansible_service_user: ansible + ansible_service_public_key_file: ~/.ssh/id_ed25519_homelab_ansible.pub + ansible_service_sudoers_file: /etc/sudoers.d/99-ansible-service-user + + tasks: + - name: Read local Ansible service public key + ansible.builtin.set_fact: + ansible_service_public_key: "{{ lookup('file', ansible_service_public_key_file) }}" + delegate_to: localhost + become: false + + - name: Ensure Ansible service user exists + ansible.builtin.user: + name: "{{ ansible_service_user }}" + shell: /bin/bash + create_home: true + state: present + + - name: Install Ansible service SSH key + ansible.posix.authorized_key: + user: "{{ ansible_service_user }}" + key: "{{ ansible_service_public_key }}" + state: present + exclusive: true + + - name: Allow passwordless sudo for Ansible service user + ansible.builtin.copy: + dest: "{{ ansible_service_sudoers_file }}" + owner: root + group: root + mode: "0440" + content: "{{ ansible_service_user }} ALL=(ALL) NOPASSWD: ALL\n" + validate: /usr/sbin/visudo -cf %s diff --git a/ansible/playbooks/bootstrap-pve-api-token.yml b/ansible/playbooks/bootstrap-pve-api-token.yml new file mode 100644 index 0000000..c5b0f99 --- /dev/null +++ b/ansible/playbooks/bootstrap-pve-api-token.yml @@ -0,0 +1,53 @@ +- name: Bootstrap Proxmox API token for Ansible + hosts: mini-pc + gather_facts: false + become: true + vars: + pve_api_user: ansible@pve + pve_api_token_id: homelab + pve_api_role: Administrator + tasks: + - name: Ensure Proxmox API user exists + ansible.builtin.command: "pveum user add {{ pve_api_user }} --comment 'Ansible automation user'" + register: pve_user_add + changed_when: pve_user_add.rc == 0 + failed_when: + - pve_user_add.rc != 0 + - "'already exists' not in (pve_user_add.stderr | lower)" + + - name: Grant Proxmox API user permissions + ansible.builtin.command: "pveum aclmod / -user {{ pve_api_user }} -role {{ pve_api_role }}" + changed_when: true + + - name: Remove old Ansible token if present + ansible.builtin.command: "pveum user token remove {{ pve_api_user }} {{ pve_api_token_id }}" + register: pve_token_remove + changed_when: pve_token_remove.rc == 0 + failed_when: false + no_log: true + + - name: Create Proxmox API token + ansible.builtin.command: "pveum user token add {{ pve_api_user }} {{ pve_api_token_id }} --privsep 0 --comment 'HomeLab Ansible token' --output-format json" + register: pve_token_add + changed_when: true + no_log: true + + - name: Store token data + ansible.builtin.set_fact: + pve_token_data: "{{ pve_token_add.stdout | from_json }}" + no_log: true + + - name: Write local ansible/.env + ansible.builtin.copy: + dest: "{{ playbook_dir }}/../.env" + mode: "0600" + content: | + export PROXMOX_HOST={{ ansible_host }} + export PROXMOX_USER='{{ pve_api_user }}' + export PROXMOX_TOKEN_ID='{{ pve_api_token_id }}' + export PROXMOX_TOKEN_SECRET='{{ pve_token_data.value }}' + export PROXMOX_VALIDATE_CERTS=false + export PVE_LXC_OSTEMPLATE='local:vztmpl/debian-13-standard_13.0-1_amd64.tar.zst' + delegate_to: localhost + become: false + no_log: true diff --git a/ansible/playbooks/check.yml b/ansible/playbooks/check.yml new file mode 100644 index 0000000..8719819 --- /dev/null +++ b/ansible/playbooks/check.yml @@ -0,0 +1,15 @@ +- name: Check HomeLab Ansible connectivity + hosts: servers + gather_facts: true + become: false + tasks: + - name: Ping host + ansible.builtin.ping: + + - name: Check expected LAN IP when defined + ansible.builtin.assert: + that: + - expected_lan_ip in ansible_facts.all_ipv4_addresses + fail_msg: "{{ inventory_hostname }} must have {{ expected_lan_ip }}; found: {{ ansible_facts.all_ipv4_addresses | join(', ') }}" + success_msg: "{{ inventory_hostname }} has {{ expected_lan_ip }}" + when: expected_lan_ip is defined diff --git a/ansible/playbooks/openvpn-check.yml b/ansible/playbooks/openvpn-check.yml new file mode 100644 index 0000000..8afa859 --- /dev/null +++ b/ansible/playbooks/openvpn-check.yml @@ -0,0 +1,19 @@ +- name: Check OpenVPN tunnel from ru-vps + hosts: ru-vps + gather_facts: false + tasks: + - name: Ping VPN LXC OpenVPN address + ansible.builtin.command: ping -c 3 -W 2 10.78.0.2 + changed_when: false + + - name: Check mini-pc PVE port through OpenVPN gateway + ansible.builtin.command: nc -vz -w 5 192.168.1.10 8006 + changed_when: false + + - name: Check cloud-pc PVE port through OpenVPN gateway + ansible.builtin.command: nc -vz -w 5 192.168.1.5 8006 + changed_when: false + + - name: Check PBS port through OpenVPN gateway + ansible.builtin.command: nc -vz -w 5 192.168.1.20 8007 + changed_when: false diff --git a/ansible/playbooks/openvpn-laptop.yml b/ansible/playbooks/openvpn-laptop.yml new file mode 100644 index 0000000..bddf80a --- /dev/null +++ b/ansible/playbooks/openvpn-laptop.yml @@ -0,0 +1,197 @@ +- name: Configure OpenVPN laptop access through ru-vps + hosts: ru-vps + gather_facts: true + become: true + vars: + laptop_profile_name: ada-x1 + laptop_openvpn_dir: /etc/openvpn/homelab-laptop + laptop_openvpn_config: /etc/openvpn/homelab-laptop/server.conf + laptop_openvpn_key: /etc/openvpn/homelab-laptop/static.key + laptop_openvpn_service: homelab-openvpn-laptop + laptop_openvpn_port: 9443 + laptop_openvpn_interface: tun1 + laptop_openvpn_site_interface: tun0 + laptop_openvpn_network_cidr: 10.79.0.0/30 + laptop_openvpn_server_ip: 10.79.0.1 + laptop_openvpn_client_ip: 10.79.0.2 + laptop_openvpn_remote: 157.22.231.198 + laptop_openvpn_client_config_local: "{{ playbook_dir }}/../generated/{{ laptop_profile_name }}.ovpn" + laptop_openvpn_home_routes: + - network: 192.168.1.5 + netmask: 255.255.255.255 + - network: 192.168.1.6 + netmask: 255.255.255.254 + - network: 192.168.1.8 + netmask: 255.255.255.248 + - network: 192.168.1.16 + netmask: 255.255.255.240 + - network: 192.168.1.32 + netmask: 255.255.255.248 + - network: 192.168.1.40 + netmask: 255.255.255.255 + + tasks: + - name: Install OpenVPN packages + ansible.builtin.apt: + name: + - openvpn + - iptables + state: present + update_cache: true + + - name: Ensure laptop OpenVPN config directory exists + ansible.builtin.file: + path: "{{ laptop_openvpn_dir }}" + state: directory + owner: root + group: root + mode: "0700" + + - name: Generate laptop static key if missing + ansible.builtin.command: "openvpn --genkey secret {{ laptop_openvpn_key }}" + args: + creates: "{{ laptop_openvpn_key }}" + no_log: true + + - name: Enable IPv4 forwarding on ru-vps + ansible.posix.sysctl: + name: net.ipv4.ip_forward + value: "1" + state: present + reload: true + + - name: Allow laptop OpenVPN TCP in UFW + ansible.builtin.command: "ufw allow {{ laptop_openvpn_port }}/tcp" + register: ufw_allow_laptop_openvpn + changed_when: "'Rule added' in ufw_allow_laptop_openvpn.stdout or 'Rules updated' in ufw_allow_laptop_openvpn.stdout" + failed_when: false + + - name: Render laptop OpenVPN server config + ansible.builtin.copy: + dest: "{{ laptop_openvpn_config }}" + owner: root + group: root + mode: "0600" + content: | + dev {{ laptop_openvpn_interface }} + ifconfig {{ laptop_openvpn_server_ip }} {{ laptop_openvpn_client_ip }} + secret {{ laptop_openvpn_key }} + cipher AES-256-CBC + auth SHA256 + proto tcp-server + port {{ laptop_openvpn_port }} + persist-key + persist-tun + verb 3 + keepalive 10 60 + notify: restart laptop openvpn + + - name: Render laptop OpenVPN up script + ansible.builtin.copy: + dest: "{{ laptop_openvpn_dir }}/up.sh" + owner: root + group: root + mode: "0700" + content: | + #!/bin/sh + iptables -t nat -C POSTROUTING -s {{ laptop_openvpn_network_cidr }} -d {{ homelab_lan_cidr }} -o {{ laptop_openvpn_site_interface }} -j MASQUERADE 2>/dev/null || \ + iptables -t nat -A POSTROUTING -s {{ laptop_openvpn_network_cidr }} -d {{ homelab_lan_cidr }} -o {{ laptop_openvpn_site_interface }} -j MASQUERADE + notify: restart laptop openvpn + + - name: Render laptop OpenVPN down script + ansible.builtin.copy: + dest: "{{ laptop_openvpn_dir }}/down.sh" + owner: root + group: root + mode: "0700" + content: | + #!/bin/sh + iptables -t nat -D POSTROUTING -s {{ laptop_openvpn_network_cidr }} -d {{ homelab_lan_cidr }} -o {{ laptop_openvpn_site_interface }} -j MASQUERADE 2>/dev/null || true + notify: restart laptop openvpn + + - name: Render laptop OpenVPN systemd service + ansible.builtin.copy: + dest: "/etc/systemd/system/{{ laptop_openvpn_service }}.service" + owner: root + group: root + mode: "0644" + content: | + [Unit] + Description=HomeLab OpenVPN laptop access + After=network-online.target homelab-openvpn.service + Wants=network-online.target + Requires=homelab-openvpn.service + + [Service] + Type=simple + ExecStartPre={{ laptop_openvpn_dir }}/up.sh + ExecStart=/usr/sbin/openvpn --config {{ laptop_openvpn_config }} + ExecStopPost={{ laptop_openvpn_dir }}/down.sh + Restart=on-failure + RestartSec=5 + + [Install] + WantedBy=multi-user.target + notify: + - reload systemd + - restart laptop openvpn + + - name: Flush handlers before starting laptop OpenVPN + ansible.builtin.meta: flush_handlers + + - name: Enable and start laptop OpenVPN + ansible.builtin.systemd: + name: "{{ laptop_openvpn_service }}" + state: started + enabled: true + + - name: Read laptop static key for client profile + ansible.builtin.slurp: + src: "{{ laptop_openvpn_key }}" + register: laptop_openvpn_static_key_raw + no_log: true + + - name: Ensure local generated directory exists + ansible.builtin.file: + path: "{{ playbook_dir }}/../generated" + state: directory + mode: "0700" + become: false + delegate_to: localhost + + - name: Write local laptop OpenVPN profile + ansible.builtin.copy: + dest: "{{ laptop_openvpn_client_config_local }}" + mode: "0600" + content: | + client + dev tun + proto tcp-client + remote {{ laptop_openvpn_remote }} {{ laptop_openvpn_port }} + ifconfig {{ laptop_openvpn_client_ip }} {{ laptop_openvpn_server_ip }} + cipher AES-256-CBC + auth SHA256 + persist-key + persist-tun + resolv-retry infinite + nobind + verb 3 + {% for route in laptop_openvpn_home_routes %} + route {{ route.network }} {{ route.netmask }} + {% endfor %} + + {{ laptop_openvpn_static_key_raw.content | b64decode }} + + become: false + delegate_to: localhost + no_log: true + + handlers: + - name: reload systemd + ansible.builtin.systemd: + daemon_reload: true + + - name: restart laptop openvpn + ansible.builtin.systemd: + name: "{{ laptop_openvpn_service }}" + state: restarted diff --git a/ansible/playbooks/openvpn-vps-mini.yml b/ansible/playbooks/openvpn-vps-mini.yml new file mode 100644 index 0000000..4e3e45c --- /dev/null +++ b/ansible/playbooks/openvpn-vps-mini.yml @@ -0,0 +1,6 @@ +- name: Configure OpenVPN on ru-vps and VPN LXC + hosts: vpn_openvpn + gather_facts: true + become: true + roles: + - openvpn_gateway diff --git a/ansible/playbooks/pve-gitea.yml b/ansible/playbooks/pve-gitea.yml new file mode 100644 index 0000000..c2aaa2f --- /dev/null +++ b/ansible/playbooks/pve-gitea.yml @@ -0,0 +1,197 @@ +- name: Create Gitea LXC on cloud-pc + hosts: cloud-pc + gather_facts: false + vars: + gitea_vmid: 141 + gitea_hostname: gitea + gitea_ip: 192.168.1.25/24 + gitea_gateway: 192.168.1.1 + gitea_bridge: vmbr0 + gitea_rootfs: data:32 + gitea_host_data_dir: /opt/data/gitea + gitea_host_data_uid: 101000 + gitea_host_data_gid: 101000 + gitea_container_data_dir: /opt/gitea/data + gitea_ostemplate: local:vztmpl/debian-13-standard_13.1-2_amd64.tar.zst + gitea_pubkey_file: ~/.ssh/id_ed25519_homelab.pub + handlers: + - name: restart gitea lxc + ansible.builtin.shell: "pct stop {{ gitea_vmid }} || true; pct start {{ gitea_vmid }}" + changed_when: true + tasks: + - name: Check if Gitea LXC exists + ansible.builtin.command: "pct config {{ gitea_vmid }}" + register: gitea_pct_config + changed_when: false + failed_when: false + + - name: Install Gitea LXC SSH public key on PVE host + ansible.builtin.copy: + dest: /tmp/gitea-lxc.pub + owner: root + group: root + mode: "0600" + content: "{{ lookup('file', gitea_pubkey_file) }}\n" + when: gitea_pct_config.rc != 0 + + - name: Create Gitea LXC + ansible.builtin.command: >- + pct create {{ gitea_vmid }} {{ gitea_ostemplate }} + --hostname {{ gitea_hostname }} + --rootfs {{ gitea_rootfs }} + --cores 2 + --memory 2048 + --swap 1024 + --net0 name=eth0,bridge={{ gitea_bridge }},gw={{ gitea_gateway }},ip={{ gitea_ip }},firewall=1 + --nameserver 1.1.1.1 + --unprivileged 1 + --features nesting=1,keyctl=1 + --onboot 1 + --startup order=50 + --cmode shell + --ssh-public-keys /tmp/gitea-lxc.pub + when: gitea_pct_config.rc != 0 + + - name: Start Gitea LXC + ansible.builtin.command: "pct start {{ gitea_vmid }}" + register: gitea_pct_start + changed_when: gitea_pct_start.rc == 0 + failed_when: gitea_pct_start.rc not in [0, 255] + + - name: Allow FUSE device in Gitea LXC config + ansible.builtin.lineinfile: + path: "/etc/pve/lxc/{{ gitea_vmid }}.conf" + line: "lxc.cgroup2.devices.allow: c 10:229 rwm" + state: present + notify: restart gitea lxc + + - name: Bind mount FUSE device in Gitea LXC config + ansible.builtin.lineinfile: + path: "/etc/pve/lxc/{{ gitea_vmid }}.conf" + line: "lxc.mount.entry: /dev/fuse dev/fuse none bind,create=file" + state: present + notify: restart gitea lxc + + - name: Bind mount Gitea data directory in LXC config + ansible.builtin.lineinfile: + path: "/etc/pve/lxc/{{ gitea_vmid }}.conf" + line: "mp0: {{ gitea_host_data_dir }},mp={{ gitea_container_data_dir }}" + state: present + notify: restart gitea lxc + + - name: Ensure Gitea host data directory ownership matches unprivileged LXC uid map + ansible.builtin.file: + path: "{{ gitea_host_data_dir }}" + state: directory + owner: "{{ gitea_host_data_uid }}" + group: "{{ gitea_host_data_gid }}" + recurse: true + + - name: Apply pending LXC config changes + ansible.builtin.meta: flush_handlers + + - name: Wait for Gitea SSH through ru-vps + ansible.builtin.wait_for_connection: + timeout: 120 + delegate_to: gitea + vars: + ansible_become: false + +- name: Configure Docker and Gitea inside LXC + hosts: gitea + gather_facts: true + vars: + ansible_become: false + gitea_data_dir: /opt/gitea/data + gitea_image: gitea/gitea:latest + gitea_container_name: gitea + gitea_http_port: 3000 + gitea_ssh_port: 2222 + tasks: + - name: Install Docker packages + ansible.builtin.apt: + name: + - docker.io + - fuse-overlayfs + - sqlite3 + - rsync + - ca-certificates + - curl + state: present + update_cache: true + + - name: Ensure Docker config directory exists + ansible.builtin.file: + path: /etc/docker + state: directory + owner: root + group: root + mode: "0755" + + - name: Configure Docker storage driver for unprivileged LXC + ansible.builtin.copy: + dest: /etc/docker/daemon.json + owner: root + group: root + mode: "0644" + content: | + { + "storage-driver": "fuse-overlayfs" + } + register: docker_daemon_config + + - name: Ensure Docker service is enabled and running + ansible.builtin.systemd: + name: docker + state: "{{ 'restarted' if docker_daemon_config.changed else 'started' }}" + enabled: true + + - name: Ensure Gitea data directory has container ownership + ansible.builtin.file: + path: "{{ gitea_data_dir }}" + state: directory + owner: "1000" + group: "1000" + mode: "0750" + + - name: Install Gitea systemd unit + ansible.builtin.copy: + dest: /etc/systemd/system/gitea.service + owner: root + group: root + mode: "0644" + content: | + [Unit] + Description=Gitea container + After=docker.service + Requires=docker.service + + [Service] + Restart=always + RestartSec=10 + ExecStartPre=-/usr/bin/docker rm -f {{ gitea_container_name }} + ExecStart=/usr/bin/docker run --rm \ + --name {{ gitea_container_name }} \ + --pull always \ + -p {{ gitea_http_port }}:3000 \ + -p {{ gitea_ssh_port }}:22 \ + -v {{ gitea_data_dir }}:/data \ + -e USER_UID=1000 \ + -e USER_GID=1000 \ + {{ gitea_image }} + ExecStop=/usr/bin/docker stop {{ gitea_container_name }} + + [Install] + WantedBy=multi-user.target + register: gitea_unit + + - name: Reload systemd when Gitea unit changes + ansible.builtin.systemd: + daemon_reload: true + when: gitea_unit.changed + + - name: Enable and start Gitea + ansible.builtin.systemd: + name: gitea + state: started + enabled: true diff --git a/ansible/playbooks/pve-vaultwarden.yml b/ansible/playbooks/pve-vaultwarden.yml new file mode 100644 index 0000000..8351ec2 --- /dev/null +++ b/ansible/playbooks/pve-vaultwarden.yml @@ -0,0 +1,174 @@ +- name: Create Vaultwarden LXC on mini-pc + hosts: mini-pc + gather_facts: false + vars: + vaultwarden_vmid: 140 + vaultwarden_hostname: vaultwarden + vaultwarden_ip: 192.168.1.24/24 + vaultwarden_gateway: 192.168.1.1 + vaultwarden_bridge: vmbr0 + vaultwarden_rootfs: local-lvm:16 + vaultwarden_ostemplate: local:vztmpl/debian-13-standard_13.1-2_amd64.tar.zst + vaultwarden_pubkey_file: ~/.ssh/id_ed25519_homelab.pub + handlers: + - name: restart vaultwarden lxc + ansible.builtin.shell: "pct stop {{ vaultwarden_vmid }} || true; pct start {{ vaultwarden_vmid }}" + changed_when: true + tasks: + - name: Check if Vaultwarden LXC exists + ansible.builtin.command: "pct config {{ vaultwarden_vmid }}" + register: vaultwarden_pct_config + changed_when: false + failed_when: false + + - name: Install Vaultwarden LXC SSH public key on PVE host + ansible.builtin.copy: + dest: /tmp/vaultwarden-lxc.pub + owner: root + group: root + mode: "0600" + content: "{{ lookup('file', vaultwarden_pubkey_file) }}\n" + when: vaultwarden_pct_config.rc != 0 + + - name: Create Vaultwarden LXC + ansible.builtin.command: >- + pct create {{ vaultwarden_vmid }} {{ vaultwarden_ostemplate }} + --hostname {{ vaultwarden_hostname }} + --rootfs {{ vaultwarden_rootfs }} + --cores 2 + --memory 1024 + --swap 512 + --net0 name=eth0,bridge={{ vaultwarden_bridge }},gw={{ vaultwarden_gateway }},ip={{ vaultwarden_ip }},firewall=1 + --nameserver 1.1.1.1 + --unprivileged 1 + --features nesting=1,keyctl=1 + --onboot 1 + --startup order=40 + --cmode shell + --ssh-public-keys /tmp/vaultwarden-lxc.pub + when: vaultwarden_pct_config.rc != 0 + + - name: Start Vaultwarden LXC + ansible.builtin.command: "pct start {{ vaultwarden_vmid }}" + register: vaultwarden_pct_start + changed_when: vaultwarden_pct_start.rc == 0 + failed_when: vaultwarden_pct_start.rc not in [0, 255] + + - name: Allow FUSE device in Vaultwarden LXC config + ansible.builtin.lineinfile: + path: "/etc/pve/lxc/{{ vaultwarden_vmid }}.conf" + line: "lxc.cgroup2.devices.allow: c 10:229 rwm" + state: present + notify: restart vaultwarden lxc + + - name: Bind mount FUSE device in Vaultwarden LXC config + ansible.builtin.lineinfile: + path: "/etc/pve/lxc/{{ vaultwarden_vmid }}.conf" + line: "lxc.mount.entry: /dev/fuse dev/fuse none bind,create=file" + state: present + notify: restart vaultwarden lxc + + - name: Apply pending LXC config changes + ansible.builtin.meta: flush_handlers + + - name: Wait for Vaultwarden SSH through ru-vps + ansible.builtin.wait_for_connection: + timeout: 120 + delegate_to: vaultwarden + vars: + ansible_become: false + +- name: Configure Docker and Vaultwarden inside LXC + hosts: vaultwarden + gather_facts: true + vars: + ansible_become: false + vaultwarden_data_dir: /opt/vaultwarden/data + vaultwarden_image: vaultwarden/server:latest + vaultwarden_container_name: vaultwarden + vaultwarden_http_port: 80 + tasks: + - name: Install Docker packages + ansible.builtin.apt: + name: + - docker.io + - fuse-overlayfs + - sqlite3 + - ca-certificates + - curl + state: present + update_cache: true + + - name: Ensure Docker config directory exists + ansible.builtin.file: + path: /etc/docker + state: directory + owner: root + group: root + mode: "0755" + + - name: Configure Docker storage driver for unprivileged LXC + ansible.builtin.copy: + dest: /etc/docker/daemon.json + owner: root + group: root + mode: "0644" + content: | + { + "storage-driver": "fuse-overlayfs" + } + register: docker_daemon_config + + - name: Ensure Docker service is enabled and running + ansible.builtin.systemd: + name: docker + state: "{{ 'restarted' if docker_daemon_config.changed else 'started' }}" + enabled: true + + - name: Ensure Vaultwarden data directory exists + ansible.builtin.file: + path: "{{ vaultwarden_data_dir }}" + state: directory + owner: root + group: root + mode: "0750" + + - name: Install Vaultwarden systemd unit + ansible.builtin.copy: + dest: /etc/systemd/system/vaultwarden.service + owner: root + group: root + mode: "0644" + content: | + [Unit] + Description=Vaultwarden container + After=docker.service + Requires=docker.service + + [Service] + Restart=always + RestartSec=10 + ExecStartPre=-/usr/bin/docker rm -f {{ vaultwarden_container_name }} + ExecStart=/usr/bin/docker run --rm \ + --name {{ vaultwarden_container_name }} \ + --pull always \ + -p {{ vaultwarden_http_port }}:80 \ + -v {{ vaultwarden_data_dir }}:/data \ + -e WEBSOCKET_ENABLED=true \ + {{ vaultwarden_image }} + ExecStop=/usr/bin/docker stop {{ vaultwarden_container_name }} + + [Install] + WantedBy=multi-user.target + register: vaultwarden_unit + + - name: Reload systemd when Vaultwarden unit changes + ansible.builtin.systemd: + daemon_reload: true + when: vaultwarden_unit.changed + + - name: Enable and start Vaultwarden + ansible.builtin.systemd: + name: vaultwarden + state: started + enabled: true diff --git a/ansible/playbooks/pve-wg-mini.yml b/ansible/playbooks/pve-wg-mini.yml new file mode 100644 index 0000000..159007f --- /dev/null +++ b/ansible/playbooks/pve-wg-mini.yml @@ -0,0 +1,38 @@ +- name: Create wg-mini LXC on mini-pc + hosts: localhost + connection: local + gather_facts: false + roles: + - role: pve_lxc + vars: + pve_lxc_vmid: 132 + pve_lxc_node: mini-pc + pve_lxc_hostname: wg-mini + pve_lxc_ip: 192.168.1.23/24 + pve_lxc_gateway: 192.168.1.1 + pve_lxc_storage: local-lvm + pve_lxc_disk: local-lvm:8 + pve_lxc_ostemplate: "{{ lookup('env', 'PVE_LXC_OSTEMPLATE') | default('local:vztmpl/debian-13-standard_13.1-2_amd64.tar.zst', true) }}" + +- name: Allow TUN device in wg-mini LXC config + hosts: mini-pc + gather_facts: false + become: true + handlers: + - name: restart wg-mini lxc + ansible.builtin.shell: pct stop 132 || true; pct start 132 + changed_when: true + tasks: + - name: Allow /dev/net/tun device + ansible.builtin.lineinfile: + path: /etc/pve/lxc/132.conf + line: "lxc.cgroup2.devices.allow: c 10:200 rwm" + state: present + notify: restart wg-mini lxc + + - name: Bind mount /dev/net/tun + ansible.builtin.lineinfile: + path: /etc/pve/lxc/132.conf + line: "lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file" + state: present + notify: restart wg-mini lxc diff --git a/ansible/playbooks/reverse-proxy-gitea.yml b/ansible/playbooks/reverse-proxy-gitea.yml new file mode 100644 index 0000000..59eb559 --- /dev/null +++ b/ansible/playbooks/reverse-proxy-gitea.yml @@ -0,0 +1,65 @@ +- name: Configure Gitea reverse proxy on ru-vps + hosts: ru-vps + gather_facts: false + vars: + caddy_dir: /opt/services/ru-vps/caddy + caddyfile_path: /opt/services/ru-vps/caddy/Caddyfile + gitea_domain: git.ada-dev.ru + gitea_upstream: 192.168.1.25:3000 + + tasks: + - name: Ensure Caddy service directory exists + ansible.builtin.file: + path: "{{ caddy_dir }}" + state: directory + owner: root + group: root + mode: "0755" + + - name: Configure Gitea Caddy site + ansible.builtin.blockinfile: + path: "{{ caddyfile_path }}" + create: true + owner: root + group: root + mode: "0644" + marker: "# {mark} ANSIBLE MANAGED GITEA SITE" + block: | + {{ gitea_domain }} { + reverse_proxy {{ gitea_upstream }} + } + register: gitea_caddy_site + + - name: Remove legacy unmanaged Gitea Caddy site + ansible.builtin.replace: + path: "{{ caddyfile_path }}" + regexp: '(?ms)^git\.ada-dev\.ru \{\n\s*reverse_proxy 10\.122\.62\.51:3002\n\}\n+' + replace: '' + register: gitea_legacy_site + + - name: Validate host Caddy config + ansible.builtin.command: caddy validate --config {{ caddyfile_path }} + changed_when: false + + - name: Check Caddy container mounted config + ansible.builtin.command: docker exec caddy grep -F 'reverse_proxy {{ gitea_upstream }}' /etc/caddy/Caddyfile + register: gitea_container_caddyfile + changed_when: false + failed_when: false + + - name: Restart Caddy when config changed or bind mount is stale + ansible.builtin.command: docker restart caddy + when: >- + gitea_caddy_site.changed or + gitea_legacy_site.changed or + gitea_container_caddyfile.rc != 0 + + - name: Validate Caddy container config after restart + ansible.builtin.command: docker exec caddy caddy validate --config /etc/caddy/Caddyfile + changed_when: false + + - name: Check Gitea upstream from ru-vps + ansible.builtin.command: curl -fsS -o /dev/null -w '%{http_code}' http://{{ gitea_upstream }}/ + register: gitea_upstream_http + changed_when: false + failed_when: gitea_upstream_http.stdout != '200' diff --git a/ansible/playbooks/reverse-proxy-vaultwarden.yml b/ansible/playbooks/reverse-proxy-vaultwarden.yml new file mode 100644 index 0000000..726d822 --- /dev/null +++ b/ansible/playbooks/reverse-proxy-vaultwarden.yml @@ -0,0 +1,65 @@ +- name: Configure Vaultwarden reverse proxy on ru-vps + hosts: ru-vps + gather_facts: false + vars: + caddy_dir: /opt/services/ru-vps/caddy + caddyfile_path: /opt/services/ru-vps/caddy/Caddyfile + vaultwarden_domain: pass.ada-dev.ru + vaultwarden_upstream: 192.168.1.24:80 + + tasks: + - name: Ensure Caddy service directory exists + ansible.builtin.file: + path: "{{ caddy_dir }}" + state: directory + owner: root + group: root + mode: "0755" + + - name: Configure Vaultwarden Caddy site + ansible.builtin.blockinfile: + path: "{{ caddyfile_path }}" + create: true + owner: root + group: root + mode: "0644" + marker: "# {mark} ANSIBLE MANAGED VAULTWARDEN SITE" + block: | + {{ vaultwarden_domain }} { + reverse_proxy {{ vaultwarden_upstream }} + } + register: vaultwarden_caddy_site + + - name: Remove legacy unmanaged Vaultwarden Caddy site + ansible.builtin.replace: + path: "{{ caddyfile_path }}" + regexp: '(?ms)^pass\.ada-dev\.ru \{\n\s*reverse_proxy 10\.122\.62\.95:10380\n\}\n+' + replace: '' + register: vaultwarden_legacy_site + + - name: Validate host Caddy config + ansible.builtin.command: caddy validate --config {{ caddyfile_path }} + changed_when: false + + - name: Check Caddy container mounted config + ansible.builtin.command: docker exec caddy grep -F 'reverse_proxy {{ vaultwarden_upstream }}' /etc/caddy/Caddyfile + register: vaultwarden_container_caddyfile + changed_when: false + failed_when: false + + - name: Restart Caddy when config changed or bind mount is stale + ansible.builtin.command: docker restart caddy + when: >- + vaultwarden_caddy_site.changed or + vaultwarden_legacy_site.changed or + vaultwarden_container_caddyfile.rc != 0 + + - name: Validate Caddy container config after restart + ansible.builtin.command: docker exec caddy caddy validate --config /etc/caddy/Caddyfile + changed_when: false + + - name: Check Vaultwarden upstream from ru-vps + ansible.builtin.command: curl -fsS -o /dev/null -w '%{http_code}' http://{{ vaultwarden_upstream }}/ + register: vaultwarden_upstream_http + changed_when: false + failed_when: vaultwarden_upstream_http.stdout != '200' diff --git a/ansible/requirements.txt b/ansible/requirements.txt new file mode 100644 index 0000000..2840088 --- /dev/null +++ b/ansible/requirements.txt @@ -0,0 +1,3 @@ +ansible-core>=2.19 +proxmoxer>=2.3 +requests>=2.31 diff --git a/ansible/requirements.yml b/ansible/requirements.yml new file mode 100644 index 0000000..ee30ab1 --- /dev/null +++ b/ansible/requirements.yml @@ -0,0 +1,6 @@ +--- +collections: + - name: ansible.posix + version: ">=2.0.0" + - name: community.proxmox + version: ">=2.0.0" diff --git a/ru-vps/mihomo/config/ui/.nojekyll b/ansible/roles/.gitkeep similarity index 100% rename from ru-vps/mihomo/config/ui/.nojekyll rename to ansible/roles/.gitkeep diff --git a/ansible/roles/bash_config/defaults/main.yml b/ansible/roles/bash_config/defaults/main.yml new file mode 100644 index 0000000..1a35b20 --- /dev/null +++ b/ansible/roles/bash_config/defaults/main.yml @@ -0,0 +1,7 @@ +--- +bash_config_file: /etc/profile.d/homelab.sh +bash_config_bashrc: /etc/bash.bashrc +bash_config_legacy_user: ada +bash_config_legacy_home: "/home/{{ bash_config_legacy_user }}" +bash_config_legacy_profile_files: + - /etc/profile.d/custom_bash.sh diff --git a/ansible/roles/bash_config/tasks/main.yml b/ansible/roles/bash_config/tasks/main.yml new file mode 100644 index 0000000..86344cf --- /dev/null +++ b/ansible/roles/bash_config/tasks/main.yml @@ -0,0 +1,63 @@ +- name: Install unified HomeLab bash config + ansible.builtin.template: + src: homelab.sh.j2 + dest: "{{ bash_config_file }}" + owner: root + group: root + mode: "0644" + +- name: Ensure system bashrc sources managed config + ansible.builtin.blockinfile: + path: "{{ bash_config_bashrc }}" + create: true + owner: root + group: root + mode: "0644" + marker: "# {mark} ANSIBLE MANAGED HOMELAB BASH CONFIG" + block: | + if [ -f /etc/profile.d/homelab.sh ]; then + . /etc/profile.d/homelab.sh + fi + +- name: List bash users with local home directories + ansible.builtin.shell: >- + getent passwd | awk -F: '$7 ~ /\/bash$/ && $6 ~ /^\// { print $1 ":" $6 }' + register: bash_config_bash_users_raw + changed_when: false + +- name: Ensure bash users source managed system config + ansible.builtin.blockinfile: + path: "{{ item.split(':')[1] }}/.bashrc" + create: true + owner: "{{ item.split(':')[0] }}" + group: "{{ item.split(':')[0] }}" + mode: "0644" + marker: "# {mark} ANSIBLE MANAGED HOMELAB SYSTEM BASH CONFIG" + block: | + if [ -f /etc/profile.d/homelab.sh ]; then + . /etc/profile.d/homelab.sh + fi + loop: "{{ bash_config_bash_users_raw.stdout_lines }}" + +- name: Check legacy per-user bashrc + ansible.builtin.stat: + path: "{{ bash_config_legacy_home }}/.bashrc" + register: bash_config_legacy_bashrc + +- name: Remove legacy per-user bashrc source block + ansible.builtin.blockinfile: + path: "{{ bash_config_legacy_home }}/.bashrc" + marker: "# {mark} ANSIBLE MANAGED HOMELAB BASH CONFIG" + state: absent + when: bash_config_legacy_bashrc.stat.exists + +- name: Remove legacy per-user bash config file + ansible.builtin.file: + path: "{{ bash_config_legacy_home }}/.bashrc.d/homelab.sh" + state: absent + +- name: Remove legacy profile scripts that conflict with unified config + ansible.builtin.file: + path: "{{ item }}" + state: absent + loop: "{{ bash_config_legacy_profile_files }}" diff --git a/ansible/roles/bash_config/templates/homelab.sh.j2 b/ansible/roles/bash_config/templates/homelab.sh.j2 new file mode 100644 index 0000000..1cad202 --- /dev/null +++ b/ansible/roles/bash_config/templates/homelab.sh.j2 @@ -0,0 +1,44 @@ +# Managed by Ansible: HomeLab unified bash config. + +export EDITOR="${EDITOR:-vim}" +export PAGER="${PAGER:-less}" +export LESS="${LESS:--FRSX}" +export HISTCONTROL="ignoreboth:erasedups" +export HISTSIZE=50000 +export HISTFILESIZE=100000 +shopt -s histappend 2>/dev/null || true +shopt -s checkwinsize 2>/dev/null || true + +case ":$PATH:" in + *":$HOME/.local/bin:"*) ;; + *) export PATH="$HOME/.local/bin:$PATH" ;; +esac + +alias ll='ls -alF' +alias la='ls -A' +alias l='ls -CF' +alias grep='grep --color=auto' +alias ip='ip --color=auto' +alias df='df -h' +alias du='du -h' +alias free='free -h' +alias ..='cd ..' +alias ...='cd ../..' +alias please='sudo $(history -p !!)' + +alias gs='git status --short --branch' +alias gd='git diff' +alias gl='git log --oneline --decorate -10' + +if command -v systemctl >/dev/null 2>&1; then + alias sctl='systemctl' + alias jctl='journalctl' +fi + +if [ -n "$PS1" ]; then + if [ "$(id -u)" -eq 0 ]; then + PS1='\[\e[31m\]\u@\h\[\e[0m\]:\[\e[34m\]\w\[\e[0m\]# ' + else + PS1='\[\e[32m\]\u@\h\[\e[0m\]:\[\e[34m\]\w\[\e[0m\]\$ ' + fi +fi diff --git a/ansible/roles/openvpn_gateway/defaults/main.yml b/ansible/roles/openvpn_gateway/defaults/main.yml new file mode 100644 index 0000000..b4d3898 --- /dev/null +++ b/ansible/roles/openvpn_gateway/defaults/main.yml @@ -0,0 +1,22 @@ +--- +openvpn_interface: tun0 +openvpn_listen_port: 8443 +openvpn_proto_server: tcp-server +openvpn_proto_client: tcp-client +openvpn_config_dir: /etc/openvpn/homelab +openvpn_config_path: /etc/openvpn/homelab/homelab.conf +openvpn_static_key_path: /etc/openvpn/homelab/static.key +openvpn_service_name: homelab-openvpn +openvpn_home_routes: + - network: 192.168.1.5 + netmask: 255.255.255.255 + - network: 192.168.1.6 + netmask: 255.255.255.254 + - network: 192.168.1.8 + netmask: 255.255.255.248 + - network: 192.168.1.16 + netmask: 255.255.255.240 + - network: 192.168.1.32 + netmask: 255.255.255.248 + - network: 192.168.1.40 + netmask: 255.255.255.255 diff --git a/ansible/roles/openvpn_gateway/handlers/main.yml b/ansible/roles/openvpn_gateway/handlers/main.yml new file mode 100644 index 0000000..316c2f2 --- /dev/null +++ b/ansible/roles/openvpn_gateway/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: restart openvpn + ansible.builtin.systemd: + name: "{{ openvpn_service_name }}" + state: restarted + enabled: true diff --git a/ansible/roles/openvpn_gateway/tasks/main.yml b/ansible/roles/openvpn_gateway/tasks/main.yml new file mode 100644 index 0000000..b10bdef --- /dev/null +++ b/ansible/roles/openvpn_gateway/tasks/main.yml @@ -0,0 +1,105 @@ +--- +- name: Install OpenVPN packages + ansible.builtin.apt: + name: + - openvpn + - iptables + - iproute2 + - netcat-openbsd + state: present + update_cache: true + +- name: Ensure OpenVPN config directory exists + ansible.builtin.file: + path: "{{ openvpn_config_dir }}" + state: directory + owner: root + group: root + mode: "0700" + +- name: Generate static key on server if missing + ansible.builtin.command: "openvpn --genkey secret {{ openvpn_static_key_path }}" + args: + creates: "{{ openvpn_static_key_path }}" + when: openvpn_role == 'server' + no_log: true + +- name: Read static key from server + ansible.builtin.slurp: + src: "{{ openvpn_static_key_path }}" + register: openvpn_static_key_raw + when: openvpn_role == 'server' + no_log: true + +- name: Copy static key to all peers + ansible.builtin.copy: + dest: "{{ openvpn_static_key_path }}" + content: "{{ hostvars['ru-vps'].openvpn_static_key_raw.content | b64decode }}" + owner: root + group: root + mode: "0600" + no_log: true + notify: restart openvpn + +- name: Enable IPv4 forwarding on gateway + ansible.posix.sysctl: + name: net.ipv4.ip_forward + value: "1" + state: present + reload: true + when: openvpn_role == 'gateway' + +- name: Allow OpenVPN TCP in UFW on server + ansible.builtin.command: "ufw allow {{ openvpn_listen_port }}/tcp" + register: ufw_allow_openvpn + changed_when: "'Rule added' in ufw_allow_openvpn.stdout or 'Rules updated' in ufw_allow_openvpn.stdout" + failed_when: false + when: openvpn_role == 'server' + +- name: Render OpenVPN config + ansible.builtin.template: + src: homelab.conf.j2 + dest: "{{ openvpn_config_path }}" + owner: root + group: root + mode: "0600" + notify: restart openvpn + +- name: Render OpenVPN gateway up script + ansible.builtin.template: + src: up.sh.j2 + dest: "{{ openvpn_config_dir }}/up.sh" + owner: root + group: root + mode: "0700" + notify: restart openvpn + when: openvpn_role == 'gateway' + +- name: Render OpenVPN gateway down script + ansible.builtin.template: + src: down.sh.j2 + dest: "{{ openvpn_config_dir }}/down.sh" + owner: root + group: root + mode: "0700" + notify: restart openvpn + when: openvpn_role == 'gateway' + +- name: Render OpenVPN systemd service + ansible.builtin.template: + src: homelab-openvpn.service.j2 + dest: "/etc/systemd/system/{{ openvpn_service_name }}.service" + owner: root + group: root + mode: "0644" + notify: restart openvpn + +- name: Reload systemd + ansible.builtin.systemd: + daemon_reload: true + +- name: Enable and start OpenVPN + ansible.builtin.systemd: + name: "{{ openvpn_service_name }}" + state: started + enabled: true diff --git a/ansible/roles/openvpn_gateway/templates/down.sh.j2 b/ansible/roles/openvpn_gateway/templates/down.sh.j2 new file mode 100644 index 0000000..b2a70ea --- /dev/null +++ b/ansible/roles/openvpn_gateway/templates/down.sh.j2 @@ -0,0 +1,2 @@ +#!/bin/sh +iptables -t nat -D POSTROUTING -s {{ openvpn_network_cidr }} -d {{ homelab_lan_cidr }} -o eth0 -j MASQUERADE 2>/dev/null || true diff --git a/ansible/roles/openvpn_gateway/templates/homelab-openvpn.service.j2 b/ansible/roles/openvpn_gateway/templates/homelab-openvpn.service.j2 new file mode 100644 index 0000000..5e71b0f --- /dev/null +++ b/ansible/roles/openvpn_gateway/templates/homelab-openvpn.service.j2 @@ -0,0 +1,13 @@ +[Unit] +Description=HomeLab OpenVPN {{ openvpn_role }} +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +ExecStart=/usr/sbin/openvpn --config {{ openvpn_config_path }} +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target diff --git a/ansible/roles/openvpn_gateway/templates/homelab.conf.j2 b/ansible/roles/openvpn_gateway/templates/homelab.conf.j2 new file mode 100644 index 0000000..5953d02 --- /dev/null +++ b/ansible/roles/openvpn_gateway/templates/homelab.conf.j2 @@ -0,0 +1,26 @@ +dev {{ openvpn_interface }} +ifconfig {{ openvpn_local_ip }} {{ openvpn_peer_ip }} +secret {{ openvpn_static_key_path }} +cipher AES-256-CBC +auth SHA256 +persist-key +persist-tun +verb 3 +keepalive 10 60 +{% if openvpn_role == 'server' %} +proto {{ openvpn_proto_server }} +port {{ openvpn_listen_port }} +{% for route in openvpn_home_routes %} +route {{ route.network }} {{ route.netmask }} +{% endfor %} +{% endif %} +{% if openvpn_role == 'gateway' %} +proto {{ openvpn_proto_client }} +remote 157.22.231.198 {{ openvpn_listen_port }} +resolv-retry infinite +nobind +route-nopull +script-security 2 +up /etc/openvpn/homelab/up.sh +down /etc/openvpn/homelab/down.sh +{% endif %} diff --git a/ansible/roles/openvpn_gateway/templates/up.sh.j2 b/ansible/roles/openvpn_gateway/templates/up.sh.j2 new file mode 100644 index 0000000..4a42c11 --- /dev/null +++ b/ansible/roles/openvpn_gateway/templates/up.sh.j2 @@ -0,0 +1,3 @@ +#!/bin/sh +iptables -t nat -C POSTROUTING -s {{ openvpn_network_cidr }} -d {{ homelab_lan_cidr }} -o eth0 -j MASQUERADE 2>/dev/null || \ + iptables -t nat -A POSTROUTING -s {{ openvpn_network_cidr }} -d {{ homelab_lan_cidr }} -o eth0 -j MASQUERADE diff --git a/ansible/roles/pve_lxc/defaults/main.yml b/ansible/roles/pve_lxc/defaults/main.yml new file mode 100644 index 0000000..8d08d7a --- /dev/null +++ b/ansible/roles/pve_lxc/defaults/main.yml @@ -0,0 +1,20 @@ +--- +pve_lxc_vmid: 132 +pve_lxc_node: mini-pc +pve_lxc_hostname: wg-mini +pve_lxc_ip: 192.168.1.23/24 +pve_lxc_gateway: 192.168.1.1 +pve_lxc_bridge: vmbr0 +pve_lxc_storage: local-lvm +pve_lxc_disk: local-lvm:8 +pve_lxc_cores: 1 +pve_lxc_memory: 256 +pve_lxc_swap: 128 +pve_lxc_onboot: true +pve_lxc_startup: order=30 +pve_lxc_unprivileged: true +pve_lxc_features: + - nesting=1 +pve_lxc_nameserver: 1.1.1.1 +pve_lxc_pubkey_file: ~/.ssh/id_ed25519_homelab.pub +pve_lxc_cmode: shell diff --git a/ansible/roles/pve_lxc/tasks/main.yml b/ansible/roles/pve_lxc/tasks/main.yml new file mode 100644 index 0000000..82a7d4f --- /dev/null +++ b/ansible/roles/pve_lxc/tasks/main.yml @@ -0,0 +1,46 @@ +--- +- name: Validate Proxmox API environment + ansible.builtin.assert: + that: + - lookup('env', 'PROXMOX_HOST') | length > 0 + - lookup('env', 'PROXMOX_USER') | length > 0 + - lookup('env', 'PROXMOX_TOKEN_ID') | length > 0 + - lookup('env', 'PROXMOX_TOKEN_SECRET') | length > 0 + fail_msg: Load ansible/.env with PROXMOX_HOST, PROXMOX_USER, PROXMOX_TOKEN_ID and PROXMOX_TOKEN_SECRET. + +- name: Create or update LXC container + community.proxmox.proxmox: + api_host: "{{ lookup('env', 'PROXMOX_HOST') }}" + api_user: "{{ lookup('env', 'PROXMOX_USER') }}" + api_token_id: "{{ lookup('env', 'PROXMOX_TOKEN_ID') }}" + api_token_secret: "{{ lookup('env', 'PROXMOX_TOKEN_SECRET') }}" + validate_certs: "{{ lookup('env', 'PROXMOX_VALIDATE_CERTS') | default('false', true) | bool }}" + vmid: "{{ pve_lxc_vmid }}" + node: "{{ pve_lxc_node }}" + hostname: "{{ pve_lxc_hostname }}" + ostemplate: "{{ pve_lxc_ostemplate }}" + disk: "{{ pve_lxc_disk }}" + cores: "{{ pve_lxc_cores }}" + memory: "{{ pve_lxc_memory }}" + swap: "{{ pve_lxc_swap }}" + nameserver: "{{ pve_lxc_nameserver }}" + cmode: "{{ pve_lxc_cmode }}" + netif: + net0: "name=eth0,gw={{ pve_lxc_gateway }},ip={{ pve_lxc_ip }},bridge={{ pve_lxc_bridge }},firewall=1" + pubkey: "{{ lookup('file', pve_lxc_pubkey_file) }}" + features: "{{ pve_lxc_features }}" + unprivileged: "{{ pve_lxc_unprivileged }}" + onboot: "{{ pve_lxc_onboot }}" + startup: "{{ pve_lxc_startup }}" + update: true + state: present + +- name: Start LXC container + community.proxmox.proxmox: + api_host: "{{ lookup('env', 'PROXMOX_HOST') }}" + api_user: "{{ lookup('env', 'PROXMOX_USER') }}" + api_token_id: "{{ lookup('env', 'PROXMOX_TOKEN_ID') }}" + api_token_secret: "{{ lookup('env', 'PROXMOX_TOKEN_SECRET') }}" + validate_certs: "{{ lookup('env', 'PROXMOX_VALIDATE_CERTS') | default('false', true) | bool }}" + vmid: "{{ pve_lxc_vmid }}" + state: started diff --git a/.gitea/workflows/deploy-cloud-pc.yml b/archive/2026-07-proxmox-migration/.gitea/workflows/deploy-cloud-pc.yml similarity index 100% rename from .gitea/workflows/deploy-cloud-pc.yml rename to archive/2026-07-proxmox-migration/.gitea/workflows/deploy-cloud-pc.yml diff --git a/.gitea/workflows/deploy-mini-pc.yml b/archive/2026-07-proxmox-migration/.gitea/workflows/deploy-mini-pc.yml similarity index 100% rename from .gitea/workflows/deploy-mini-pc.yml rename to archive/2026-07-proxmox-migration/.gitea/workflows/deploy-mini-pc.yml diff --git a/.gitea/workflows/deploy-ru-vps.yml b/archive/2026-07-proxmox-migration/.gitea/workflows/deploy-ru-vps.yml similarity index 100% rename from .gitea/workflows/deploy-ru-vps.yml rename to archive/2026-07-proxmox-migration/.gitea/workflows/deploy-ru-vps.yml diff --git a/.gitea/workflows/nixos-switch-cloud-pc.yml b/archive/2026-07-proxmox-migration/.gitea/workflows/nixos-switch-cloud-pc.yml similarity index 100% rename from .gitea/workflows/nixos-switch-cloud-pc.yml rename to archive/2026-07-proxmox-migration/.gitea/workflows/nixos-switch-cloud-pc.yml diff --git a/.gitea/workflows/nixos-switch-mini-pc.yml b/archive/2026-07-proxmox-migration/.gitea/workflows/nixos-switch-mini-pc.yml similarity index 100% rename from .gitea/workflows/nixos-switch-mini-pc.yml rename to archive/2026-07-proxmox-migration/.gitea/workflows/nixos-switch-mini-pc.yml diff --git a/archive/2026-07-proxmox-migration/README.md b/archive/2026-07-proxmox-migration/README.md new file mode 100644 index 0000000..6600072 --- /dev/null +++ b/archive/2026-07-proxmox-migration/README.md @@ -0,0 +1,13 @@ +# Archive: 2026-07 Proxmox Migration + +Historical configuration from the pre-Proxmox HomeLab setup. + +Moved here: + +- `nixos/` — old NixOS host configs and modules. +- `cloud-pc/`, `mini-pc/`, `ru-vps/` — old Docker Compose service trees. +- `.gitea/` — old GitOps workflows. +- `scripts/` — old deploy scripts. +- `legacy-ansible/` — old bootstrap/base/dirs/restic/rclone playbooks and bootstrap role. + +Use these files only as reference when implementing new Ansible roles/playbooks. diff --git a/cloud-pc/ada-dev.ru/docker-compose.yml b/archive/2026-07-proxmox-migration/cloud-pc/ada-dev.ru/docker-compose.yml similarity index 100% rename from cloud-pc/ada-dev.ru/docker-compose.yml rename to archive/2026-07-proxmox-migration/cloud-pc/ada-dev.ru/docker-compose.yml diff --git a/cloud-pc/gitea-runner/Dockerfile b/archive/2026-07-proxmox-migration/cloud-pc/gitea-runner/Dockerfile similarity index 100% rename from cloud-pc/gitea-runner/Dockerfile rename to archive/2026-07-proxmox-migration/cloud-pc/gitea-runner/Dockerfile diff --git a/cloud-pc/gitea-runner/docker-compose.yml b/archive/2026-07-proxmox-migration/cloud-pc/gitea-runner/docker-compose.yml similarity index 100% rename from cloud-pc/gitea-runner/docker-compose.yml rename to archive/2026-07-proxmox-migration/cloud-pc/gitea-runner/docker-compose.yml diff --git a/cloud-pc/gitea/docker-compose.yml b/archive/2026-07-proxmox-migration/cloud-pc/gitea/docker-compose.yml similarity index 100% rename from cloud-pc/gitea/docker-compose.yml rename to archive/2026-07-proxmox-migration/cloud-pc/gitea/docker-compose.yml diff --git a/cloud-pc/neural_miad/docker-compose.yml b/archive/2026-07-proxmox-migration/cloud-pc/neural_miad/docker-compose.yml similarity index 100% rename from cloud-pc/neural_miad/docker-compose.yml rename to archive/2026-07-proxmox-migration/cloud-pc/neural_miad/docker-compose.yml diff --git a/cloud-pc/nextcloud/docker-compose.yml b/archive/2026-07-proxmox-migration/cloud-pc/nextcloud/docker-compose.yml similarity index 100% rename from cloud-pc/nextcloud/docker-compose.yml rename to archive/2026-07-proxmox-migration/cloud-pc/nextcloud/docker-compose.yml diff --git a/cloud-pc/resticprofile/profiles.toml b/archive/2026-07-proxmox-migration/cloud-pc/resticprofile/profiles.toml similarity index 100% rename from cloud-pc/resticprofile/profiles.toml rename to archive/2026-07-proxmox-migration/cloud-pc/resticprofile/profiles.toml diff --git a/cloud-pc/samba/.env.example b/archive/2026-07-proxmox-migration/cloud-pc/samba/.env.example similarity index 100% rename from cloud-pc/samba/.env.example rename to archive/2026-07-proxmox-migration/cloud-pc/samba/.env.example diff --git a/cloud-pc/samba/docker-compose.yml b/archive/2026-07-proxmox-migration/cloud-pc/samba/docker-compose.yml similarity index 100% rename from cloud-pc/samba/docker-compose.yml rename to archive/2026-07-proxmox-migration/cloud-pc/samba/docker-compose.yml diff --git a/cloud-pc/syncthing/!docker-compose.yml b/archive/2026-07-proxmox-migration/cloud-pc/syncthing/!docker-compose.yml similarity index 100% rename from cloud-pc/syncthing/!docker-compose.yml rename to archive/2026-07-proxmox-migration/cloud-pc/syncthing/!docker-compose.yml diff --git a/cloud-pc/zerotier/docker-compose.yml b/archive/2026-07-proxmox-migration/cloud-pc/zerotier/docker-compose.yml similarity index 100% rename from cloud-pc/zerotier/docker-compose.yml rename to archive/2026-07-proxmox-migration/cloud-pc/zerotier/docker-compose.yml diff --git a/ansible/playbooks/base.yml b/archive/2026-07-proxmox-migration/legacy-ansible/playbooks/base.yml similarity index 100% rename from ansible/playbooks/base.yml rename to archive/2026-07-proxmox-migration/legacy-ansible/playbooks/base.yml diff --git a/ansible/playbooks/bootstrap.yml b/archive/2026-07-proxmox-migration/legacy-ansible/playbooks/bootstrap.yml similarity index 100% rename from ansible/playbooks/bootstrap.yml rename to archive/2026-07-proxmox-migration/legacy-ansible/playbooks/bootstrap.yml diff --git a/ansible/playbooks/dirs.yml b/archive/2026-07-proxmox-migration/legacy-ansible/playbooks/dirs.yml similarity index 100% rename from ansible/playbooks/dirs.yml rename to archive/2026-07-proxmox-migration/legacy-ansible/playbooks/dirs.yml diff --git a/ansible/playbooks/rclone.yml b/archive/2026-07-proxmox-migration/legacy-ansible/playbooks/rclone.yml similarity index 100% rename from ansible/playbooks/rclone.yml rename to archive/2026-07-proxmox-migration/legacy-ansible/playbooks/rclone.yml diff --git a/ansible/playbooks/resticprofile.yml b/archive/2026-07-proxmox-migration/legacy-ansible/playbooks/resticprofile.yml similarity index 100% rename from ansible/playbooks/resticprofile.yml rename to archive/2026-07-proxmox-migration/legacy-ansible/playbooks/resticprofile.yml diff --git a/ansible/roles/bootstrap/defaults/main.yml b/archive/2026-07-proxmox-migration/legacy-ansible/roles/bootstrap/defaults/main.yml similarity index 100% rename from ansible/roles/bootstrap/defaults/main.yml rename to archive/2026-07-proxmox-migration/legacy-ansible/roles/bootstrap/defaults/main.yml diff --git a/ansible/roles/bootstrap/handlers/main.yml b/archive/2026-07-proxmox-migration/legacy-ansible/roles/bootstrap/handlers/main.yml similarity index 100% rename from ansible/roles/bootstrap/handlers/main.yml rename to archive/2026-07-proxmox-migration/legacy-ansible/roles/bootstrap/handlers/main.yml diff --git a/ansible/roles/bootstrap/tasks/main.yml b/archive/2026-07-proxmox-migration/legacy-ansible/roles/bootstrap/tasks/main.yml similarity index 100% rename from ansible/roles/bootstrap/tasks/main.yml rename to archive/2026-07-proxmox-migration/legacy-ansible/roles/bootstrap/tasks/main.yml diff --git a/mini-pc/adguard/docker-compose.yml b/archive/2026-07-proxmox-migration/mini-pc/adguard/docker-compose.yml similarity index 100% rename from mini-pc/adguard/docker-compose.yml rename to archive/2026-07-proxmox-migration/mini-pc/adguard/docker-compose.yml diff --git a/mini-pc/caddy/.env.example b/archive/2026-07-proxmox-migration/mini-pc/caddy/.env.example similarity index 100% rename from mini-pc/caddy/.env.example rename to archive/2026-07-proxmox-migration/mini-pc/caddy/.env.example diff --git a/mini-pc/caddy/Caddyfile b/archive/2026-07-proxmox-migration/mini-pc/caddy/Caddyfile similarity index 100% rename from mini-pc/caddy/Caddyfile rename to archive/2026-07-proxmox-migration/mini-pc/caddy/Caddyfile diff --git a/mini-pc/caddy/docker-compose.yml b/archive/2026-07-proxmox-migration/mini-pc/caddy/docker-compose.yml similarity index 100% rename from mini-pc/caddy/docker-compose.yml rename to archive/2026-07-proxmox-migration/mini-pc/caddy/docker-compose.yml diff --git a/mini-pc/gitea-runner/Dockerfile b/archive/2026-07-proxmox-migration/mini-pc/gitea-runner/Dockerfile similarity index 100% rename from mini-pc/gitea-runner/Dockerfile rename to archive/2026-07-proxmox-migration/mini-pc/gitea-runner/Dockerfile diff --git a/mini-pc/gitea-runner/docker-compose.yml b/archive/2026-07-proxmox-migration/mini-pc/gitea-runner/docker-compose.yml similarity index 100% rename from mini-pc/gitea-runner/docker-compose.yml rename to archive/2026-07-proxmox-migration/mini-pc/gitea-runner/docker-compose.yml diff --git a/mini-pc/memoir_bot/docker-compose.yml b/archive/2026-07-proxmox-migration/mini-pc/memoir_bot/docker-compose.yml similarity index 100% rename from mini-pc/memoir_bot/docker-compose.yml rename to archive/2026-07-proxmox-migration/mini-pc/memoir_bot/docker-compose.yml diff --git a/mini-pc/resticprofile/profiles.toml b/archive/2026-07-proxmox-migration/mini-pc/resticprofile/profiles.toml similarity index 100% rename from mini-pc/resticprofile/profiles.toml rename to archive/2026-07-proxmox-migration/mini-pc/resticprofile/profiles.toml diff --git a/mini-pc/uptime-kuma/docker-compose.yml b/archive/2026-07-proxmox-migration/mini-pc/uptime-kuma/docker-compose.yml similarity index 100% rename from mini-pc/uptime-kuma/docker-compose.yml rename to archive/2026-07-proxmox-migration/mini-pc/uptime-kuma/docker-compose.yml diff --git a/mini-pc/v2raya/docker-compose.yml b/archive/2026-07-proxmox-migration/mini-pc/v2raya/docker-compose.yml similarity index 100% rename from mini-pc/v2raya/docker-compose.yml rename to archive/2026-07-proxmox-migration/mini-pc/v2raya/docker-compose.yml diff --git a/mini-pc/vaultwarden/.env.example b/archive/2026-07-proxmox-migration/mini-pc/vaultwarden/.env.example similarity index 100% rename from mini-pc/vaultwarden/.env.example rename to archive/2026-07-proxmox-migration/mini-pc/vaultwarden/.env.example diff --git a/mini-pc/vaultwarden/docker-compose.yml b/archive/2026-07-proxmox-migration/mini-pc/vaultwarden/docker-compose.yml similarity index 100% rename from mini-pc/vaultwarden/docker-compose.yml rename to archive/2026-07-proxmox-migration/mini-pc/vaultwarden/docker-compose.yml diff --git a/mini-pc/zerotier/docker-compose.yml b/archive/2026-07-proxmox-migration/mini-pc/zerotier/docker-compose.yml similarity index 100% rename from mini-pc/zerotier/docker-compose.yml rename to archive/2026-07-proxmox-migration/mini-pc/zerotier/docker-compose.yml diff --git a/nixos/flake.nix b/archive/2026-07-proxmox-migration/nixos/flake.nix similarity index 100% rename from nixos/flake.nix rename to archive/2026-07-proxmox-migration/nixos/flake.nix diff --git a/nixos/hosts/cloud-pc/default.nix b/archive/2026-07-proxmox-migration/nixos/hosts/cloud-pc/default.nix similarity index 100% rename from nixos/hosts/cloud-pc/default.nix rename to archive/2026-07-proxmox-migration/nixos/hosts/cloud-pc/default.nix diff --git a/nixos/hosts/cloud-pc/firewall.nix b/archive/2026-07-proxmox-migration/nixos/hosts/cloud-pc/firewall.nix similarity index 100% rename from nixos/hosts/cloud-pc/firewall.nix rename to archive/2026-07-proxmox-migration/nixos/hosts/cloud-pc/firewall.nix diff --git a/nixos/hosts/cloud-pc/hardware.nix b/archive/2026-07-proxmox-migration/nixos/hosts/cloud-pc/hardware.nix similarity index 100% rename from nixos/hosts/cloud-pc/hardware.nix rename to archive/2026-07-proxmox-migration/nixos/hosts/cloud-pc/hardware.nix diff --git a/nixos/hosts/mini-pc/default.nix b/archive/2026-07-proxmox-migration/nixos/hosts/mini-pc/default.nix similarity index 100% rename from nixos/hosts/mini-pc/default.nix rename to archive/2026-07-proxmox-migration/nixos/hosts/mini-pc/default.nix diff --git a/nixos/hosts/mini-pc/firewall.nix b/archive/2026-07-proxmox-migration/nixos/hosts/mini-pc/firewall.nix similarity index 100% rename from nixos/hosts/mini-pc/firewall.nix rename to archive/2026-07-proxmox-migration/nixos/hosts/mini-pc/firewall.nix diff --git a/nixos/hosts/mini-pc/hardware.nix b/archive/2026-07-proxmox-migration/nixos/hosts/mini-pc/hardware.nix similarity index 100% rename from nixos/hosts/mini-pc/hardware.nix rename to archive/2026-07-proxmox-migration/nixos/hosts/mini-pc/hardware.nix diff --git a/nixos/modules/base.nix b/archive/2026-07-proxmox-migration/nixos/modules/base.nix similarity index 100% rename from nixos/modules/base.nix rename to archive/2026-07-proxmox-migration/nixos/modules/base.nix diff --git a/nixos/modules/docker.nix b/archive/2026-07-proxmox-migration/nixos/modules/docker.nix similarity index 100% rename from nixos/modules/docker.nix rename to archive/2026-07-proxmox-migration/nixos/modules/docker.nix diff --git a/nixos/modules/libvirtd.nix b/archive/2026-07-proxmox-migration/nixos/modules/libvirtd.nix similarity index 100% rename from nixos/modules/libvirtd.nix rename to archive/2026-07-proxmox-migration/nixos/modules/libvirtd.nix diff --git a/nixos/modules/zerotier.nix b/archive/2026-07-proxmox-migration/nixos/modules/zerotier.nix similarity index 100% rename from nixos/modules/zerotier.nix rename to archive/2026-07-proxmox-migration/nixos/modules/zerotier.nix diff --git a/ru-vps/caddy/Caddyfile b/archive/2026-07-proxmox-migration/ru-vps/caddy/Caddyfile similarity index 100% rename from ru-vps/caddy/Caddyfile rename to archive/2026-07-proxmox-migration/ru-vps/caddy/Caddyfile diff --git a/ru-vps/caddy/docker-compose.yml b/archive/2026-07-proxmox-migration/ru-vps/caddy/docker-compose.yml similarity index 100% rename from ru-vps/caddy/docker-compose.yml rename to archive/2026-07-proxmox-migration/ru-vps/caddy/docker-compose.yml diff --git a/ru-vps/gitea-runner/Dockerfile b/archive/2026-07-proxmox-migration/ru-vps/gitea-runner/Dockerfile similarity index 100% rename from ru-vps/gitea-runner/Dockerfile rename to archive/2026-07-proxmox-migration/ru-vps/gitea-runner/Dockerfile diff --git a/ru-vps/gitea-runner/docker-compose.yml b/archive/2026-07-proxmox-migration/ru-vps/gitea-runner/docker-compose.yml similarity index 100% rename from ru-vps/gitea-runner/docker-compose.yml rename to archive/2026-07-proxmox-migration/ru-vps/gitea-runner/docker-compose.yml diff --git a/ru-vps/mihomo/config/config.yaml b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/config.yaml similarity index 100% rename from ru-vps/mihomo/config/config.yaml rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/config.yaml diff --git a/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/.nojekyll b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/ru-vps/mihomo/config/ui/200.html b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/200.html similarity index 100% rename from ru-vps/mihomo/config/ui/200.html rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/200.html diff --git a/ru-vps/mihomo/config/ui/404.html b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/404.html similarity index 100% rename from ru-vps/mihomo/config/ui/404.html rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/404.html diff --git a/ru-vps/mihomo/config/ui/CNAME b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/CNAME similarity index 100% rename from ru-vps/mihomo/config/ui/CNAME rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/CNAME diff --git a/ru-vps/mihomo/config/ui/_fonts/0BHDupFl2CWCe8Ht57JjRElqtRm4w3OaWdbdbcYNe7M-_Zv4nKkXFw7udPt2Y9VUPPAAPn5xlSz7-MFfN2mU3Lw.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/0BHDupFl2CWCe8Ht57JjRElqtRm4w3OaWdbdbcYNe7M-_Zv4nKkXFw7udPt2Y9VUPPAAPn5xlSz7-MFfN2mU3Lw.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/0BHDupFl2CWCe8Ht57JjRElqtRm4w3OaWdbdbcYNe7M-_Zv4nKkXFw7udPt2Y9VUPPAAPn5xlSz7-MFfN2mU3Lw.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/0BHDupFl2CWCe8Ht57JjRElqtRm4w3OaWdbdbcYNe7M-_Zv4nKkXFw7udPt2Y9VUPPAAPn5xlSz7-MFfN2mU3Lw.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/2jtKtjn0jVUoC-Z7Cf8SbbyAq7lWLO_YmjHrE0jt6os-s_gu8XvkQiqM_341oryL2NWuuio3LSudT9bWkGkZuLQ.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/2jtKtjn0jVUoC-Z7Cf8SbbyAq7lWLO_YmjHrE0jt6os-s_gu8XvkQiqM_341oryL2NWuuio3LSudT9bWkGkZuLQ.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/2jtKtjn0jVUoC-Z7Cf8SbbyAq7lWLO_YmjHrE0jt6os-s_gu8XvkQiqM_341oryL2NWuuio3LSudT9bWkGkZuLQ.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/2jtKtjn0jVUoC-Z7Cf8SbbyAq7lWLO_YmjHrE0jt6os-s_gu8XvkQiqM_341oryL2NWuuio3LSudT9bWkGkZuLQ.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/2uj_NkgfcQ3iYnC8ta4ZjyGs0SQG5G8mTV9oTj2xhdk-OwpznulC9p3zW2ObRx0B51k6g1pPy2dUscCCpm_AchI.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/2uj_NkgfcQ3iYnC8ta4ZjyGs0SQG5G8mTV9oTj2xhdk-OwpznulC9p3zW2ObRx0B51k6g1pPy2dUscCCpm_AchI.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/2uj_NkgfcQ3iYnC8ta4ZjyGs0SQG5G8mTV9oTj2xhdk-OwpznulC9p3zW2ObRx0B51k6g1pPy2dUscCCpm_AchI.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/2uj_NkgfcQ3iYnC8ta4ZjyGs0SQG5G8mTV9oTj2xhdk-OwpznulC9p3zW2ObRx0B51k6g1pPy2dUscCCpm_AchI.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/4LCKN0m2mWPjCD0Vg9ZxJ8hmIpE4ZUvT6wD610sQ3xQ-Tvw7sjBhFGZ6EWRXywmjm7BQjP55tT_R9T6v5YfzwGo.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/4LCKN0m2mWPjCD0Vg9ZxJ8hmIpE4ZUvT6wD610sQ3xQ-Tvw7sjBhFGZ6EWRXywmjm7BQjP55tT_R9T6v5YfzwGo.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/4LCKN0m2mWPjCD0Vg9ZxJ8hmIpE4ZUvT6wD610sQ3xQ-Tvw7sjBhFGZ6EWRXywmjm7BQjP55tT_R9T6v5YfzwGo.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/4LCKN0m2mWPjCD0Vg9ZxJ8hmIpE4ZUvT6wD610sQ3xQ-Tvw7sjBhFGZ6EWRXywmjm7BQjP55tT_R9T6v5YfzwGo.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/5Uc1gNFjdWhvWuSCZAsc_KC7PRQ8dSy-6_2-9J2yfkk-j1Y4C4rMRleKY2joVhkot9UpPmfABEsrsuDfKG3QJIE.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/5Uc1gNFjdWhvWuSCZAsc_KC7PRQ8dSy-6_2-9J2yfkk-j1Y4C4rMRleKY2joVhkot9UpPmfABEsrsuDfKG3QJIE.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/5Uc1gNFjdWhvWuSCZAsc_KC7PRQ8dSy-6_2-9J2yfkk-j1Y4C4rMRleKY2joVhkot9UpPmfABEsrsuDfKG3QJIE.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/5Uc1gNFjdWhvWuSCZAsc_KC7PRQ8dSy-6_2-9J2yfkk-j1Y4C4rMRleKY2joVhkot9UpPmfABEsrsuDfKG3QJIE.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/7w4X4tGJFS7OWo1GoNl6cvsXligoB8Z-xWbQFrYWGQE-8h5xTfzAA_h9VIWTxNB67Ucry5cQRTjJhoZaHShhl5M.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/7w4X4tGJFS7OWo1GoNl6cvsXligoB8Z-xWbQFrYWGQE-8h5xTfzAA_h9VIWTxNB67Ucry5cQRTjJhoZaHShhl5M.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/7w4X4tGJFS7OWo1GoNl6cvsXligoB8Z-xWbQFrYWGQE-8h5xTfzAA_h9VIWTxNB67Ucry5cQRTjJhoZaHShhl5M.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/7w4X4tGJFS7OWo1GoNl6cvsXligoB8Z-xWbQFrYWGQE-8h5xTfzAA_h9VIWTxNB67Ucry5cQRTjJhoZaHShhl5M.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/8jC3-1nM22MOOOUOpFvcJfCmHgDwWxJS8N7UggifZYY-asoANahgLf4q1qOPyngavpeqon9_izlETTXfe5Ithr8.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/8jC3-1nM22MOOOUOpFvcJfCmHgDwWxJS8N7UggifZYY-asoANahgLf4q1qOPyngavpeqon9_izlETTXfe5Ithr8.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/8jC3-1nM22MOOOUOpFvcJfCmHgDwWxJS8N7UggifZYY-asoANahgLf4q1qOPyngavpeqon9_izlETTXfe5Ithr8.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/8jC3-1nM22MOOOUOpFvcJfCmHgDwWxJS8N7UggifZYY-asoANahgLf4q1qOPyngavpeqon9_izlETTXfe5Ithr8.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/8ttekgdTgvCkovyeTQZqskfy0dYRy5afQbIR-nG3XpQ-jRXYNQM2VwQOkADB_pwchHeF2Q0ISvsVs_wFd6FiS6k.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/8ttekgdTgvCkovyeTQZqskfy0dYRy5afQbIR-nG3XpQ-jRXYNQM2VwQOkADB_pwchHeF2Q0ISvsVs_wFd6FiS6k.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/8ttekgdTgvCkovyeTQZqskfy0dYRy5afQbIR-nG3XpQ-jRXYNQM2VwQOkADB_pwchHeF2Q0ISvsVs_wFd6FiS6k.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/8ttekgdTgvCkovyeTQZqskfy0dYRy5afQbIR-nG3XpQ-jRXYNQM2VwQOkADB_pwchHeF2Q0ISvsVs_wFd6FiS6k.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/94jBSMN2q8k-mwt9PC-tVG5Xs5k1rEBNDrP9eoW_4DA-j1W30ucBnsJtpkDfRSNomos9AEfcvtgDfyyX4SKhBDE.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/94jBSMN2q8k-mwt9PC-tVG5Xs5k1rEBNDrP9eoW_4DA-j1W30ucBnsJtpkDfRSNomos9AEfcvtgDfyyX4SKhBDE.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/94jBSMN2q8k-mwt9PC-tVG5Xs5k1rEBNDrP9eoW_4DA-j1W30ucBnsJtpkDfRSNomos9AEfcvtgDfyyX4SKhBDE.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/94jBSMN2q8k-mwt9PC-tVG5Xs5k1rEBNDrP9eoW_4DA-j1W30ucBnsJtpkDfRSNomos9AEfcvtgDfyyX4SKhBDE.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/9ZFRJH8Df7SbrP8j5KgC-ZLn9gb1pCWo8G9nFtxgcMQ-EyGwRsKbziIn3DnympkstqXjIDKYICanPtmtVOnxkSA.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/9ZFRJH8Df7SbrP8j5KgC-ZLn9gb1pCWo8G9nFtxgcMQ-EyGwRsKbziIn3DnympkstqXjIDKYICanPtmtVOnxkSA.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/9ZFRJH8Df7SbrP8j5KgC-ZLn9gb1pCWo8G9nFtxgcMQ-EyGwRsKbziIn3DnympkstqXjIDKYICanPtmtVOnxkSA.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/9ZFRJH8Df7SbrP8j5KgC-ZLn9gb1pCWo8G9nFtxgcMQ-EyGwRsKbziIn3DnympkstqXjIDKYICanPtmtVOnxkSA.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/AsEJQEfkU0qunVYWAPueu8RGAg5hTo3kNzUt6XTw0zM-IOANSBgts8tg6KjK82QaqLoQyM_hFwYy9TaiQ_I2uRc.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/AsEJQEfkU0qunVYWAPueu8RGAg5hTo3kNzUt6XTw0zM-IOANSBgts8tg6KjK82QaqLoQyM_hFwYy9TaiQ_I2uRc.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/AsEJQEfkU0qunVYWAPueu8RGAg5hTo3kNzUt6XTw0zM-IOANSBgts8tg6KjK82QaqLoQyM_hFwYy9TaiQ_I2uRc.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/AsEJQEfkU0qunVYWAPueu8RGAg5hTo3kNzUt6XTw0zM-IOANSBgts8tg6KjK82QaqLoQyM_hFwYy9TaiQ_I2uRc.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/AsIupFAeXnc8EeKJ3Bzhy5tKUlFo3vxm7xHaubFA08A-YrRsOOt3iKCLcm2Pu5fqAAkM_bVZsGPdTiJpxDjXDoc.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/AsIupFAeXnc8EeKJ3Bzhy5tKUlFo3vxm7xHaubFA08A-YrRsOOt3iKCLcm2Pu5fqAAkM_bVZsGPdTiJpxDjXDoc.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/AsIupFAeXnc8EeKJ3Bzhy5tKUlFo3vxm7xHaubFA08A-YrRsOOt3iKCLcm2Pu5fqAAkM_bVZsGPdTiJpxDjXDoc.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/AsIupFAeXnc8EeKJ3Bzhy5tKUlFo3vxm7xHaubFA08A-YrRsOOt3iKCLcm2Pu5fqAAkM_bVZsGPdTiJpxDjXDoc.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/CkxZ8SnY8ZppZqgQG8swA5c-q9nVbv-9vyoUoPla7JI-RdFZKpBPbhkz_K7cepi8LXb_TOmZ5GL0GmK_cjXd1qo.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/CkxZ8SnY8ZppZqgQG8swA5c-q9nVbv-9vyoUoPla7JI-RdFZKpBPbhkz_K7cepi8LXb_TOmZ5GL0GmK_cjXd1qo.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/CkxZ8SnY8ZppZqgQG8swA5c-q9nVbv-9vyoUoPla7JI-RdFZKpBPbhkz_K7cepi8LXb_TOmZ5GL0GmK_cjXd1qo.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/CkxZ8SnY8ZppZqgQG8swA5c-q9nVbv-9vyoUoPla7JI-RdFZKpBPbhkz_K7cepi8LXb_TOmZ5GL0GmK_cjXd1qo.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/DzszzorZ5O_YqWq6oS8V82335SNybMUhSCcSYa40KQM-jnTR4jvLVmdaih6m51J9wjp8ghB9NSpItDVLjTnoTO8.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/DzszzorZ5O_YqWq6oS8V82335SNybMUhSCcSYa40KQM-jnTR4jvLVmdaih6m51J9wjp8ghB9NSpItDVLjTnoTO8.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/DzszzorZ5O_YqWq6oS8V82335SNybMUhSCcSYa40KQM-jnTR4jvLVmdaih6m51J9wjp8ghB9NSpItDVLjTnoTO8.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/DzszzorZ5O_YqWq6oS8V82335SNybMUhSCcSYa40KQM-jnTR4jvLVmdaih6m51J9wjp8ghB9NSpItDVLjTnoTO8.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/FgiUOrCnyqHgSsiMw3bPlXJv0qHxBYl0440tdW9jAwM-R9dtGSBkuEEiILTacQhp8WyE02txSq3B7JfOfXDW_uY.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/FgiUOrCnyqHgSsiMw3bPlXJv0qHxBYl0440tdW9jAwM-R9dtGSBkuEEiILTacQhp8WyE02txSq3B7JfOfXDW_uY.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/FgiUOrCnyqHgSsiMw3bPlXJv0qHxBYl0440tdW9jAwM-R9dtGSBkuEEiILTacQhp8WyE02txSq3B7JfOfXDW_uY.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/FgiUOrCnyqHgSsiMw3bPlXJv0qHxBYl0440tdW9jAwM-R9dtGSBkuEEiILTacQhp8WyE02txSq3B7JfOfXDW_uY.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/HHVyYFetjSnAMoAsHyG7VlXWlW9HR9skWh_RgpLlAk4-yHQGjuyu1IMhLHv6ZZLXBV2M_ez3NlJHg7ho0MHGhhc.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/HHVyYFetjSnAMoAsHyG7VlXWlW9HR9skWh_RgpLlAk4-yHQGjuyu1IMhLHv6ZZLXBV2M_ez3NlJHg7ho0MHGhhc.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/HHVyYFetjSnAMoAsHyG7VlXWlW9HR9skWh_RgpLlAk4-yHQGjuyu1IMhLHv6ZZLXBV2M_ez3NlJHg7ho0MHGhhc.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/HHVyYFetjSnAMoAsHyG7VlXWlW9HR9skWh_RgpLlAk4-yHQGjuyu1IMhLHv6ZZLXBV2M_ez3NlJHg7ho0MHGhhc.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/KMzk6ptaouoRl0pusYNLIoZ27ufg20n7FjJ0r-jWX24-evmKS3cTd7KDwv5oVFiF4mwiN1qzHIYcMr18MtkX_YU.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/KMzk6ptaouoRl0pusYNLIoZ27ufg20n7FjJ0r-jWX24-evmKS3cTd7KDwv5oVFiF4mwiN1qzHIYcMr18MtkX_YU.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/KMzk6ptaouoRl0pusYNLIoZ27ufg20n7FjJ0r-jWX24-evmKS3cTd7KDwv5oVFiF4mwiN1qzHIYcMr18MtkX_YU.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/KMzk6ptaouoRl0pusYNLIoZ27ufg20n7FjJ0r-jWX24-evmKS3cTd7KDwv5oVFiF4mwiN1qzHIYcMr18MtkX_YU.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/LOyDiycmdc284_x2PD8CKYz5cDiR1bvb6TdlwA0zW0s-ap4WMcTz1MBJHpMZlE5MzrbWeElXKfB4EeQJuwR793A.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/LOyDiycmdc284_x2PD8CKYz5cDiR1bvb6TdlwA0zW0s-ap4WMcTz1MBJHpMZlE5MzrbWeElXKfB4EeQJuwR793A.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/LOyDiycmdc284_x2PD8CKYz5cDiR1bvb6TdlwA0zW0s-ap4WMcTz1MBJHpMZlE5MzrbWeElXKfB4EeQJuwR793A.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/LOyDiycmdc284_x2PD8CKYz5cDiR1bvb6TdlwA0zW0s-ap4WMcTz1MBJHpMZlE5MzrbWeElXKfB4EeQJuwR793A.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/OfcLxPoYN4z-8y8M9zu0Lgp54b5Y92RcBeUfxpfwMDY-0y0pF9QqHnKQaabEVfxS1MzVRmO0Jc_zlIZi74obv3Y.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/OfcLxPoYN4z-8y8M9zu0Lgp54b5Y92RcBeUfxpfwMDY-0y0pF9QqHnKQaabEVfxS1MzVRmO0Jc_zlIZi74obv3Y.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/OfcLxPoYN4z-8y8M9zu0Lgp54b5Y92RcBeUfxpfwMDY-0y0pF9QqHnKQaabEVfxS1MzVRmO0Jc_zlIZi74obv3Y.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/OfcLxPoYN4z-8y8M9zu0Lgp54b5Y92RcBeUfxpfwMDY-0y0pF9QqHnKQaabEVfxS1MzVRmO0Jc_zlIZi74obv3Y.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/Uq9LPEX26JTSK0gaNQn_6Z3pVOPFb1aIFVxuUFAjYBE-TDIVAiZtfw7lleo9WReLlozuDd68_MbAu2ZRGoMRkdc.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/Uq9LPEX26JTSK0gaNQn_6Z3pVOPFb1aIFVxuUFAjYBE-TDIVAiZtfw7lleo9WReLlozuDd68_MbAu2ZRGoMRkdc.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/Uq9LPEX26JTSK0gaNQn_6Z3pVOPFb1aIFVxuUFAjYBE-TDIVAiZtfw7lleo9WReLlozuDd68_MbAu2ZRGoMRkdc.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/Uq9LPEX26JTSK0gaNQn_6Z3pVOPFb1aIFVxuUFAjYBE-TDIVAiZtfw7lleo9WReLlozuDd68_MbAu2ZRGoMRkdc.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/asDbZN4mAiciWG8XORT25XqmGyK-zogmTYnblp3pVF4-FGfuoN0TSZzxs0_GHKLx4D-M9Hqhp_fbCODfd4SlMpo.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/asDbZN4mAiciWG8XORT25XqmGyK-zogmTYnblp3pVF4-FGfuoN0TSZzxs0_GHKLx4D-M9Hqhp_fbCODfd4SlMpo.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/asDbZN4mAiciWG8XORT25XqmGyK-zogmTYnblp3pVF4-FGfuoN0TSZzxs0_GHKLx4D-M9Hqhp_fbCODfd4SlMpo.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/asDbZN4mAiciWG8XORT25XqmGyK-zogmTYnblp3pVF4-FGfuoN0TSZzxs0_GHKLx4D-M9Hqhp_fbCODfd4SlMpo.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/cG9bT2Rs2wiXiudTcBbVHAP8NMYWSL32yGVzrjFKb4M-8cAYaNW_GKa8bPWNt62mbVYKHutBAOOXFILll_PsRU0.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/cG9bT2Rs2wiXiudTcBbVHAP8NMYWSL32yGVzrjFKb4M-8cAYaNW_GKa8bPWNt62mbVYKHutBAOOXFILll_PsRU0.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/cG9bT2Rs2wiXiudTcBbVHAP8NMYWSL32yGVzrjFKb4M-8cAYaNW_GKa8bPWNt62mbVYKHutBAOOXFILll_PsRU0.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/cG9bT2Rs2wiXiudTcBbVHAP8NMYWSL32yGVzrjFKb4M-8cAYaNW_GKa8bPWNt62mbVYKHutBAOOXFILll_PsRU0.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/dSpBk9EdNZcjl8BVvxvaTZugpF82DPW56k94wdlcmEc-O8K0fmcIPYdTe6plKwcD69_SoxqvChiImre8p6VPPKk.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/dSpBk9EdNZcjl8BVvxvaTZugpF82DPW56k94wdlcmEc-O8K0fmcIPYdTe6plKwcD69_SoxqvChiImre8p6VPPKk.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/dSpBk9EdNZcjl8BVvxvaTZugpF82DPW56k94wdlcmEc-O8K0fmcIPYdTe6plKwcD69_SoxqvChiImre8p6VPPKk.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/dSpBk9EdNZcjl8BVvxvaTZugpF82DPW56k94wdlcmEc-O8K0fmcIPYdTe6plKwcD69_SoxqvChiImre8p6VPPKk.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/g7BqkA7uFNDI7eI1pzx_5kzyxVueaAPKInjDHKnyCVE-rhGg5KPGrwlT4UBKeLa0Nc37lA7xFq5WcK5PZmLJfWQ.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/g7BqkA7uFNDI7eI1pzx_5kzyxVueaAPKInjDHKnyCVE-rhGg5KPGrwlT4UBKeLa0Nc37lA7xFq5WcK5PZmLJfWQ.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/g7BqkA7uFNDI7eI1pzx_5kzyxVueaAPKInjDHKnyCVE-rhGg5KPGrwlT4UBKeLa0Nc37lA7xFq5WcK5PZmLJfWQ.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/g7BqkA7uFNDI7eI1pzx_5kzyxVueaAPKInjDHKnyCVE-rhGg5KPGrwlT4UBKeLa0Nc37lA7xFq5WcK5PZmLJfWQ.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/icpQ3IFJA0mIrVln0qyi-EvCdm5pv5oS__KZwBVcj2o-3UqbZ1wQb8y3GLqtWlf20RgFLj861gtVRD9IWIxUygk.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/icpQ3IFJA0mIrVln0qyi-EvCdm5pv5oS__KZwBVcj2o-3UqbZ1wQb8y3GLqtWlf20RgFLj861gtVRD9IWIxUygk.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/icpQ3IFJA0mIrVln0qyi-EvCdm5pv5oS__KZwBVcj2o-3UqbZ1wQb8y3GLqtWlf20RgFLj861gtVRD9IWIxUygk.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/icpQ3IFJA0mIrVln0qyi-EvCdm5pv5oS__KZwBVcj2o-3UqbZ1wQb8y3GLqtWlf20RgFLj861gtVRD9IWIxUygk.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/jyn5EWxbXux8roFTYzZO9pZ0sYE58a7qdf4QyvFsFHc-vDZ7Zk0QlPIOPQcacDE30IaDsklbi0tTxrsa_V_OVjg.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/jyn5EWxbXux8roFTYzZO9pZ0sYE58a7qdf4QyvFsFHc-vDZ7Zk0QlPIOPQcacDE30IaDsklbi0tTxrsa_V_OVjg.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/jyn5EWxbXux8roFTYzZO9pZ0sYE58a7qdf4QyvFsFHc-vDZ7Zk0QlPIOPQcacDE30IaDsklbi0tTxrsa_V_OVjg.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/jyn5EWxbXux8roFTYzZO9pZ0sYE58a7qdf4QyvFsFHc-vDZ7Zk0QlPIOPQcacDE30IaDsklbi0tTxrsa_V_OVjg.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/mUm0eTfamh3-N48vpdGRyU1-8P_4QNM1H-GR9VkmaVo-E21d7LMNlUytZ2o2uaz6GXP771FCmWYkyio2ejxryFg.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/mUm0eTfamh3-N48vpdGRyU1-8P_4QNM1H-GR9VkmaVo-E21d7LMNlUytZ2o2uaz6GXP771FCmWYkyio2ejxryFg.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/mUm0eTfamh3-N48vpdGRyU1-8P_4QNM1H-GR9VkmaVo-E21d7LMNlUytZ2o2uaz6GXP771FCmWYkyio2ejxryFg.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/mUm0eTfamh3-N48vpdGRyU1-8P_4QNM1H-GR9VkmaVo-E21d7LMNlUytZ2o2uaz6GXP771FCmWYkyio2ejxryFg.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/nArJRSx2Q24CGpdJJWGwkxKDhHq0xGvqfIamLxzjDjo-Mltmvj57qb9_unPzZYqCLr-qzIs90nwFqUYE1Tl0eYw.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/nArJRSx2Q24CGpdJJWGwkxKDhHq0xGvqfIamLxzjDjo-Mltmvj57qb9_unPzZYqCLr-qzIs90nwFqUYE1Tl0eYw.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/nArJRSx2Q24CGpdJJWGwkxKDhHq0xGvqfIamLxzjDjo-Mltmvj57qb9_unPzZYqCLr-qzIs90nwFqUYE1Tl0eYw.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/nArJRSx2Q24CGpdJJWGwkxKDhHq0xGvqfIamLxzjDjo-Mltmvj57qb9_unPzZYqCLr-qzIs90nwFqUYE1Tl0eYw.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/ofWS0IfeK_KhqRnikx2Co7qe5YKZmoqGqoP4DSYij1U-_ofRanqowt6OGJBwb7qtGvU6ktG24_LiXZazouoWpDY.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/ofWS0IfeK_KhqRnikx2Co7qe5YKZmoqGqoP4DSYij1U-_ofRanqowt6OGJBwb7qtGvU6ktG24_LiXZazouoWpDY.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/ofWS0IfeK_KhqRnikx2Co7qe5YKZmoqGqoP4DSYij1U-_ofRanqowt6OGJBwb7qtGvU6ktG24_LiXZazouoWpDY.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/ofWS0IfeK_KhqRnikx2Co7qe5YKZmoqGqoP4DSYij1U-_ofRanqowt6OGJBwb7qtGvU6ktG24_LiXZazouoWpDY.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/vFJFVYMeF4SNq9_9jbsFgjkWqsj7xU4tgEc8hk6bKvA-uG8FVyK2fumEENugz2bwVrLqwY7YVP0g_t2oyGuwO9Q.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/vFJFVYMeF4SNq9_9jbsFgjkWqsj7xU4tgEc8hk6bKvA-uG8FVyK2fumEENugz2bwVrLqwY7YVP0g_t2oyGuwO9Q.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/vFJFVYMeF4SNq9_9jbsFgjkWqsj7xU4tgEc8hk6bKvA-uG8FVyK2fumEENugz2bwVrLqwY7YVP0g_t2oyGuwO9Q.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/vFJFVYMeF4SNq9_9jbsFgjkWqsj7xU4tgEc8hk6bKvA-uG8FVyK2fumEENugz2bwVrLqwY7YVP0g_t2oyGuwO9Q.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/xFR3Nl6fsInXTackRCpfgVTJKL8DQxw-1oEkWSe9Y5I-e_L9Ue7eE-1gHzR0pCgXjLetn5FMSaElSfnTCnuDUnw.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/xFR3Nl6fsInXTackRCpfgVTJKL8DQxw-1oEkWSe9Y5I-e_L9Ue7eE-1gHzR0pCgXjLetn5FMSaElSfnTCnuDUnw.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/xFR3Nl6fsInXTackRCpfgVTJKL8DQxw-1oEkWSe9Y5I-e_L9Ue7eE-1gHzR0pCgXjLetn5FMSaElSfnTCnuDUnw.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/xFR3Nl6fsInXTackRCpfgVTJKL8DQxw-1oEkWSe9Y5I-e_L9Ue7eE-1gHzR0pCgXjLetn5FMSaElSfnTCnuDUnw.woff2 diff --git a/ru-vps/mihomo/config/ui/_fonts/yZXiTO8lc29KbhbsIOqgeKiLjnNedg-HOtkV0o7UtWU-nPJL30mZaI72Qy1WDkWplqib3zQz3yFnnLwvRgeFKDU.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/yZXiTO8lc29KbhbsIOqgeKiLjnNedg-HOtkV0o7UtWU-nPJL30mZaI72Qy1WDkWplqib3zQz3yFnnLwvRgeFKDU.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_fonts/yZXiTO8lc29KbhbsIOqgeKiLjnNedg-HOtkV0o7UtWU-nPJL30mZaI72Qy1WDkWplqib3zQz3yFnnLwvRgeFKDU.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_fonts/yZXiTO8lc29KbhbsIOqgeKiLjnNedg-HOtkV0o7UtWU-nPJL30mZaI72Qy1WDkWplqib3zQz3yFnnLwvRgeFKDU.woff2 diff --git a/ru-vps/mihomo/config/ui/_nuxt/0_dMItsY.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/0_dMItsY.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/0_dMItsY.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/0_dMItsY.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/B794cfQr.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/B794cfQr.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/B794cfQr.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/B794cfQr.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/B7WZYyaj.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/B7WZYyaj.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/B7WZYyaj.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/B7WZYyaj.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/BPcdvgpx.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/BPcdvgpx.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/BPcdvgpx.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/BPcdvgpx.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/BShnNZNf.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/BShnNZNf.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/BShnNZNf.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/BShnNZNf.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/BZddqkRp.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/BZddqkRp.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/BZddqkRp.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/BZddqkRp.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/BcteWY0Z.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/BcteWY0Z.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/BcteWY0Z.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/BcteWY0Z.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/Bd17z0YL.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/Bd17z0YL.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/Bd17z0YL.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/Bd17z0YL.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/Bmqvg1eR.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/Bmqvg1eR.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/Bmqvg1eR.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/Bmqvg1eR.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/BtmxTiib2.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/BtmxTiib2.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/BtmxTiib2.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/BtmxTiib2.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/Button.BZ68r_km.css b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/Button.BZ68r_km.css similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/Button.BZ68r_km.css rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/Button.BZ68r_km.css diff --git a/ru-vps/mihomo/config/ui/_nuxt/C5Y2gFoU.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/C5Y2gFoU.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/C5Y2gFoU.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/C5Y2gFoU.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/C7rl-mRr2.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/C7rl-mRr2.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/C7rl-mRr2.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/C7rl-mRr2.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/CAiAuG3x2.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CAiAuG3x2.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/CAiAuG3x2.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CAiAuG3x2.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/CF7Y_Yoj.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CF7Y_Yoj.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/CF7Y_Yoj.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CF7Y_Yoj.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/CIa-1CJu.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CIa-1CJu.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/CIa-1CJu.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CIa-1CJu.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/CJKiW56e.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CJKiW56e.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/CJKiW56e.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CJKiW56e.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/CJgAejf_.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CJgAejf_.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/CJgAejf_.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CJgAejf_.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/CX_RojMw.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CX_RojMw.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/CX_RojMw.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CX_RojMw.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/CaGtQlYh.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CaGtQlYh.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/CaGtQlYh.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CaGtQlYh.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/Ce_uH7zp.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/Ce_uH7zp.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/Ce_uH7zp.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/Ce_uH7zp.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/CqOBGK95.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CqOBGK95.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/CqOBGK95.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CqOBGK95.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/CsU6pgHx.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CsU6pgHx.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/CsU6pgHx.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CsU6pgHx.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/CuyTkb7v.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CuyTkb7v.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/CuyTkb7v.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CuyTkb7v.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/CxiWMChH.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CxiWMChH.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/CxiWMChH.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/CxiWMChH.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/DAvMhUmu.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DAvMhUmu.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/DAvMhUmu.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DAvMhUmu.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/DBeOglbT.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DBeOglbT.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/DBeOglbT.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DBeOglbT.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/DEcpuQGr.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DEcpuQGr.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/DEcpuQGr.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DEcpuQGr.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/DIJlUfKz.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DIJlUfKz.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/DIJlUfKz.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DIJlUfKz.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/DKY2UQsB.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DKY2UQsB.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/DKY2UQsB.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DKY2UQsB.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/DNKnP_p9.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DNKnP_p9.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/DNKnP_p9.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DNKnP_p9.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/DY0SBW17.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DY0SBW17.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/DY0SBW17.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DY0SBW17.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/DhTvfVif.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DhTvfVif.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/DhTvfVif.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DhTvfVif.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/DohEsvF1.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DohEsvF1.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/DohEsvF1.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/DohEsvF1.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/Hw_CdiGx.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/Hw_CdiGx.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/Hw_CdiGx.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/Hw_CdiGx.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/Modal.Bos6Z9KR.css b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/Modal.Bos6Z9KR.css similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/Modal.Bos6Z9KR.css rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/Modal.Bos6Z9KR.css diff --git a/ru-vps/mihomo/config/ui/_nuxt/QTnfLwEv.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/QTnfLwEv.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/QTnfLwEv.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/QTnfLwEv.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/TwemojiMozilla-flags.B12sb_Bp.woff2 b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/TwemojiMozilla-flags.B12sb_Bp.woff2 similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/TwemojiMozilla-flags.B12sb_Bp.woff2 rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/TwemojiMozilla-flags.B12sb_Bp.woff2 diff --git a/ru-vps/mihomo/config/ui/_nuxt/config.CPN2rk7N.css b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/config.CPN2rk7N.css similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/config.CPN2rk7N.css rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/config.CPN2rk7N.css diff --git a/ru-vps/mihomo/config/ui/_nuxt/connections.CVCaXG6C.css b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/connections.CVCaXG6C.css similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/connections.CVCaXG6C.css rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/connections.CVCaXG6C.css diff --git a/ru-vps/mihomo/config/ui/_nuxt/default.DZBhgs-l.css b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/default.DZBhgs-l.css similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/default.DZBhgs-l.css rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/default.DZBhgs-l.css diff --git a/ru-vps/mihomo/config/ui/_nuxt/entry.B_k74qUh.css b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/entry.B_k74qUh.css similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/entry.B_k74qUh.css rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/entry.B_k74qUh.css diff --git a/ru-vps/mihomo/config/ui/_nuxt/error-404.C7v-Yf5D.css b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/error-404.C7v-Yf5D.css similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/error-404.C7v-Yf5D.css rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/error-404.C7v-Yf5D.css diff --git a/ru-vps/mihomo/config/ui/_nuxt/error-500.CiQk-w4Y.css b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/error-500.CiQk-w4Y.css similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/error-500.CiQk-w4Y.css rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/error-500.CiQk-w4Y.css diff --git a/ru-vps/mihomo/config/ui/_nuxt/f4M304qm.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/f4M304qm.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/f4M304qm.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/f4M304qm.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/gReBw4PU.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/gReBw4PU.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/gReBw4PU.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/gReBw4PU.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/j6AC8cpi2.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/j6AC8cpi2.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/j6AC8cpi2.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/j6AC8cpi2.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/logs.CCPRQARx.css b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/logs.CCPRQARx.css similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/logs.CCPRQARx.css rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/logs.CCPRQARx.css diff --git a/ru-vps/mihomo/config/ui/_nuxt/overview.CTR8EHmD.css b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/overview.CTR8EHmD.css similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/overview.CTR8EHmD.css rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/overview.CTR8EHmD.css diff --git a/ru-vps/mihomo/config/ui/_nuxt/p5ExTIuN.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/p5ExTIuN.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/p5ExTIuN.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/p5ExTIuN.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/pages.D31ly-rM.css b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/pages.D31ly-rM.css similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/pages.D31ly-rM.css rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/pages.D31ly-rM.css diff --git a/ru-vps/mihomo/config/ui/_nuxt/proxies.BV77Mb6o.css b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/proxies.BV77Mb6o.css similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/proxies.BV77Mb6o.css rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/proxies.BV77Mb6o.css diff --git a/ru-vps/mihomo/config/ui/_nuxt/rules.CncxuuNE.css b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/rules.CncxuuNE.css similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/rules.CncxuuNE.css rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/rules.CncxuuNE.css diff --git a/ru-vps/mihomo/config/ui/_nuxt/setup.Ncn7rZsf.css b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/setup.Ncn7rZsf.css similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/setup.Ncn7rZsf.css rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/setup.Ncn7rZsf.css diff --git a/ru-vps/mihomo/config/ui/_nuxt/shortcuts.Yt_EetdT.css b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/shortcuts.Yt_EetdT.css similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/shortcuts.Yt_EetdT.css rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/shortcuts.Yt_EetdT.css diff --git a/ru-vps/mihomo/config/ui/_nuxt/taTi6IIU.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/taTi6IIU.js similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/taTi6IIU.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/taTi6IIU.js diff --git a/ru-vps/mihomo/config/ui/_nuxt/traffic.BZwB8MEO.css b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/traffic.BZwB8MEO.css similarity index 100% rename from ru-vps/mihomo/config/ui/_nuxt/traffic.BZwB8MEO.css rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/_nuxt/traffic.BZwB8MEO.css diff --git a/ru-vps/mihomo/config/ui/apple-touch-icon-180x180.png b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/apple-touch-icon-180x180.png similarity index 100% rename from ru-vps/mihomo/config/ui/apple-touch-icon-180x180.png rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/apple-touch-icon-180x180.png diff --git a/ru-vps/mihomo/config/ui/config.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/config.js similarity index 100% rename from ru-vps/mihomo/config/ui/config.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/config.js diff --git a/ru-vps/mihomo/config/ui/favicon.ico b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/favicon.ico similarity index 100% rename from ru-vps/mihomo/config/ui/favicon.ico rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/favicon.ico diff --git a/ru-vps/mihomo/config/ui/favicon.svg b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/favicon.svg similarity index 100% rename from ru-vps/mihomo/config/ui/favicon.svg rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/favicon.svg diff --git a/ru-vps/mihomo/config/ui/index.html b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/index.html similarity index 100% rename from ru-vps/mihomo/config/ui/index.html rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/index.html diff --git a/ru-vps/mihomo/config/ui/manifest.webmanifest b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/manifest.webmanifest similarity index 100% rename from ru-vps/mihomo/config/ui/manifest.webmanifest rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/manifest.webmanifest diff --git a/ru-vps/mihomo/config/ui/maskable-icon-512x512.png b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/maskable-icon-512x512.png similarity index 100% rename from ru-vps/mihomo/config/ui/maskable-icon-512x512.png rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/maskable-icon-512x512.png diff --git a/ru-vps/mihomo/config/ui/pwa-192x192.png b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/pwa-192x192.png similarity index 100% rename from ru-vps/mihomo/config/ui/pwa-192x192.png rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/pwa-192x192.png diff --git a/ru-vps/mihomo/config/ui/pwa-512x512.png b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/pwa-512x512.png similarity index 100% rename from ru-vps/mihomo/config/ui/pwa-512x512.png rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/pwa-512x512.png diff --git a/ru-vps/mihomo/config/ui/pwa-64x64.png b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/pwa-64x64.png similarity index 100% rename from ru-vps/mihomo/config/ui/pwa-64x64.png rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/pwa-64x64.png diff --git a/ru-vps/mihomo/config/ui/sw.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/sw.js similarity index 100% rename from ru-vps/mihomo/config/ui/sw.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/sw.js diff --git a/ru-vps/mihomo/config/ui/workbox-2fbc6a65.js b/archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/workbox-2fbc6a65.js similarity index 100% rename from ru-vps/mihomo/config/ui/workbox-2fbc6a65.js rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/config/ui/workbox-2fbc6a65.js diff --git a/ru-vps/mihomo/docker-compose.yml b/archive/2026-07-proxmox-migration/ru-vps/mihomo/docker-compose.yml similarity index 100% rename from ru-vps/mihomo/docker-compose.yml rename to archive/2026-07-proxmox-migration/ru-vps/mihomo/docker-compose.yml diff --git a/ru-vps/resticprofile/profiles.toml b/archive/2026-07-proxmox-migration/ru-vps/resticprofile/profiles.toml similarity index 100% rename from ru-vps/resticprofile/profiles.toml rename to archive/2026-07-proxmox-migration/ru-vps/resticprofile/profiles.toml diff --git a/ru-vps/zerotier/docker-compose.yml b/archive/2026-07-proxmox-migration/ru-vps/zerotier/docker-compose.yml similarity index 100% rename from ru-vps/zerotier/docker-compose.yml rename to archive/2026-07-proxmox-migration/ru-vps/zerotier/docker-compose.yml diff --git a/scripts/deploy.sh b/archive/2026-07-proxmox-migration/scripts/deploy.sh similarity index 100% rename from scripts/deploy.sh rename to archive/2026-07-proxmox-migration/scripts/deploy.sh diff --git a/archive/2026-07-proxmox-migration/wireguard-attempt/playbooks/wireguard-check.yml b/archive/2026-07-proxmox-migration/wireguard-attempt/playbooks/wireguard-check.yml new file mode 100644 index 0000000..f27c49a --- /dev/null +++ b/archive/2026-07-proxmox-migration/wireguard-attempt/playbooks/wireguard-check.yml @@ -0,0 +1,19 @@ +- name: Check WireGuard tunnel from ru-vps + hosts: ru-vps + gather_facts: false + tasks: + - name: Ping wg-mini WireGuard address + ansible.builtin.command: ping -c 3 -W 2 10.77.0.2 + changed_when: false + + - name: Check mini-pc PVE port through wg-mini gateway + ansible.builtin.command: nc -vz -w 5 192.168.1.10 8006 + changed_when: false + + - name: Check cloud-pc PVE port through wg-mini gateway + ansible.builtin.command: nc -vz -w 5 192.168.1.5 8006 + changed_when: false + + - name: Check PBS port through wg-mini gateway + ansible.builtin.command: nc -vz -w 5 192.168.1.20 8007 + changed_when: false diff --git a/archive/2026-07-proxmox-migration/wireguard-attempt/playbooks/wireguard-teardown.yml b/archive/2026-07-proxmox-migration/wireguard-attempt/playbooks/wireguard-teardown.yml new file mode 100644 index 0000000..7c22583 --- /dev/null +++ b/archive/2026-07-proxmox-migration/wireguard-attempt/playbooks/wireguard-teardown.yml @@ -0,0 +1,61 @@ +- name: Remove WireGuard from ru-vps and wg-mini + hosts: wireguard + gather_facts: false + become: true + vars: + wireguard_interface: wg0 + wireguard_listen_port: 3422 + wireguard_home_routes: + - 192.168.1.5/32 + - 192.168.1.6/31 + - 192.168.1.8/29 + - 192.168.1.16/28 + - 192.168.1.32/29 + - 192.168.1.40/32 + tasks: + - name: Stop WireGuard service + ansible.builtin.systemd: + name: "wg-quick@{{ wireguard_interface }}" + state: stopped + enabled: false + failed_when: false + + - name: Remove WireGuard route entries on server + ansible.builtin.command: "ip route del {{ item }} dev {{ wireguard_interface }}" + loop: "{{ wireguard_home_routes }}" + changed_when: false + failed_when: false + when: inventory_hostname == 'ru-vps' + + - name: Remove WireGuard NAT rule on gateway + ansible.builtin.command: "iptables -t nat -D POSTROUTING -s 10.77.0.0/30 -d {{ homelab_lan_cidr }} -o eth0 -j MASQUERADE" + changed_when: false + failed_when: false + when: inventory_hostname == 'wg-mini' + + - name: Remove WireGuard config directory + ansible.builtin.file: + path: /etc/wireguard + state: absent + + - name: Remove WireGuard package + ansible.builtin.apt: + name: wireguard-tools + state: absent + purge: true + + - name: Remove diagnostic tcpdump from gateway + ansible.builtin.apt: + name: tcpdump + state: absent + purge: true + when: inventory_hostname == 'wg-mini' + + - name: Delete UFW WireGuard UDP rules on server + ansible.builtin.command: "ufw delete allow {{ item }}/udp" + loop: + - 3422 + - 51820 + changed_when: false + failed_when: false + when: inventory_hostname == 'ru-vps' diff --git a/archive/2026-07-proxmox-migration/wireguard-attempt/playbooks/wireguard-vps-mini.yml b/archive/2026-07-proxmox-migration/wireguard-attempt/playbooks/wireguard-vps-mini.yml new file mode 100644 index 0000000..706820c --- /dev/null +++ b/archive/2026-07-proxmox-migration/wireguard-attempt/playbooks/wireguard-vps-mini.yml @@ -0,0 +1,6 @@ +- name: Configure WireGuard on ru-vps and wg-mini + hosts: wireguard + gather_facts: true + become: true + roles: + - wireguard_gateway diff --git a/archive/2026-07-proxmox-migration/wireguard-attempt/roles/wireguard_gateway/defaults/main.yml b/archive/2026-07-proxmox-migration/wireguard-attempt/roles/wireguard_gateway/defaults/main.yml new file mode 100644 index 0000000..7c21cc0 --- /dev/null +++ b/archive/2026-07-proxmox-migration/wireguard-attempt/roles/wireguard_gateway/defaults/main.yml @@ -0,0 +1,12 @@ +--- +wireguard_interface: wg0 +wireguard_listen_port: 3422 +wireguard_private_key_path: /etc/wireguard/privatekey +wireguard_public_key_path: /etc/wireguard/publickey +wireguard_home_routes: + - 192.168.1.5/32 + - 192.168.1.6/31 + - 192.168.1.8/29 + - 192.168.1.16/28 + - 192.168.1.32/29 + - 192.168.1.40/32 diff --git a/archive/2026-07-proxmox-migration/wireguard-attempt/roles/wireguard_gateway/handlers/main.yml b/archive/2026-07-proxmox-migration/wireguard-attempt/roles/wireguard_gateway/handlers/main.yml new file mode 100644 index 0000000..38ade77 --- /dev/null +++ b/archive/2026-07-proxmox-migration/wireguard-attempt/roles/wireguard_gateway/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: restart wireguard + ansible.builtin.systemd: + name: "wg-quick@{{ wireguard_interface }}" + state: restarted + enabled: true diff --git a/archive/2026-07-proxmox-migration/wireguard-attempt/roles/wireguard_gateway/tasks/main.yml b/archive/2026-07-proxmox-migration/wireguard-attempt/roles/wireguard_gateway/tasks/main.yml new file mode 100644 index 0000000..a35226d --- /dev/null +++ b/archive/2026-07-proxmox-migration/wireguard-attempt/roles/wireguard_gateway/tasks/main.yml @@ -0,0 +1,75 @@ +--- +- name: Install WireGuard packages + ansible.builtin.apt: + name: + - wireguard-tools + - iptables + - iproute2 + - netcat-openbsd + state: present + update_cache: true + +- name: Ensure WireGuard config directory exists + ansible.builtin.file: + path: /etc/wireguard + state: directory + owner: root + group: root + mode: "0700" + +- name: Generate private key if missing + ansible.builtin.shell: umask 077 && wg genkey > {{ wireguard_private_key_path }} + args: + creates: "{{ wireguard_private_key_path }}" + +- name: Generate public key + ansible.builtin.shell: wg pubkey < {{ wireguard_private_key_path }} > {{ wireguard_public_key_path }} + args: + creates: "{{ wireguard_public_key_path }}" + +- name: Read private key + ansible.builtin.slurp: + src: "{{ wireguard_private_key_path }}" + register: wireguard_private_key_raw + no_log: true + +- name: Read public key + ansible.builtin.slurp: + src: "{{ wireguard_public_key_path }}" + register: wireguard_public_key_raw + +- name: Store WireGuard keys as facts + ansible.builtin.set_fact: + wireguard_private_key: "{{ wireguard_private_key_raw.content | b64decode | trim }}" + wireguard_public_key: "{{ wireguard_public_key_raw.content | b64decode | trim }}" + no_log: true + +- name: Enable IPv4 forwarding on gateway + ansible.posix.sysctl: + name: net.ipv4.ip_forward + value: "1" + state: present + reload: true + when: wireguard_role == 'gateway' + +- name: Allow WireGuard UDP in UFW on server + ansible.builtin.command: "ufw allow {{ wireguard_listen_port }}/udp" + register: ufw_allow_wireguard + changed_when: "'Rule added' in ufw_allow_wireguard.stdout or 'Rules updated' in ufw_allow_wireguard.stdout" + failed_when: false + when: wireguard_role == 'server' + +- name: Render WireGuard config + ansible.builtin.template: + src: "wg0.conf.j2" + dest: "/etc/wireguard/{{ wireguard_interface }}.conf" + owner: root + group: root + mode: "0600" + notify: restart wireguard + +- name: Enable and start WireGuard + ansible.builtin.systemd: + name: "wg-quick@{{ wireguard_interface }}" + state: started + enabled: true diff --git a/archive/2026-07-proxmox-migration/wireguard-attempt/roles/wireguard_gateway/templates/wg0.conf.j2 b/archive/2026-07-proxmox-migration/wireguard-attempt/roles/wireguard_gateway/templates/wg0.conf.j2 new file mode 100644 index 0000000..6d9ee58 --- /dev/null +++ b/archive/2026-07-proxmox-migration/wireguard-attempt/roles/wireguard_gateway/templates/wg0.conf.j2 @@ -0,0 +1,26 @@ +[Interface] +Address = {{ wireguard_address }} +PrivateKey = {{ wireguard_private_key }} +{% if wireguard_role == 'server' %} +ListenPort = {{ wireguard_listen_port }} +{% for route in wireguard_home_routes %} +PostUp = ip route replace {{ route }} dev {{ wireguard_interface }} +PostDown = ip route del {{ route }} dev {{ wireguard_interface }} || true +{% endfor %} +{% endif %} +{% if wireguard_role == 'gateway' %} +PostUp = iptables -t nat -A POSTROUTING -s {{ wireguard_network_cidr }} -d {{ homelab_lan_cidr }} -o eth0 -j MASQUERADE +PostDown = iptables -t nat -D POSTROUTING -s {{ wireguard_network_cidr }} -d {{ homelab_lan_cidr }} -o eth0 -j MASQUERADE || true +{% endif %} + +[Peer] +{% if wireguard_role == 'server' %} +PublicKey = {{ hostvars['wg-mini'].wireguard_public_key }} +AllowedIPs = {{ wireguard_peer_address }}/32, {{ wireguard_home_routes | join(', ') }} +{% endif %} +{% if wireguard_role == 'gateway' %} +PublicKey = {{ hostvars['ru-vps'].wireguard_public_key }} +Endpoint = 157.22.231.198:{{ wireguard_listen_port }} +AllowedIPs = {{ wireguard_peer_address }}/32 +PersistentKeepalive = 25 +{% endif %}