Перейти к содержанию

Пакет B — задачи через SSH-доступ

Составлено 06.08.2026 · Требует ручного выполнения пользователем через ssh oswold@... Агент готовит команды и промпты, ты выполняешь и присылаешь вывод для верификации.

Правила: - По одной задаче за раз — не параллелим - Каждая команда с sudo выполняется тобой (я не могу через API) - После каждой задачи — вывод в чат, я обновлю KB и TODO - Секреты (новые ключи, токены) никогда в чат — только в Vaultwarden, в чате только "готово"


📋 Порядок выполнения

Задачи отсортированы: сначала быстрые + без риска простоя, потом сложные + требующие downtime.

Порядок # Задача Хост Downtime Риск Время
B1 27 Пароли роутера/Reg.ru/Hostkey → Vaultwarden локально нет нет 5 мин
B2 3 Продублировать OPENWEBUI_API_TOKEN в Vaultwarden ragserver нет нет 5 мин
B3 4 Диагностика DPI (какой SNI ловит Инетком) локально нет нет 10 мин
B4 5 AmneziaWG auto-connect дома локально нет нет 5 мин
B5 21 Security headers в nginx на ragserver ragserver reload низкий 10 мин
B6 6 Cron для sync-to-openwebui.sh ragserver нет низкий 15 мин
B7 23 Зафиксировать версию образа Vaultwarden VPS 30 сек низкий 15 мин
B8 26 Убрать дубликат MASQUERADE в amnezia-awg2 VPS нет низкий 10 мин
B9 25 Аудит клиентов AmneziaWG VPS нет нет 20 мин
B10 24 Переоформить awg-rag через Amnezia GUI VPS несколько сек средний 20 мин
B11 1 Ротировать QDRANT_API_KEY ragserver 30 сек средний 20 мин
B12 2 Ротировать POSTGRES_PASSWORD ragserver 1-2 мин высокий 30 мин
B13 17 Off-site бэкап Vaultwarden (VPS → ragserver) VPS + ragserver нет низкий 30 мин
B14 19 Расширить бэкапы на AmneziaWG VPS нет низкий 20 мин
B15 20 Бэкап /opt/rag-platform/data/ ragserver зависит низкий 30 мин
B16 22 SMTP для Vaultwarden VPS + Yandex 360 нет низкий 30 мин
B17 18 Test restore Vaultwarden ragserver нет нет 30 мин
B18 28 Мониторинг (Uptime Kuma) ragserver нет нет 30 мин
B19 36 Open WebUI API наружу для Perplexity VPS + ragserver reload средний 45 мин

Итого: ~7-8 часов работы, разбито на подходы по 30-60 минут.


🎯 Рекомендованные группировки

Если делать в один заход — группируй по хосту:

  • Только локально (B1, B3, B4) — 20 минут, полностью без SSH
  • Ragserver, лёгкое (B2, B5, B6) — 30 минут
  • VPS, лёгкое (B7, B8, B9, B10) — 60 минут
  • Ротация секретов (B11, B12) — 50 минут, требует внимания
  • Бэкапы (B13, B14, B15, B17) — 2 часа
  • Мониторинг + SMTP + API (B16, B18, B19) — 1.5 часа

B1. Пароли роутера/Reg.ru/Hostkey → Vaultwarden

Задача 27 в TODO. Хост: локально (Vaultwarden UI).

Проще всего сделать сейчас пока не забыли. Открой https://vault.alatyr-service.ru (или через VPN если DPI режет), заведи три записи:

Название Логин URL
Router ASUS RT-N12E (192.168.1.1) admin http://192.168.1.1
Reg.ru — DNS панель (твой email/логин) https://www.reg.ru/
Hostkey — панель управления VPS (твой логин) https://hostkey.com/

После завершения: напиши "B1 done" — я обновлю TODO.


B2. Продублировать OPENWEBUI_API_TOKEN в Vaultwarden

Задача 3 в TODO. Хост: ragserver 192.168.1.200 (SSH).

ssh oswold@192.168.1.200
# Извлекаем токен из .env (в чат НЕ копируй!)
sudo grep OPENWEBUI_API_TOKEN /opt/rag-sync/.env

