본문으로 건너뛰기

같은 서버에 설치

번들 설치는 Remnawave 패널과 동일한 서버에 구독 페이지를 설치하는 것을 의미합니다.

단계 1 - .env 파일 준비

/opt/remnawave/.env 파일을 편집하고 SUB_PUBLIC_DOMAIN을 구독 페이지 도메인 이름으로 변경합니다.

.env 파일 편집
cd /opt/remnawave && nano .env

SUB_PUBLIC_DOMAIN을 구독 페이지 도메인 이름으로 변경합니다. 도메인 이름은 http 또는 https 없이 지정해야 합니다.

.env 파일 내용
SUB_PUBLIC_DOMAIN=subscription.domain.com

Remnawave 패널 컨테이너를 재시작하는 것을 잊지 마세요:

cd /opt/remnawave && docker compose down remnawave && docker compose up -d && docker compose logs -f

단계 2 - docker-compose.yml 파일 만들기

docker-compose.yml 파일 만들기
mkdir -p /opt/remnawave/subscription && cd /opt/remnawave/subscription && nano docker-compose.yml
docker-compose.yml 파일 내용
services:
remnawave-subscription-page:
image: remnawave/subscription-page:latest
container_name: remnawave-subscription-page
hostname: remnawave-subscription-page
restart: always
env_file:
- .env
ports:
- '127.0.0.1:3010:3010'
networks:
- remnawave-network

networks:
remnawave-network:
driver: bridge
external: true

이제 .env 파일을 만듭니다:

.env 파일 만들기
mkdir -p /opt/remnawave/subscription && cd /opt/remnawave/subscription && nano .env

Remnawave 대시보드에서 API 토큰을 만드세요. Remnawave 설정 → API 토큰.

다음 내용을 .env 파일에 붙여넣습니다:

.env 파일
APP_PORT=3010
REMNAWAVE_PANEL_URL=http://remnawave:3000
REMNAWAVE_API_TOKEN=API_TOKEN_FROM_REMNAWAVE
전체 .env 파일 참조
.env 파일
APP_PORT=3010

### Remnawave 패널 URL, http://remnawave:3000 또는 https://panel.example.com 사용 가능
REMNAWAVE_PANEL_URL=http://remnawave:3000
REMNAWAVE_API_TOKEN=API_TOKEN_FROM_REMNAWAVE

# 사용자 지정 루트 경로에서 제공, 예를 들어: CUSTOM_SUB_PREFIX=sub
# 시작/끝에 /를 사용하지 마세요
CUSTOM_SUB_PREFIX=



# Marzban 링크 지원
MARZBAN_LEGACY_LINK_ENABLED=false
MARZBAN_LEGACY_SECRET_KEY=


# "Caddy with security" 애드온을 사용하는 경우, X-Api-Key를 여기에 지정할 수 있습니다.
CADDY_AUTH_API_TOKEN=

단계 3 - 컨테이너 시작

컨테이너 시작
docker compose up -d && docker compose logs -f

단계 4 - 역방향 프록시 구성

위험

Remnawave와 그 구성 요소는 서브 경로에서의 서비스를 지원하지 않습니다. (예: location /subscription {)

도메인 또는 서브도메인의 루트 경로에서 제공되어야 합니다.

사용자 지정 경로에는 CUSTOM_SUB_PREFIX 매개변수를 사용할 수 있습니다.

Caddy

Caddy 구성

이미 Caddy를 구성한 경우, Caddyfile에 새 사이트 블록만 추가하면 됩니다.

Caddyfile 편집
cd /opt/remnawave/caddy && nano Caddyfile
Caddyfile
https://REPLACE_WITH_YOUR_DOMAIN {
reverse_proxy * http://remnawave:3000
}
https://SUBSCRIPTION_PAGE_DOMAIN {
reverse_proxy * http://remnawave-subscription-page:3010
}
docker compose down && docker compose up -d && docker compose logs -f

Nginx

Nginx 구성

구독 페이지 도메인 이름에 대한 인증서를 발급합니다:

acme.sh --issue --standalone -d 'SUBSCRIPTION_PAGE_DOMAIN' --key-file /opt/remnawave/nginx/subdomain_privkey.key --fullchain-file /opt/remnawave/nginx/subdomain_fullchain.pem --alpn --tlsport 8443 --reloadcmd "docker exec remnawave-nginx nginx -s reload"
cd /opt/remnawave/nginx && nano nginx.conf
nginx.conf
upstream remnawave {
server remnawave:3000;
}

upstream remnawave-subscription-page {
server remnawave-subscription-page:3010;
}
nginx.conf
server {
server_name SUBSCRIPTION_PAGE_DOMAIN;

listen 443 ssl;
listen [::]:443 ssl;
http2 on;

location / {
proxy_http_version 1.1;
proxy_pass http://remnawave-subscription-page;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_certificate "/etc/nginx/ssl/subdomain_fullchain.pem";
ssl_certificate_key "/etc/nginx/ssl/subdomain_privkey.key";
ssl_trusted_certificate "/etc/nginx/ssl/subdomain_fullchain.pem";
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
resolver_timeout 2s;

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types application/atom+xml application/geo+json application/javascript application/x-javascript application/json application/ld+json application/manifest+json application/rdf+xml application/rss+xml application/xhtml+xml application/xml font/eot font/otf font/ttf image/svg+xml text/css text/javascript text/plain text/xml;
}
cd /opt/remnawave/nginx && nano docker-compose.yml
docker-compose.yml
services:
remnawave-nginx:
image: nginx:1.28
container_name: remnawave-nginx
hostname: remnawave-nginx
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./fullchain.pem:/etc/nginx/ssl/fullchain.pem:ro
- ./privkey.key:/etc/nginx/ssl/privkey.key:ro
- ./subdomain_fullchain.pem:/etc/nginx/ssl/subdomain_fullchain.pem:ro
- ./subdomain_privkey.key:/etc/nginx/ssl/subdomain_privkey.key:ro
restart: always
ports:
- '0.0.0.0:443:443'
networks:
- remnawave-network

networks:
remnawave-network:
name: remnawave-network
driver: bridge
external: true
docker compose down && docker compose up -d && docker compose logs -f

Traefik

Traefik 구성

/opt/remnawave/traefik/config 디렉토리에 remnawave-sub-page.yml이라는 새 동적 구성 파일을 만듭니다.

cd /opt/remnawave/traefik/config && nano remnawave-sub-page.yml
remnawave-sub-page.yml
http:
routers:
remnawave-sub-page:
rule: "Host(`SUBSCRIPTION_PAGE_DOMAIN`)"
entrypoints:
- https
tls:
certResolver: letsencrypt
middlewares:
- remnawave-sub-page-https-redirect
service: remnawave-sub-page

middlewares:
remnawave-sub-page-https-redirect:
redirectScheme:
scheme: https

services:
remnawave-sub-page:
loadBalancer:
servers:
- url: "http://remnawave-subscription-page:3010"

단계 5 - 사용

구독 페이지는 https://subdomain.panel.com/<shortUuid>에서 사용할 수 있습니다.

구독 페이지 구성 (선택 사항)

Remnawave 대시보드의 서브페이지 빌더에서 구독 페이지를 사용자 지정할 수 있습니다. 이를 통해:

  • 다양한 VPN 앱에 대한 지원 추가
  • 여러 언어로 텍스트 및 지침 사용자 지정
  • 자체 브랜딩 추가 (로고, 회사 이름, 지원 링크)
  • "주요" 앱으로 표시할 앱 구성