diff --git a/group_vars/all.yml b/group_vars/all.yml index e13ceb5..d04cb3e 100644 --- a/group_vars/all.yml +++ b/group_vars/all.yml @@ -203,69 +203,75 @@ ampache_logs_dir: "{{ ampache_base_dir }}/logs" ampache_mysql_dir: "{{ ampache_base_dir }}/mysql" ampache_port: "45134" -qbittorrent_base_dir: "/opt/qbittorrent" +qbittorrent_base_dir: "/mnt/service/qbittorrent" qbittorrent_config_dir: "{{ qbittorrent_base_dir }}/appdata" qbittorrent_downloads_dir: "{{ qbittorrent_base_dir }}/downloads" qbittorrent_puid: 1000 qbittorrent_pgid: 1000 qbittorrent_port_webui: 45135 qbittorrent_port_torrent: 6881 +qbittorrent_user: "qbittorrent" qbittorrent_password: "13qeadZC" - +qbittorrent_smb_credentials_dir: "/etc/smb-creds" +qbittorrent_smb_creds: + olimp: + username: "Olimp" + password: "13qeadZC" + file: "olimp" qbittorrent_shares: - # Windows-шара с входящими торрентами - name: downloads src: "//192.168.1.101/Downloads" dest: "/mnt/downloads" - opts: "uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8" + credential: "olimp" + opts: "rw,uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8,vers=3.0" - name: abook src: "//192.168.1.203/Abook" dest: "/mnt/video/abook" - opts: "uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8" + opts: "rw,uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8,vers=3.0,guest" - name: music src: "//192.168.1.203/Music" dest: "/mnt/audio" - opts: "uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8" + opts: "rw,uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8,vers=3.0,guest" - name: books src: "//192.168.1.203/Books" dest: "/mnt/books" - opts: "uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8" + opts: "rw,uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8,vers=3.0,guest" - name: films src: "//192.168.1.203/Films" dest: "/mnt/video/films" - opts: "uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8" + opts: "rw,uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8,vers=3.0,guest" - name: mult src: "//192.168.1.203/Mult" dest: "/mnt/video/mult" - opts: "uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8" + opts: "rw,uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8,vers=3.0,guest" - name: anime src: "//192.168.1.203/Anime" dest: "/mnt/video/anime" - opts: "uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8" + opts: "rw,uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8,vers=3.0,guest" - name: serial src: "//192.168.1.203/Serial" dest: "/mnt/video/serial" - opts: "uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8" + opts: "rw,uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8,vers=3.0,guest" - name: mserials src: "//192.168.1.203/Mserials" dest: "/mnt/video/mserials" - opts: "uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8" + opts: "rw,uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8,vers=3.0,guest" - name: doc src: "//192.168.1.203/Doc" dest: "/mnt/documents" - opts: "uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8" + opts: "rw,uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8,vers=3.0,guest" - name: ztube src: "//192.168.1.203/Ztube" dest: "/mnt/video/ztube" - opts: "uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8" + opts: "rw,uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8,vers=3.0,guest" - name: show src: "//192.168.1.203/Show" dest: "/mnt/video/show" - opts: "uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8" + opts: "rw,uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8,vers=3.0,guest" - name: games src: "//192.168.1.207/Games" dest: "/mnt/games" - opts: "uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8" + opts: "rw,uid={{ qbittorrent_puid }},gid={{ qbittorrent_pgid }},file_mode=0777,dir_mode=0777,iocharset=utf8,vers=3.0,guest" torrserver_base_dir: "/mnt/service/torrserver" torrserver_config_dir: "{{ torrserver_base_dir }}/config" diff --git a/roles/qbittorrent/tasks/main.yml b/roles/qbittorrent/tasks/main.yml index a044fcb..fd63444 100644 --- a/roles/qbittorrent/tasks/main.yml +++ b/roles/qbittorrent/tasks/main.yml @@ -1,166 +1,79 @@ --- -- name: Create qBittorrent base and local directories +- name: Создание директорий для qBittorrent file: path: "{{ item }}" state: directory - mode: '0755' owner: "{{ qbittorrent_puid }}" group: "{{ qbittorrent_pgid }}" + mode: '0755' loop: - - "{{ qbittorrent_base_dir }}" - "{{ qbittorrent_config_dir }}" - "{{ qbittorrent_downloads_dir }}" - - "/mnt/downloads" - - "/mnt/video" - - "/mnt/video/abook" - - "/mnt/video/films" - - "/mnt/video/mult" - - "/mnt/video/anime" - - "/mnt/video/serial" - - "/mnt/video/mserials" - - "/mnt/video/ztube" - - "/mnt/video/show" - - "/mnt/audio" - - "/mnt/books" - - "/mnt/documents" - - "/mnt/games" - tags: qbittorrent -- name: Ensure cifs-utils is installed - apt: - name: cifs-utils - state: present - tags: qbittorrent +- name: Создание директории для учетных данных SMB + file: + path: "{{ qbittorrent_smb_credentials_dir }}" + state: directory + mode: '0700' -- name: Create SMB credentials file - copy: - content: | - username=Zailon - password=Welc0metohell - dest: /etc/smb-creds-qbt - owner: root - group: root +- name: Создание файлов учетных данных SMB + template: + src: smb-credentials.j2 + dest: "{{ qbittorrent_smb_credentials_dir }}/{{ item.key }}" mode: '0600' - tags: qbittorrent + loop: "{{ qbittorrent_smb_creds | dict2items }}" + loop_control: + label: "{{ item.key }}" -- name: Mount all SMB shares +- name: Монтирование SMB-шаров mount: - src: "{{ item.src }}" path: "{{ item.dest }}" + src: "{{ item.src }}" fstype: cifs - opts: "{{ item.opts }},credentials=/etc/smb-creds-qbt" + opts: "{{ item.opts }}{% if item.credential is defined %},credentials={{ qbittorrent_smb_credentials_dir }}/{{ item.credential }}{% endif %}" state: mounted loop: "{{ qbittorrent_shares }}" - tags: qbittorrent + loop_control: + label: "{{ item.name }}" -- name: Verify write access for UID {{ qbittorrent_puid }} - command: runuser -u {{ qbittorrent_puid }} -- touch "{{ item.dest }}/.qbt_mount_test" - loop: "{{ qbittorrent_shares }}" - register: write_test - ignore_errors: yes - tags: qbittorrent - -- name: Fail if any share is not writable - fail: - msg: "❌ Нет прав на запись в шару {{ item.item.dest }} (проверьте SMB-сервер, права, UID/GID)" - when: item.failed - loop: "{{ write_test.results }}" - tags: qbittorrent - -- name: Generate password hash for qBittorrent - shell: | - echo -n "admin:Web UI:{{ qbittorrent_password }}" | md5sum | awk '{print $1}' - register: password_hash - changed_when: false - no_log: true - tags: qbittorrent - -- name: Create qBittorrent configuration with password hash - copy: - content: | - # Auto-generated qBittorrent configuration - [AutoRun] - enabled=false - [BitTorrent] - Session\DefaultSavePath=/downloads - Session\Port={{ qbittorrent_port_torrent }} - [Core] - AutoDeleteAddedTorrentFile=Never - [LegalNotice] - Accepted=true - [Preferences] - Connection\PortRangeMin={{ qbittorrent_port_torrent }} - Connection\PortRangeMax={{ qbittorrent_port_torrent }} - Downloads\SavePath=/downloads - Downloads\TempPath=/downloads/incomplete - WebUI\Address=* - WebUI\Port=8080 - WebUI\LocalHostAuth=false - WebUI\AuthSubnetWhitelist=192.168.1.0/24 - WebUI\UseUPnP=false - WebUI\ClickjackingProtection=false - WebUI\CSRFProtection=false - WebUI\HostHeaderValidation=false - WebUI\DomainList=192.168.1.201:{{ qbittorrent_port_webui }},localhost:{{ qbittorrent_port_webui }} - WebUI\MaxAuthenticationFailCount=-1 - WebUI\Username=admin - WebUI\Password_PBKDF2="@ByteArray({{ password_hash.stdout }}:100000)" - WebUI\Password_ha1=@ByteArray({{ password_hash.stdout }}) - Advanced\RecheckOnCompletion=false - dest: "{{ qbittorrent_config_dir }}/qBittorrent.conf" - owner: "{{ qbittorrent_puid }}" - group: "{{ qbittorrent_pgid }}" - mode: '0644' - tags: qbittorrent - -- name: Deploy docker-compose.yml +- name: Копирование docker-compose файла для qBittorrent template: src: docker-compose.yml.j2 dest: "{{ qbittorrent_base_dir }}/docker-compose.yml" - owner: root - group: root mode: '0644' - tags: qbittorrent -- name: Start qBittorrent container with docker compose +- name: Запуск qBittorrent контейнера community.docker.docker_compose_v2: project_src: "{{ qbittorrent_base_dir }}" state: present - pull: "always" - build: "never" - recreate: "always" - remove_orphans: yes - tags: qbittorrent -- name: Wait for qBittorrent to start +- name: Ожидание запуска qBittorrent wait_for: - host: "127.0.0.1" port: "{{ qbittorrent_port_webui }}" - timeout: 120 - delay: 5 - tags: qbittorrent + timeout: 60 -- name: Display access and mount info - debug: - msg: | - ✅ qBittorrent успешно развернут на {{ ansible_host }}! - 🔗 Доступ: http://{{ ansible_host }}:{{ qbittorrent_port_webui }} - 👤 Логин: admin | 🔑 Пароль: {{ qbittorrent_password }} - 📁 Локальные точки монтирования: - {% for share in qbittorrent_shares %} - - {{ share.name }} → {{ share.dest }} - {% endfor %} - 💡 Совет: в веб-интерфейсе создайте категории («Фильмы», «Сериалы», «Аниме») и укажите пути: - - Фильмы → /mnt/video/films - - Сериалы → /mnt/video/serial - - Аниме → /mnt/video/anime - - Мультфильмы → /mnt/video/mult - - Мультсериалы → /mnt/video/mserials - - Аудиокниги → /mnt/video/abook - - Музыка → /mnt/audio - - Книги → /mnt/books - - Документалистика → /mnt/documents - - Игры → /mnt/games - - YouTube → /mnt/video/ztube - - Шоу → /mnt/video/show - tags: qbittorrent \ No newline at end of file +- name: Настройка пользователя qBittorrent + uri: + url: "http://localhost:{{ qbittorrent_port_webui }}/api/v2/auth/login" + method: POST + body_format: form-urlencoded + body: + username: "admin" + password: "adminadmin" + status_code: 200 + register: login_response + until: login_response.status == 200 + retries: 10 + delay: 5 + +- name: Смена пароля по умолчанию + uri: + url: "http://localhost:{{ qbittorrent_port_webui }}/api/v2/app/setPreferences" + method: POST + body_format: json + body: + json: '{"web_ui":{"username":"{{ qbittorrent_user }}","password":"{{ qbittorrent_password }}","session_timeout":3600}}' + headers: + Cookie: "{{ login_response.set_cookie }}" + status_code: 200 + when: login_response.status == 200 \ No newline at end of file diff --git a/roles/qbittorrent/templates/docker-compose.yml.j2 b/roles/qbittorrent/templates/docker-compose.yml.j2 index aee4646..73eeb5c 100644 --- a/roles/qbittorrent/templates/docker-compose.yml.j2 +++ b/roles/qbittorrent/templates/docker-compose.yml.j2 @@ -9,13 +9,13 @@ services: - TZ={{ timezone }} - WEBUI_PORT=8080 volumes: - - {{ qbittorrent_config_dir }}:/config - - {{ qbittorrent_downloads_dir }}:/downloads - {% for share in qbittorrent_shares %} - - {{ share.dest }}:{{ share.dest }}:rw - {% endfor %} + - "{{ qbittorrent_config_dir }}:/config" + - "{{ qbittorrent_downloads_dir }}:/downloads" +{% for share in qbittorrent_shares %} + - "{{ share.dest }}:{{ share.dest }}:rw" +{% endfor %} ports: - "{{ qbittorrent_port_webui }}:8080" - - "6881:6881" - - "6881:6881/udp" + - "{{ qbittorrent_port_torrent }}:{{ qbittorrent_port_torrent }}/udp" + - "{{ qbittorrent_port_torrent }}:{{ qbittorrent_port_torrent }}/tcp" restart: unless-stopped \ No newline at end of file diff --git a/roles/qbittorrent/templates/smb-credentials.j2 b/roles/qbittorrent/templates/smb-credentials.j2 new file mode 100644 index 0000000..e52753b --- /dev/null +++ b/roles/qbittorrent/templates/smb-credentials.j2 @@ -0,0 +1,2 @@ +username={{ item.value.username }} +password={{ item.value.password }} \ No newline at end of file