[!tip] Важно
Перед обновлением, обязательно сделать полный бекап ваших данных (база данных,.env-файл). См. Инструменты бекапа и восстановления.
На что обратить внимание?
Это мажорный релиз с серьезными изменениями API. Самое главное: пользователи больше не идентифицируются по UUID – везде используется числовой id. Кроме того, приведены в порядок коды ответов, все ошибки (400, 404, 500) типизированы и задокументированы в OpenAPI-спецификации. Если вы используете API напрямую или через сгенерированный SDK – обязательно прочитайте разделы ниже.
Новые .env переменные
// error-start
JWT_AUTH_SECRET=значение_1
// error-end
// success-start
APP_SECRET=значение_1
// success-end
Переименуйте переменную JWT_AUTH_SECRET на APP_SECRET (содержимое оставьте прежним!).
Следующие переменные можно удалить:
JWT_API_TOKENS_SECRET=change_me
SWAGGER_PATH=/docs
SCALAR_PATH=/scalar
IS_DOCS_ENABLED=true
Документация и инструменты теперь всегда доступны по фиксированным путям:
- Swagger –
/api/backend-tools/swagger - Scalar –
/api/backend-tools/scalar - Bull Board (очереди) –
/api/backend-tools/queues
Всё, что находится под /api/backend-tools, защищено новой авторизацией. В панели для этого появилась карточка Backend Tools (раздел Remnawave Settings) с кнопкой входа в один клик.
Настройки подписки переехали в Response Headers
Из настроек подписки удалены поля profileTitle, profileUpdateInterval, supportLink, isProfileWebpageUrlEnabled, happAnnounce, happRouting (и соответствующие карточки в UI). Их значения автоматически мигрируют в обычные кастомные заголовки ответа (хедеры): profile-title, profile-update-interval, support-url, profile-web-page-url, announce, routing.
Обратите внимание на изменение поведения: раньше заголовок routing отправлялся только клиентам Happ, теперь настроенные заголовки отправляются всем клиентам без фильтра по User-Agent. Значения заголовков поддерживают Template Variables и префикс rwEncodeBase64: (кодирует значение и отдаёт его как base64:<...>).
У внешних сквадов поле responseHeaders разделено на responseHeadersAdd (добавить заголовки) и responseHeadersRemove (список заголовков, которые нужно вырезать из ответа). Существующие значения мигрируют автоматически.
Пользователи теперь идентифицируются числовым id, поле uuid удалено
Поле uuid полностью удалено из объекта пользователя во всех ответах API. Единственный идентификатор пользователя теперь – числовой id. Все пути с {uuid} пользователя переехали на {userId}:
| Было | Стало | |
|---|---|---|
DELETE /api/users/{uuid} |
DELETE /api/users/{userId} |
|
GET /api/bandwidth-stats/users/{uuid} |
GET /api/bandwidth-stats/users/{userId} |
|
GET /api/hwid/devices/{userUuid} |
GET /api/hwid/devices/{userId} |
|
GET /api/subscriptions/by-uuid/{uuid} |
GET /api/subscriptions/by-id/{userId} |
|
GET /api/subscriptions/connection-keys/{uuid} |
GET /api/subscriptions/connection-keys/{userId} |
|
GET /api/users/{uuid}/accessible-nodes |
GET /api/users/{userId}/accessible-nodes |
|
GET /api/users/{uuid}/subscription-request-history |
GET /api/users/{userId}/subscription-request-history |
|
GET /api/users/{uuid} |
GET /api/users/{userId} |
|
GET/PUT /api/metadata/user/{uuid} |
GET/PUT /api/metadata/user/{userId} |
|
POST /api/users/{uuid}/actions/* |
POST /api/users/{userId}/actions/* |
Тела запросов изменились соответственно:
- все bulk-операции над пользователями (
/api/users/bulk/*) принимаютuserIds(массив чисел) вместоuuids; - HWID-эндпоинты (
/api/hwid/devices*) принимаютuserIdвместоuserUuid; PATCH /api/usersидентифицирует пользователя поidвместоuuid;POST /api/usersбольше не принимает свойuuidпри создании;POST /api/users/resolve– полеuuidудалено (используйтеid,shortUuidилиusername).
Поиск по username и shortUuid (/api/users/by-username/{username},/api/users/by-short-uuid/{shortUuid}) не изменился. Если вы где-то храните UUID пользователей – мигрируйте на числовые id до обновления интеграций.
Удалены эндпоинты поиска пользователей по Telegram ID, email, тегу и ID
Следующие эндпоинты удалены:
GET /api/users/by-telegram-id/{telegramId}GET /api/users/by-email/{email}GET /api/users/by-tag/{tag}GET /api/users/by-id/{id}(теперь это простоGET /api/users/{userId})
Вместо них используйте GET /api/users/stream – эндпоинт получил новые query-параметры фильтрации: telegramId, email, tag, а также status, trafficLimitStrategy и externalSquadUuid.
Пример – получить пользователей по Telegram ID: GET /api/users/stream?telegramId=123456789
Эндпоинт использует курсорную пагинацию: передавайте nextCursor из предыдущего ответа в параметре cursor, пока не получите все записи (size – до 1000 записей за запрос, по умолчанию 250).
Новый эндпоинт: продление подписки одного пользователя
POST /api/users/{userId}/actions/extend с телом { "days": N } продлевает срок действия:
- если пользователь
EXPIRED– новая дата считается от текущего момента, и пользователь становитсяACTIVE; - если пользователь
ACTIVE– дни добавляются к текущей дате истечения.
Новые эндпоинты статистики
GET /api/system/stats/digest– агрегированная сводка за период: созданные и истёкшие пользователи, общий трафик, трафик пользователей, созданных за период, новые HWID-устройства;GET /api/system/stats/http– счётчики HTTP-запросов по роутам;POST /api/bandwidth-stats/nodes/usage– пользователи, потратившие на указанных нодах большеminTotalBytesза период;GET /api/internal-squads/{uuid}/usage– потребление трафика пользователями сквада.GET /api/bandwidth-stats/internal-squads/{squadUuid}/users/{userId}/usage– дневное потребление одного пользователя на нодах сквада.
Legacy-эндпоинты статистики (.../users/{uuid}/legacy, .../nodes/{uuid}/users/legacy) удалены.
Также у внутренних сквадов появились операции над списком пользователей: POST .../bulk-actions/add-many-users и DELETE .../bulk-actions/remove-many-users (тело userIds, до 1000 за запрос, выполняются в фоне, 202).
DELETE-запросы теперь возвращают 204 (или 202) без тела ответа
Раньше все DELETE-эндпоинты возвращали 200 с телом вида { "response": { "isDeleted": true } }. Теперь:
204 No Content– операция выполнена, тело ответа отсутствует (удаление пользователя, ноды, хоста, токена и т.д.);202 Accepted– операция принята и выполняется в фоне (например, удаление пользователей из сквада).
Массовые (bulk) операции теперь возвращают 202 или 204 без тела
Bulk-операции над пользователями и нодами (/api/users/bulk/*, /api/nodes/bulk-actions, /api/hosts/bulk/*, добавление/удаление пользователей в сквадах, рестарт нод) больше не возвращают { "affectedRows": N } :
202 Accepted– операция поставлена в очередь и выполняется в фоне;204 No Content– операция выполнена, тело не возвращается.
Число затронутых записей из ответа узнать больше нельзя – учитывайте это в интеграциях.
Типизированные ошибки 400, 404 и 500
Все эндпоинты теперь документируют ошибки едиными схемами:
400–RemnawaveBadRequestErrorDto(бизнес-ошибки, с полямиtimestamp,path,message,errorCode) илиRemnawaveValidationErrorDto(ошибки валидации, с полямиmessage,statusCode,errors[]);404–RemnawaveNotFoundErrorDto;500–RemnawaveInternalServerErrorDto.
Все возможные значения message и errorCode перечислены в спецификации per-endpoint.
GET /api/keygen: pubKey заменён на secretKey
В ответе эндпоинта поле response.pubKey заменено на response.secretKey.
Переименован модуль IP: /api/ip-control → /api/connections
Эндпоинты переехали на новые пути и получили единообразную структуру:
| Было | Стало |
|---|---|
POST /api/ip-control/fetch-ips/{uuid} |
POST /api/connections/by-user/{userId} |
GET /api/ip-control/fetch-ips/result/{jobId} |
GET /api/connections/by-user/{jobId} |
POST /api/ip-control/fetch-users-ips/{nodeUuid} |
POST /api/connections/by-node/{nodeUuid |
GET /api/ip-control/fetch-users-ips/result/{jobId} |
GET /api/connections/by-node/{jobId} |
POST /api/ip-control/drop-connections |
POST /api/connections/drop |
Логика не изменилась: POST запускает фоновую задачу и возвращает jobId, GET с этим jobId отдаёт результат. Старые пути удалены. Обратите внимание: by-user теперь принимает числовой userId, а в теле POST /api/connections/drop поле userUuids заменено на userIds.
Скоупы API-токенов мигрируют автоматически. Ресурс ip-control переименован в connections (ip-control:fetch-ips → connections:by-user, ip-control:drop-connections → connections:drop и т.д.). Скоупы существующих токенов будут обновлены при апдейте панели автоматически – ничего делать не нужно. Но если ваша интеграция сама создаёт токены с этими скоупами, обновите строки на новые.
Внешние сквады: responseHeaders разделён на add/remove
В настройках внешних сквадов поле responseHeaders заменено на два: responseHeadersAdd (объект «заголовок → значение») и responseHeadersRemove (массив имён заголовков). Это касается тела PATCH /api/external-squads и объектов сквадов во всех ответах.
Из настроек подписки удалены некоторые поля
Из GET/PATCH /api/subscription-settings удалены поля profileTitle, profileUpdateInterval, supportLink, isProfileWebpageUrlEnabled, happAnnounce, happRouting – эти настройки теперь управляются через “Кастомные хедеры”.
Также из ответа GET /api/tokens удалён объект docs.
Бекенд
Новый функционал
- Экспорт событий в Redis Streams
Опциональный экспорт данных панели во внешние системы. ВключаетсяEXPORT_TO_STREAM_ENABLED=true, длина стримов ограничиваетсяEXPORT_TO_STREAM_MAXLEN(по умолчанию 3000).
Три стрима:ioraw:export:user_usage(данные трафика пользователей по нодам),ioraw:export:subscription_requests(запросы подписки; работает даже приSERVICE_DISABLE_SRH_RECORDS=true),ioraw:export:node_connections(снапшот онлайн-пользователей и их IP по нодам каждые 5 минут, хранится 1 час). Схемы сообщений опубликованы в@remnawave/backend-contractи вOpenAPI. - Сводная статистика за период (digest)
GET /api/system/stats/digest– созданные и истёкшие пользователи, общий трафик, трафик пользователей, созданных за период, и новые HWID-устройства за диапазонstart, end. - Raw-хост в кастомных примечаниях
Custom remark (в настройках подписки и внешних сквадах) может быть JSON-объектом – он валидируется по схеме хоста из raw-формата подписки и вставляется в подписку как «сырой» хост. - Дополнительные вебхук-URL для отдельных событий
- В
notifications-config.ymlу события можно указатьadditionalWebhookUrls: [...]– эти URL добавляются к глобальномуWEBHOOK_URLтолько для конкретного события.
Исправления
- Mihomo: Hysteria2 obfs Gecko (#194)
- Shadowsocks 2022: валидация ключа (#193)
- Fallback-хосты в raw-подписке
- Запрет пустых outbounds
Валидатор Xray-конфига теперь отклоняет конфиг безoutbounds. - …прочие изменения
Улучшения
- Zod v4
- Лимиты уведомлений расширены до 31 дня
EXPIRATION_NOTIFICATIONSтеперь принимает значения от−744до744часов (было±168),NOT_CONNECTED_USERS_NOTIFICATIONS_AFTER_HOURS– до744.