Files
moonwell-web/docs/ssh-core-tunnel.md
T
2026-10-04 13:36:43 +04:00

184 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SSH-туннель от веба к БД ядра
Для Ubuntu/Debian и production Compose этого проекта. Адрес сервера ядра,
SSH-порт и SSH-пользователь заменяются вашими значениями. Настройка выполняется
на двух серверах. SSH-пароль и пароль MariaDB — разные данные.
Схема: `app → core-db-tunnel:3306 → SSH → 127.0.0.1:13306 → MariaDB ядра`.
Порт `3306` туннеля доступен только в сети контейнеров веба; на хост он не публикуется.
Ключ хранится вне репозитория в `/etc/moonwell/ssh-tunnel`, в образ он не копируется.
## 1. На сервере ядра: доступ к MariaDB через localhost
В папке с production `compose.yaml` ядра создайте дополнительный файл:
```bash
cat > compose.ssh-db.yaml <<'YAML'
services:
db:
ports:
- "127.0.0.1:13306:3306"
YAML
docker compose -f compose.yaml -f compose.ssh-db.yaml up -d --no-deps db
```
Этот шаг пересоздаёт контейнер MariaDB, сохраняя его volume; соединения с БД
прервутся на время перезапуска. Выполните его в подходящее для этого время.
Если MariaDB уже доступна на localhost сервера ядра, используйте существующий порт
и пропустите этот шаг. В будущих командах управления ядром сохраняйте
`-f compose.ssh-db.yaml`, чтобы порт не пропал после пересоздания БД.
Проверка:
```bash
ss -lnt | grep ':13306'
docker compose -f compose.yaml -f compose.ssh-db.yaml ps db
```
При использовании другого имени сервиса замените `db` на имя MariaDB вашего ядра.
На сервере ядра SSH должен разрешать локальный TCP forwarding
(`AllowTcpForwarding yes` или `local`); ограничения пользователя и ключа
должны разрешать `127.0.0.1:13306`.
## 2. На сервере веба: отдельный SSH-ключ
Выполняйте команды от root, как в текущем сеансе. Подставьте адрес, SSH-порт
и существующего SSH-пользователя сервера ядра:
```bash
CORE_HOST=IP_ИЛИ_ДОМЕН_ЯДРА
CORE_PORT=22
CORE_USER=SSH_ПОЛЬЗОВАТЕЛЬ
apt-get update
apt-get install -y openssh-client
install -d -m 700 /etc/moonwell/ssh-tunnel
ssh-keygen -t ed25519 -N '' \
-C moonwell-web-db-tunnel \
-f /etc/moonwell/ssh-tunnel/id_ed25519
ssh-copy-id -p "$CORE_PORT" \
-i /etc/moonwell/ssh-tunnel/id_ed25519.pub \
-o UserKnownHostsFile=/etc/moonwell/ssh-tunnel/known_hosts \
"$CORE_USER@$CORE_HOST"
```
`ssh-copy-id` запросит SSH-пароль выбранного пользователя и сохранит публичный ключ.
При первом подключении сверьте показанный fingerprint с ключом сервера ядра,
проверенным через его существующую SSH-сессию или консоль:
```bash
# На сервере ядра:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
```
Не запускайте `ssh-keygen` повторно поверх существующего ключа. Если вход
по SSH-паролю отключён, добавьте содержимое `id_ed25519.pub` в
`~/.ssh/authorized_keys` выбранного пользователя через существующий доступ
и выполните первое подключение вручную с параметром `UserKnownHostsFile` выше.
На веб-сервере проверьте, что вход теперь работает без пароля:
```bash
chmod 600 /etc/moonwell/ssh-tunnel/id_ed25519 /etc/moonwell/ssh-tunnel/known_hosts
ssh -p "$CORE_PORT" \
-i /etc/moonwell/ssh-tunnel/id_ed25519 \
-o IdentitiesOnly=yes -o BatchMode=yes -o StrictHostKeyChecking=yes \
-o UserKnownHostsFile=/etc/moonwell/ssh-tunnel/known_hosts \
"$CORE_USER@$CORE_HOST" true
```
## 3. Настройки веба
Перенесите обновлённый `compose.prod.yaml` и новые файлы этого проекта на веб-сервер:
- `compose.prod.ssh-tunnel.yaml`;
- `docker/ssh-tunnel/Dockerfile`;
- `docker/ssh-tunnel/start.sh`.
В `.env` веба укажите фактические SSH-данные и подключения через туннель:
```dotenv
CORE_SSH_HOST=IP_ИЛИ_ДОМЕН_ЯДРА
CORE_SSH_PORT=22
CORE_SSH_USER=SSH_ПОЛЬЗОВАТЕЛЬ
CORE_DB_HOST=127.0.0.1
CORE_DB_PORT=13306
VMANGOS_AUTH_DB_HOST=core-db-tunnel
VMANGOS_AUTH_DB_PORT=3306
VMANGOS_AUTH_DB_DATABASE=realmd
VMANGOS_AUTH_DB_USERNAME=vmangos
VMANGOS_AUTH_DB_PASSWORD="ПАРОЛЬ_БД_ЯДРА"
VMANGOS_CHARACTERS_DB_HOST=core-db-tunnel
VMANGOS_CHARACTERS_DB_PORT=3306
VMANGOS_CHARACTERS_DB_DATABASE=characters
VMANGOS_CHARACTERS_DB_USERNAME=vmangos
VMANGOS_CHARACTERS_DB_PASSWORD="ПАРОЛЬ_БД_ЯДРА"
```
Здесь `CORE_DB_HOST=127.0.0.1` означает localhost **сервера ядра**, а не веба.
Порты `13306` (MariaDB на сервере ядра) и `3306` (туннель в сети веба) различаются.
`CORE_SSH_PORT` — SSH-порт, он может отличаться от `22`.
Настройки `DB_*` MySQL самого веба и `AWS_*` S3 остаются прежними.
Удалите старые `VMANGOS_AUTH_DB_URL` и `VMANGOS_CHARACTERS_DB_URL`, если они
указаны: иначе Laravel может использовать адреса из URL вместо настроек выше.
`VMANGOS_DOCKER_NETWORK` для production с удалённым ядром не используется.
Для проверки статуса игрового сервера укажите `MOONWELL_REALM_STATUS_HOST`
равным доступному с веба адресу игрового сервера, а не `mangosd` из локального Docker.
## 4. Запуск на веб-сервере
Из папки `moonwell-web`:
```bash
docker compose -f compose.prod.yaml -f compose.prod.ssh-tunnel.yaml up -d --build core-db-tunnel
docker compose -f compose.prod.yaml -f compose.prod.ssh-tunnel.yaml ps core-db-tunnel
docker compose -f compose.prod.yaml -f compose.prod.ssh-tunnel.yaml logs --tail=30 core-db-tunnel
```
После состояния `healthy` пересоздайте приложение и nginx:
```bash
docker compose -f compose.prod.yaml -f compose.prod.ssh-tunnel.yaml up -d --no-deps --force-recreate app web
docker compose -f compose.prod.yaml -f compose.prod.ssh-tunnel.yaml exec -T --user app app php artisan config:cache
```
Docker запускает туннель после перезагрузки и перезапускает завершившийся SSH-процесс.
SSH keepalive обнаруживает обрыв соединения. `healthy` подтверждает, что SSH
создал локальный слушающий порт; доступность самой MariaDB проверяется следующим шагом.
## 5. Проверка из Laravel
```bash
docker compose -f compose.prod.yaml -f compose.prod.ssh-tunnel.yaml exec -T --user app app php artisan tinker --execute='foreach (["vmangos_auth", "vmangos_characters"] as $name) { DB::connection($name)->select("SELECT 1"); echo $name." OK\n"; }'
```
Ожидаемый результат:
```text
vmangos_auth OK
vmangos_characters OK
```
Команда выполняет только `SELECT 1`, игровые аккаунты не меняются.
Если `tinker` не установлен в вашей production-сборке, проверьте наличие
`laravel/tinker` в production-зависимостях перед запуском этой команды.
Ошибки:
- `Permission denied (publickey)`: SSH-пользователь, публичный ключ или права файла ключа.
- `Host key verification failed`: известный ключ не соответствует адресу/порту;
сверьте fingerprint и обновите файл `known_hosts` через подтверждённое подключение.
- `administratively prohibited`: сервер SSH запретил forwarding или цель туннеля.
- `connect failed: Connection refused`: MariaDB не слушает на адресе/порту
`CORE_DB_HOST:CORE_DB_PORT` на сервере ядра.
- `Access denied for user`: туннель работает, но неверны учётные данные или
MariaDB не разрешает этому пользователю подключение с адреса хоста Docker.
Документация: [OpenSSH forwarding](https://man.openbsd.org/ssh),
[OpenSSH keepalive](https://man.openbsd.org/ssh_config),
[Docker published ports](https://docs.docker.com/engine/network/port-publishing/).