Document current architecture and operational practices.

Update README with Steam launch scripts, shm sizing, Moonlight setup, and troubleshooting; add рекомендации.md and ignore local SSH keys.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-27 18:49:02 +03:00
parent ab4ee8b9d6
commit 1dd56ee73d
3 changed files with 275 additions and 101 deletions

264
README.md
View File

@@ -1,140 +1,202 @@
# Game Server с использованием Sunshine и Steam
# Game Server (Sunshine + Steam)
Этот проект предоставляет Docker-конфигурацию для запуска игрового сервера с использованием Sunshine и Steam, позволяя запускать игры на нескольких клиентах одновременно.
Docker-конфигурация для запуска до четырёх игровых сессий через **Moonlight**. Каждый контейнер стримит виртуальный рабочий стол 1920×1080 с **Steam Big Picture** и отдельным профилем Steam на выделенном GPU.
## Архитектура
```
Moonlight → Sunshine → Xorg dummy (:99) → fluxbox + Steam (CEF)
tini (PID 1, перезапуск дочерних процессов)
```
- **Sunshine v0.20.0** — стриминг и захват экрана
- **Xorg dummy** — виртуальный дисплей 1920×1080 (корректный ввод из Moonlight)
- **fluxbox** — панель задач внизу экрана
- **Steam** — запускается от пользователя `steam` через `start-steam.sh`
- **tini** — init-процесс контейнера, предотвращает zombie-процессы fluxbox
## Структура проекта
- `Dockerfile` - файл для создания Docker-образа с Sunshine и Steam
- `docker-compose.yml` - конфигурация для запуска нескольких контейнеров
- `players/` - директория с конфигурациями и данными для каждого игрока
- `p1_config/`, `p2_config/`, `p3_config/`, `p4_config/` - конфигурации для каждого клиента
- `p1_steam/`, `p2_steam/`, `p3_steam/`, `p4_steam/` - данные Steam для каждого клиента
```
.
├── Dockerfile # Образ: Sunshine, Steam, Xorg, fluxbox, tini, xdotool
├── docker-compose.yml # 4 сервиса player1player4
├── scripts/
│ ├── entrypoint.sh # Запуск DBus, Xorg, fluxbox, Sunshine
│ └── fluxbox/init # Конфиг панели задач (в образе)
├── players/
│ ├── p1_config/ # Конфиг Sunshine для player1 (монтируется в контейнер)
│ │ ├── apps.json
│ │ ├── start-steam.sh # Сценарий запуска Steam
│ │ └── keep-steam-window.sh
│ ├── p2_config/ … p4_config/
│ └── p1_steam/ … p4_steam/ # Данные Steam (не в git, создаются на сервере)
├── .env.example # Опциональный APT-прокси для сборки
└── рекомендации.md # Проверенные практики эксплуатации
```
## Особенности
- Поддержка 4 одновременных клиентов
- Использование NVIDIA GPU для ускорения работы
- Автоматическое восстановление контейнеров
- Healthcheck для мониторинга состояния
- Логирование для отладки
Файлы `players/pX_config/` монтируются в `/root/.config/sunshine/` — изменения скриптов применяются **без пересборки образа**. Изменения `Dockerfile` и `scripts/` требуют `docker compose build`.
## Требования
- Docker и Docker Compose
- NVIDIA драйверы
- NVIDIA Container Toolkit
- 2x Tesla K80 (суммарно 4 GPU-чипа)
- Docker и Docker Compose v2
- NVIDIA драйверы и [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html)
- 2× Tesla K80 (4 GPU-чипа) или аналогичная конфигурация
- На хосте: `sysctl kernel.unprivileged_userns_clone=1` (нужно для Steam runtime)
## Установка
1. Убедитесь, что у вас установлен Docker и Docker Compose
2. Склонируйте репозиторий
3. Настройте пути к папкам Steam в `docker-compose.yml`
4. Проверьте назначение GPU-чипов в `NVIDIA_VISIBLE_DEVICES`:
- `player1` -> GPU `1`
- `player2` -> GPU `2`
- `player3` -> GPU `3`
- `player4` -> GPU `4`
GPU `0` в этой конфигурации обычно занят отдельной видеокартой (например, Quadro) и не используется для игровых контейнеров.
5. Запустите команду:
1. Склонируйте репозиторий на сервер:
```bash
docker-compose up -d
git clone https://git.core.com.ru/bilal/game-server.git /DATA/AppData/game-server
cd /DATA/AppData/game-server
```
### APT кэширующий прокси (опционально)
Если у вас есть `apt-cacher-ng` (например `http://192.168.1.60:3142`), можно ускорить сборку образов:
1. Создайте `.env` рядом с `docker-compose.yml`:
2. Создайте каталоги данных Steam (если их ещё нет):
```bash
echo 'APT_PROXY=http://192.168.1.60:3142' > .env
mkdir -p players/p{1,2,3,4}_steam
```
2. Пересоберите контейнеры:
3. При необходимости измените пути volume в `docker-compose.yml` (по умолчанию `/DATA/AppData/game-server/players/...`).
4. Назначение GPU (`NVIDIA_VISIBLE_DEVICES`):
| Сервис | GPU |
|----------|-----|
| player1 | 1 |
| player2 | 2 |
| player3 | 3 |
| player4 | 4 |
GPU `0` обычно занят отдельной видеокартой хоста и не используется игровыми контейнерами.
5. Соберите и запустите:
```bash
docker compose up -d --build
```
Прокси передается в `Dockerfile` через build-arg `APT_PROXY` и автоматически записывается в `/etc/apt/apt.conf.d/01proxy` при сборке.
### APT-прокси (опционально)
## Настройка
Для ускорения сборки через `apt-cacher-ng`:
### Конфигурация Sunshine
Конфигурационные файлы Sunshine находятся в директориях `players/pX_config/`:
- `apps.json` - список установленных игр
- `credentials/` - SSL сертификаты
`sunshine.conf` не хранится в репозитории и генерируется Sunshine автоматически при первом запуске контейнера.
`Steam Big Picture` запускается от отдельного пользователя `steam` внутри контейнера. Данные Steam сохраняются в `players/pX_steam` и не теряются после перезапуска контейнеров/сервера.
Важно: для корректной обработки ввода из Moonlight в контейнерах используется `Xorg dummy` (вместо `Xvfb`) и проброс `/run/udev` в контейнер. Это нужно, чтобы виртуальные устройства ввода Sunshine попадали в тот же X-сеанс, который стримится.
### Порты
В Moonlight при ручном добавлении указывается один адрес в формате `IP:base_port`.
`base_port` для каждого клиента:
- `player1` -> `47989` (можно просто `IP`, это дефолт)
- `player2` -> `48019`
- `player3` -> `48049`
- `player4` -> `48079`
Порты проброшены для каждого клиента отдельно (формат: `host:container`):
- `player1`
- TCP: `47984-47990:47984-47990`
- TCP/UDP: `48010:48010`
- UDP: `47998-48000:47998-48000`
- `player2`
- TCP: `48014-48020:47984-47990`
- TCP/UDP: `48040:48010`
- UDP: `48028-48030:47998-48000`
- `player3`
- TCP: `48044-48050:47984-47990`
- TCP/UDP: `48070:48010`
- UDP: `48058-48060:47998-48000`
- `player4`
- TCP: `48074-48080:47984-47990`
- TCP/UDP: `48100:48010`
- UDP: `48088-48090:47998-48000`
Moonlight использует `base_port` и вычисляет остальные порты автоматически.
### Первый запуск Steam
При первом запуске Steam скачивает и распаковывает клиент (может занять 10-20 минут, в зависимости от канала). В это время в Moonlight может отображаться пустой/черный рабочий стол.
Проверка прогресса для `player1`:
```bash
docker exec -it game-player-1 bash -lc 'tail -f /home/steam/.local/share/Steam/debian-installation/logs/bootstrap_log.txt'
cp .env.example .env
# отредактируйте APT_PROXY при необходимости
docker compose up -d --build
```
После завершения первичной загрузки повторно откройте сессию Moonlight и запустите `Steam Big Picture`.
## Подключение Moonlight
В Moonlight добавьте хост вручную: `IP:base_port`.
| Сервис | base_port | Web UI Sunshine |
|---------|-----------|-----------------|
| player1 | 47989 | https://IP:47990 |
| player2 | 48019 | https://IP:48019 |
| player3 | 48049 | https://IP:48049 |
| player4 | 48079 | https://IP:48079 |
Запускайте приложение **Steam Big Picture**, не Desktop.
### Порты (host → container)
| Сервис | TCP | TCP/UDP | UDP |
|---------|------------------|-----------|------------------|
| player1 | 4798447990 | 48010 | 4799848000 |
| player2 | 4801448020 | 48040 | 4802848030 |
| player3 | 4804448050 | 48070 | 4805848060 |
| player4 | 4807448080 | 48100 | 4808848090 |
## Конфигурация
### Sunshine
- `players/pX_config/apps.json` — список приложений Moonlight
- `players/pX_config/credentials/` — TLS-сертификаты (генерируются при первом запуске, не в git)
- `sunshine.conf` — создаётся автоматически при первом запуске, не хранится в репозитории
### Запуск Steam
`start-steam.sh` вызывается из `apps.json` при выборе **Steam Big Picture**:
1. Проверяет и поднимает system DBus и fluxbox
2. Если Steam уже работает и UI виден — **не перезапускает** процесс
3. Иначе: чистый старт `-silent -no-cef-sandbox`, затем однократно `steam://open/gamepadui`
4. `keep-steam-window.sh` удерживает окно входа на экране и центрирует его
Steam работает от пользователя `steam`; данные сохраняются в `players/pX_steam/`.
### Shared memory
В `docker-compose.yml` задано `shm_size: "2gb"`. Стандартные 64 MB Docker недостаточны для CEF (Steam UI) — окно входа начинает мигать и пропадать. После изменения `shm_size` контейнер нужно **пересоздать**:
Если запуск Steam прерывается после выхода из терминала (`Hangup`), используйте лог:
```bash
docker exec -it game-player-1 bash -lc 'tail -f /home/steam/steam-app.log'
docker compose up -d --force-recreate player1
```
### Первичная загрузка Steam
При первом запуске Steam скачивает клиент (~500 MB, 1020 минут). Прогресс:
```bash
docker exec -it game-player-1 bash -lc \
'tail -f /home/steam/.local/share/Steam/debian-installation/logs/bootstrap_log.txt'
```
После завершения снова откройте **Steam Big Picture** в Moonlight.
## Отладка
Для проверки состояния контейнеров используйте:
### Быстрая проверка
```bash
docker-compose ps
docker compose ps
docker compose logs --tail=100 player1
docker exec -it game-player-1 bash -lc '
echo "PID1: $(cat /proc/1/comm)" # должно быть tini
pgrep -a sunshine
pgrep -a "steam -srt" || echo "steam not running"
df -h /dev/shm # должно быть ~2G, занято <20%
DISPLAY=:99 xwininfo -root -tree | grep -iE "Sign in|Big Picture|1918x"
'
```
Для просмотра логов:
### Логи Steam
```bash
docker-compose logs player1
docker exec -it game-player-1 bash -lc 'tail -f /home/steam/steam-app.log'
docker exec -it game-player-1 bash -lc \
'tail -50 /home/steam/.local/share/Steam/debian-installation/logs/cef_log.txt'
```
## Улучшения
### Типичные проблемы
1. Добавлен healthcheck для лучшей стабильности
2. Добавлено логирование для отладки
3. Оптимизирован Dockerfile
4. Улучшена стабильность запуска контейнеров
| Симптом | Причина | Решение |
|---------|---------|---------|
| Окно входа мигает / пропадает | `/dev/shm` переполнен | `shm_size: "2gb"` + `--force-recreate` |
| Нет панели задач внизу | fluxbox zombie или `-tenfoot` fullscreen | Пересоздать контейнер; не использовать `-tenfoot` |
| Чёрный экран, Steam не виден | Bootstrap ещё идёт или webhelper упал | Смотреть `bootstrap_log.txt`, `webhelper-linux.txt` |
| Steam перезапускается при каждом клике | Старый inline-скрипт в apps.json | Использовать `start-steam.sh` из репозитория |
### Пересборка после изменений
| Что изменили | Команда |
|--------------|---------|
| `start-steam.sh`, `apps.json` | Достаточно перезапустить Steam в Moonlight |
| `Dockerfile`, `scripts/` | `docker compose up -d --build --force-recreate player1` |
| `docker-compose.yml` (shm, GPU, порты) | `docker compose up -d --force-recreate` |
## Обновление из репозитория
```bash
cd /DATA/AppData/game-server
git pull
docker compose up -d --build
```
Скрипты в `players/pX_config/` обновятся автоматически через bind-mount. Если `git pull` перезаписал локальные правки на сервере — проверьте diff перед перезапуском.
## Дополнительно
Подробные рекомендации по эксплуатации — в файле [рекомендации.md](рекомендации.md).