commit 32667c657dd9b8c7e2dbf7c88bcdedf32d9625b1 Author: Storozhenko Evgeniy Vladimirovich Date: Sun May 31 11:58:36 2026 +0300 first_commit diff --git a/.become_pass b/.become_pass new file mode 100644 index 0000000..8ab736b --- /dev/null +++ b/.become_pass @@ -0,0 +1 @@ +Ghjcgtrn73 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b40528d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.bocome_pass +.vault_pass +.venv diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..5e794aa --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,10 @@ +[defaults] +inventory = inventory.ini +host_key_checking = False +retry_files_enabled = False +vault_password_file = .vault_pass +become_password_file = .become_pass + +[ssh_connection] +# Стандартные безопасные настройки +ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o ForwardAgent=yes diff --git a/group_vars/garage_nodes.yml b/group_vars/garage_nodes.yml new file mode 100644 index 0000000..3803cb7 --- /dev/null +++ b/group_vars/garage_nodes.yml @@ -0,0 +1,27 @@ +--- +# WireGuard настройки +wireguard_port: 51820 +wireguard_subnet: "10.8.0.0/24" + +# Топология Full Mesh +wireguard_peers: + - name: vps01 + ip: 10.8.0.1 + pubkey: "ZAvz4xCEPmlbor7/sg7+gCC5X5ju4IBK0KEmqD7xmBc=" + endpoint: "5.129.217.146:51820" + - name: vps02 + ip: 10.8.0.4 + pubkey: "JbC++sMcNaw1L7qL4ZvjfHYIjgw7h77aXXuz1sCHQlQ=" + endpoint: "195.161.62.100:51820" + - name: bigbox + ip: 10.8.0.2 + pubkey: "SXCR8BgJcomhe2pygfhNmXiRgoJynuwoQxMsqFDL/W8=" + endpoint: "" # Bigbox за NAT, входящие соединения инициирует он сам + +# Garage настройки +garage_rpc_secret: "a3f1c8b2e9d4a7c6f0e5b8a2d1c4f7e9a3b6c9d2e5f8a1c4b7e0d3f6a9c2b5e8" +garage_admin_token: "c213debe864061cefe501f7791d557b6dba701710b41791b4a4a0fb036690d1d" +garage_replication_factor: 2 +garage_read_quorum: 1 +garage_write_quorum: 2 +garage_version: "v2.1.0" diff --git a/host_vars/bigbox.yml b/host_vars/bigbox.yml new file mode 100644 index 0000000..8e47687 --- /dev/null +++ b/host_vars/bigbox.yml @@ -0,0 +1,10 @@ +$ANSIBLE_VAULT;1.1;AES256 +61643130343565383630613661363963396462386231663361623263666236386166613931393936 +3834613362613439656230366538336439346534353536610a366238353163393135343365393432 +30626430653038666439303762613463396165373964633634646466633466313533623339393536 +3563306536326331310a636436333563386261666565316461653538373131656164336665326339 +32346661646662393534383261633765383633336237393431336365386362663535376537663537 +61343864613961306366363465376330396437383438336534336630643365316136313866326439 +39343439383238343239333038636137623631363261326536313838306535653631326666326232 +32303332303266346331396339623632336165373864363238663663373639323038383136363531 +66623638663838353737386130383433663835383332343361663966613038666261 diff --git a/host_vars/vps01.yml b/host_vars/vps01.yml new file mode 100644 index 0000000..2f9832a --- /dev/null +++ b/host_vars/vps01.yml @@ -0,0 +1,10 @@ +$ANSIBLE_VAULT;1.1;AES256 +38653533356362336439326463303238383835336131373337366666393763643337656266346262 +3134636164386636363765313861376437346566343935370a623633643835316162396237323038 +35393666376533613535373262303830313564383237633830373566643536396134333130313331 +3938613431646232390a363230616561383037353631653839343637636163633330366161663932 +62653965313330313539313136336265653136623966383965343965643730373339323433376437 +39653861343230653032333462306364653437656563326135393438643236343330376265356630 +66646635323135656336393630383066613235626433653163356462623733613733633431343862 +31346339363830643231626336336263316534393137633432383436343136373133326638326562 +39623562633866333334656566303532616231373037343437383263333936363166 diff --git a/host_vars/vps02.yml b/host_vars/vps02.yml new file mode 100644 index 0000000..8deb1e9 --- /dev/null +++ b/host_vars/vps02.yml @@ -0,0 +1,10 @@ +$ANSIBLE_VAULT;1.1;AES256 +64393034393333373737623763623366313139346139626130356664356536333435373431363564 +6664623430323434313132313031323830343166313230360a353731366262346638313434376637 +34323137373733653761356661353835393664323365336332656535316633373736393465326130 +3864396365346534370a346434346132623262643434363464326338656237633666366435366366 +35346530623236323233386466363761363637396438386263623866303562383839616639623032 +66346539333233316135643834613837356338653335326632346565636662383330326662326135 +31323933323439396566363362366335363635393338323433653738396236333431636237383261 +34643362333531653966363135646662663565626238313536613537316361653063373762316439 +38643866663533373034626437333130346438383138306533393030303065376331 diff --git a/inventory.ini b/inventory.ini new file mode 100644 index 0000000..74c00bf --- /dev/null +++ b/inventory.ini @@ -0,0 +1,10 @@ +[garage_nodes] +vps01 ansible_host=5.129.217.146 ansible_user=root ansible_ssh_private_key_file=/home/estorozhenko/.ssh/timewebVPS +vps02 ansible_host=87.242.100.206 ansible_user=estorozhenko ansible_ssh_private_key_file=/home/estorozhenko/.ssh/cloudruVPS +bigbox ansible_host=192.168.1.3 ansible_user=estorozhenko ansible_ssh_private_key_file=/home/estorozhenko/.ssh/gelonet + +[garage_nodes:vars] +ansible_become=yes +ansible_become_method=sudo +# Для bigbox и vps02, возможно, потребуется ввод пароля sudo, если он не настроен на безпарольный вход. +# Если sudo без пароля, то всё ок. Если нет, добавь флаг --ask-become-pass при запуске плейбука. diff --git a/roles/garage/docker-compose.yml.j2 b/roles/garage/docker-compose.yml.j2 new file mode 100644 index 0000000..0ba200b --- /dev/null +++ b/roles/garage/docker-compose.yml.j2 @@ -0,0 +1,10 @@ +services: + garage: + image: dxflrs/garage:v2.1.0 + container_name: garage + restart: unless-stopped + network_mode: "host" + volumes: + - ./garage.toml:/etc/garage.toml:ro + - ./meta:/var/lib/garage/meta + - ./data:/var/lib/garage/data diff --git a/roles/garage/garage.toml.j2 b/roles/garage/garage.toml.j2 new file mode 100644 index 0000000..164957a --- /dev/null +++ b/roles/garage/garage.toml.j2 @@ -0,0 +1,28 @@ +metadata_dir = "/var/lib/garage/meta" +data_dir = "/var/lib/garage/data" + +db_engine = "lmdb" +replication_factor = 2 +read_quorum = 1 +write_quorum = 2 +compression_level = 2 + +# RPC слушает на WG интерфейсе +rpc_bind_addr = "{{ wg_ip }}:3901" +rpc_public_addr = "{{ wg_ip }}:3901" +rpc_secret = "{{ garage_rpc_secret }}" + +[s3_api] +s3_region = "garage" +# S3 API доступно везде (для простоты отладки), но можно ограничить +api_bind_addr = "0.0.0.0:3900" + +[admin] +admin_token = "{{ garage_admin_token }}" + +[kademlia] +bootstrap_peers = [ +{% for peer in wireguard_peers %} + "{{ peer.pubkey }}@{{ peer.ip }}:3901"{% if not loop.last %},{% endif %} +{% endfor %} +] diff --git a/roles/garage/handlers/main.yml b/roles/garage/handlers/main.yml new file mode 100644 index 0000000..543a94d --- /dev/null +++ b/roles/garage/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart Garage + community.docker.docker_compose_v2: + project_src: /opt/garage + state: restarted diff --git a/roles/garage/tasks/main.yml b/roles/garage/tasks/main.yml new file mode 100644 index 0000000..669d4df --- /dev/null +++ b/roles/garage/tasks/main.yml @@ -0,0 +1,96 @@ +--- +- name: Install prerequisites for Docker + apt: + name: + - apt-transport-https + - ca-certificates + - curl + - gnupg + - lsb-release + state: present + update_cache: yes + ignore_errors: yes # Игнорируем ошибки, если старые репо битые + +- name: Install software-properties-common on Ubuntu + apt: + name: software-properties-common + state: present + when: ansible_distribution == "Ubuntu" + ignore_errors: yes + +- name: Create keyrings directory + file: + path: /etc/apt/keyrings + state: directory + mode: '0755' + +# --- Логика для UBUNTU --- +- name: Download Docker GPG key for Ubuntu + shell: | + curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc + chmod a+r /etc/apt/keyrings/docker.asc + args: + creates: /etc/apt/keyrings/docker.asc + when: ansible_distribution == "Ubuntu" + +- name: Add Docker repository for Ubuntu + copy: + # Используем переменную Ansible для архитектуры, чтобы избежать shell-синтаксиса в файле + content: "deb [arch={{ ansible_architecture }} signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable\n" + dest: /etc/apt/sources.list.d/docker.list + mode: '0644' + when: ansible_distribution == "Ubuntu" + +# --- Логика для DEBIAN --- +- name: Download and convert Docker GPG key for Debian + shell: | + curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg + args: + creates: /usr/share/keyrings/docker-archive-keyring.gpg + when: ansible_distribution == "Debian" + +- name: Add Docker repository for Debian + copy: + content: "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian {{ ansible_distribution_release }} stable\n" + dest: /etc/apt/sources.list.d/docker.list + mode: '0644' + when: ansible_distribution == "Debian" + +- name: Update apt cache after adding Docker repo + apt: + update_cache: yes + +- name: Install Docker packages + apt: + name: + - docker-ce + - docker-ce-cli + - containerd.io + - docker-buildx-plugin + - docker-compose-plugin + state: present + update_cache: yes + +- name: Ensure Garage directory exists + file: + path: /opt/garage + state: directory + mode: '0755' + +- name: Deploy Garage docker-compose.yml + template: + src: docker-compose.yml.j2 + dest: /opt/garage/docker-compose.yml + mode: '0644' + +- name: Deploy Garage configuration (garage.toml) + template: + src: garage.toml.j2 + dest: /opt/garage/garage.toml + mode: '0644' + notify: Restart Garage + +- name: Start Garage services + community.docker.docker_compose_v2: + project_src: /opt/garage + state: present diff --git a/roles/garage/templates/docker-compose.yml.j2 b/roles/garage/templates/docker-compose.yml.j2 new file mode 100644 index 0000000..2076c59 --- /dev/null +++ b/roles/garage/templates/docker-compose.yml.j2 @@ -0,0 +1,10 @@ +services: + garage: + image: dxflrs/garage:{{ garage_version }} + container_name: garage + restart: unless-stopped + network_mode: "host" + volumes: + - ./garage.toml:/etc/garage.toml:ro + - ./meta:/var/lib/garage/meta + - ./data:/var/lib/garage/data diff --git a/roles/garage/templates/garage.toml.j2 b/roles/garage/templates/garage.toml.j2 new file mode 100644 index 0000000..da25928 --- /dev/null +++ b/roles/garage/templates/garage.toml.j2 @@ -0,0 +1,29 @@ +metadata_dir = "/var/lib/garage/meta" +data_dir = "/var/lib/garage/data" + +db_engine = "lmdb" +replication_factor = {{ garage_replication_factor }} +read_quorum = {{ garage_read_quorum }} +write_quorum = {{ garage_write_quorum }} +compression_level = 2 +metadata_auto_snapshot_interval = "6h" + +# RPC привязан к WG интерфейсу для безопасности +rpc_bind_addr = "{{ wireguard_ip }}:3901" +rpc_public_addr = "{{ wireguard_ip }}:3901" +rpc_secret = "{{ garage_rpc_secret }}" + +[s3_api] +s3_region = "garage" +# S3 API доступно на всех интерфейсах (для доступа из LAN и через WG) +api_bind_addr = "0.0.0.0:3900" + +[admin] +admin_token = "{{ garage_admin_token }}" + +[kademlia] +bootstrap_peers = [ +{% for peer in wireguard_peers %} + "{{ peer.pubkey }}@{{ peer.ip }}:3901"{% if not loop.last %},{% endif %} +{% endfor %} +] diff --git a/roles/wireguard/handlers/main.yml b/roles/wireguard/handlers/main.yml new file mode 100644 index 0000000..d3b8d99 --- /dev/null +++ b/roles/wireguard/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart WireGuard + systemd: + name: wg-quick@wg0 + state: restarted diff --git a/roles/wireguard/tasks/main.yml b/roles/wireguard/tasks/main.yml new file mode 100644 index 0000000..6e9ba58 --- /dev/null +++ b/roles/wireguard/tasks/main.yml @@ -0,0 +1,34 @@ +--- +- name: Remove any broken Docker repository files to prevent apt errors + file: + path: "{{ item }}" + state: absent + with_fileglob: + - "/etc/apt/sources.list.d/*docker*" + ignore_errors: yes + +- name: Install WireGuard + apt: + name: wireguard + state: present + update_cache: yes + ignore_errors: yes + +- name: Ensure WireGuard directory exists + file: + path: /etc/wireguard + state: directory + mode: '0700' + +- name: Deploy WireGuard configuration + template: + src: wg0.conf.j2 + dest: /etc/wireguard/wg0.conf + mode: '0600' + notify: Restart WireGuard + +- name: Enable and start WireGuard service + systemd: + name: wg-quick@wg0 + enabled: yes + state: started diff --git a/roles/wireguard/templates/wg0.conf.j2 b/roles/wireguard/templates/wg0.conf.j2 new file mode 100644 index 0000000..397eb37 --- /dev/null +++ b/roles/wireguard/templates/wg0.conf.j2 @@ -0,0 +1,17 @@ +[Interface] +PrivateKey = {{ wireguard_private_key }} +Address = {{ wireguard_ip }}/24 +ListenPort = {{ wireguard_port }} + +{% for peer in wireguard_peers %} +{% if peer.ip != wireguard_ip %} +[Peer] +# {{ peer.name }} +PublicKey = {{ peer.pubkey }} +AllowedIPs = {{ peer.ip }}/32 +{% if peer.endpoint %} +Endpoint = {{ peer.endpoint }} +PersistentKeepalive = 25 +{% endif %} +{% endif %} +{% endfor %} diff --git a/roles/wireguard/wg0.conf.j2 b/roles/wireguard/wg0.conf.j2 new file mode 100644 index 0000000..fddb87c --- /dev/null +++ b/roles/wireguard/wg0.conf.j2 @@ -0,0 +1,16 @@ +[Interface] +PrivateKey = {{ host_private_key }} +Address = {{ wg_ip }}/24 +ListenPort = {{ wg_port }} + +{% for peer in wireguard_peers %} +{% if peer.ip != wg_ip %} +[Peer] +PublicKey = {{ peer.pubkey }} +AllowedIPs = {{ peer.ip }}/32 +{% if peer.endpoint %} +Endpoint = {{ peer.endpoint }} +PersistentKeepalive = 25 +{% endif %} +{% endif %} +{% endfor %} diff --git a/site.yaml b/site.yaml new file mode 100644 index 0000000..e69de29 diff --git a/site.yml b/site.yml new file mode 100644 index 0000000..6323406 --- /dev/null +++ b/site.yml @@ -0,0 +1,7 @@ +--- +- name: Configure WireGuard and Garage Cluster + hosts: garage_nodes + become: true + roles: + - wireguard + - garage diff --git a/uv-x86_64-unknown-linux-gnu.tar.gz b/uv-x86_64-unknown-linux-gnu.tar.gz new file mode 100644 index 0000000..963a447 Binary files /dev/null and b/uv-x86_64-unknown-linux-gnu.tar.gz differ