From fb5dcbc3afc132c289e3bb02d0db810b287f1fdf Mon Sep 17 00:00:00 2001 From: Sergey Antropoff Date: Sun, 26 Apr 2026 06:39:50 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=B0=D0=B4=D0=B4=D0=BE=D0=BD=20hysteria2-serve?= =?UTF-8?q?r=20+=20playbook.yml=20=D0=B4=D0=BB=D1=8F=20=D0=B2=D1=81=D0=B5?= =?UTF-8?q?=D1=85=20=D0=B0=D0=B4=D0=B4=D0=BE=D0=BD=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hysteria2-server: - Устанавливает Hysteria2 v2 на удалённый VPS (группа [hysteria2_server]) - TLS: selfsigned (IP, insecure=1) | acme (Let's Encrypt) | custom - Obfuscation salamander, masquerade, лимиты полосы - systemd-сервис, открытие firewall (ufw/firewalld) - Вывод готового URL hysteria2://... для vault_hysteria2_url - SSH с паролем: make addon-hysteria2-server ARGS="-k" (интерактивный ввод) playbook.yml: - addons/mediaserver/playbook.yml — hosts: k3s_master[0] - addons/hysteria2-server/playbook.yml — hosts: hysteria2_server Интеграция: - inventory/hosts.ini: группа [hysteria2_server] (закомментированный пример) - group_vars/all/addons.yml: addon_hysteria2_server - vault.yml.example: vault_hysteria2_server_password, vault_hysteria2_obfs_password - playbooks/addons.yml: оба аддона - Makefile: addon-hysteria2-server target --- Makefile | 6 +- addons/hysteria2-server/README.md | 266 ++++++++++++++++++ addons/hysteria2-server/playbook.yml | 7 + .../hysteria2-server/role/defaults/main.yml | 50 ++++ .../hysteria2-server/role/handlers/main.yml | 11 + addons/hysteria2-server/role/tasks/main.yml | 264 +++++++++++++++++ .../role/templates/config.yaml.j2 | 43 +++ .../role/templates/hysteria2.service.j2 | 21 ++ addons/mediaserver/playbook.yml | 7 + group_vars/all/addons.yml | 1 + group_vars/all/vault.yml.example | 9 +- inventory/hosts.ini | 8 + playbooks/addons.yml | 8 + 13 files changed, 699 insertions(+), 2 deletions(-) create mode 100644 addons/hysteria2-server/README.md create mode 100644 addons/hysteria2-server/playbook.yml create mode 100644 addons/hysteria2-server/role/defaults/main.yml create mode 100644 addons/hysteria2-server/role/handlers/main.yml create mode 100644 addons/hysteria2-server/role/tasks/main.yml create mode 100644 addons/hysteria2-server/role/templates/config.yaml.j2 create mode 100644 addons/hysteria2-server/role/templates/hysteria2.service.j2 create mode 100644 addons/mediaserver/playbook.yml diff --git a/Makefile b/Makefile index 79667f0..e198f7f 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ DOCKER_RUN := docker run --rm -it \ addon-harbor addon-gitea addon-owncloud addon-nextcloud \ addon-csi-s3 addon-csi-ceph addon-csi-glusterfs addon-vaultwarden \ addon-smtp-relay addon-vault addon-external-secrets \ - addon-jenkins addon-netbird addon-mediaserver \ + addon-jenkins addon-netbird addon-mediaserver addon-hysteria2-server \ add-node remove-node \ add-etcd-node remove-etcd-node \ etcd-backup etcd-restore etcd-list-snapshots \ @@ -412,6 +412,10 @@ addon-mediaserver: _check_env _check_image ## Установить MediaServer @printf "$(CYAN)Устанавливаю MediaServer стек...$(NC)\n" $(DOCKER_RUN) addon mediaserver $(ARGS) +addon-hysteria2-server: _check_env _check_image ## Установить Hysteria2 VPN сервер на удалённый VPS из группы [hysteria2_server] (ARGS="-k" для SSH пароля, ARGS="-k -K" для SSH+sudo) + @printf "$(CYAN)Устанавливаю Hysteria2 сервер на удалённый VPS...$(NC)\n" + $(DOCKER_RUN) addon hysteria2-server $(ARGS) + # Generic цель — любой аддон из addons//playbook.yml addon-%: _check_env _check_image @if [ ! -f "addons/$*/playbook.yml" ]; then \ diff --git a/addons/hysteria2-server/README.md b/addons/hysteria2-server/README.md new file mode 100644 index 0000000..a497d33 --- /dev/null +++ b/addons/hysteria2-server/README.md @@ -0,0 +1,266 @@ +# Hysteria2 Server + +Устанавливает [Hysteria2](https://v2.hysteria.network/) VPN-сервер на удалённый VPS. На выходе даёт готовый URL для вставки в Shadowrocket, NekoBox, Hiddify или `vault_hysteria2_url` (Prowlarr sidecar). + +## Что устанавливается + +- Бинарник `hysteria` последней версии с GitHub +- Системный пользователь `hysteria` +- Конфиг в `/etc/hysteria/config.yaml` +- systemd-сервис `hysteria2` (autostart) +- Правило firewall (ufw / firewalld) +- TLS: self-signed cert **или** Let's Encrypt (ACME) **или** свой сертификат + +## Быстрый старт + +### 1. Добавить VPS в inventory + +```ini +# inventory/hosts.ini +[hysteria2_server] +myvps ansible_host=1.2.3.4 ansible_user=root +``` + +### 2. Vault секреты + +```bash +make vault-edit +``` + +```yaml +# group_vars/all/vault.yml +vault_hysteria2_server_password: "my-secure-password-32chars+" +vault_hysteria2_obfs_password: "obfs-secret" # если obfs включён +``` + +### 3. Деплой + +**С SSH-ключом** (рекомендуется): +```bash +make addon-hysteria2-server +``` + +**С SSH-паролем** (ввод в терминале): +```bash +make addon-hysteria2-server ARGS="-k" +``` + +**С SSH-паролем + sudo-паролем**: +```bash +make addon-hysteria2-server ARGS="-k -K" +``` + +**На конкретный хост** (без inventory): +```bash +make addon-hysteria2-server ARGS="-i '1.2.3.4,' -u root -k" +``` + +После деплоя Ansible выведет готовый URL: +``` +vault_hysteria2_url: "hysteria2://password@1.2.3.4:443?insecure=1#MyVPS" +``` + +--- + +## Конфигурация + +### Режимы TLS + +#### Self-signed (по умолчанию) — без домена, IP-only + +```yaml +# group_vars/all/main.yml +hysteria2_server_tls_mode: "selfsigned" +``` + +Клиент подключается с `insecure=1`. URL автоматически получает `?insecure=1`. + +#### ACME — Let's Encrypt (нужен домен) + +```yaml +hysteria2_server_tls_mode: "acme" +hysteria2_server_domain: "vpn.example.com" +hysteria2_server_acme_email: "admin@example.com" +``` + +Требования: порт 80 открыт, DNS A-запись указывает на VPS. Hysteria2 сам получает и обновляет сертификат. + +#### Custom — свои cert/key файлы + +```yaml +hysteria2_server_tls_mode: "custom" +hysteria2_server_tls_cert_path: "/etc/hysteria/server.crt" +hysteria2_server_tls_key_path: "/etc/hysteria/server.key" +``` + +Сертификаты должны уже лежать на сервере до запуска роли. + +--- + +### Obfuscation (salamander) + +Скрывает протокол от DPI — важно если Hysteria2 блокируется провайдером: + +```yaml +hysteria2_server_obfs_enabled: true +``` + +```yaml +# vault.yml +vault_hysteria2_obfs_password: "random-obfs-phrase" +``` + +--- + +### Лимиты полосы на клиента + +```yaml +hysteria2_server_up_mbps: 100 # исходящий с сервера (= входящий у клиента) +hysteria2_server_down_mbps: 100 # входящий на сервер (= исходящий у клиента) +``` + +`0` — без ограничений. + +--- + +### Все переменные + +```yaml +hysteria2_server_version: "" # "" = автоопределение последней версии +hysteria2_server_port: 443 +hysteria2_server_password: "{{ vault_hysteria2_server_password }}" + +hysteria2_server_tls_mode: "selfsigned" # selfsigned | acme | custom +hysteria2_server_domain: "" +hysteria2_server_acme_email: "" +hysteria2_server_tls_cert_path: "/etc/hysteria/server.crt" +hysteria2_server_tls_key_path: "/etc/hysteria/server.key" + +hysteria2_server_obfs_enabled: false +hysteria2_server_obfs_password: "{{ vault_hysteria2_obfs_password | default('') }}" + +hysteria2_server_masquerade_enabled: true +hysteria2_server_masquerade_url: "https://bing.com/" + +hysteria2_server_up_mbps: 0 +hysteria2_server_down_mbps: 0 + +hysteria2_server_name: "MyVPS" # метка в URL (для клиентов) +``` + +--- + +## Подключение SSH + +### Ключ (рекомендуется) + +```bash +# Скопировать ключ на VPS +ssh-copy-id root@1.2.3.4 + +# Деплой +make addon-hysteria2-server +``` + +### Пароль + +```bash +# Ввод пароля в терминале: +make addon-hysteria2-server ARGS="-k" +``` + +Или хранить в vault (не рекомендуется для SSH): + +```yaml +# inventory/hosts.ini +[hysteria2_server] +myvps ansible_host=1.2.3.4 ansible_user=root ansible_ssh_pass="{{ vault_hysteria2_vps_ssh_password }}" +``` + +### Нестандартный SSH порт + +```ini +# inventory/hosts.ini +[hysteria2_server] +myvps ansible_host=1.2.3.4 ansible_user=root ansible_port=2222 +``` + +--- + +## Примеры inventory + +### Один VPS, root + ключ + +```ini +[hysteria2_server] +myvps ansible_host=1.2.3.4 ansible_user=root +``` + +### Один VPS, обычный пользователь + sudo + +```ini +[hysteria2_server] +myvps ansible_host=1.2.3.4 ansible_user=ubuntu +``` + +```bash +make addon-hysteria2-server ARGS="-K" # -K = prompt sudo password +``` + +### Несколько серверов (мульти-регион) + +```ini +[hysteria2_server] +vps-nl ansible_host=1.2.3.4 ansible_user=root +vps-de ansible_host=5.6.7.8 ansible_user=root +``` + +--- + +## Что делать с URL после деплоя + +Ansible выведет в конце: + +``` +vault_hysteria2_url: "hysteria2://mypassword@1.2.3.4:443?insecure=1&obfs=salamander&obfs-password=secret#MyVPS" +``` + +**Вариант 1 — вставить в vault для Prowlarr:** +```yaml +# group_vars/all/vault.yml +vault_hysteria2_url: "hysteria2://mypassword@1.2.3.4:443?insecure=1#MyVPS" +``` +Затем: `make addon-mediaserver` + +**Вариант 2 — вставить в Shadowrocket / NekoBox / Hiddify:** +Скопируй строку `hysteria2://...` и добавь как новый профиль в клиент. + +--- + +## Управление сервисом + +```bash +# Статус +ssh root@1.2.3.4 systemctl status hysteria2 + +# Логи в реальном времени +ssh root@1.2.3.4 journalctl -u hysteria2 -f + +# Перезапуск после изменения конфига +ssh root@1.2.3.4 systemctl restart hysteria2 + +# Обновить до последней версии +make addon-hysteria2-server +``` + +## Обновление + +```bash +# Скачает последнюю версию и перезапустит сервис +make addon-hysteria2-server +``` + +Для фиксации версии: +```yaml +hysteria2_server_version: "app/v2.5.1" +``` diff --git a/addons/hysteria2-server/playbook.yml b/addons/hysteria2-server/playbook.yml new file mode 100644 index 0000000..3404a37 --- /dev/null +++ b/addons/hysteria2-server/playbook.yml @@ -0,0 +1,7 @@ +--- +- name: Install Hysteria2 VPN Server + hosts: hysteria2_server + gather_facts: true + become: true + roles: + - role: "{{ playbook_dir }}/role" diff --git a/addons/hysteria2-server/role/defaults/main.yml b/addons/hysteria2-server/role/defaults/main.yml new file mode 100644 index 0000000..324fdc9 --- /dev/null +++ b/addons/hysteria2-server/role/defaults/main.yml @@ -0,0 +1,50 @@ +--- +# ─── Hysteria2 Server ───────────────────────────────────────────────────────── +# Устанавливает Hysteria2 на удалённый VPS как системный сервис + +# Версия — пустая строка = авто-определение последней с GitHub +hysteria2_server_version: "" + +# Порт прослушивания +hysteria2_server_port: 443 + +# Пароль аутентификации клиентов +hysteria2_server_password: "{{ vault_hysteria2_server_password }}" + +# ─── TLS ────────────────────────────────────────────────────────────────────── +# Режим: acme | selfsigned | custom +# acme — Let's Encrypt (нужен домен + порт 80 открыт) +# selfsigned — самоподписанный сертификат (клиент: insecure=1) +# custom — указать свои cert/key файлы +hysteria2_server_tls_mode: "selfsigned" + +# Для acme: +hysteria2_server_domain: "" # домен, e.g. "vpn.example.com" +hysteria2_server_acme_email: "" # e-mail для Let's Encrypt + +# Для custom: +hysteria2_server_tls_cert_path: "/etc/hysteria/server.crt" +hysteria2_server_tls_key_path: "/etc/hysteria/server.key" + +# ─── Obfuscation (salamander) ───────────────────────────────────────────────── +# Скрывает протокол от DPI — рекомендуется для обхода блокировок +hysteria2_server_obfs_enabled: false +hysteria2_server_obfs_password: "{{ vault_hysteria2_obfs_password | default('') }}" + +# ─── Masquerade ─────────────────────────────────────────────────────────────── +# Делает трафик похожим на обычный HTTPS (важно для DPI) +hysteria2_server_masquerade_enabled: true +hysteria2_server_masquerade_url: "https://bing.com/" + +# ─── Лимиты полосы пропускания (на клиента) ─────────────────────────────────── +# 0 = без ограничений +hysteria2_server_up_mbps: 0 +hysteria2_server_down_mbps: 0 + +# ─── Пути ───────────────────────────────────────────────────────────────────── +hysteria2_server_install_dir: /usr/local/bin +hysteria2_server_config_dir: /etc/hysteria +hysteria2_server_log_dir: /var/log/hysteria + +# ─── Имя сервера (для метки в URL) ──────────────────────────────────────────── +hysteria2_server_name: "MyVPS" diff --git a/addons/hysteria2-server/role/handlers/main.yml b/addons/hysteria2-server/role/handlers/main.yml new file mode 100644 index 0000000..c351ecc --- /dev/null +++ b/addons/hysteria2-server/role/handlers/main.yml @@ -0,0 +1,11 @@ +--- +- name: Reload systemd + ansible.builtin.systemd: + daemon_reload: true + become: true + +- name: Restart hysteria2 + ansible.builtin.systemd: + name: hysteria2 + state: restarted + become: true diff --git a/addons/hysteria2-server/role/tasks/main.yml b/addons/hysteria2-server/role/tasks/main.yml new file mode 100644 index 0000000..a1afa51 --- /dev/null +++ b/addons/hysteria2-server/role/tasks/main.yml @@ -0,0 +1,264 @@ +--- +# ── Проверка обязательных переменных ───────────────────────────────────────── + +- name: Assert required variables + ansible.builtin.assert: + that: + - hysteria2_server_password != "" + - hysteria2_server_password != "vault_hysteria2_server_password" + fail_msg: | + Необходимо задать vault_hysteria2_server_password в group_vars/all/vault.yml + Пример: vault_hysteria2_server_password: "my-secure-password" + run_once: true + +- name: Assert ACME requires domain + ansible.builtin.assert: + that: + - hysteria2_server_domain != "" + - hysteria2_server_acme_email != "" + fail_msg: | + Для tls_mode=acme обязательны: + hysteria2_server_domain: "vpn.example.com" + hysteria2_server_acme_email: "admin@example.com" + when: hysteria2_server_tls_mode == "acme" + run_once: true + +# ── Определить архитектуру ─────────────────────────────────────────────────── + +- name: Set CPU architecture fact + ansible.builtin.set_fact: + _hy2_arch: "{{ 'arm64' if ansible_architecture == 'aarch64' else 'amd64' }}" + +# ── Получить последнюю версию с GitHub ─────────────────────────────────────── + +- name: Get latest Hysteria2 release from GitHub + ansible.builtin.uri: + url: https://api.github.com/repos/apernet/hysteria/releases/latest + return_content: true + headers: + Accept: "application/vnd.github.v3+json" + register: _hy2_github_release + when: hysteria2_server_version == "" + delegate_to: localhost + become: false + run_once: true + +- name: Set Hysteria2 version fact + ansible.builtin.set_fact: + _hy2_version: >- + {{ (hysteria2_server_version != '') + | ternary(hysteria2_server_version, + _hy2_github_release.json.tag_name | default('app/latest')) }} + run_once: true + +- name: Show Hysteria2 version + ansible.builtin.debug: + msg: "Installing Hysteria2 {{ _hy2_version }} ({{ _hy2_arch }})" + +# ── Установить зависимости ──────────────────────────────────────────────────── + +- name: Install dependencies + ansible.builtin.package: + name: + - curl + - openssl + - ca-certificates + state: present + become: true + +# ── Создать системного пользователя и директории ───────────────────────────── + +- name: Create hysteria group + ansible.builtin.group: + name: hysteria + system: true + state: present + become: true + +- name: Create hysteria user + ansible.builtin.user: + name: hysteria + group: hysteria + system: true + shell: /sbin/nologin + home: /var/lib/hysteria + create_home: false + comment: "Hysteria2 VPN Server" + become: true + +- name: Create directories + ansible.builtin.file: + path: "{{ item }}" + state: directory + owner: hysteria + group: hysteria + mode: "0750" + loop: + - "{{ hysteria2_server_config_dir }}" + - "{{ hysteria2_server_log_dir }}" + - /var/lib/hysteria + become: true + +# ── Скачать и установить бинарник ──────────────────────────────────────────── + +- name: Set download URL + ansible.builtin.set_fact: + _hy2_download_url: >- + https://github.com/apernet/hysteria/releases/download/{{ _hy2_version }}/hysteria-linux-{{ _hy2_arch }} + +- name: Download Hysteria2 binary + ansible.builtin.get_url: + url: "{{ _hy2_download_url }}" + dest: "{{ hysteria2_server_install_dir }}/hysteria" + mode: "0755" + owner: root + group: root + become: true + register: _hy2_binary_downloaded + notify: Restart hysteria2 + +# ── TLS сертификат ─────────────────────────────────────────────────────────── + +- name: Generate self-signed TLS certificate + ansible.builtin.command: > + openssl req -x509 -newkey rsa:4096 -keyout {{ hysteria2_server_tls_key_path }} + -out {{ hysteria2_server_tls_cert_path }} -sha256 -days 3650 -nodes + -subj "/CN={{ ansible_default_ipv4.address }}" + args: + creates: "{{ hysteria2_server_tls_cert_path }}" + become: true + when: hysteria2_server_tls_mode == "selfsigned" + notify: Restart hysteria2 + +- name: Set permissions on TLS files + ansible.builtin.file: + path: "{{ item }}" + owner: hysteria + group: hysteria + mode: "0600" + loop: + - "{{ hysteria2_server_tls_cert_path }}" + - "{{ hysteria2_server_tls_key_path }}" + become: true + when: hysteria2_server_tls_mode in ["selfsigned", "custom"] + +# ── Конфигурация ───────────────────────────────────────────────────────────── + +- name: Template Hysteria2 config + ansible.builtin.template: + src: config.yaml.j2 + dest: "{{ hysteria2_server_config_dir }}/config.yaml" + owner: hysteria + group: hysteria + mode: "0640" + become: true + notify: Restart hysteria2 + +# ── systemd сервис ──────────────────────────────────────────────────────────── + +- name: Template systemd service + ansible.builtin.template: + src: hysteria2.service.j2 + dest: /etc/systemd/system/hysteria2.service + owner: root + group: root + mode: "0644" + become: true + notify: + - Reload systemd + - Restart hysteria2 + +- name: Enable and start Hysteria2 + ansible.builtin.systemd: + name: hysteria2 + enabled: true + state: started + daemon_reload: true + become: true + +# ── Firewall ───────────────────────────────────────────────────────────────── + +- name: Check if ufw is active + ansible.builtin.command: ufw status + register: _ufw_status + changed_when: false + failed_when: false + become: true + +- name: Allow Hysteria2 port in ufw (TCP + UDP) + community.general.ufw: + rule: allow + port: "{{ hysteria2_server_port | string }}" + proto: "{{ item }}" + comment: "Hysteria2 VPN" + loop: + - tcp + - udp + become: true + when: "'active' in (_ufw_status.stdout | default(''))" + +- name: Check if firewalld is running + ansible.builtin.command: firewall-cmd --state + register: _firewalld_status + changed_when: false + failed_when: false + become: true + +- name: Allow Hysteria2 port in firewalld + ansible.posix.firewalld: + port: "{{ hysteria2_server_port }}/{{ item }}" + permanent: true + state: enabled + immediate: true + loop: + - tcp + - udp + become: true + when: "_firewalld_status.stdout | default('') == 'running'" + +# ── Проверить что сервис запустился ────────────────────────────────────────── + +- name: Wait for Hysteria2 to start listening + ansible.builtin.wait_for: + port: "{{ hysteria2_server_port }}" + host: "{{ ansible_default_ipv4.address }}" + timeout: 30 + when: hysteria2_server_tls_mode != "acme" + +- name: Verify Hysteria2 service status + ansible.builtin.command: systemctl status hysteria2 --no-pager + register: _hy2_service_status + changed_when: false + become: true + +# ── Вывести итоговый URL для клиента ───────────────────────────────────────── + +- name: Build client connection URL + ansible.builtin.set_fact: + _hy2_client_url: >- + hysteria2://{{ hysteria2_server_password | urlencode + }}@{{ ansible_default_ipv4.address }}:{{ hysteria2_server_port + }}{% if hysteria2_server_tls_mode == "selfsigned" %}?insecure=1{% else %}?insecure=0{% endif + %}{% if hysteria2_server_obfs_enabled and hysteria2_server_obfs_password != "" + %}&obfs=salamander&obfs-password={{ hysteria2_server_obfs_password | urlencode }}{% endif + %}#{{ hysteria2_server_name | urlencode }} + +- name: "=== Hysteria2 Server Ready ===" + ansible.builtin.debug: + msg: + - "╔══════════════════════════════════════════════════════════════╗" + - "║ Hysteria2 Server установлен ║" + - "╚══════════════════════════════════════════════════════════════╝" + - "" + - " Сервер: {{ ansible_default_ipv4.address }}:{{ hysteria2_server_port }}" + - " TLS: {{ hysteria2_server_tls_mode }}" + - " Obfs: {{ 'salamander' if hysteria2_server_obfs_enabled else 'отключён' }}" + - "" + - " ── URL для клиента (Shadowrocket / NekoBox / Hiddify) ───────" + - " {{ _hy2_client_url }}" + - "" + - " ── vault.yml для использования с Prowlarr ───────────────────" + - " vault_hysteria2_url: \"{{ _hy2_client_url }}\"" + - "" + - " Логи: journalctl -u hysteria2 -f" + - " Статус: systemctl status hysteria2" diff --git a/addons/hysteria2-server/role/templates/config.yaml.j2 b/addons/hysteria2-server/role/templates/config.yaml.j2 new file mode 100644 index 0000000..4b71bb7 --- /dev/null +++ b/addons/hysteria2-server/role/templates/config.yaml.j2 @@ -0,0 +1,43 @@ +listen: :{{ hysteria2_server_port }} + +{% if hysteria2_server_tls_mode == "acme" %} +acme: + domains: + - {{ hysteria2_server_domain }} + email: {{ hysteria2_server_acme_email }} + +{% elif hysteria2_server_tls_mode == "selfsigned" or hysteria2_server_tls_mode == "custom" %} +tls: + cert: {{ hysteria2_server_tls_cert_path }} + key: {{ hysteria2_server_tls_key_path }} + +{% endif %} +auth: + type: password + password: {{ hysteria2_server_password }} + +{% if hysteria2_server_obfs_enabled and hysteria2_server_obfs_password != "" %} +obfs: + type: salamander + salamander: + password: {{ hysteria2_server_obfs_password }} + +{% endif %} +{% if hysteria2_server_masquerade_enabled %} +masquerade: + type: proxy + proxy: + url: {{ hysteria2_server_masquerade_url }} + rewriteHost: true + +{% endif %} +{% if hysteria2_server_up_mbps | int > 0 or hysteria2_server_down_mbps | int > 0 %} +bandwidth: +{% if hysteria2_server_up_mbps | int > 0 %} + up: {{ hysteria2_server_up_mbps }} mbps +{% endif %} +{% if hysteria2_server_down_mbps | int > 0 %} + down: {{ hysteria2_server_down_mbps }} mbps +{% endif %} + +{% endif %} diff --git a/addons/hysteria2-server/role/templates/hysteria2.service.j2 b/addons/hysteria2-server/role/templates/hysteria2.service.j2 new file mode 100644 index 0000000..758da6d --- /dev/null +++ b/addons/hysteria2-server/role/templates/hysteria2.service.j2 @@ -0,0 +1,21 @@ +[Unit] +Description=Hysteria2 VPN Server +Documentation=https://v2.hysteria.network/ +After=network.target network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=hysteria +Group=hysteria +ExecStart={{ hysteria2_server_install_dir }}/hysteria server --config {{ hysteria2_server_config_dir }}/config.yaml +Restart=on-failure +RestartSec=5s +LimitNOFILE=1048576 + +# Логи +StandardOutput=append:{{ hysteria2_server_log_dir }}/hysteria2.log +StandardError=append:{{ hysteria2_server_log_dir }}/hysteria2.log + +[Install] +WantedBy=multi-user.target diff --git a/addons/mediaserver/playbook.yml b/addons/mediaserver/playbook.yml new file mode 100644 index 0000000..2cb0248 --- /dev/null +++ b/addons/mediaserver/playbook.yml @@ -0,0 +1,7 @@ +--- +- name: Install MediaServer (Plex, *arr, Transmission, Prowlarr+Hysteria2, Samba) + hosts: k3s_master[0] + gather_facts: false + become: true + roles: + - role: "{{ playbook_dir }}/role" diff --git a/group_vars/all/addons.yml b/group_vars/all/addons.yml index 18510f8..5379853 100644 --- a/group_vars/all/addons.yml +++ b/group_vars/all/addons.yml @@ -39,6 +39,7 @@ addon_external_secrets: false # External Secrets Operator → Vault/AWS/GCP addon_jenkins: false # Jenkins CI/CD (Helm, dynamic k8s agents, JCasC) addon_netbird: false # NetBird VPN (управляющий сервер + subnet router + exit node) addon_mediaserver: false # MediaServer — Plex, *arr, Transmission, Prowlarr+Hysteria2, Samba +addon_hysteria2_server: false # Hysteria2 VPN сервер на удалённый VPS (группа [hysteria2_server] в inventory) # ─── NFS Server ─────────────────────────────────────────────────────────────── nfs_exports: diff --git a/group_vars/all/vault.yml.example b/group_vars/all/vault.yml.example index 5845bca..a54e0bd 100644 --- a/group_vars/all/vault.yml.example +++ b/group_vars/all/vault.yml.example @@ -105,13 +105,20 @@ vault_plex_claim_token: "" # Hysteria2 SOCKS5 прокси (sidecar в Prowlarr) # # Способ 1 — вставить URL целиком из Shadowrocket / NekoBox / Hiddify: +# URL генерируется аддоном hysteria2-server автоматически (make addon-hysteria2-server) vault_hysteria2_url: "" -# Пример: vault_hysteria2_url: "hysteria2://mypassword@vps.example.com:443?insecure=0&obfs=salamander&obfs-password=secret" +# Пример: vault_hysteria2_url: "hysteria2://mypassword@vps.example.com:443?insecure=1&obfs=salamander&obfs-password=secret" # # Способ 2 — указать параметры по отдельности (если vault_hysteria2_url пустой): vault_hysteria2_server: "your-hysteria2-server.example.com:443" # host:port vault_hysteria2_auth: "your-hysteria2-password" # пароль аутентификации +# ─── Hysteria2 VPN сервер (аддон hysteria2-server) ──────────────────────────── +# Пароль для клиентов, подключающихся к VPS +vault_hysteria2_server_password: "changeme-hysteria2-server" +# Пароль obfuscation salamander (если hysteria2_server_obfs_enabled: true) +vault_hysteria2_obfs_password: "" + # Samba LAN-шара vault_samba_password: "changeme-samba" diff --git a/inventory/hosts.ini b/inventory/hosts.ini index 0f86b64..cc064d6 100644 --- a/inventory/hosts.ini +++ b/inventory/hosts.ini @@ -51,3 +51,11 @@ master01 # nas01 ansible_host=192.168.1.30 # devbox ansible_host=192.168.1.31 # proxy01 ansible_host=192.168.1.32 + +# ───────────────────────────────────────────────────────────────────────────── +# Hysteria2 VPN сервер (удалённый VPS — НЕ часть k3s кластера) +# Используется аддоном: make addon-hysteria2-server +# Подключение: SSH ключ (рекомендуется) или make addon-hysteria2-server ARGS="-k" +# ───────────────────────────────────────────────────────────────────────────── +[hysteria2_server] +# myvps ansible_host=1.2.3.4 ansible_user=root diff --git a/playbooks/addons.yml b/playbooks/addons.yml index a29f2ff..870cba3 100644 --- a/playbooks/addons.yml +++ b/playbooks/addons.yml @@ -279,3 +279,11 @@ when: addon_mediaserver | default(false) | bool roles: - role: "{{ playbook_dir }}/../addons/mediaserver/role" + +- name: Install Hysteria2 VPN Server on remote VPS + hosts: hysteria2_server + gather_facts: true + become: true + when: addon_hysteria2_server | default(false) | bool + roles: + - role: "{{ playbook_dir }}/../addons/hysteria2-server/role"