Открываешь Vaultwarden в браузере → создаёшь запись: - Название: RAG sync — OpenWebUI API token - Логин: perplexity-agent (или чей токен) - Пароль: вставляешь значение из вывода - URL: https://192.168.1.200:3000/

После завершения: "B2 done", я поставлю ✅ в TODO.


B3. Диагностика DPI (SNI-паттерн Инетком)

Задача 4 в TODO. Хост: локально с домашнего Wi-Fi (без VPN!).

Отключи AmneziaWG перед тестом. Выполни:

# 1. Основной домен — должен упасть на ERR_CONNECTION_RESET
curl -v https://vault.alatyr-service.ru 2>&1 | head -30

# 2. Тот же IP, другой SNI — работает?
curl -v --resolve vw.alatyr-service.ru:443:176.99.153.164 https://vw.alatyr-service.ru 2>&1 | head -20
curl -v --resolve pw.alatyr-service.ru:443:176.99.153.164 https://pw.alatyr-service.ru 2>&1 | head -20
curl -v --resolve test.alatyr-service.ru:443:176.99.153.164 https://test.alatyr-service.ru 2>&1 | head -20

# 3. Прямо по IP без SNI — работает?
curl -vk https://176.99.153.164:8443/alive 2>&1 | head -30

# 4. Bonus — что режется по слову "vault":
curl -v https://vault.example.com 2>&1 | head -5   # если такого домена нет, ошибка DNS — норм

После завершения: пришли выводы (без BODY, только заголовки/ошибки), я разберу и запишу в vaultwarden.md § Повторная диагностика.


B4. AmneziaWG auto-connect дома

Задача 5 в TODO. Хост: локально.

Windows/Amnezia GUI: - Открой Amnezia app → Настройки → Общие - Включи "Auto-connect at startup" / "Запускать при старте системы" - Проверь что после ребута туннель поднимается сам

Android (если используешь): - Настройки телефона → VPN → AmneziaWG → Always-on VPN: ON - Block connections without VPN: рекомендую тоже ON (кроме LAN)

После завершения: "B4 done".


B5. Security headers в nginx на ragserver

Задача 21 в TODO. Хост: ragserver 192.168.1.200.

ssh oswold@192.168.1.200

# Бэкап перед правкой
sudo cp /etc/nginx/sites-enabled/rag.alatyr-service.ru /etc/nginx/sites-enabled/rag.alatyr-service.ru.bak.$(date +%Y%m%d)

# Правка (открой в редакторе)
sudo nano /etc/nginx/sites-enabled/rag.alatyr-service.ru

Добавь внутри server { ... } блока (после listen 443 или рядом с другими add_header):

    # Security headers (2026-08-06)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

Проверка + reload:

sudo nginx -t
sudo systemctl reload nginx

# Проверка снаружи (через VPN если ты не дома)
curl -sI https://rag.alatyr-service.ru | grep -iE "strict-transport|x-frame|x-content|referrer|permissions"

После завершения: пришли последний curl -sI — я запишу в nginx-ragserver-config.md.


B6. Cron для sync-to-openwebui.sh

Задача 6 в TODO. Хост: ragserver 192.168.1.200.

Рекомендую вариант A (user cron) — проще и достаточно надёжно для не-критичной задачи.

ssh oswold@192.168.1.200

# Проверить что скрипт есть и исполняем
ls -la /opt/rag-sync/sync-to-openwebui.sh
# Ожидаем -rwx------ 1 oswold oswold

# Создать директорию под лог
mkdir -p /opt/rag-sync/logs

# Открыть user crontab
crontab -e

Добавь строку:

# RAG KB sync каждые 15 минут (при первом прогоне 10 мин на 10 файлов, потом секунды)
*/15 * * * * /opt/rag-sync/sync-to-openwebui.sh >> /opt/rag-sync/logs/sync.log 2>&1

Сохрани, проверь:

crontab -l
# Подожди 15 минут, потом:
tail -50 /opt/rag-sync/logs/sync.log

После завершения: пришли crontab -l и первые строки нового прогона из sync.log.

Альтернатива (systemd user timer) — если хочешь надёжнее с ретраем: скажи, дам конфиг.


B7. Зафиксировать версию образа Vaultwarden

