feat: customize internal ports

This commit is contained in:
kastov 2025-12-29 01:02:41 +03:00
parent 93faef9a71
commit 9ed437a1f7
No known key found for this signature in database
GPG key ID: 1B27BE29057F4C90
16 changed files with 93 additions and 44 deletions

11
.env.sample Normal file
View file

@ -0,0 +1,11 @@
### VITALS ###
NODE_PORT=2222
SECRET_KEY=SECRET_KEY_FROM_PANEL
### Internal (local) ports
SUPERVISORD_PORT=61002
INTERNAL_REST_PORT=61001
XTLS_API_PORT=61000

View file

@ -52,6 +52,10 @@ RUN ln -s /usr/local/bin/xray /usr/local/bin/rw-core
ENV NODE_ENV=production
ENV NODE_OPTIONS="--max-http-header-size=65536"
ENV SUPERVISORD_PORT=61002
ENV INTERNAL_REST_PORT=61001
ENV XTLS_API_PORT=61000
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["node", "dist/src/main"]

View file

@ -10,14 +10,13 @@ RUN apt-get update && apt-get install -y \
ENV NVM_DIR=/root/.nvm
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash \
&& . $NVM_DIR/nvm.sh \
&& nvm install v22.14.0 \
&& nvm alias default v22.14.0 \
&& nvm install v24.12.0 \
&& nvm alias default v24.12.0 \
&& nvm use default
ENV PATH="/root/.nvm/versions/node/v22.14.0/bin:${PATH}"
ENV PATH="/root/.nvm/versions/node/v24.12.0/bin:${PATH}"
# Установка Xray
RUN curl -L https://raw.githubusercontent.com/remnawave/scripts/main/scripts/install-latest-xray.sh | bash -s -- v25.12.8
@ -36,6 +35,11 @@ RUN echo '#!/bin/bash\n\
exec "$@"' > /usr/local/bin/entrypoint.sh \
&& chmod +x /usr/local/bin/entrypoint.sh
ENV SUPERVISORD_PORT=61002
ENV INTERNAL_REST_PORT=61001
ENV XTLS_API_PORT=61000
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD tail -f /dev/null

View file

@ -8,7 +8,7 @@ services:
networks:
- remnawave-node-dev
ports:
- 24000:24000
- 11000:11000
restart: no
labels:
dev.containers.features: 'common'

View file

@ -5,6 +5,13 @@ services:
build:
context: .
dockerfile: Dockerfile
network_mode: host
networks:
- remnawave-node-dev
ports:
- '11000:11000'
env_file:
- .env
networks:
remnawave-node-dev:
external: false

View file

@ -1,4 +1,3 @@
export const XRAY_INTERNAL_API_PORT = 61001;
export const XRAY_INTERNAL_API_CONTROLLER = 'internal';
export const XRAY_INTERNAL_API_PATH = '/get-config';
export const XRAY_INTERNAL_FULL_PATH = `/${XRAY_INTERNAL_API_CONTROLLER}${XRAY_INTERNAL_API_PATH}`;

View file

