Subscription page
The Subscription Page is the page your users open (https://sub.yourdomain.com/<shortUuid>): connection instructions and QR codes for apps (Happ, sing-box, v2rayNG, Clash, Shadowrocket). It also hides the panel’s domain and IP from clients.
GoWave works with the official remnawave/subscription-page image.
Preparation
Section titled “Preparation”- In the panel, open Settings, then API tokens.
- Create a token with subscription page permissions and copy it.
Option 1: on the panel server
Section titled “Option 1: on the panel server”-
Set the page domain in the panel
.env(/opt/gowave-docker/.envfor Docker,/opt/gowave/.envfor systemd):SUB_PUBLIC_DOMAIN=sub.yourdomain.comThen restart the panel:
docker compose up -d(Docker) orsystemctl restart gowave(systemd). -
Create
/opt/gowave-sub/docker-compose.yml. The page runs on a regular Docker network and its port is published on127.0.0.1only, so the outside world cannot reach it past the reverse proxy and no firewall rule is needed. How the page reaches the panel depends on how the panel is installed.Panel in Docker. The page joins the panel’s Docker network
gowave-networkand talks to the panel container directly athttp://gowave:3000, bypassing the reverse proxy. This is the same scheme as Remnawave with itsremnawave-network:services:gowave-subscription-page:image: remnawave/subscription-page:latestcontainer_name: gowave-subpagehostname: gowave-subpagerestart: alwaysports:- "127.0.0.1:3010:3010"environment:- APP_PORT=3010- REMNAWAVE_PANEL_URL=http://gowave:3000- REMNAWAVE_API_TOKEN=YOUR_API_TOKEN- TRUST_PROXY=1networks:- gowave-networknetworks:gowave-network:external: trueStart the panel first: the
gowave-networknetwork appears afterdocker compose up -din/opt/gowave-docker. Ifdocker network lsdoes not list it, the panel’sdocker-compose.ymlpredates the network: download the current one (or copy itsnetworkssections) and rundocker compose up -dagain.Panel under systemd. The panel listens on the host’s
127.0.0.1, which a container cannot reach, so the page goes through the panel domain:services:gowave-subscription-page:image: remnawave/subscription-page:latestcontainer_name: gowave-subpagerestart: alwaysports:- "127.0.0.1:3010:3010"environment:- APP_PORT=3010- REMNAWAVE_PANEL_URL=https://panel.yourdomain.com- REMNAWAVE_API_TOKEN=YOUR_API_TOKEN- TRUST_PROXY=1REMNAWAVE_PANEL_URLis the address of the panel;APP_PORTis the subscription page’s own port. If you changeAPP_PORT, change the port inportsand in the reverse proxy as well. -
Start it:
cd /opt/gowave-sub && docker compose up -d. -
Point
sub.yourdomain.comto127.0.0.1:<APP_PORT>in the reverse proxy. For Caddy withAPP_PORT=3010:sub.yourdomain.com {encode zstd gzipreverse_proxy 127.0.0.1:3010}
Option 2: on a separate server
Section titled “Option 2: on a separate server”This way clients never learn the panel server’s IP.
-
On the panel server set
SUB_PUBLIC_DOMAIN=sub.yourdomain.comin.envand restart the panel. -
On the separate server create
docker-compose.yml:services:gowave-subscription-page:image: remnawave/subscription-page:latestcontainer_name: gowave-subpagerestart: alwaysports:- "127.0.0.1:3010:3010"environment:- APP_PORT=3010- REMNAWAVE_PANEL_URL=https://panel.yourdomain.com- REMNAWAVE_API_TOKEN=YOUR_API_TOKEN- TRUST_PROXY=1 -
Run
docker compose up -dand pointsub.yourdomain.comat127.0.0.1:3010in the reverse proxy.