Задача 23 в TODO. Хост: VPS 46.17.99.183.

ssh oswold@46.17.99.183

# Проверить какая сейчас версия
sudo docker inspect vaultwarden --format '{{.Config.Image}}'
sudo docker exec vaultwarden /vaultwarden --version

# Посмотреть актуальные стабильные теги
curl -s https://hub.docker.com/v2/repositories/vaultwarden/server/tags/?page_size=20 | \
    grep -oE '"name":"[^"]+"' | head -20

Открой docker-compose.yml:

cd /opt/vaultwarden
sudo -e docker-compose.yml

Замени image: vaultwarden/server:latestimage: vaultwarden/server:1.35.0 (или актуальную стабильную из вывода выше — на 06.08.2026 самая свежая была 1.35.x, уточни).

Перезапуск:

sudo docker compose pull
sudo docker compose up -d
sudo docker logs vaultwarden --tail 30
# Проверить снаружи
curl -sI https://vault.alatyr-service.ru

После завершения: пришли версию, я обновлю vaultwarden.md.


B8. Проверить MASQUERADE в amnezia-awg2 ✅

Задача 26 закрыта 24.08.2026. Хост: VPS 46.17.99.183.

ssh oswold@46.17.99.183

# Проверить полные условия каждого правила
sudo docker exec amnezia-awg2 iptables -t nat -S POSTROUTING

Проверка показала, что похожие правила для 10.8.1.0/24 имеют разные выходные интерфейсы: eth0 и eth1. Они не являются дубликатами. Отдельное правило через awg0 нужно для маршрута rag-api к 10.8.1.12.

⚠ Не удалять правила по line number. Подробности: fix-masquerade-duplicate.md.


B9. Аудит клиентов AmneziaWG

Задача 25 в TODO. Хост: VPS 46.17.99.183.

ssh oswold@46.17.99.183

# Список всех клиентов из clientsTable
sudo cat /opt/amnezia/awg/clientsTable 2>/dev/null | \
    python3 -c "import json,sys; d=json.load(sys.stdin); [print(f'{c.get(\"clientName\",\"—\")}\t{c.get(\"clientId\",\"\")[:16]}') for c in d]"

# Кто когда последний раз подключался
sudo docker exec amnezia-awg2 wg show awg0 latest-handshakes

Открой Amnezia GUI на VPS (или через SSH-туннель на порт GUI): - Каждый клиент из clientsTable — есть в GUI? - В GUI есть, а latest-handshakes показывает 0 — никогда не подключались - Названия New client (X) от 04.08.2026 → определи по IP кого и переименуй, либо удали

После завершения: пришли список "оставить"/"удалить"/"переименовать", я запишу в amneziawg-tunnels.md.


B10. Переоформить awg-rag через Amnezia GUI

Задача 24 в TODO. Хост: VPS 46.17.99.183 + ragserver.

⚠ Есть риск на 30-60 секунд оставить ragserver без туннеля. Делаем аккуратно.

Шаг 1. В Amnezia GUI на VPS создать нового клиента awg-rag-new. Скачать конфиг.

Шаг 2. На ragserver:

ssh oswold@192.168.1.200

# Бэкап старого конфига
sudo cp /etc/amnezia/awg-rag.conf /etc/amnezia/awg-rag.conf.bak.$(date +%Y%m%d)

# Загрузить новый конфиг с VPS (или через scp с локальной машины)
# ... вставить новый содержание awg-rag-new.conf в /etc/amnezia/awg-rag.conf
sudo -e /etc/amnezia/awg-rag.conf

# Рестарт туннеля
sudo systemctl restart amneziawg-awg-rag  # или awg-quick@awg-rag
sudo wg show awg-rag  # или awg show awg-rag

Шаг 3. На VPS удалить старого клиента через GUI. Проверить что новый handshake активен:

sudo docker exec amnezia-awg2 wg show awg0 latest-handshakes | grep <ip-нового-клиента>

После завершения: пришли wg show awg-rag с ragserver.


B11. Ротировать QDRANT_API_KEY

RAG-02 в TODO. Хост: ragserver 192.168.1.200.

⚠ Downtime OpenWebUI ~30 сек.

ssh oswold@192.168.1.200
cd /opt/rag-platform

