Some updates, mostly problems with postgres permissions and logs permissions, mess with improper master management service processing from .env
This commit is contained in:
parent
b3fee7eec2
commit
2786f5ba72
@ -1,4 +1,35 @@
|
|||||||
# This file should be generated from ansible/templates/.env.ytdlp.j2
|
# This file is managed by Ansible. Do not edit manually.
|
||||||
# Do not edit manually - your changes will be overwritten.
|
|
||||||
#
|
# --- Common Settings ---
|
||||||
# To generate this file, run the Ansible playbook that processes the templates.
|
HOSTNAME="af-green"
|
||||||
|
COMPOSE_PROJECT_NAME="ytdlp-ops-management"
|
||||||
|
TZ="Europe/Moscow"
|
||||||
|
service_role="management"
|
||||||
|
|
||||||
|
# --- Docker Image Settings ---
|
||||||
|
YTDLP_OPS_IMAGE="pangramia/ytdlp-ops-server:latest"
|
||||||
|
AIRFLOW_IMAGE_NAME="pangramia/ytdlp-ops-airflow:latest"
|
||||||
|
|
||||||
|
# --- Network Settings ---
|
||||||
|
ENVOY_PORT=9080
|
||||||
|
ENVOY_ADMIN_PORT=9901
|
||||||
|
YTDLP_BASE_PORT=9090
|
||||||
|
YTDLP_WORKERS=3
|
||||||
|
MANAGEMENT_SERVICE_PORT=9091
|
||||||
|
REDIS_PORT=52909
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
|
||||||
|
# --- Security Settings ---
|
||||||
|
REDIS_PASSWORD="rOhTAIlTFFylXsjhqwxnYxDChFc"
|
||||||
|
POSTGRES_PASSWORD="pgdb_pwd_A7bC2xY9zE1wV5uP"
|
||||||
|
AIRFLOW_ADMIN_PASSWORD="2r234sdfrt3q454arq45q355"
|
||||||
|
FLOWER_PASSWORD="dO4eXm7UkF81OdMvT8E2tIKFtPYPCzyzwlcZ4RyOmCsmG4qzrNFqM5sNTOT9"
|
||||||
|
|
||||||
|
# --- User and Group IDs ---
|
||||||
|
AIRFLOW_UID=1003
|
||||||
|
AIRFLOW_GID=1001
|
||||||
|
|
||||||
|
# --- Master-specific settings ---
|
||||||
|
MASTER_HOST_IP=89.253.221.173
|
||||||
|
# Camoufox is not used on master, but the config generator expects the variable.
|
||||||
|
CAMOUFOX_PROXIES=
|
||||||
|
|||||||
@ -149,6 +149,7 @@ services:
|
|||||||
retries: 5
|
retries: 5
|
||||||
start_period: 5s
|
start_period: 5s
|
||||||
restart: always
|
restart: always
|
||||||
|
user: "999:999"
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
# Redis is limited to 7.2-bookworm due to licencing change
|
# Redis is limited to 7.2-bookworm due to licencing change
|
||||||
|
|||||||
@ -78,7 +78,7 @@ services:
|
|||||||
- "--service-role"
|
- "--service-role"
|
||||||
- "{{ service_role }}"
|
- "{{ service_role }}"
|
||||||
|
|
||||||
{% if service_role != 'management' %}
|
{% if service_role is defined and service_role != 'management' %}
|
||||||
# --- Parameters for worker/all-in-one roles ONLY ---
|
# --- Parameters for worker/all-in-one roles ONLY ---
|
||||||
- "--script-dir"
|
- "--script-dir"
|
||||||
- "/app"
|
- "/app"
|
||||||
@ -100,9 +100,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
context-data:
|
context-data:
|
||||||
|
|
||||||
{% if service_role == 'management' or not camoufox_proxies %}
|
|
||||||
networks:
|
networks:
|
||||||
proxynet:
|
proxynet:
|
||||||
name: airflow_proxynet
|
name: airflow_proxynet
|
||||||
external: true
|
external: true
|
||||||
{% endif %}
|
|
||||||
|
|||||||
@ -8,6 +8,6 @@ services:
|
|||||||
- ./.env
|
- ./.env
|
||||||
volumes:
|
volumes:
|
||||||
# Mount the entire project directory to access scripts and write output files
|
# Mount the entire project directory to access scripts and write output files
|
||||||
- ../:/app
|
- .:/app
|
||||||
command: >
|
command: >
|
||||||
sh -c "pip install jinja2 && python3 /app/generate_envoy_config.py"
|
sh -c "pip install jinja2 && python3 /app/generate_envoy_config.py"
|
||||||
|
|||||||
135
airflow/dags/ORCHESTRATOR.ru.md
Normal file
135
airflow/dags/ORCHESTRATOR.ru.md
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
# Архитектура и описание YTDLP Airflow DAGs
|
||||||
|
|
||||||
|
Этот документ описывает архитектуру и назначение DAG'ов, используемых для скачивания видео с YouTube. Система построена на модели непрерывного, самоподдерживающегося цикла для параллельной и отказоустойчивой обработки.
|
||||||
|
|
||||||
|
## Основной цикл обработки
|
||||||
|
|
||||||
|
Обработка выполняется двумя основными DAG'ами, которые работают в паре: оркестратор и воркер.
|
||||||
|
|
||||||
|
### `ytdlp_ops_orchestrator` (Система "зажигания")
|
||||||
|
|
||||||
|
- **Назначение:** Этот DAG действует как "система зажигания" для запуска обработки. Он запускается вручную для старта указанного количества параллельных циклов-воркеров.
|
||||||
|
- **Принцип работы:**
|
||||||
|
- Он **не** обрабатывает URL-адреса самостоятельно.
|
||||||
|
- Его единственная задача — запустить сконфигурированное количество DAG'ов `ytdlp_ops_worker_per_url`.
|
||||||
|
- Он передает всю необходимую конфигурацию (пул аккаунтов, подключение к Redis и т.д.) воркерам.
|
||||||
|
|
||||||
|
### `ytdlp_ops_worker_per_url` (Самоподдерживающийся воркер)
|
||||||
|
|
||||||
|
- **Назначение:** Этот DAG обрабатывает один URL и спроектирован для работы в непрерывном цикле.
|
||||||
|
- **Принцип работы:**
|
||||||
|
1. **Запуск:** Начальный запуск инициируется `ytdlp_ops_orchestrator`.
|
||||||
|
2. **Получение задачи:** Воркер извлекает один URL из очереди `_inbox` в Redis. Если очередь пуста, выполнение воркера завершается, и его "линия" обработки останавливается.
|
||||||
|
3. **Обработка:** Он взаимодействует с сервисом `ytdlp-ops-server` для получения `info.json` и прокси, после чего скачивает видео.
|
||||||
|
4. **Продолжение или остановка:**
|
||||||
|
- **В случае успеха:** Он запускает новый экземпляр самого себя, создавая непрерывный цикл для обработки следующего URL.
|
||||||
|
- **В случае сбоя:** Цикл прерывается (если `stop_on_failure` установлено в `True`), останавливая эту "линию" обработки. Это предотвращает остановку всей системы из-за одного проблемного URL или аккаунта.
|
||||||
|
|
||||||
|
## Управляющие DAG'и
|
||||||
|
|
||||||
|
### `ytdlp_mgmt_proxy_account`
|
||||||
|
|
||||||
|
- **Назначение:** Это основной инструмент для мониторинга и управления состоянием ресурсов, используемых `ytdlp-ops-server`.
|
||||||
|
- **Функциональность:**
|
||||||
|
- **Просмотр статусов:** Позволяет увидеть текущий статус всех прокси и аккаунтов (например, `ACTIVE`, `BANNED`, `RESTING`).
|
||||||
|
- **Управление прокси:** Позволяет вручную банить, разбанивать или сбрасывать статус прокси.
|
||||||
|
- **Управление аккаунтами:** Позволяет вручную банить или разбанивать аккаунты.
|
||||||
|
|
||||||
|
### `ytdlp_mgmt_queues`
|
||||||
|
|
||||||
|
- **Назначение:** Предоставляет набор инструментов для управления очередями Redis, используемыми в конвейере обработки.
|
||||||
|
- **Функциональность (через параметр `action`):**
|
||||||
|
- `add_videos`: Добавление одного или нескольких URL-адресов YouTube в очередь.
|
||||||
|
- `clear_queue`: Очистка (удаление) указанного ключа Redis.
|
||||||
|
- `list_contents`: Просмотр содержимого ключа Redis (списка или хэша).
|
||||||
|
- `check_status`: Проверка общего состояния очередей (тип, размер).
|
||||||
|
- `requeue_failed`: Перемещение всех URL-адресов из очереди сбоев `_fail` обратно в очередь `_inbox` для повторной обработки.
|
||||||
|
|
||||||
|
## Стратегия управления ресурсами (Прокси и Аккаунты)
|
||||||
|
|
||||||
|
Система использует интеллектуальную стратегию для управления жизненным циклом и состоянием аккаунтов и прокси, чтобы максимизировать процент успеха и минимизировать блокировки.
|
||||||
|
|
||||||
|
- **Жизненный цикл аккаунта ("Cooldown"):**
|
||||||
|
- Чтобы предотвратить "выгорание", аккаунты автоматически переходят в состояние "отдыха" (`RESTING`) после периода интенсивного использования.
|
||||||
|
- По истечении периода отдыха они автоматически возвращаются в `ACTIVE` и снова становятся доступными для воркеров.
|
||||||
|
|
||||||
|
- **Умная стратегия банов:**
|
||||||
|
- **Сначала бан аккаунта:** При возникновении серьезной ошибки (например, `BOT_DETECTED`) система наказывает **только аккаунт**, который вызвал сбой. Прокси при этом продолжает работать.
|
||||||
|
- **Бан прокси по "скользящему окну":** Прокси банится автоматически, только если он демонстрирует **систематические сбои с РАЗНЫМИ аккаунтами** за короткий промежуток времени. Это является надежным индикатором того, что проблема именно в прокси.
|
||||||
|
|
||||||
|
- **Мониторинг:**
|
||||||
|
- DAG `ytdlp_mgmt_proxy_account` является основным инструментом для мониторинга. Он показывает текущий статус всех ресурсов, включая время, оставшееся до активации забаненных или отдыхающих аккаунтов.
|
||||||
|
- Граф выполнения DAG `ytdlp_ops_worker_per_url` теперь явно показывает шаги, такие как `assign_account`, `get_token`, `ban_account`, `retry_get_token`, что делает процесс отладки более наглядным.
|
||||||
|
|
||||||
|
## Внешние сервисы
|
||||||
|
|
||||||
|
### `ytdlp-ops-server` (Thrift Service)
|
||||||
|
|
||||||
|
- **Назначение:** Внешний сервис, который предоставляет аутентификационные данные (токены, cookies, proxy) для скачивания видео.
|
||||||
|
- **Взаимодействие:** Worker DAG (`ytdlp_ops_worker_per_url`) обращается к этому сервису перед началом загрузки для получения необходимых данных для `yt-dlp`.
|
||||||
|
|
||||||
|
## Логика работы Worker DAG (`ytdlp_ops_worker_per_url`)
|
||||||
|
|
||||||
|
Этот DAG является "рабочей лошадкой" системы. Он спроектирован как самоподдерживающийся цикл для обработки одного URL за запуск.
|
||||||
|
|
||||||
|
### Задачи и их назначение:
|
||||||
|
|
||||||
|
- **`pull_url_from_redis`**: Извлекает один URL из очереди `_inbox` в Redis. Если очередь пуста, DAG завершается со статусом `skipped`, останавливая эту "линию" обработки.
|
||||||
|
- **`assign_account`**: Выбирает аккаунт для выполнения задачи. Он будет повторно использовать тот же аккаунт, который был успешно использован в предыдущем запуске в своей "линии" (привязка аккаунта). Если это первый запуск, он выбирает случайный аккаунт.
|
||||||
|
- **`get_token`**: Основная задача. Она обращается к `ytdlp-ops-server` для получения `info.json`.
|
||||||
|
- **`handle_bannable_error_branch`**: Если `get_token` завершается с ошибкой, требующей бана, эта задача-развилка решает, что делать дальше, в зависимости от политики `on_bannable_failure`.
|
||||||
|
- **`ban_account_and_prepare_for_retry`**: Если политика разрешает повтор, эта задача банит сбойный аккаунт и выбирает новый для повторной попытки.
|
||||||
|
- **`retry_get_token`**: Выполняет вторую попытку получить токен с новым аккаунтом.
|
||||||
|
- **`ban_second_account_and_proxy`**: Если и вторая попытка неудачна, эта задача банит второй аккаунт и использованный прокси.
|
||||||
|
- **`download_and_probe`**: Если `get_token` (или `retry_get_token`) завершилась успешно, эта задача использует `yt-dlp` для скачивания медиа и `ffmpeg` для проверки целостности скачанного файла.
|
||||||
|
- **`mark_url_as_success`**: Если `download_and_probe` завершилась успешно, эта задача записывает результат в хэш `_result` в Redis.
|
||||||
|
- **`handle_generic_failure`**: Если любая из основных задач завершается с неисправимой ошибкой, эта задача записывает подробную информацию об ошибке в хэш `_fail` в Redis.
|
||||||
|
- **`decide_what_to_do_next`**: Задача-развилка, которая запускается после успеха или неудачи. Она решает, продолжать ли цикл.
|
||||||
|
- **`trigger_self_run`**: Задача, которая фактически запускает следующий экземпляр DAG, создавая непрерывный цикл.
|
||||||
|
|
||||||
|
## Механизм привязки воркеров к конкретным машинам (Worker Pinning / Affinity)
|
||||||
|
|
||||||
|
Для обеспечения того, чтобы все задачи, связанные с обработкой одного конкретного URL, выполнялись на одной и той же машине (воркере), система использует комбинацию из трех компонентов: Оркестратора, Диспетчера и специального хука Airflow.
|
||||||
|
|
||||||
|
### 1. `ytdlp_ops_orchestrator` (Оркестратор)
|
||||||
|
|
||||||
|
- **Роль:** Инициирует процесс обработки.
|
||||||
|
- **Действие:** При запуске он создает несколько DAG-запусков `ytdlp_ops_dispatcher`. Каждый такой запуск предназначен для обработки одного URL.
|
||||||
|
- **Передача параметров:** Оркестратор передает свои параметры конфигурации (например, `account_pool`, `redis_conn_id`, `service_ip`) каждому запуску диспетчера.
|
||||||
|
|
||||||
|
### 2. `ytdlp_ops_dispatcher` (Диспетчер)
|
||||||
|
|
||||||
|
- **Роль:** Основной механизм обеспечения привязки.
|
||||||
|
- **Действие:**
|
||||||
|
1. **Получает URL:** Извлекает один URL из очереди Redis (`_inbox`).
|
||||||
|
2. **Определяет воркер:** Использует `socket.gethostname()` для определения имени текущей машины (воркера), на которой он выполняется.
|
||||||
|
3. **Формирует имя очереди:** Создает уникальное имя очереди для этого воркера, например, `queue-dl-dl-worker-1`.
|
||||||
|
4. **Запускает Worker DAG:** Инициирует запуск DAG `ytdlp_ops_worker_per_url`, передавая ему:
|
||||||
|
* Извлеченный `url_to_process`.
|
||||||
|
* Сформированное имя очереди `worker_queue` через параметр `conf`.
|
||||||
|
* Все остальные параметры, полученные от оркестратора.
|
||||||
|
- **Ключевой момент:** Именно на этом этапе устанавливается связь между конкретным URL и конкретным воркером, на котором началась обработка этого URL.
|
||||||
|
|
||||||
|
### 3. `task_instance_mutation_hook` (Хук изменения задач)
|
||||||
|
|
||||||
|
- **Расположение:** `airflow/config/custom_task_hooks.py`
|
||||||
|
- **Роль:** Является механизмом, который обеспечивает выполнение *всех* задач Worker DAG на нужной машине.
|
||||||
|
- **Как это работает:**
|
||||||
|
1. **Регистрация:** Хук регистрируется в конфигурации Airflow и вызывается перед запуском *каждой* задачи.
|
||||||
|
2. **Проверка DAG ID:** Хук проверяет, принадлежит ли задача (`TaskInstance`) DAG `ytdlp_ops_worker_per_url`.
|
||||||
|
3. **Извлечение `conf`:** Если да, он безопасно извлекает `conf` из `DagRun`, связанного с этой задачей.
|
||||||
|
4. **Изменение очереди:**
|
||||||
|
* Если в `conf` найден ключ `worker_queue` (что будет true для всех запусков, инициированных диспетчером), хук *переопределяет* стандартную очередь задачи на это значение.
|
||||||
|
* Это означает, что Airflow планировщик поставит эту задачу именно в ту очередь, которая прослушивается нужным воркером.
|
||||||
|
5. **Резервный вариант:** Если `worker_queue` не найден (например, DAG запущен вручную), задача возвращается в стандартную очередь `queue-dl`.
|
||||||
|
- **Ключевой момент:** Этот хук гарантирует, что *все последующие задачи* в рамках одного запуска `ytdlp_ops_worker_per_url` (например, `get_token`, `download_and_probe`, `mark_url_as_success`) будут выполнены на том же воркере, который изначально получил URL в диспетчере.
|
||||||
|
|
||||||
|
### Резюме
|
||||||
|
|
||||||
|
Комбинация `Оркестратор -> Диспетчер -> Хук` эффективно реализует привязку задач к воркерам:
|
||||||
|
|
||||||
|
1. **Оркестратор** запускает процесс.
|
||||||
|
2. **Диспетчер** связывает конкретный URL с конкретным воркером, определяя его имя хоста и передавая его как `worker_queue` в Worker DAG.
|
||||||
|
3. **Хук** гарантирует, что все задачи Worker DAG выполняются в очереди, соответствующей этому воркеру.
|
||||||
|
|
||||||
|
Это позволяет системе использовать локальные ресурсы воркера (например, кэш, временные файлы) эффективно и предсказуемо для обработки каждого отдельного URL.
|
||||||
@ -33,7 +33,7 @@ def load_dotenv(dotenv_path):
|
|||||||
"""
|
"""
|
||||||
if not os.path.exists(dotenv_path):
|
if not os.path.exists(dotenv_path):
|
||||||
logging.warning(f".env file not found at {dotenv_path}. Using system environment variables or defaults.")
|
logging.warning(f".env file not found at {dotenv_path}. Using system environment variables or defaults.")
|
||||||
return
|
return False
|
||||||
try:
|
try:
|
||||||
with open(dotenv_path) as f:
|
with open(dotenv_path) as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
@ -43,6 +43,7 @@ def load_dotenv(dotenv_path):
|
|||||||
key = key.strip()
|
key = key.strip()
|
||||||
value = value.strip()
|
value = value.strip()
|
||||||
# Remove surrounding quotes which are common in .env files
|
# Remove surrounding quotes which are common in .env files
|
||||||
|
# Handle both single and double quotes
|
||||||
if (value.startswith('"') and value.endswith('"')) or \
|
if (value.startswith('"') and value.endswith('"')) or \
|
||||||
(value.startswith("'") and value.endswith("'")):
|
(value.startswith("'") and value.endswith("'")):
|
||||||
value = value[1:-1]
|
value = value[1:-1]
|
||||||
@ -53,9 +54,10 @@ def load_dotenv(dotenv_path):
|
|||||||
if key not in os.environ:
|
if key not in os.environ:
|
||||||
os.environ[key] = value
|
os.environ[key] = value
|
||||||
logging.info(f"Successfully loaded variables from {dotenv_path}")
|
logging.info(f"Successfully loaded variables from {dotenv_path}")
|
||||||
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Failed to read or parse {dotenv_path}: {e}")
|
logging.error(f"Failed to read or parse {dotenv_path}: {e}")
|
||||||
# Continue, will use defaults or system env vars
|
return False
|
||||||
|
|
||||||
def _get_port_from_proxy_url(url: str) -> Optional[str]:
|
def _get_port_from_proxy_url(url: str) -> Optional[str]:
|
||||||
"""Extracts the port from a proxy URL string."""
|
"""Extracts the port from a proxy URL string."""
|
||||||
@ -94,9 +96,18 @@ def generate_configs():
|
|||||||
project_root = os.path.dirname(os.path.abspath(__file__)) # This will be /app
|
project_root = os.path.dirname(os.path.abspath(__file__)) # This will be /app
|
||||||
configs_dir = os.path.join(project_root, 'configs')
|
configs_dir = os.path.join(project_root, 'configs')
|
||||||
|
|
||||||
# Load .env from the 'configs' directory.
|
# Load .env from the project root ONLY - no fallback
|
||||||
dotenv_path = os.path.join(configs_dir, '.env')
|
dotenv_path = os.path.join(project_root, '.env')
|
||||||
load_dotenv(dotenv_path)
|
logging.info(f"Looking for .env file at: {dotenv_path}")
|
||||||
|
|
||||||
|
if os.path.exists(dotenv_path):
|
||||||
|
if load_dotenv(dotenv_path):
|
||||||
|
logging.info(f"Using .env file from: {dotenv_path}")
|
||||||
|
else:
|
||||||
|
logging.error(f"Failed to load .env file from: {dotenv_path}")
|
||||||
|
exit(1)
|
||||||
|
else:
|
||||||
|
logging.warning(f".env file not found at {dotenv_path}. Using system environment variables or defaults.")
|
||||||
|
|
||||||
# --- Common Configuration ---
|
# --- Common Configuration ---
|
||||||
ytdlp_workers_str = os.getenv('YTDLP_WORKERS', '3').strip()
|
ytdlp_workers_str = os.getenv('YTDLP_WORKERS', '3').strip()
|
||||||
@ -117,7 +128,13 @@ def generate_configs():
|
|||||||
env.globals['_get_port_from_proxy_url'] = _get_port_from_proxy_url
|
env.globals['_get_port_from_proxy_url'] = _get_port_from_proxy_url
|
||||||
|
|
||||||
# Get service role from environment to determine what to generate
|
# Get service role from environment to determine what to generate
|
||||||
service_role = os.getenv('SERVICE_ROLE', 'all-in-one')
|
# Ensure we strip any remaining quotes that might have slipped through
|
||||||
|
service_role = os.getenv('service_role', 'management')
|
||||||
|
# Additional stripping of quotes for robustness
|
||||||
|
if (service_role.startswith('"') and service_role.endswith('"')) or \
|
||||||
|
(service_role.startswith("'") and service_role.endswith("'")):
|
||||||
|
service_role = service_role[1:-1]
|
||||||
|
|
||||||
logging.info(f"Service role for generation: '{service_role}'")
|
logging.info(f"Service role for generation: '{service_role}'")
|
||||||
|
|
||||||
# --- Camoufox Configuration (only for worker/all-in-one roles) ---
|
# --- Camoufox Configuration (only for worker/all-in-one roles) ---
|
||||||
|
|||||||
@ -17,7 +17,7 @@ external_access_ips: []
|
|||||||
file_permissions: '0644'
|
file_permissions: '0644'
|
||||||
host_timezone: Europe/Moscow
|
host_timezone: Europe/Moscow
|
||||||
management_service_port: 9091
|
management_service_port: 9091
|
||||||
master_host_ip: 89.253.223.97
|
master_host_ip: 89.253.221.173
|
||||||
postgres_port: 5432
|
postgres_port: 5432
|
||||||
redis_port: 52909
|
redis_port: 52909
|
||||||
rsync_default_opts:
|
rsync_default_opts:
|
||||||
|
|||||||
22
ansible/host_vars/af-green.yml
Normal file
22
ansible/host_vars/af-green.yml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
# Variables for af-green
|
||||||
|
master_host_ip: 89.253.221.173
|
||||||
|
redis_port: 52909
|
||||||
|
shadowsocks_proxies:
|
||||||
|
sslocal-rust-1087:
|
||||||
|
server: "91.103.252.51"
|
||||||
|
server_port: 8388
|
||||||
|
local_port: 1087
|
||||||
|
vault_password_key: "vault_ss_password_1"
|
||||||
|
sslocal-rust-1086:
|
||||||
|
server: "62.60.178.45"
|
||||||
|
server_port: 8388
|
||||||
|
local_port: 1086
|
||||||
|
vault_password_key: "vault_ss_password_2"
|
||||||
|
sslocal-rust-1081:
|
||||||
|
server: "79.137.207.43"
|
||||||
|
server_port: 8388
|
||||||
|
local_port: 1081
|
||||||
|
vault_password_key: "vault_ss_password_2"
|
||||||
|
worker_proxies:
|
||||||
|
- "socks5://sslocal-rust-1087:1087"
|
||||||
22
ansible/host_vars/dl001.yml
Normal file
22
ansible/host_vars/dl001.yml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
# Variables for dl001
|
||||||
|
master_host_ip: 89.253.221.173
|
||||||
|
redis_port: 52909
|
||||||
|
shadowsocks_proxies:
|
||||||
|
sslocal-rust-1087:
|
||||||
|
server: "91.103.252.51"
|
||||||
|
server_port: 8388
|
||||||
|
local_port: 1087
|
||||||
|
vault_password_key: "vault_ss_password_1"
|
||||||
|
sslocal-rust-1086:
|
||||||
|
server: "62.60.178.45"
|
||||||
|
server_port: 8388
|
||||||
|
local_port: 1086
|
||||||
|
vault_password_key: "vault_ss_password_2"
|
||||||
|
sslocal-rust-1081:
|
||||||
|
server: "79.137.207.43"
|
||||||
|
server_port: 8388
|
||||||
|
local_port: 1081
|
||||||
|
vault_password_key: "vault_ss_password_2"
|
||||||
|
worker_proxies:
|
||||||
|
- "socks5://sslocal-rust-1087:1087"
|
||||||
22
ansible/host_vars/dl003.yml
Normal file
22
ansible/host_vars/dl003.yml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
# Variables for dl003
|
||||||
|
master_host_ip: 89.253.221.173
|
||||||
|
redis_port: 52909
|
||||||
|
shadowsocks_proxies:
|
||||||
|
sslocal-rust-1087:
|
||||||
|
server: "91.103.252.51"
|
||||||
|
server_port: 8388
|
||||||
|
local_port: 1087
|
||||||
|
vault_password_key: "vault_ss_password_1"
|
||||||
|
sslocal-rust-1086:
|
||||||
|
server: "62.60.178.45"
|
||||||
|
server_port: 8388
|
||||||
|
local_port: 1086
|
||||||
|
vault_password_key: "vault_ss_password_2"
|
||||||
|
sslocal-rust-1081:
|
||||||
|
server: "79.137.207.43"
|
||||||
|
server_port: 8388
|
||||||
|
local_port: 1081
|
||||||
|
vault_password_key: "vault_ss_password_2"
|
||||||
|
worker_proxies:
|
||||||
|
- "socks5://sslocal-rust-1087:1087"
|
||||||
@ -3,7 +3,8 @@
|
|||||||
# Edit cluster.yml and re-run the generator instead.
|
# Edit cluster.yml and re-run the generator instead.
|
||||||
|
|
||||||
[airflow_master]
|
[airflow_master]
|
||||||
af-test ansible_host=89.253.223.97 ansible_port=22
|
af-green ansible_host=89.253.221.173 ansible_port=22
|
||||||
|
|
||||||
[airflow_workers]
|
[airflow_workers]
|
||||||
dl002 ansible_host=62.60.178.54
|
dl003 ansible_host=62.60.245.103
|
||||||
|
dl001 ansible_host=109.107.189.106
|
||||||
|
|||||||
@ -47,6 +47,7 @@
|
|||||||
- "docker-compose-ytdlp-ops.yaml.j2"
|
- "docker-compose-ytdlp-ops.yaml.j2"
|
||||||
- "docker-compose.config-generate.yaml"
|
- "docker-compose.config-generate.yaml"
|
||||||
- "envoy.yaml.j2"
|
- "envoy.yaml.j2"
|
||||||
|
- "docker-compose.camoufox.yaml.j2"
|
||||||
|
|
||||||
- name: Create .env file for YT-DLP master service
|
- name: Create .env file for YT-DLP master service
|
||||||
template:
|
template:
|
||||||
|
|||||||
@ -1,55 +1,59 @@
|
|||||||
# This file is managed by Ansible.
|
# This file is managed by Ansible. Do not edit manually.
|
||||||
# Set the timezone for all services to ensure consistency in logs.
|
|
||||||
TZ=Europe/Moscow
|
|
||||||
|
|
||||||
|
# --- Common Settings ---
|
||||||
HOSTNAME="{{ inventory_hostname }}"
|
HOSTNAME="{{ inventory_hostname }}"
|
||||||
SERVICE_ROLE={{ service_role }}
|
COMPOSE_PROJECT_NAME="ytdlp-ops-{{ service_role | default('all-in-one') }}"
|
||||||
{% if server_identity is defined %}
|
TZ="{{ host_timezone }}"
|
||||||
SERVER_IDENTITY={{ server_identity }}
|
service_role={{ service_role | default('all-in-one') }}
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
# Passwords
|
# --- Docker Image Settings ---
|
||||||
|
YTDLP_OPS_IMAGE="{{ ytdlp_ops_image }}"
|
||||||
|
AIRFLOW_IMAGE_NAME="{{ airflow_image_name }}"
|
||||||
|
|
||||||
|
# --- Network Settings ---
|
||||||
|
ENVOY_PORT={{ envoy_port }}
|
||||||
|
ENVOY_ADMIN_PORT={{ envoy_admin_port }}
|
||||||
|
YTDLP_BASE_PORT={{ ytdlp_base_port }}
|
||||||
|
YTDLP_WORKERS={{ ytdlp_workers | default(3) }}
|
||||||
|
MANAGEMENT_SERVICE_PORT={{ management_service_port }}
|
||||||
|
REDIS_PORT={{ redis_port }}
|
||||||
|
POSTGRES_PORT={{ postgres_port }}
|
||||||
|
|
||||||
|
# --- Security Settings ---
|
||||||
REDIS_PASSWORD="{{ vault_redis_password }}"
|
REDIS_PASSWORD="{{ vault_redis_password }}"
|
||||||
POSTGRES_PASSWORD="{{ vault_postgres_password }}"
|
POSTGRES_PASSWORD="{{ vault_postgres_password }}"
|
||||||
|
|
||||||
# Common settings
|
|
||||||
AIRFLOW_UID={{ airflow_uid | default(1003) }}
|
|
||||||
AIRFLOW_GID={{ deploy_group_gid | default(1001) }}
|
|
||||||
YTDLP_BASE_PORT={{ ytdlp_base_port }}
|
|
||||||
REDIS_PORT={{ redis_port }}
|
|
||||||
|
|
||||||
# Master-specific settings
|
|
||||||
{% if 'master' in service_role or 'management' in service_role %}
|
|
||||||
AIRFLOW_ADMIN_PASSWORD="{{ vault_airflow_admin_password }}"
|
AIRFLOW_ADMIN_PASSWORD="{{ vault_airflow_admin_password }}"
|
||||||
FLOWER_PASSWORD="{{ vault_flower_password }}"
|
FLOWER_PASSWORD="{{ vault_flower_password }}"
|
||||||
AIRFLOW_VAR_MASTER_HOST_IP={{ hostvars[groups['airflow_master'][0]].ansible_host }}
|
|
||||||
# MASTER_HOST_IP is not needed on the master node itself for ytdlp-ops,
|
# --- User and Group IDs ---
|
||||||
# as it connects to Redis via the internal Docker service name 'redis'.
|
AIRFLOW_UID={{ airflow_uid | default(1003) }}
|
||||||
# It is defined for workers to connect back to the master.
|
AIRFLOW_GID={{ deploy_group_gid | default(1001) }}
|
||||||
|
|
||||||
|
# --- Master-specific settings ---
|
||||||
|
{% if 'master' in service_role or 'management' in service_role %}
|
||||||
|
MASTER_HOST_IP={{ hostvars[groups['airflow_master'][0]].ansible_host }}
|
||||||
# Camoufox is not used on master, but the config generator expects the variable.
|
# Camoufox is not used on master, but the config generator expects the variable.
|
||||||
CAMOUFOX_PROXIES=
|
CAMOUFOX_PROXIES=
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
# Worker-specific settings
|
# --- Worker-specific settings ---
|
||||||
{% if 'worker' in service_role %}
|
{% if 'worker' in service_role %}
|
||||||
AIRFLOW_PROJ_DIR={{ airflow_worker_dir }}
|
AIRFLOW_PROJ_DIR={{ airflow_worker_dir }}
|
||||||
MASTER_HOST_IP={{ hostvars[groups['airflow_master'][0]].ansible_host }}
|
MASTER_HOST_IP={{ hostvars[groups['airflow_master'][0]].ansible_host }}
|
||||||
|
|
||||||
# --- Envoy & Worker Configuration ---
|
# --- Envoy & Worker Configuration ---
|
||||||
ENVOY_PORT={{ envoy_port }}
|
ENVOY_BACKEND_ADDRESS=ytdlp-ops-service
|
||||||
ENVOY_ADMIN_PORT={{ envoy_admin_port }}
|
YTDLP_TIMEOUT=600
|
||||||
MANAGEMENT_SERVICE_PORT={{ management_service_port }}
|
|
||||||
YTDLP_WORKERS=4
|
|
||||||
|
|
||||||
# --- Camoufox (Browser) Configuration ---
|
# --- Camoufox (Browser) Configuration ---
|
||||||
CAMOUFOX_PROXIES="{{ (worker_proxies | default([])) | join(',') }}"
|
CAMOUFOX_PROXIES="{{ (worker_proxies | default([])) | join(',') }}"
|
||||||
VNC_PASSWORD="{{ vault_vnc_password }}"
|
VNC_PASSWORD="{{ vault_vnc_password }}"
|
||||||
CAMOUFOX_BASE_VNC_PORT={{ camoufox_base_vnc_port }}
|
CAMOUFOX_BASE_VNC_PORT={{ camoufox_base_vnc_port }}
|
||||||
CAMOUFOX_PORT=12345
|
CAMOUFOX_PORT={{ camoufox_port }}
|
||||||
|
|
||||||
# --- Account Manager Configuration ---
|
# --- Account Manager Configuration ---
|
||||||
ACCOUNT_ACTIVE_DURATION_MIN=7
|
ACCOUNT_ACTIVE_DURATION_MIN={{ account_active_duration_min | default(7) }}
|
||||||
ACCOUNT_COOLDOWN_DURATION_MIN=30
|
ACCOUNT_COOLDOWN_DURATION_MIN={{ account_cooldown_duration_min | default(30) }}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@ -88,7 +88,7 @@ shadowsocks_proxies:
|
|||||||
|
|
||||||
master:
|
master:
|
||||||
af-green:
|
af-green:
|
||||||
ip: 89.253.223.97
|
ip: 89.253.221.173
|
||||||
port: 22
|
port: 22
|
||||||
proxies:
|
proxies:
|
||||||
- "socks5://sslocal-rust-1087:1087"
|
- "socks5://sslocal-rust-1087:1087"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user