Connecting a node and issuing your first subscription
The panel is up, the domain resolves, the super-admin is created. Next we hook up the first node and issue a client that will actually connect. Copy the commands in order and enter your own data in the builder above. The mechanics of all this were covered in the paired theory.
Read the theory →This material covers the engineering of your own network infrastructure and is educational in nature. Complying with the laws of your own jurisdiction is on you.
Preparing the node's server
The node is a separate server, not the one with the panel. It needs only Docker; the panel will load everything else itself:
# install docker in one command
curl -fsSL https://get.docker.com | shRepeat the basic host hardening (SSH by key, firewall, fail2ban) on the node the same way as on the panel — there's a separate start checklist for that. For now we assume the server is clean and ready.
Registering the node in the panel
Go to the panel, Nodes → Create new node. Fill in:
- Name — internal, for you (for example,
DE-01). - Country — for display to the client.
- Address — the IP or domain of the node's server.
- Port — the node agent's port,
2222by default. - Config Profile — pick a profile (you can load a ready-made VLESS Reality via "Load from GitHub" and refine it).
- Inbounds — with checkboxes, mark which to enable on this node.
The panel will show an "Important information" block with the secret key — this is the SECRET_KEY, the node's only password to the panel. And it will give you a ready docker-compose.yml with the port and key already substituted.
Installing the agent on the node
Copy the ready compose from the node card (the Copy docker-compose.yml button) — the NODE_PORT and SECRET_KEY are already substituted there. Put it on the node's server:
services:
remnanode:
image: remnawave/node:latest
network_mode: host
cap_add: [NET_ADMIN]
restart: always
environment:
- NODE_PORT=2222
- SECRET_KEY=KEY_FROM_PANELBring it up:
docker compose up -d
docker compose logs -fWithin a few seconds the node will go online in the panel. What happened: the agent connected to the panel, authorized by its key, the panel pushed it the profile's Xray JSON with the enabled inbounds, and the agent brought up Xray. For Reality no certificates are needed — the disguise works without them.
Opening the node's port
The firewall must let the transport's working port out (usually 443), while the agent's port — only from the panel's IP, so no stranger knocks on management:
ufw allow 443/tcp
ufw allow from PANEL_IP to any port 2222 proto tcp # node agent only from the panelAssembling visibility: host and squad
The node is online, but the client won't see it yet — you have to finish building the chain. Recall the formula: a server is visible only if the inbound is enabled on the node, served by a host, and included in the user's squad.
- Hosts → Create host. You specify:
- Remark — the name the client will see (for example,🇩🇪 DE-01).
- Address — the node's address.
- Inbound — that same inbound enabled on the node. The port will be pulled from it.
- Fingerprint (under advanced) — setfirefox, it can't be left empty. - Squads → create a squad (a plan) and add this inbound to it. Without this step the subscription will be empty.
Creating a client and issuing a subscription
Now the user. Users → Create:
- Username — the client's login.
- Expiry (
expireAt) — the date until which they're active. - Traffic limit — how many gigabytes (or unlimited).
- Squads — add the client to the created squad.
- Device limit (
hwidDeviceLimit) — against sharing.
The panel will generate a CLIENT_UUID and a subscription link for the client. This link the client pastes into their app (Happ, v2rayTun, any xray client) — and gets a list of servers. That's it, the first user is ready.
Checking by hand
Don't take the panel's word for it. Grab the test client's subscription, paste it into the app, connect, and look at the real exit:
# from a device under the VPN — should show the node's IP, not your home one
curl -s https://api.ipify.orgThe node's IP came back — the chain is assembled: client → node → internet. If the subscription is empty — you almost certainly forgot to add the inbound to the squad. If the connection hangs — check the node's logs and the firewall:
# on the node — is the container alive and what's in the logs
docker compose logs --tail 50Backup — right now
As soon as the first live client appears — back up the panel's database. No backup = one failure = loss of all clients:
cd /opt/remnawave
docker compose exec -T remnawave-db pg_dump -U postgres postgres > backup-$(date +%F).sql
tar czf conf-$(date +%F).tgz .env docker-compose.ymlStore it off the server. There's a separate practice in this section on the full backup and restore scheme.
The first node lives, the first client connects. Next in this section — branding the subscription page for your service, fine-tuning hosts, and protecting the panel. And the mechanics of what you just assembled were covered in the paired theory "Nodes and subscriptions."
Next guide Branding the subscription page for your service → ↗ Article unclear or something off? Message me and I will help or fix it. @notrealvpn →