# Сгенерировать новый ключ (в чат НЕ вставляй!)
NEW_KEY=$(openssl rand -hex 32)
echo "$NEW_KEY" | wc -c   # должно быть 65 (64 символа + \n)

# Прямо в этом же терминале — сохранить в клипборд через файл
echo "$NEW_KEY" > /tmp/newkey.txt
chmod 600 /tmp/newkey.txt

Открой .env:

sudo -e /opt/rag-platform/.env

Замени QDRANT_API_KEY=... на QDRANT_API_KEY=<новый>. Сохрани.

Рестарт:

cd /opt/rag-platform
sudo docker compose down qdrant openwebui
sudo docker compose up -d qdrant openwebui

# Проверить логи
sudo docker logs rag-openwebui --tail 30 | grep -iE "qdrant|error"
sudo docker logs rag-qdrant --tail 20

Открой Vaultwarden → запись Qdrant API key (ragserver) → обнови значение из /tmp/newkey.txt. Затем удали временный файл:

shred -u /tmp/newkey.txt

После завершения: пришли последние строки логов OpenWebUI (проверяем что коннект к Qdrant есть).


B12. Ротировать POSTGRES_PASSWORD

RAG-03 в TODO. Хост: ragserver 192.168.1.200.

⚠ Downtime OpenWebUI 1-2 мин. Требует внимания к DATABASE_URL.

ssh oswold@192.168.1.200
cd /opt/rag-platform

# 1. Сгенерировать новый пароль (в чат НЕ вставляй!)
NEW_PW=$(openssl rand -hex 24)
echo "$NEW_PW" > /tmp/newpw.txt && chmod 600 /tmp/newpw.txt

# 2. Обновить пароль в самом Postgres
sudo docker exec -it rag-postgres psql -U postgres -c "ALTER USER postgres WITH PASSWORD '$NEW_PW';"
# ⚠ пароль ушёл в bash history! Затрём:
history -d $(history 1 | awk '{print $1}')

# 3. Проверить что можем зайти с новым паролем
sudo docker exec -e PGPASSWORD="$NEW_PW" rag-postgres psql -U postgres -c "SELECT current_user;"

Открой .env:

sudo -e /opt/rag-platform/.env

Обнови два места: - POSTGRES_PASSWORD=<новый> - DATABASE_URL=postgresql://postgres:<новый>@postgres:5432/openwebui (если он там)

Рестарт:

sudo docker compose down openwebui
sudo docker compose up -d openwebui

# Проверка (даём 30 сек на старт)
sleep 30
sudo docker logs rag-openwebui --tail 50 | grep -iE "postgres|database|error"
curl -sI http://192.168.1.200:3000/  # 200 OK ожидаем

Обнови в Vaultwarden запись Postgres — RAG platform. Затри временный файл:

shred -u /tmp/newpw.txt

После завершения: пришли последние строки логов + curl ответ.

Если что-то сломалось: откати .env из бэкапа .env.bak.<дата> (если делал) и обратно ALTER USER postgres WITH PASSWORD 'старый';.


B13. Off-site бэкап Vaultwarden (VPS → ragserver)

Задача 17 в TODO. Хост: VPS + ragserver.

Шаг 1. Подготовить приёмник на ragserver:

ssh oswold@192.168.1.200
sudo mkdir -p /opt/backups/vaultwarden
sudo chown oswold:oswold /opt/backups/vaultwarden
chmod 750 /opt/backups/vaultwarden

# SSH-ключ для приёма (генерим на VPS позже)
mkdir -p ~/.ssh && chmod 700 ~/.ssh

Шаг 2. Сгенерировать SSH-ключ на VPS (только для бэкапа):

ssh oswold@46.17.99.183
sudo -u root ssh-keygen -t ed25519 -f /root/.ssh/backup-to-ragserver -N ""
sudo cat /root/.ssh/backup-to-ragserver.pub
# Скопируй публичную часть

Шаг 3. На ragserver добавить ключ:

# На ragserver
echo "команда=rsync --server -vlogDtprze.iLsfxCIvu . /opt/backups/vaultwarden/ ssh-ed25519 AAAA... backup@vps" \
    >> ~/.ssh/authorized_keys
