Setup X-Ray Server in Debian 12
Before we begin, when we come to any "nano" command, it refers to a text editor in linux. It is recommended to copy them to notepad first, then copy from notepad to putty. As I found that some php code will also be copied to putty if we copy the code directly from here. I will always remind you to copy to notepad first when we come to those instance. When you finished editing the file, press "Ctrl"+"X" together, then press "Y" to confirm edit, follow with "Enter" to quit editor. I will always call that command before I explain what I'm going to do with that file, so you won't be confused for what should copy
1. Setting up environment of Debian
Get super user right
Change timezone to HK
Edit source list for updating image to Debian 11 (in case there you want to update from old version or there is no Bullseye image in VPS)
Change the file to following (Please copy it to notepad first)
Update installed packages
Perform full upgrade (From 10 to 11)
In the middle, there is license term confirmation, press q
Then, reboot
Remove old packages that will not use anymore after upgrade
Prepare the folder for xray
set VPS to use Google BBR as TCP congestion control
2. Get a Free DDNS (for example, freemyip)
Please remember the token you received (if you use freemyip), the following is an example:
The above example, token is 7f5b79f4f0aaab7c33f04d8a, domain is testbunch.freemyip.com
Then, Install ddclient
Since some items are not shown, anything prompt, press enter We will reconfig ddelient below
Option A. For freemyip (assume using example domain name)
Dynamic DNS service provider: select “other”.
Dynamic DNS update protocol: select "freemyip".
Dynamic DNS server: leave blank.
Optional HTTP proxy: leave blank.
Username: 7f5b79f4f0aaab7c33f04d8a
Password: 7f5b79f4f0aaab7c33f04d8a
Re-enter password: 7f5b79f4f0aaab7c33f04d8a
IP address discovery method: Web-based IP discovery service.
IP discovery services: ipify-ipv4 https://api.ipify.org/
Time between address checks: 5m
Hosts to update: testbunch.freemyip.com
Option B. For cloudflare (assume the full name is a.bname.com)
Dynamic DNS service provider: select “other”.
Dynamic DNS update protocol: select "cloudflare".
Dynamic DNS server: leave blank.
Optional HTTP proxy: leave blank.
Username: email address of cloudflare account.
Password: Cloudflare Global API key.
Re-enter password: Cloudflare Global API key.
IP address discovery method: Web-based IP discovery service.
IP discovery services: ipify-ipv4 https://api.ipify.org/
Time between address checks: 5m
Hosts to update: a.bname.com
Option B(cont.). Edit ddclient config (as zone should be missing)
Option B(cont.). Add the following line before the line of a.bname.com, then save
End of Option B.
Restart ddclient
Try to ping the DDNS to check the IP, you might need to restart the ddclient a few times if the DDNS was just created seconds ago.

3. Install NGINX as HTTPS page for fallback
The meaning of fallback is to fake GFW, if GFW tried to access the server without correct setup, a real https page will be shown You can host a your webpage if you want, folder location is /var/www/html/
Install NGINX
Edit NGINX config to recognize acme folder and deny invalid access to folder view

Better copy it to notepad, then copy it from notepad again (as it might copy the background code in putty) You may ignore the 3 lines for acme-challenge if you use cloudflare, but you must add the deny all lines
*If you planning to install haproxy later, please change port 80 too.
restart NGINX, create folder to store acme-challenge file Again, you can ignore the 2 lines which mkdir if you use cloudflare
4. Install acme.sh and get SSL cert
Register an account in ZeroSSL with email Change [email protected] to your email address
Option A. for user that use freemyip only
Issue SSL cert to your system and install it to xray folder (Remember to change testbunch.freemyip.com to your ddns name) This method requires opening port 80 or port forward of port 80
Option B. for user using cloudflare (non Proxied) only
You can generate cert with port 80 closed Issue SSL cert to your system and install it to xray folder, you can add more domain with -d when issue cert Never put your proxied CNAME record here. (Remember to change a.bname.co to your ddns name)
CF_Token=Generate a new Cloudflare API token with 2 Permission: Zone.Zone.Read, Zone.DNS.Edit You can set it can access all Zone, which you don't need to export zoneID here. Or you can set it access target zone and get the zone ID in Cloudflare webpage
Option C. for user using cloudflare (with CDN) only
Since there will be 2 domain name pointing to the same server, you need a cert that accept 2 names
b.bname.co is the proxied cname in Cloudflare
*Haproxy case, add \ after -force, next line type --reloadcmd "cat /root/.acme.sh/a.bname.co_ecc/fullchain.cer /root/.acme.sh/a.bname.co_ecc/a.bname.com.key | tee /etc/ssl/private/a.bname.co.pem"
End of Option parts
Schedule should be auto created, check with following Choose 1 (nano) when asked for choosing editor
There should be a line with command similar to following, if none, add it
5. Generate Cloudflare warp setting
Since Xray 1.7.0, xray support wireguard outbound connections. We can use Cloudflare warp to protect connection to CN instead of blocking all CN traffic
Create a folder to store Cloudflare warp config and download wgcf for generating config (Current version is 2.2.22 on 4 Jun 2024)
Modify permission of wgcf to be able to execute Then, register Cloudflare warp free account
Generate Cloudflare warp config file
Show the config of Cloudflare warp, you need to save the following 2 items: PrivateKey, PublicKey

With the above example PrivateKey: UI.......u/Wk= PublicKey: bm......yo=
6. Install and config Xray
Install Xray
Generate UUID use for XRAY (Please remember the uuid, you will reuse it)

Remove stock X-Ray config and create new one
Current config applies to Xray 1.8.13
Option A. For someone who will only use direct connection (No CDN setting)
Config description: Default using vless, xtls-rprx-vision, fallback to webpage if invalid If destination is CN domain or CN IP, use Cloudflare warp for outbound
Better copy it to notepad, then copy it from notepad again (as it might copy the background code in putty) Replace the following items: 90000000-0000-0000-0000-00000000000a : UUID you generated UI0000000000000000000000000000000000000u/Wk= : PrivateKey in 5 bm000000000000000000000000000000000000000yo= : PublicKey in 5
Option B. For someone who will use CDN for backup connection (Cloudflare Proxied)
Config description: Default using vless, xtls-rprx-vision, fallback to webpage if invalid If path /fallws is provided, fallback to use ws, and it only accept proxy protocol connection (for example Cloudflare CDN) If destination is CN domain or CN IP, use Cloudflare warp for outbound
Better copy it to notepad, then copy it from notepad again (as it might copy the background code in putty) Replace the following items: 90000000-0000-0000-0000-00000000000a : UUID you generated (2 instance) /fallws : the folder you name to tell xray fallback using ws/CDN (2 instance) UI0000000000000000000000000000000000000u/Wk= : PrivateKey in 5 bm000000000000000000000000000000000000000yo= : PublicKey in 5
Note: there are 6 lines with "#" in front, if you use reverse proxy (like HAProxy) to handle all traffic in TCP443, and you enabled "Proxy Protocol" in that config. Remove those "#" in this config. If you don't know what I'm talking about, please ignore this
End of Options part
Since XRay will not load new cert automatically if cert updated, you need to restart xray after cert updated.
Add the following to the bottom line to restart xray everyday 4 AM
Then, restart XRay
You can check xray status with following command
The result will be something like below, which shows it is running and the version of xray

Last updated
Was this helpful?