- C# 59.3%
- Vue 30.6%
- JavaScript 9%
- CSS 0.8%
- Dockerfile 0.2%
| backend | ||
| cs2-plugin | ||
| frontend | ||
| nginx | ||
| .env.example | ||
| .gitignore | ||
| docker-compose.yml | ||
| NuGet.Config | ||
| README.md | ||
| TASK-Plugin.md | ||
| TASK.md | ||
CS2 Server Management Panel
Web-панель для управления Counter-Strike 2 сервером. Полный контроль сервера через браузер: игроки, карты, раунды, боты, fun-режимы, игровые режимы, мини-игры, конфигурация.
Архитектура
[Vue.js Frontend] ←→ [ASP.NET Core API] ←→ [CS2 Game Server]
:5173/80 :5000 :27015 (RCON)
↕ HTTP + WebSocket
[CounterStrikeSharp Plugin]
:27020 (localhost)
- Backend — C# ASP.NET Core Web API, SignalR (real-time), JWT авторизация
- Frontend — Vue 3, Vite, Tailwind CSS v4, Pinia, ApexCharts
- Plugin — CounterStrikeSharp (опциональный, расширенный контроль + игровые режимы)
- БД — PostgreSQL 16 (10 таблиц)
- Infra — Docker Compose, Nginx reverse proxy
Быстрый старт (Docker)
1. Клонирование и настройка
git clone <repository-url> cs2-panel
cd cs2-panel
cp .env.example .env
Отредактируйте .env:
DB_PASSWORD=strong_database_password_here
JWT_SECRET=your_jwt_secret_minimum_32_characters_long
CS2_HOST=127.0.0.1
CS2_RCON_PORT=27015
CS2_RCON_PASSWORD=your_rcon
STEAM_API_KEY=
2. Запуск
docker-compose up -d
Панель доступна на http://localhost:80.
3. Первый вход
При первом запуске создайте администратора:
curl -X POST http://localhost:5000/api/auth/register-first \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "your_secure_password"}'
Или используйте Swagger: http://localhost:5000/swagger → POST /api/auth/register-first.
Локальная разработка (без Docker)
Требования
- .NET 8 SDK
- Node.js 20+
- PostgreSQL 16
Backend
cd backend
# Запуск миграций (создаёт все 10 таблиц)
export PATH="$PATH:$HOME/.dotnet/tools"
dotnet ef database update --project CS2Panel.Data --startup-project CS2Panel.Api
# Запуск
dotnet run --project CS2Panel.Api
# API: http://localhost:5000
# Swagger: http://localhost:5000/swagger
Frontend
cd frontend
npm install --no-bin-links # --no-bin-links нужен на ExFAT/NTFS дисках
npm run dev
# или:
node node_modules/vite/bin/vite.js dev
# Dev-сервер: http://localhost:5173
Vite проксирует /api, /hubs и /ws на http://localhost:5000.
Production build
node node_modules/vite/bin/vite.js build
# Результат в frontend/dist/
Поднятие CS2 сервера
Установка SteamCMD
# Ubuntu/Debian
sudo dpkg --add-architecture i386
sudo apt update
sudo apt install steamcmd
# Или вручную
mkdir ~/steamcmd && cd ~/steamcmd
curl -sqL "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz" | tar zxvf -
Установка CS2 Dedicated Server
sudo useradd -m -s /bin/bash steam
sudo -iu steam
steamcmd +force_install_dir /home/steam/cs2 \
+login anonymous \
+app_update 730 validate \
+quit
Запуск CS2 сервера
cd /home/steam/cs2
./game/bin/linuxsteamrt64/cs2 \
-dedicated \
-port 27015 \
+map de_dust2 \
+sv_lan 0 \
+sv_setsteamaccount YOUR_GSLT_TOKEN \
-maxplayers 16 \
+rcon_password "your_rcon_password"
Важные параметры:
-port 27015— порт сервера (должен совпадать сCS2_RCON_PORT)+rcon_password— пароль RCON (должен совпадать сCS2_RCON_PASSWORD)+sv_setsteamaccount— GSLT токен (https://steamcommunity.com/dev/managegameservers, AppID: 730)-authkey YOUR_STEAM_API_KEY— для загрузки Workshop карт
Запуск через systemd
# /etc/systemd/system/cs2-server.service
[Unit]
Description=CS2 Dedicated Server
After=network.target
[Service]
Type=simple
User=steam
WorkingDirectory=/home/steam/cs2
ExecStart=/home/steam/cs2/game/bin/linuxsteamrt64/cs2 \
-dedicated -port 27015 +map de_dust2 +sv_lan 0 \
+rcon_password "your_rcon_password" -maxplayers 16
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
sudo systemctl enable cs2-server
sudo systemctl start cs2-server
В appsettings.json панели:
{
"ServerProcess": {
"UseSystemd": true,
"SystemdServiceName": "cs2-server"
}
}
Обновление CS2 сервера
steamcmd +force_install_dir /home/steam/cs2 +login anonymous +app_update 730 +quit
Установка CounterStrikeSharp Plugin
Плагин опционален, но значительно расширяет возможности панели: per-player управление (телепортация, HP, броня, оружие, эффекты), игровые режимы (VIP, Gun Game, Deathmatch, Randomizer), мини-игры (Прятки, Зомби, Гонки), kill feed, статистика игроков.
1. Установка Metamod:Source
cd /home/steam/cs2/game/csgo
wget https://mms.alliedmods.net/mmsdrop/2.0/mmsource-2.0.0-gitXXXX-linux.tar.gz
tar -xzf mmsource-*.tar.gz
# В файл game/csgo/gameinfo.gi, секция SearchPaths, добавить:
# Game csgo/addons/metamod
2. Установка CounterStrikeSharp
cd /home/steam/cs2/game/csgo
wget https://github.com/roflmuffin/CounterStrikeSharp/releases/download/vXXX/counterstrikesharp-with-runtime-build-XXX-linux.zip
unzip counterstrikesharp-*.zip -d .
3. Сборка и установка плагина
cd cs2-panel/cs2-plugin/CS2PanelPlugin
dotnet publish -c Release -o publish
mkdir -p /home/steam/cs2/game/csgo/addons/counterstrikesharp/plugins/CS2PanelPlugin
cp publish/* /home/steam/cs2/game/csgo/addons/counterstrikesharp/plugins/CS2PanelPlugin/
4. Настройка
При первом запуске плагин создаст файл cs2panel-plugin.json в своей папке:
{
"HttpPort": 27020,
"SharedSecret": "change-me-shared-secret",
"BackendWebSocketUrl": "ws://localhost:5000/ws/plugin-events",
"EventFlushIntervalMs": 100
}
В appsettings.json панели:
{
"Plugin": {
"Enabled": true,
"Host": "127.0.0.1",
"Port": "27020",
"SharedSecret": "change-me-shared-secret"
}
}
Важно: SharedSecret должен совпадать в конфиге плагина и бэкенда. Все HTTP-запросы к плагину защищены заголовком X-Plugin-Secret.
Функционал
Dashboard
- Статус сервера (онлайн/оффлайн, карта, игроки)
- График онлайна за 6ч / 24ч / 3 дня / 7 дней (ApexCharts)
- Start / Stop / Restart сервера
- Мини-консоль (live через SignalR)
- Список игроков онлайн
- Лог последних действий администраторов
Console
- Полноэкранный лог сервера в реальном времени (SignalR)
- Ввод RCON команд с историей (стрелки вверх/вниз)
- Фильтрация по уровню (info / warn / error)
- Автоскролл
Players
- Таблица: имя, SteamID, счёт, пинг, команда
- С плагином: HP, броня, деньги, K/D/A, позиция, оружие, экипировка
- Действия (RCON):
- Kick, Kill, выдать оружие, сменить команду
- God mode / Noclip (глобальные)
- Действия (с плагином — per-player):
- Телепортация (X/Y/Z)
- Установить HP / броню / деньги
- Выдать любой предмет / снять всё оружие
- Эффекты: burn, blind, freeze, shake (с длительностью)
- Изменить скорость / цвет модели
- Респавн
- Массовые: Slay All, Broadcast, Respawn All, Teleport All
Maps
- Текущая карта + сетка стандартных карт
- Steam Workshop: поиск (превью, подписчики, рейтинг), загрузка по ID
- Кэширование результатов в PostgreSQL
Round Control
- Restart / End Round / Pause / Unpause
- Настройки (friendly fire, balance, время, freeze time, max rounds, buy time)
- Round Backup Recovery
- Текущий счёт матча CT:T (с плагином: phase, bomb status, warmup)
- С плагином: freeze-all, set-score
Bots
- Добавление (CT/T, несколько), kick (один/все/по команде)
- Настройки: quota, difficulty, fill mode, chatter, auto-vacate
Fun Modes (RCON)
- Гравитация, скорость, Infinite Ammo, Knife/Pistol/Zeus Only, Random Weapons
- Disco Mode, Moon Gravity, Healthshot, VIP Mode
- DB-пресеты: создание, применение, удаление
Config
- 30+ server variables в реальном времени с описаниями
- Inline-редактирование, подсветка изменённых, Apply Changes
- Config Presets: snapshot текущего состояния
Plugin (требуется CS# плагин)
Расширенное управление
- Per-player: teleport, health, armor, money, give-item, strip-weapons, speed, color, effects, respawn
- Массовые: earthquake, party, random-teleport, random-weapons, give-all, set-all-health/speed/color, respawn-loop
Игровые режимы
| Режим | Описание |
|---|---|
| VIP | Один игрок с повышенным HP/скоростью, команда защищает |
| One vs All | Один с огромным HP (нож) против всех |
| Gun Game | Убийство = апгрейд оружия, нож-килл = победа |
| Deathmatch | Авто-респавн, случайное оружие, лимит по убийствам |
| Randomizer | Случайное оружие/скорость при каждом убийстве, случайный HP при спавне |
Мини-игры
| Игра | Описание |
|---|---|
| Hide & Seek | Искатель заморожен на N секунд, остальные прячутся |
| Zombie | Случайные зомби (красные, нож, высокий HP) vs люди, заражение |
| Race | Чекпоинты на карте, гонка с ножом, live-прогресс через SignalR |
Kill Feed & Статистика
- Живая лента убийств (real-time через SignalR)
- Таблица статистики: K/D, хедшоты, раунды (хранится в PostgreSQL)
Settings
- Параметры RCON подключения
- Смена пароля администратора
API Reference
Swagger UI: http://localhost:5000/swagger
Основные endpoints
| Группа | Prefix | Ключевые endpoints |
|---|---|---|
| Auth | /api/auth |
POST /login, POST /register-first |
| Server | /api/server |
GET /status, POST /start|stop|restart, POST /console, GET /online-history, GET /action-logs |
| Players | /api/players |
GET /, POST /kick|kill|give-weapon|teleport|god|noclip|team|set-health|respawn|slay-all |
| Maps | /api/maps |
GET /current|list, POST /change|workshop, GET /workshop/search |
| Round | /api/round |
GET /info|settings|backups, POST /restart|end|pause|unpause|restore-backup, PUT /settings |
| Bots | /api/bots |
GET /status, POST /add|kick|kick-all, PUT /settings |
| Fun | /api/fun |
POST /gravity|speed|knife-only|..., CRUD /presets |
| Config | /api/config |
GET /|sv-vars|presets, PUT /, CRUD /presets |
| Chat | /api/chat |
POST /say|say-team|announce |
| Plugin | /api/plugin |
GET /status, player actions, game modes, mini-games, stats |
Plugin API (/api/plugin)
| Endpoint | Описание |
|---|---|
GET /status |
Статус плагина, активный режим |
POST /players/{id}/teleport |
Телепортация (x, y, z) |
POST /players/{id}/health |
Установить HP |
POST /players/{id}/armor |
Установить броню |
POST /players/{id}/money |
Установить деньги |
POST /players/{id}/give-item |
Выдать предмет |
POST /players/{id}/strip-weapons |
Снять оружие |
POST /players/{id}/effect |
Эффект (burn/blind/freeze/shake) |
POST /players/{id}/respawn |
Респавн |
POST /players/{id}/set-speed |
Множитель скорости |
POST /players/{id}/color |
Цвет модели (RGBA) |
POST /players/respawn-all |
Респавн всех |
POST /fun/earthquake |
Землетрясение |
POST /fun/party |
Цветная вечеринка |
POST /fun/random-teleport-all |
Случайная телепортация |
POST /fun/random-weapons-all |
Случайное оружие |
POST /fun/respawn-loop |
Авто-респавн (DM) |
POST /gamemode/activate |
Активировать режим (VIP, Gun Game...) |
POST /gamemode/deactivate |
Деактивировать |
POST /minigame/start |
Запустить мини-игру |
POST /minigame/stop |
Остановить |
GET /stats/players |
Статистика игроков |
GET /events/recent |
Последние события плагина |
GET /gamemode/history |
История игровых режимов |
Все endpoints (кроме auth) требуют JWT: Authorization: Bearer <token>
SignalR Hub
Подключение: ws://host/hubs/server?access_token=<jwt>
| Событие | Данные | Частота |
|---|---|---|
ServerStatus |
Статус сервера | каждые 5 сек |
PlayerList |
Список игроков | каждые 5 сек |
ConsoleLog |
Строка лога | real-time |
ChatMessage |
Сообщение из чата | real-time |
RoundEvent |
round_start, round_end | real-time |
KillFeed |
Убийство (attacker, victim, weapon, HS) | real-time (plugin) |
PluginEvent |
Любое событие плагина | real-time (plugin) |
WebSocket: Plugin Events
Endpoint: ws://host/ws/plugin-events (плагин → бэкенд)
15 типов событий: PlayerConnected, PlayerDisconnected, PlayerDeath, PlayerHurt, RoundStart, RoundEnd, BombPlanted, BombDefused, BombExploded, PlayerTeamChange, ChatMessage, WeaponFire, GameModeChanged, MiniGameEvent
Конфигурация
appsettings.json (Backend)
{
"ConnectionStrings": {
"Default": "Host=localhost;Database=cs2panel;Username=cs2panel;Password=password"
},
"Rcon": {
"Host": "127.0.0.1",
"Port": "27015",
"Password": "rcon_password",
"ReconnectIntervalSeconds": "5",
"CommandTimeoutSeconds": "10"
},
"ServerProcess": {
"ExecutablePath": "/home/steam/cs2/game/bin/linuxsteamrt64/cs2",
"Arguments": "-dedicated -port 27015 +map de_dust2 +sv_lan 0",
"WorkingDirectory": "/home/steam/cs2",
"UseSystemd": false,
"SystemdServiceName": "cs2-server"
},
"Steam": {
"ApiKey": ""
},
"Plugin": {
"Enabled": false,
"Host": "127.0.0.1",
"Port": "27020",
"SharedSecret": "change-me-shared-secret"
},
"Jwt": {
"Secret": "minimum_32_characters_secret_key_here",
"ExpirationHours": "24"
}
}
cs2panel-plugin.json (Плагин)
{
"HttpPort": 27020,
"SharedSecret": "change-me-shared-secret",
"BackendWebSocketUrl": "ws://localhost:5000/ws/plugin-events",
"EventFlushIntervalMs": 100
}
Получение Steam API Key
- https://steamcommunity.com/dev/apikey → зарегистрировать
- Указать в
STEAM_API_KEYилиSteam:ApiKey
Получение GSLT токена
- https://steamcommunity.com/dev/managegameservers → App ID
730 - Использовать:
+sv_setsteamaccount YOUR_TOKEN
База данных
10 таблиц, автомиграция при старте:
| Таблица | Описание |
|---|---|
panel_users |
Администраторы панели |
console_logs |
Логи RCON консоли |
action_logs |
История действий админов |
server_online_history |
График онлайна (player count + map) |
config_presets |
Пресеты конфигурации сервера |
fun_presets |
Пресеты fun-режимов |
workshop_cache |
Кэш Steam Workshop карт |
plugin_events |
Все события от плагина (JSONB) |
player_stats |
Статистика K/D/HS по игрокам |
gamemode_history |
История активации игровых режимов |
Структура проекта
cs2-panel/
├── docker-compose.yml
├── .env.example
├── nginx/nginx.conf
├── backend/
│ ├── CS2Panel.sln
│ ├── CS2Panel.Api/
│ │ ├── Controllers/ # Auth, Server, Player, Map, Round, Bot, Fun, Chat, Config, Plugin
│ │ ├── Hubs/ # SignalR ServerHub
│ │ ├── Services/ # Jwt, Polling, ConsoleLog, Workshop, PluginBridge, PluginEventReceiver
│ │ ├── DTOs/
│ │ └── Program.cs
│ ├── CS2Panel.Core/ # RCON, Query, интерфейсы (IRconService, IPluginBridgeService...)
│ └── CS2Panel.Data/ # EF Core, 10 сущностей, 2 миграции
├── frontend/
│ ├── src/
│ │ ├── views/ # Dashboard, Console, Players, Maps, Round, Bots, Fun, Config, Plugin, Settings, Login
│ │ ├── components/ # Layout, UI (Toast, ConfirmDialog, ModeCard)
│ │ ├── stores/ # Pinia (auth, server, players, console)
│ │ ├── composables/ # useSignalR, useToast
│ │ └── api/http.js
│ └── vite.config.js
└── cs2-plugin/
└── CS2PanelPlugin/
├── CS2PanelPlugin.cs # Точка входа, роуты, события
├── PluginConfig.cs # Конфиг
├── HttpAgent/
│ └── PluginHttpServer.cs # HTTP сервер + auth + роутинг
├── EventBus/
│ └── EventStreamer.cs # WebSocket → бэкенд
└── Managers/
├── PlayerManager.cs # Per-player действия
├── RoundManager.cs # Информация о раунде, freeze-all, set-score
├── FunManager.cs # Earthquake, party, respawn-loop...
├── GameModeManager.cs # VIP, Gun Game, Deathmatch, One vs All, Randomizer
└── MiniGameManager.cs # Прятки, Зомби, Гонки
Технологии
| Компонент | Стек |
|---|---|
| Backend | C# .NET 8, ASP.NET Core, SignalR, EF Core, CoreRCON |
| Frontend | Vue 3 (Composition API), Vite, Tailwind CSS v4, Pinia, ApexCharts |
| Plugin | C# .NET 8, CounterStrikeSharp API, custom TCP HTTP server |
| Database | PostgreSQL 16, EF Core Migrations (10 таблиц) |
| Auth | JWT Bearer + SharedSecret (plugin) |
| Real-time | SignalR WebSocket (фронт), raw WebSocket (плагин → бэкенд) |
| Deploy | Docker Compose, Nginx |
Лицензия
MIT