# ⚠ Ограничим ключ только rsync с force_command — безопаснее чем полный доступ

Шаг 4. Настроить туннель AmneziaWG (если VPS → ragserver не работает напрямую): Ragserver из VPN должен быть доступен на IP 10.8.1.12 (если это тот awg-rag). Проверь с VPS:

ssh oswold@46.17.99.183
ping -c 3 10.8.1.12
ssh -i /root/.ssh/backup-to-ragserver oswold@10.8.1.12 "hostname"

Шаг 5. Крон на VPS после ежедневного бэкапа (03:15):

sudo crontab -e
# Добавить:
# 20 3 * * * rsync -az -e "ssh -i /root/.ssh/backup-to-ragserver" /opt/vaultwarden/backups/*.gpg oswold@10.8.1.12:/opt/backups/vaultwarden/ >> /var/log/vw-offsite.log 2>&1

После завершения: пришли вывод первого прогона sudo rsync -avn ... (dry-run) — я проверю пути.


B14. Расширить бэкапы на AmneziaWG

Задача 19 в TODO. Хост: VPS.

ssh oswold@46.17.99.183

# Найти текущий backup-скрипт
sudo find /opt -name "backup*.sh" 2>/dev/null
sudo find /root -name "backup*.sh" 2>/dev/null
sudo crontab -l | grep -i backup

Добавь в существующий скрипт (или создай новый) блок:

# AmneziaWG config backup
BACKUP_TMP=$(mktemp -d)
sudo docker cp amnezia-awg2:/opt/amnezia/awg "$BACKUP_TMP/"
tar czf "$BACKUP_TMP/awg-$(date +%Y%m%d).tar.gz" -C "$BACKUP_TMP" awg
gpg --batch --yes --passphrase-file /root/.backup-pass \
    -c --cipher-algo AES256 "$BACKUP_TMP/awg-$(date +%Y%m%d).tar.gz"
mv "$BACKUP_TMP/awg-$(date +%Y%m%d).tar.gz.gpg" /opt/backups/awg/
rm -rf "$BACKUP_TMP"

После завершения: покажи ls -la /opt/backups/awg/ и что бэкап-крон включает.


B15. Бэкап /opt/rag-platform/data/

Задача 20 в TODO. Хост: ragserver.

Есть два подхода:

Вариант A — offline снапшот (простой, есть downtime):

ssh oswold@192.168.1.200
cd /opt/rag-platform
sudo docker compose down
sudo tar czf /opt/backups/rag-platform-$(date +%Y%m%d).tar.gz -C /opt/rag-platform data
sudo docker compose up -d

Вариант B — online (сложнее, без downtime): - Postgres: sudo docker exec rag-postgres pg_dumpall -U postgres > /opt/backups/pg-$(date +%Y%m%d).sql - Qdrant: snapshot API curl -X POST http://localhost:6333/collections/open-webui_knowledge/snapshots - OpenWebUI: копия data/webui.db (SQLite) на живой системе — риск повреждения, но обычно ок

Рекомендую A для еженедельного бэкапа + B ежедневно. Скажи какой вариант — дам полный скрипт + крон.


B16. SMTP для Vaultwarden

Задача 22 в TODO. Хост: VPS + Yandex 360.

Шаг 1 (Yandex 360, локально): - Создай ящик vault@alatyr-service.ru (или noreply@) в Y360 - Настройки → Пароли приложений → Создать → сохрани в Vaultwarden как Y360 — vault@ app password

Шаг 2 (VPS):

ssh oswold@46.17.99.183
cd /opt/vaultwarden
sudo -e .env

Добавь:

SMTP_HOST=smtp.yandex.ru
SMTP_FROM=vault@alatyr-service.ru
SMTP_FROM_NAME="Vaultwarden Alatyr"
SMTP_SECURITY=starttls
SMTP_PORT=587
SMTP_USERNAME=vault@alatyr-service.ru
SMTP_PASSWORD=<application password>
SMTP_TIMEOUT=15

Рестарт + тест:

sudo docker compose restart vaultwarden
sudo docker logs vaultwarden --tail 30
# В /admin панели → Send test email → на свой ящик

После завершения: "B16 done" + подтверди что тестовое письмо пришло.


