1. Architecture
2. Preflight audit
Start with a small Debian or Ubuntu VPS. Record the OS, memory, routes, listeners, firewall state, existing web server and failed services before making changes.
cat /etc/os-release uname -a free -h ip -brief address ip route ss -lntup systemctl --failed systemctl list-unit-files --state=enabled ufw status verbose nginx -T 2>/dev/null certbot certificates 2>/dev/null
- Reserve at least 512 MB RAM; add swap or reduce the protocol set on smaller systems.
- Keep SSH reachable before enabling or changing the firewall.
- Back up existing sing-box, Xray, Nginx and firewall files with a timestamp.
- Create a written port plan so protocols never compete for the same TCP or UDP socket.
3. Protocol and port plan
Use your own high ports; the values below are examples, not a required public layout. Generate a separate UUID, password or key for every row.
| Engine | Protocol / transport | Example | Notes |
|---|---|---|---|
| sing-box | Shadowsocks | 8388/TCP+UDP | Use a modern AEAD or 2022 method supported by the client. |
| sing-box | VLESS + Reality | 8443/TCP | Useful without a domain; select a real reachable target and never invent a certificate. |
| sing-box | Trojan / VMess over TLS | 9443–9444/TCP | Use a valid domain or IP certificate. |
| sing-box | Hysteria2 / TUIC | 9445–9446/UDP | QUIC-based; test from an external network and check provider UDP policy. |
| sing-box | AnyTLS | 9447/TCP | Use a valid certificate and a unique password. |
| sing-box | SOCKS5 / HTTP CONNECT | 9450–9451/TCP | Always require authentication; do not expose an open relay. |
| Xray | VLESS / VMess + XHTTP + TLS | 9471–9473/TCP | Test both current core compatibility and subscription parsing. |
| Xray | VLESS / VMess + mKCP + TLS | 9474–9475 | Verify the actual listener and firewall protocol in the selected Xray release. |
| Xray | VLESS + gRPC or RAW Vision + TLS | 9476–9477/TCP | Keep each transport on its own port during app testing. |
WireGuard, OpenVPN, IKEv2 and OpenConnect are useful comparison VPNs, but they normally use separate client files rather than VLESS/VMess-style subscription links.
4. Install maintained cores
sing-box from its official APT repository
install -d -m 0755 /etc/apt/keyrings curl -fsSL https://sing-box.app/gpg.key -o /etc/apt/keyrings/sagernet.asc chmod a+r /etc/apt/keyrings/sagernet.asc # Add the official deb.sagernet.org source as documented upstream. apt-get update apt-get install sing-box nginx ufw curl unzip
Xray from the official release
- Download the current stable Linux archive and its
.dgstfile from the official XTLS/Xray-core release. - Compare the local SHA-256 with
SHA2-256in the digest file before extracting. - Install the binary and geodata, create an unprivileged
xraysystem user, and keep configuration under/etc/xray/.
sha256sum Xray-linux-64.zip sed -n '1,8p' Xray-linux-64.zip.dgst unzip Xray-linux-64.zip -d xray-release install -m 0755 xray-release/xray /usr/local/bin/xray /usr/local/bin/xray version
Official references: sing-box package installation and Xray installation and checksum verification.
5. Choose TLS or Reality honestly
Place readable certificate copies in service-specific directories with restricted ownership instead of granting the proxy daemon broad access to the entire ACME archive. Add a Certbot deploy hook that refreshes the copies and restarts or reloads only the affected services.
6. Configure, isolate and validate
Generate credentials locally on the server and store the mapping in a root-only inventory. Use a different secret for every protocol so one test account can be revoked independently.
/usr/local/bin/xray uuid /usr/local/bin/xray x25519 openssl rand -base64 32 openssl rand -hex 16 chmod 0640 /etc/sing-box/config.json /etc/xray/config.json chown root:sing-box /etc/sing-box/config.json chown root:xray /etc/xray/config.json
Build one inbound per protocol with a unique tag, port and credential. Keep direct and block outbounds explicit, block private destination ranges unless the lab specifically needs them, and avoid logging credentials or full subscription URLs.
sing-box check -c /etc/sing-box/config.json /usr/local/bin/xray run -test -c /etc/xray/config.json systemctl enable --now sing-box systemctl enable --now xray systemctl status sing-box xray --no-pager journalctl -u sing-box -u xray --since "10 minutes ago" --no-pager
Firewall
ufw allow OpenSSH ufw allow <tcp-port>/tcp ufw allow <udp-port>/udp ufw enable ufw status numbered
7. Build the SpellVPN subscription
- Create standards-compatible share links such as
ss://,vless://,vmess://,trojan://,hysteria2://,tuic://,socks5://and authenticatedhttps://proxy links. - Put exactly one link on each line. URL-encode names, paths and query values; Base64-encode the complete newline-delimited file for a common subscription endpoint.
- Do not put WireGuard, OpenVPN, IKEv2 or OpenConnect client files into a URI list unless the chosen subscription format explicitly supports them. Offer a separate protected bundle.
install -d -m 0755 /var/www/vpn-sub
base64 -w 0 share-links.txt > /var/www/vpn-sub/subscription.b64
chmod 0644 /var/www/vpn-sub/subscription.b64
# Nginx location inside an HTTPS server block:
location = /sub/<long-random-token> {
alias /var/www/vpn-sub/subscription.b64;
default_type text/plain;
add_header Cache-Control "no-store";
}In SpellVPN, open Dashboard → + → subscription URL, paste the HTTPS endpoint, import, then open Nodes and test each protocol separately.
8. Verify real traffic
A listening port is not a successful proxy. Test every protocol with a matching client configuration, first through a local SOCKS test inbound and then from a different external network.
ss -lntup curl --socks5-hostname 127.0.0.1:<local-test-port> https://api.ipify.org curl -fsS https://<subscription-host>/sub/<token> | base64 -d systemctl is-active sing-box xray nginx systemctl is-enabled sing-box xray nginx
- The returned public IP is the server IP for every tested node.
- TCP and UDP transports are tested from outside the VPS.
- The subscription downloads over trusted HTTPS and imports without silently skipping nodes.
- Reboot testing confirms service startup, firewall persistence and certificate readability.
- Failure tests confirm wrong passwords and expired credentials are rejected.
9. Operations and hardening
- Use SSH keys, disable password login after verifying key access, and prohibit direct root login where practical.
- Run sing-box, Xray and Nginx as separate unprivileged users with restrictive file permissions.
- Enable security updates, monitor failed services, disk space, memory and certificate renewal.
- Rate-limit or restrict public SOCKS5 and HTTP CONNECT listeners; never operate unauthenticated open proxies.
- Rotate UUIDs, passwords, Reality keys and subscription tokens after sharing or test completion.
- Keep a redacted port-and-protocol inventory, plus encrypted backups of configs and client bundles.
- Upgrade one engine at a time, validate configuration before restart, and retain a tested rollback copy.