A comprehensive step-by-step guide on how to deploy a SelfSteal node on Remnawave, including the complete setup process for the Remnawave platform itself. This guide covers prerequisites, installation, configuration, and troubleshooting tips to ensure a smooth and secure deployment.
This guide provides a step-by-step walkthrough for configuring the control panel and the node, each deployed on at least two separate VPS instances that meet the system requirements outlined here: https://remna.st/docs/install/requirements.
We will begin with the basic setup of the Remnawave control panel.
Step 0 — Updating and installing requirement tools
apt update && apt upgrade && apt install curl
Step 1 — Install Docker
curl -fsSL https://get.docker.com | sh
Step 2 — Download required files
mkdir -p /opt/remnawave && cd /opt/remnawave
curl -o docker-compose.yml https://raw.githubusercontent.com/remnawave/backend/refs/heads/main/docker-compose-prod.yml
curl -o .env https://raw.githubusercontent.com/remnawave/backend/refs/heads/main/.env.sample
Step 3 — Configure .env
sed -i "s/^JWT_AUTH_SECRET=.*/JWT_AUTH_SECRET=$(openssl rand -hex 64)/" .env && sed -i "s/^JWT_API_TOKENS_SECRET=.*/JWT_API_TOKENS_SECRET=$(openssl rand -hex 64)/" .env
sed -i "s/^METRICS_PASS=.*/METRICS_PASS=$(openssl rand -hex 64)/" .env && sed -i "s/^WEBHOOK_SECRET_HEADER=.*/WEBHOOK_SECRET_HEADER=$(openssl rand -hex 64)/" .env
pw=$(openssl rand -hex 24) && sed -i "s/^POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=$pw/" .env && sed -i "s|^\(DATABASE_URL=\"postgresql://postgres:\)[^\@]*\(@.*\)|\1$pw\2|" .env
Set domains
nano .env
FRONT_END_DOMAIN="panel.yourdomain.com" SUB_PUBLIC_DOMAIN="sub.yourdomain.com"
Step 4 — Start the stack
docker compose up -d && docker compose logs -f -t
Step 5 — Point domain names to your server via DNS provider or registar
Step 6 — Caddy configuration
mkdir -p /opt/remnawave/caddy && cd /opt/remnawave/caddy && nano Caddyfile
https://REPLACE_WITH_YOUR_DOMAIN { reverse_proxy * http://remnawave:3000}:443 { tls internal respond 204}https://SUBSCRIPTION_PAGE_DOMAIN { reverse_proxy * http://remnawave-subscription-page:3010}
cd /opt/remnawave/caddy && nano docker-compose.yml
services: caddy: image: caddy:2.9 container_name: 'caddy' hostname: caddy restart: always ports: - '0.0.0.0:443:443' - '0.0.0.0:80:80' networks: - remnawave-network volumes: - ./Caddyfile:/etc/caddy/Caddyfile - caddy-ssl-dаta:/datanetworks: remnawave-network: name: remnawave-network driver: bridge external: truevolumes: caddy-ssl-dаta: driver: local external: false name: caddy-ssl-data
docker compose up -d && docker compose logs -f -t
Creating docker-compose.yml file mkdir -p /opt/remnawave/subscription && cd /opt/remnawave/subscription && nano docker-compose.yml
services: remnawave-subscription-page: image: remnawave/subscription-page:latest container_name: remnawave-subscription-page hostname: remnawave-subscription-page restart: always environment: - REMNAWAVE_PANEL_URL=https://panel.com - APP_PORT=3010 - META_TITLE="Subscription Page Title" - META_DESCRIPTION="Subscription Page Description" ports: - '127.0.0.1:3010:3010' networks: - remnawave-networknetworks: remnawave-network: driver: bridge external: true
docker compose up -d && docker compose logs -f
Step 7 — Remnawave Node configuration
apt update && apt upgrade && apt install curl
curl -fsSL https://get.docker.com | sh
mkdir -p /opt/remnanode && cd /opt/remnanode
nano .env
APP_PORT=2222SSL_CERT=CERT_FROM_MAIN_PANEL
Create docker-compose.yml file
nano docker-compose.yml
services: remnanode: container_name: remnanode hostname: remnanode image: remnawave/node:latest restart: always network_mode: host env_file: - .env
docker compose up -d && docker compose logs -f
Step 8 — Selfsteal (SNI) Setup
mkdir -p /opt/selfsteel && cd /opt/selfsteel && nano Caddyfile
{ https_port {$SELF_STEAL_PORT} default_bind 127.0.0.1 servers { listener_wrappers { proxy_protocol { allow 127.0.0.1/32 } tls } } auto_https disable_redirects}http://{$SELF_STEAL_DOMAIN} { bind 0.0.0.0 redir https://{$SELF_STEAL_DOMAIN}{uri} permanent}https://{$SELF_STEAL_DOMAIN} { root * /var/www/html try_files {path} /index.html file_server}:{$SELF_STEAL_PORT} { tls internal respond 204}:80 { bind 0.0.0.0 respond 204}
nano .env
SELF_STEAL_DOMAIN=steel.domain.com |
MUST match XRAY realitySettings.serverNames |
SELF_STEAL_PORT=9443 |
MUST match XRAY realitySettings.dest |
nano docker-compose.yml
services: caddy: image: caddy:2.9.1 container_name: caddy-remnawave restart: unless-stopped volumes: - ./Caddyfile:/etc/caddy/Caddyfile - ../html:/var/www/html - ./logs:/var/log/caddy - caddy_data_selfsteal:/data - caddy_config_selfsteal:/config env_file: - .env network_mode: "host"volumes: caddy_data_selfsteal: caddy_config_selfsteal:
docker compose up -d && docker compose logs -f -t
mkdir -p /opt/htmlprintf '%s\n' '<!doctype html><meta charset="utf-8"><title>Selfsteal</title><h1>It works.</h1>' \ > /opt/html/index.html
Step 9
Note: The Shadowsocks inbound is optional and may be safely removed in the future if not required.
{ "log": { "loglevel": "info" }, "inbounds": [ { "tag": "Shadowsocks", "port": 1234, "protocol": "shadowsocks", "settings": { "clients": [], "network": "tcp,udp" }, "sniffing": { "enabled": true, "destOverride": [ "http", "tls", "quic" ] } }, { "tag": "VLESS", "port": 443, "listen": "0.0.0.0", "protocol": "vless", "settings": { "clients": [], "decryption": "none" }, "sniffing": { "enabled": true, "routeOnly": false, "destOverride": [ "http", "tls", "quic", "fakedns" ], "metadataOnly": false }, "streamSettings": { "network": "tcp", "security": "reality", "tcpSettings": { "header": { "type": "none" }, "acceptProxyProtocol": false }, "realitySettings": { "dest": "9443", "show": false, "xver": 0, "spiderX": "/", "shortIds": [ "CHANGE_ME_SHORTID" ], "publicKey": "CHANGE_ME_PUBLIC_KEY", "privateKey": "CHANGE_ME_PRIVATE_KEY", "fingerprint": "chrome", "serverNames": [ "steel.domen.com" ] } } } ], "outbounds": [ { "tag": "DIRECT", "protocol": "freedom" }, { "tag": "BLOCK", "protocol": "blackhole" } ], "routing": { "rules": [ { "ip": [ "geoip:private" ], "type": "field", "outboundTag": "BLOCK" }, { "type": "field", "domain": [ "geosite:private" ], "outboundTag": "BLOCK" }, { "type": "field", "protocol": [ "bittorrent" ], "outboundTag": "BLOCK" } ] }}
Нет комментариев.