B17. Test restore Vaultwarden

Задача 18 в TODO. Хост: ragserver или VPS в отдельном контейнере.

ssh oswold@192.168.1.200
mkdir -p /tmp/vw-restore-test
cd /tmp/vw-restore-test

# Скопировать последний бэкап
scp oswold@46.17.99.183:/opt/vaultwarden/backups/$(ssh oswold@46.17.99.183 'ls -1t /opt/vaultwarden/backups/*.gpg | head -1') .

# Расшифровать
gpg -d $(ls *.gpg) > backup.tar.gz
tar xzf backup.tar.gz

# Запустить временный Vaultwarden с этими данными на другом порту
docker run -d --name vw-test \
    -v $(pwd):/data \
    -p 8080:80 \
    vaultwarden/server:1.35.0

# Открыть http://192.168.1.200:8080 → залогиниться своим паролем
# Проверить что вижу свои записи

Уборка:

docker stop vw-test && docker rm vw-test
cd / && rm -rf /tmp/vw-restore-test

Задокументируй процедуру в vaultwarden.md § План восстановления.

После завершения: "B17 done" + сколько записей увидел.


B18. Мониторинг (Uptime Kuma)

Задача 28 в TODO. Хост: ragserver.

ssh oswold@192.168.1.200
sudo mkdir -p /opt/uptime-kuma/data
cd /opt/uptime-kuma

cat > docker-compose.yml <<'YAML'
services:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    container_name: uptime-kuma
    restart: unless-stopped
    ports:
      - "3001:3001"
    volumes:
      - ./data:/app/data
YAML

sudo docker compose up -d
sudo docker logs uptime-kuma --tail 20

Через nginx на VPS (или напрямую 192.168.1.200:3001 из LAN): - Добавь мониторы: - HTTPS https://vault.alatyr-service.ru — 200 OK - HTTPS https://rag.alatyr-service.ru — 200 OK - HTTPS https://alatyr-service.ru — 200 OK - HTTPS https://alatyr-taverna.ru — 200 OK - Ping 46.17.99.183 - Уведомления: Telegram-бот или email

После завершения: пришли скриншот дашборда или список мониторов.


B19. Open WebUI API наружу для Perplexity

Задача 36 в TODO. Хост: VPS + ragserver + локально.

Большая задача, разбита на подшаги:

B19.1 — проверить что rag.alatyr-service.ru отдаёт Open WebUI:

curl -sI https://rag.alatyr-service.ru/
# Должен быть 200 или 302

B19.2 — создать пользователя perplexity-agent в Open WebUI: - Открой https://rag.alatyr-service.ru → Settings → Users → Add - Сгенерируй API key в его профиле

B19.3 — тест API:

TOKEN="<новый ключ, в чат не вставлять>"
curl -s -H "Authorization: Bearer $TOKEN" https://rag.alatyr-service.ru/api/v1/chats/ | head -20

B19.4 — fail2ban jail для этого endpoint (нужно защитить ключ от brute-force): - Добавь в nginx access_log паттерн запросов /api/ - Создай jail в /etc/fail2ban/jail.local (проксируем через VPS)

B19.5 — сохранить ключ: - В Vaultwarden как OPEN_WEBUI_PERPLEXITY_TOKEN - В Perplexity через custom-credentials (skill custom-credentials)

B19.6 — тест из Perplexity: - В новой сессии попроси: "через RAG rag.alatyr-service.ru найди что было про DPI Инетком" - Должен ответить содержимым vaultwarden.md

После завершения: "B19 done" + скажи какой сессии этот доступ уже пригодился.


Что делать когда всё выполнено

  1. Обновить TODO — все закрытые задачи помечены ✅
  2. Обновить changelog в конце TODO
  3. Обновить прогресс-счётчик (было 9/43, станет ~28/43)
  4. Финальный коммит Пакет B выполнен через SSH: <список задач>

Что мне присылать после каждой задачи

  • Формат: B<N> done + вывод команд без секретов
  • Секреты (новые ключи, пароли): только "готово, положил в Vaultwarden запись <название>"
  • Ошибки: полный текст ошибки — я разберу и дам исправление

Составлено агентом 06.08.2026 для сессии по Alatyr Infrastructure.