@ -20,13 +20,14 @@ export const XRAY_DEFAULT_STATS_MODEL = {
stats: {},
} as const;
export const XRAY_DEFAULT_API_MODEL = {
api: {
services: ['HandlerService', 'StatsService', 'RoutingService'],
listen: '127.0.0.1:61000',
tag: 'REMNAWAVE_API',
},
} as const;
export const XRAY_DEFAULT_API_MODEL = (port: number) =>
({
api: {
services: ['HandlerService', 'StatsService', 'RoutingService'],
listen: `127.0.0.1:${port}`,
tag: 'REMNAWAVE_API',
},
}) as const;
export const XRAY_API_INBOUND_MODEL = {
tag: 'api',

View file

@ -1,10 +1,11 @@
import { ConfigModule, ConfigService } from '@nestjs/config';
import { ConfigModule } from '@nestjs/config';
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { SupervisordNestjsModule } from '@remnawave/supervisord-nestjs';
import { XtlsSdkNestjsModule } from '@remnawave/xtls-sdk-nestjs';
import { getSupervisordPort, getXtlsApiPort } from '@common/utils/get-initial-ports';
import { JwtStrategy } from '@common/guards/jwt-guards/strategies/validate-token';
import { validateEnvConfig } from '@common/utils/validate-env-config';
import { configSchema, Env } from '@common/config/app-config';
@ -21,11 +22,11 @@ import { InternalModule } from './modules/internal/internal.module';
validate: (config) => validateEnvConfig<Env>(configSchema, config),
}),
XtlsSdkNestjsModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
ip: configService.getOrThrow<string>('XTLS_IP'),
port: configService.getOrThrow<string>('XTLS_PORT'),
imports: [],
inject: [],
useFactory: () => ({
ip: '127.0.0.1',
port: getXtlsApiPort().toString(),
options: {
'grpc.max_receive_message_length': 100_000_000, // 100MB
},
@ -35,7 +36,7 @@ import { InternalModule } from './modules/internal/internal.module';
imports: [],
inject: [],
useFactory: () => ({
host: 'http://127.0.0.1:61002',
host: `http://127.0.0.1:${getSupervisordPort()}`,
options: {
username: 'remnawave',
password: 'glcmYQLRwPXDXIBq',

View file

@ -10,12 +10,19 @@ export const configSchema = z
}),
SECRET_KEY: z.string(),
JWT_PUBLIC_KEY: z.string().optional(),
XTLS_IP: z.string().default('127.0.0.1'),
XTLS_PORT: z.string().default('61000'),
DISABLE_HASHED_SET_CHECK: z
.string()
.default('false')
.transform((val) => val === 'true'),
SUPERVISORD_PORT: z.string().transform((port) => {
return parseInt(port, 10);
}),
INTERNAL_REST_PORT: z.string().transform((port) => {
return parseInt(port, 10);
}),
XTLS_API_PORT: z.string().transform((port) => {
return parseInt(port, 10);
}),
})
.superRefine((data, ctx) => {
if (data.SECRET_KEY) {

View file

@ -5,6 +5,7 @@ import {
// XRAY_ROUTING_RULES_MODEL,
} from '@libs/contracts/constants/xray';
import { getXtlsApiPort } from './get-initial-ports';
import { IPolicyConfig } from './interfaces';
export const generateApiConfig = (config: Record<string, unknown>): Record<string, unknown> => {
@ -26,7 +27,7 @@ export const generateApiConfig = (config: Record<string, unknown>): Record<strin
return {
...config,
...XRAY_DEFAULT_STATS_MODEL,
...XRAY_DEFAULT_API_MODEL,
...XRAY_DEFAULT_API_MODEL(getXtlsApiPort()),
policy: builtPolicy,
// routing: {
// ...(routing || {}),

View file

@ -0,0 +1,17 @@
export function getSupervisordPort(): number {
const port = process.env.SUPERVISORD_PORT;
if (!port) return 61002;
return parseInt(port, 10);
}
export function getInternalRestPort(): number {
const port = process.env.INTERNAL_REST_PORT;
if (!port) return 61001;
return parseInt(port, 10);
}
export function getXtlsApiPort(): number {
const port = process.env.XTLS_API_PORT;
if (!port) return 61000;
return parseInt(port, 10);
}

View file

@ -3,13 +3,10 @@ import { readPackageJSON } from 'pkg-types';
import { INestApplication } from '@nestjs/common';
import { getInternalRestPort, getSupervisordPort, getXtlsApiPort } from './get-initial-ports';
import { XrayService } from '../../modules/xray-core/xray.service';
export async function getStartMessage(
appPort: number,
internalPort: number,
app: INestApplication,
) {
export async function getStartMessage(appPort: number, app: INestApplication) {
const pkg = await readPackageJSON();
const xrayService = app.get(XrayService);
@ -19,7 +16,9 @@ export async function getStartMessage(
return table(
[
['Docs → https://docs.rw\nCommunity → https://t.me/remnawave'],
[`API Port: ${appPort}\nInternal Ports: 61000, ${internalPort}, 61002`],
[
`API Port: ${appPort}\nInternal Ports: ${getXtlsApiPort()}, ${getInternalRestPort()}, ${getSupervisordPort()}`,
],
[`XRay Core: v${xrayInfo.version || 'N/A'}\nXRay Path: ${xrayInfo.path}`],
[
`SI: ${xrayInfo.systemInfo?.cpuCores}C, ${xrayInfo.systemInfo?.cpuModel}, ${xrayInfo.systemInfo?.memoryTotal}`,

View file

@ -12,12 +12,13 @@ import morgan from 'morgan';
import { ConfigService } from '@nestjs/config';
import { NestFactory } from '@nestjs/core';
import { getInternalRestPort } from '@common/utils/get-initial-ports';
import { parseNodePayload } from '@common/utils/decode-node-payload';
import { getStartMessage } from '@common/utils/get-start-message';
import { isDevelopment } from '@common/utils/is-development';
import { NotFoundExceptionFilter } from '@common/exception';
import { customLogFilter } from '@common/utils/filter-logs';
import { XRAY_INTERNAL_API_PORT, XRAY_INTERNAL_FULL_PATH } from '@libs/contracts/constants';
import { XRAY_INTERNAL_FULL_PATH } from '@libs/contracts/constants';
import { REST_API, ROOT } from '@libs/contracts/api';
import { AppModule } from './app.module';
@ -109,7 +110,7 @@ async function bootstrap(): Promise<void> {
},
);
const internalServer = internalApp.listen(XRAY_INTERNAL_API_PORT, '127.0.0.1');
const internalServer = internalApp.listen(getInternalRestPort(), '127.0.0.1');
let internalServerClosed = false;
@ -131,7 +132,7 @@ async function bootstrap(): Promise<void> {
'\n' +
(await getStartMessage(
Number(config.getOrThrow<string>('NODE_PORT')),
XRAY_INTERNAL_API_PORT,
app,
)) +
'\n',

View file

@ -1,17 +1,14 @@
import { Controller, Get, UseFilters, UseGuards } from '@nestjs/common';
import { getInternalRestPort } from '@common/utils/get-initial-ports';
import { PortGuard } from '@common/guards/request-port-guard';
import { HttpExceptionFilter } from '@common/exception';
import { OnPort } from '@common/decorators/port';
import {
XRAY_INTERNAL_API_CONTROLLER,
XRAY_INTERNAL_API_PATH,
XRAY_INTERNAL_API_PORT,
} from '@libs/contracts/constants';
import { XRAY_INTERNAL_API_CONTROLLER, XRAY_INTERNAL_API_PATH } from '@libs/contracts/constants';
import { InternalService } from './internal.service';
@OnPort(XRAY_INTERNAL_API_PORT)
@OnPort(getInternalRestPort())
@UseFilters(HttpExceptionFilter)
@UseGuards(PortGuard)
@Controller(XRAY_INTERNAL_API_CONTROLLER)

View file

@ -1,17 +1,17 @@
import { Body, Controller, Post, UseFilters, UseGuards } from '@nestjs/common';
import { getInternalRestPort } from '@common/utils/get-initial-ports';
import { OnPort } from '@common/decorators/port/port.decorator';
import { PortGuard } from '@common/guards/request-port-guard';
import { HttpExceptionFilter } from '@common/exception';
import { errorHandler } from '@common/helpers';
import { VISION_CONTROLLER, VISION_ROUTES } from '@libs/contracts/api/controllers/vision';
import { XRAY_INTERNAL_API_PORT } from '@libs/contracts/constants';
import { UnblockIpRequestDto, UnblockIpResponseDto } from './dtos/unblock-ip.dto';
import { BlockIpRequestDto, BlockIpResponseDto } from './dtos/block-ip.dto';
import { VisionService } from './vision.service';
@OnPort(XRAY_INTERNAL_API_PORT)
@OnPort(getInternalRestPort())
@UseFilters(HttpExceptionFilter)
@UseGuards(PortGuard)
@Controller(VISION_CONTROLLER)

View file

@ -10,12 +10,12 @@ loglevel=info
silent=true
[supervisorctl]
serverurl=127.0.0.1:61002
serverurl=127.0.0.1:%(ENV_SUPERVISORD_PORT)s
username=remnawave
password=glcmYQLRwPXDXIBq
[inet_http_server]
port=127.0.0.1:61002
port=127.0.0.1:%(ENV_SUPERVISORD_PORT)s
username=remnawave
password=glcmYQLRwPXDXIBq
@ -23,7 +23,7 @@ password=glcmYQLRwPXDXIBq
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[program:xray]
command=/usr/local/bin/rw-core -config http://127.0.0.1:61001/internal/get-config -format json
command=/usr/local/bin/rw-core -config http://127.0.0.1:%(ENV_INTERNAL_REST_PORT)s/internal/get-config -format json
autostart=false
autorestart=false
stderr_logfile=/var/log/supervisor/xray.err.log