6389 字
32 分钟
购买并配置 Linux VPS 以搭建个人网络服务

1. 购买服务器#

购买服务器的方式有很多种,也是这篇教程中最模糊的地方,我不可能一一说明,只能说如果你没有MasterCard或者Visa卡,那我还是建议你去先找找哪些VPS供应商比较靠谱。

如果你有,那么大概两三年你都不用担心没有免费的代理服务器可用。

单纯用作VPS用途的服务器,本身费用也不高,你可以去闲鱼找闲置的海外服务器购买。

首选甲骨文的终身免费云服务器,但是这个真的很难申请,而且很容易就被甲骨文封了,主要面对的还是海外群体——但如果你身在海外的话,这东西你如果不是开发,那么意义并不是很大,跟你也没关系。

常见的云服务供应商:

  • Azure
  • Google
  • AWS
  • Aliyun
  • 腾讯云

各个厂商设置的位置都不一样,但是核心的设置是通用的,建议服务器系统用Ubuntu

特别提醒:

AWS的免费是有条件的,注意看条款,不要被扣钱了。

它开/关机一次操作有最小时长计数单位,请不要频繁开关。

而且所谓的720h指的是一个实例的时间,如果你创建了多个实例,时长为叠加计算。

包括它的免费计划也是如此,AWS你就老老实实选t3.micro全部都选最基础的机器,系统选Ubuntu,别乱整。

1.1 设置规则以及获取ppk/pem密钥#

找到类似编辑入站规则/端口规则的界面,需要在云服务商的控制台(Console)找到防火墙或安全组设置,放行上述端口:

类型协议端口地址
HTTPTCP80任意IPV4地址(0.0.0.0/0)0.0.0.0/0->一般来说是网站的入口,不过其功能包括但不限于用于申请SSL证书等功能,在这里基本上只是服务于证书的自动申请和续期,但我们第一章仅设计自己用的话并不需要申请SSL证书,如果你不满足于自己使用,想要搭建服务去服务他人,那么可能会用得上,而且80跟443同时开也符合一个网站的特征。
SSHTCP22任意IPV4地址(0.0.0.0/0)0.0.0.0/0-> 使用SSH连接服务器端口,建议将ssh端口改成别的端口,比如说2222去连接服务器,或者干脆使用云服务器里面的终端。这里只是告诉你这个端口是SSH远程服务器的默认端口,并不建议全网开放,你可以设置成仅限于你的家宽ip地址访问,不过家宽地址会变所以很麻烦,涉及到后面marzban的端口映射问题,所以还是先开放了吧,等设置好之后再去掉。
HTTPSTCP443任意IPV4地址(0.0.0.0/0)0.0.0.0/0-> 用于 VLESS + Reality 协议。Xray 内核直接在此端口监听流量,并利用 Reality 技术将其伪装成访问某个真实网站(如 www.yahoo.com)的常规 TLS 加密流量。

1.1.1 ppk/pem密钥#

通常在起服务器的时候它就会给你,这个很重要,一定要保存好。 推荐使用pem密钥,可以直接由Windows的CMD或者Powershell连接,后面的介绍以pem密钥为基准。

1.2 连接服务器#

你可以打开CMD或者Powershell之后,输入ssh -i,然后将密钥文件拖进去,再输入后面的命令

Terminal window
ssh -i 密钥文件路径 服务器用户名@服务器地址
# 比如说 ssh -i "C:\Users\Admin\Downloads\aws.pem" ubuntu@1.2.3.4

不想每次都那么麻烦,去C:\Users\你的用户名\.ssh\下面创建一个文本文件:

Host vps
HostName 你的服务器ip
User 你服务器默认的登录的用户名
# 写上你的 PEM 文件的绝对路径,比如说下面这个
IdentityFile "D:/Documents/Singapore.pem"
# 你的端口转发规则(可以直接照抄)
LocalForward 9999 localhost:8000

Linux/macOS 同样在 ~/.ssh/config 配置,内容与上面一致。

关于默认用户名(可能,请自行查看):

  • AWS (Ubuntu 系统): ubuntu
  • AWS (Amazon Linux): ec2-user
  • Oracle Cloud (甲骨文): opc 或 ubuntu
  • Google Cloud (GCP): 也就是你注册谷歌账号的那个用户名(或者是 google_user)。
  • 大部分其它小厂 VPS: root

文本文件设置完后,请把它的后缀名去掉,不知道怎么做的话,在Windows的文件查看器地址栏下方,点击:查看->显示->文件拓展名

1.2.1 更新package管理工具,下载Marzban#

连接成功后,输入:

Terminal window
sudo apt update
Terminal window
# 安装Marzban
sudo bash -c "$(curl -sL https://github.com/Gozargah/Marzban-scripts/raw/master/marzban.sh)" @ install
# 它会自动运行服务,这个时候上面留的配置文件就派上了用场
ssh vps
# 这样就可以再连接服务器而不终止Marzban了
## 你会看到如下日志
marzban-1 | Use the following command:
marzban-1 | ssh -L 8000:localhost:8000 user@server
marzban-1 | Then, navigate to http://127.0.0.1:8000 on your computer.
# 但之前我们设置了Forward,使用SSH连接的话,我们是将端口从8000映射到了9999,所以在本地中,应该使用9999端口去访问

1.2.2 设置管理员账号密码#

Terminal window
# 如果你最后要暴露在公网里面,建议复杂一些
sudo marzban cli admin create --sudo

1.2.3 设置marzban#

登录marzban,点击设置(齿轮图标)

虽然LLM里面有说有图形化的inbounds添加,这个功能实际上也很好做,但实际上就是没有,不然我也不会让你去写配置,等待它做易用性更新吧。

参考Marzban文档:inbounds设置

你可以看到里面有很多种类型的inbounds,我们首选Vless+Reality,协议则是TCP

挑其中一个来说,gRPC是给符合用途的人用的,比如说他服务器担当梯子+博客之类的符合功能,需要做一定伪装,而我们做VPSTCP就足够使用,轻量而且满足我们的需求。

Terminal window
# 首先,在服务器中生成pk对,复制备用,下面的文本需要。
sudo docker exec marzban-marzban-1 xray x25519
#然后,生成你的shortid,复制备用,下面的文本需要。
openssl rand -hex 8

接下来则是介绍dest以及serverName,你可以理解成你伪装的网站以及访问的网站名

Terminal window
# dest 有一定的硬性要求:1. 支持TLS1.3 2. 支持H2 3. 目标服务器与VPS物理位置相近(同机房/同地区最佳),否则握手延迟会暴露异常,这里使用apple仅作为示例。
# serverNames则是dest的名字,可填内容跟dest的证书挂钩,建议选择证书San覆盖广的。
# 使用以下命令验证dest,以apple为例:
# 检查 TLS 版本和 ALPN(必须看到 TLSv1.3 和 h2)
openssl s_client -connect www.apple.com:443 -tls1_3 -alpn h2 </dev/null 2>/dev/null | grep -E "TLSv1.3|ALPN"
# 使用 curl(看到 HTTP/2 即支持)
curl -I --http2 -v https://www.apple.com 2>&1 | grep "Using HTTP2"
# 查看其支持的serverNames,列出的DNS:xxxxx即为你可以使用的域名,前面的*可以替换为任意子域名。
echo | openssl s_client -connect www.apple.com:443 -servername www.apple.com 2>/dev/null | openssl x509 -noout -text | grep -A 10 "Subject Alternative Name"

但并非什么域名都适合作为serverNames,遵循以下规则:

类型示例Reality 配置写法
完全匹配www.apple.com"www.apple.com"
裸域apple.com"apple.com"
通配符替换*.apple.com 证书 → cdn.apple.com"cdn.apple.com"(任意子域名)
同级域名证书含 microsoft.comoffice.com两者可同时放入 serverNames 数组

然后就到了正式配置,再强调一下,dest以及serverNames不要照抄,按自己VPS的地理位置去选择。

将下面的配置复制进inbounds数组中,如果不知道怎么复制,建议把原来的配置,加上下面这一段配置,让LLM帮你组装再一起复制进去。

其实很简单,在Shadowsocks TCP大括号的上面加上下面这个大括号对里面的内容即可,记得使用”,“衔接,不然JSON格式会出错。

{
"tag": "VLESS TCP REALITY",
"listen": "0.0.0.0",
"port": 443,
"protocol": "vless",
"settings": {
"clients": [],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"tcpSettings": {},
"security": "reality",
"realitySettings": {
"show": false,
"dest": "www.apple.com:443",
"xver": 0,
"serverNames": [
"www.apple.com",
"apple.com"
],
"privateKey": "你的privateKey",
"shortIds": [
"你生成的shortid"
]
}
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
}
}

接下来我们要重启marzban

Terminal window
sudo marzban restart

1.2.4 marzban添加用户#

登录marzban,键入你刚创建的管理员账号密码:

  • 添加用户
  • 选择Vless
  • 取消Shadowsocks TCP(点击一下就能取消,它默认会自动勾选)

配置如下:

  • 用户名:随便
  • 流量限制:看你服务器的套餐到底是怎么样的
  • 过期日期:看你自己
  • 备注:一样

点击一下你的用户,在弹出的窗口中,Vless右边有三个点,点击一下。

在flow那边选择xtls-rprx-vision

选好后记得保存,否则不生效。

1.2.5 与代理连接#

添加用户后,你会发现它在列表里面有三个按钮

  • 订阅
  • 链接
  • 二维码。

如果你不暴露在外网的话,流量限制之类的填空项是没用的,因为你没办法正常通过订阅的方式来获取信息。

也就是说,你只能用链接或者二维码使用这个Vless链接

但主流的科学上网软件Clash并不直接支持单个Vless链接读取,如果你不想搞那么多配置,去用v2rayNNekobox,可以直接识别Vless链接

如果你使用Clash,那么这个链接是无法直接使用的,它长得像下面这样:

Terminal window
vless://uuidaa@server:443?security=reality&type=tcp&headerType=&path=&host=&sni=www.yahoo.com&fp=chrome&pbk=BDYTuMVtogMm9fJP5WT1wwd0uoT3n_UqyRWKAlEAW1E&sid=sidF%9A%80%20Marz%20%28Meteor%29%20%5BVLESS%20-%20tcp%5D

接下来则是在Clash那边与服务器的marzban启动的xray连接,需要在订阅那边,新建一个Local file,然后编辑文件,将下面的内容复制进去,对需要更改的内容进行修改。

记住,不要改任何缩进。

# ===============================================================
# Clash (Meta Core) 配置文件
# 适用于 Marzban VLESS+Reality
# ===============================================================
# 代理监听端口
port: 7890
socks-port: 7891
allow-lan: false
# 模式:rule(规则模式),global(全局模式),direct(直连模式)
mode: rule
# 日志级别
log-level: info
29 collapsed lines
# Clash 控制面板和 API
external-controller: "127.0.0.1:9090"
# 代理节点列表
# 在这里定义你的 VLESS 和 SS 节点
proxies:
- name: "🚀 Marz (your vps name) [VLESS - tcp]" # 节点名称,可以自定义
type: vless
# --- 请在这里填入你的 VLESS 节点信息 ---
server: xxxxxx # <--- 你服务器的ip地址
port: 443 # <--- 默认443,没改就别动
uuid: xxx # <--- 修改这里
network: tcp
tls: true
flow: xtls-rprx-vision
client-fingerprint: chrome
servername: www.yahoo.com # Reality 伪装的目标域名 (SNI)
reality-opts:
public-key: xxx # <--- 之前你在服务器上面生成的公钥
short-id: xxx # <--- 之前你在服务器上面生成的shortid
# 代理组配置
# 用于在多个代理节点之间进行选择和切换
proxy-groups:
- name: "节点选择" # 这是你在 Clash UI 中看到的策略组名称
type: select
proxies:
- "🚀 Marz (你的用户名) [VLESS - tcp]"
- "DIRECT" # 直连选项
# 规则配置
# 决定哪些流量走代理,哪些直连
rules:
- GEOSITE,CN,DIRECT
- GEOIP,CN,DIRECT
- MATCH,节点选择

1.2.6 安全向考虑#

注意,以下默认你使用pem密钥登录,如果默认为root登录的话,建议:

  1. 先创建普通用户并加入 sudo;确认能用密钥登录
  2. 再禁 root、禁密码

1.2.6.1 禁用密码登录#

Terminal window
sudo nano /etc/ssh/sshd_config

做出如下改动,保存并退出:

sshd_config
# 找到并修改以下行(没有就添加):
PermitRootLogin no # 禁止 root 登录(可选但建议)
PasswordAuthentication no # 禁止密码登录
PubkeyAuthentication yes # 允许密钥登录(确认是 yes)

然后重启你的ssh,试试是否还可以登录:

Terminal window
# 可能会不起作用,有些linux里面叫ssh,有些叫sshd。
sudo systemctl restart sshd
# 不生效就使用这句
sudo systemctl restart ssh

1.2.6.2 Fail2ban#

简单的说就是通过封ip禁止别人低成本暴力破解你的密码。

Terminal window
# 安装
sudo apt update
sudo apt install fail2ban -y
# 创建本地配置文件(不要直接改默认配置,会被更新覆盖)
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# 编辑配置
sudo nano /etc/fail2ban/jail.local

在文件中找到 [sshd] 部分,改为:

jail.local
[sshd]
enabled = true
port = ssh # 如果你改了 SSH 端口,这里改成你的端口,如 2222
filter = sshd
logpath = /var/log/auth.log #Amazon Linux / RHEL 系常见是 /var/log/secure,Ubuntu 为 /var/log/auth.log 请自行确认。
maxretry = 3 # 失败 3 次就封禁
bantime = 3600 # 封禁 1 小时(单位秒)
findtime = 600 # 在 10 分钟内累计 3 次失败才封禁

然后开启服务:

Terminal window
sudo systemctl enable --now fail2ban

1.2.6.3 更改SSH端口#

上面提到了修改SSH端口,也就是22端口,这个端口算是高风险端口,有很多嗅探机器人在扫描。

当然,其实也没那么恐怖,这种服务器其实也没几个人会在意。

不过就像这个大章节的名字,如果你想将概率降至最低,直接更改默认SSH的端口。

Terminal window
sudo nano /etc/ssh/sshd_config
sshd_config
Port 2222

或者其它端口,你喜欢就行,然后:

Terminal window
# 查看一下防火墙是否开启,一般来说是不开启的,谨慎起见:
sudo ufw status
#应该是inactive
inactive
#如果不是,开放你设置的端口,假设为2222
sudo ufw allow 2222/tcp
Terminal window
# 保存,重启 SSH
sudo systemctl restart sshd

1.2.6.4 验证#

Terminal window
# 方法一:
sudo ss -tlnp | grep ssh
# 方法 2:使用 netstat(传统方式)
sudo netstat -tlnp | grep ssh
# 方法 3:查看 sshd 进程打开的网络端口
sudo lsof -i -n | grep sshd
# 方法 4:直接看 PID 为 1 的 systemd 启动的 ssh 监听
sudo systemctl status ssh | grep -i "listening"

看当前的SSH端口是否已经绑定到你设定的端口,如果没有的话,说明重启sshd失效,因为不同的linux环境或许对应不一,可以自行寻找LLM获取解决方案。

一切就绪以后,在亚马逊EC2实例里头,选择安全组,将22端口去掉,加上自定义TCP->你刚刚设置的端口,保存即可。

如果设置后无法登录的时候该怎么办?

建议先申请一个弹性ip,然后将实例停止,并且在操作->实例设置->编辑用户数据中,输入命令,这些命令相当于你直接在bash中执行一个脚本文件,比如说你想恢复22端口,那么输入:

#!/bin/bash
# 按需往里面塞内容,不要一下在全恢复,可能你什么都不用动,只是重启就可以了,一般来说只是端口绑定的问题。
# 修复 SSH 配置:改回 22 端口并允许密钥登录
sed -i 's/^Port 2222/Port 22/' /etc/ssh/sshd_config
sed -i 's/^#*Port.*/Port 22/' /etc/ssh/sshd_config
# 确保密钥登录开启
sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
# 禁用密码登录(保持安全)
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
# 重启 SSH(兼容 Ubuntu/Amazon Linux)
systemctl restart sshd || systemctl restart ssh || service ssh restart
# 记录日志
echo "SSH fixed at $(date)" >> /var/log/fix-ssh.log

不过很多镜像的 cloud-init 默认只在首次启动执行 user-data,之后改 user-data 未必会再跑(除非显式配置 cloud-init 重新执行策略),所以这种救援其实并不是那么可靠。

更可靠的救援路径通常是:控制台串口/SSM/挂载系统盘到另一台机器修改配置(不同云有不同方式)。

1.2.7 注意事项#

如果你还想要使用面板管理,或者将订阅链接分享给他人,这时候则需要域名以及域名保护。

直接IP+端口分享一个面板在公网,很容易被GFW检测到然后封杀,你所做的一切Vless+Reality保护你的VPS就像是穿着皇帝的新衣,在GFW面前过于明显。

确定想要面板管理的话,往下看,否则直接到此为止即可。

2. 域名购买:Namesilo#

2.1 随便输入一个你想购买的域名#

首先说明一下为什么要买域名。

其实如果你直接使用Vless+Reality方案,本质上并不需要购买域名,做伪装之类费劲不讨好的事情。

这个主要还是伪装你的面板。

GFW眼里,你这个ip开放了一个很可疑的面板到外面,特征非常明显。

买域名起到一个什么作用?其实就是把你的服务器伪装成一个网站,能把IP地址通信,伪装成一次正常的访问网站的行为。

对于GFW来说,你可能只是一个正在浏览境外博客、或者在看技术文档的普通网民。

只要你的目的仅限于个人使用,就你这点微不足道的流量,混在每天数以亿计的正常跨境网站访问中,就像大海里的一滴水,基本上没人会注意到你,这就是花几块钱买个域名的核心价值所在。

比如说test123456,里面有很多后缀可选。

一般来说cfd后缀可能是最便宜的,之前$0.99的可能已经买不到了,现在最便宜的应该是$1.79(¥12.61附近/年,支持支付宝付款)

2.2 删除Namesilo提供的默认DNS域名解释#

支付完成后,会直接跳转到Dashboard面板。

点击Dashboard页面中的1 active Domains下面的manage

在options中找到一个蓝色图标的按钮,找不到那就鼠标一个个挪上去,看看哪个是Manage DNS for this domain

我们后面要更换成Cloudflare保护这个域名,将指挥权全权交给Cloudflare。

DNS Record -> Existing Resource Records 下面的分配全部删光即可。

2.3 保留Namesilo的页面#

待会还要用到

3. 域名保护:Cloudflare#

Cloudflare对于小微用户基本上算是活菩萨,免费给你清洗流量抵御攻击做隐私保护。

域名可以理解为你的门牌号,域名解析(DNS)则是负责在路由与路由之间指导那些IP最后中转到域名的服务。

如果Namesilo跟Cloudflare的共存,那么对于所有访问指向你域名的人而言,可能时而会跑去找Namesilo的,时而跑去找Cloudflare的,但两者的能力是有区别的。

Cloudflare会负责将别人导向这个地址,但是不会告诉别人这个地址的其它消息,面对恶意找上门的人会加以辨别并且阻拦,如果你的服务是网站,他还会预判别人到这里来做什么,提供给想要来访的用户对应加速服务。

不过对于VPS服务来说,主要功能还是隐藏你域名背后服务器面板的地址。

如果你后面有更多的需求,基本上只会考虑他们家的服务, Cloudflare已经遍布全地球。

3.1 注册什么的略过,计划选择免费#

如题,不多赘述

3.2 添加域名#

添加域名图片

3.3 复制Cloudflare服务器至Namesilo#

添加cloudflare保护图片Namesilo最右侧像是三个硬币堆叠的图标那边点击进入Using Custom DNS Records

将Cloudflare名称服务器中的链接复制进去就好,点击Submit,在外面列表的Name Servers中看到改动即可。

3.4 设置DNS代理#

在Cloudflare左侧导航栏点击 DNS->记录(records) -> 页面中点击添加记录(records)

类型A,名称就是域名的前缀,随便你输什么,建议fly之类有意义的动/名词,ipv4地址填你服务器的地址,保存。

这个主要用于给你的面板当掩护,你VPS跟Clash还是使用ip+reality的模式连接,代理云朵必须开启为橙色,表示启用。

记得在SSL设置里面,将加密模式改为完全(严格)

4. 暴露面板至公网#

在服务器设置的页面(你买服务器的地方)开放80、443、2053端口。

解释一下:

  • 80端口用于caddy自动申请ssl证书
  • 443端口用于Xray通信
  • 2053端口用于面板操作以及订阅。

假设在3.4步骤后,你用于在公网保护的的域名为test12345.cfd,名称为fly。

Terminal window
# 1. 安装 Caddy (Ubuntu)
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
# 2. 修改 Marzban 的 .env 文件
# 确保面板只监听本地,让 Caddy 来处理公网流量
sudo nano /opt/marzban/.env
UVICORN_HOST=127.0.0.1
UVICORN_PORT=10086 # 换一个非标准端口
21 collapsed lines
XRAY_SUBSCRIPTION_URL_PREFIX=/my-secret-panel #你想设置的前缀,比如说my-secret-panel
# 注释掉 SSL 相关行,如果没设置就不用动
# UVICORN_SSL_CERTFILE=...
# UVICORN_SSL_KEYFILE=...
# Ctrl+O 确定保存,然后Ctrl+X退出
sudo marzban restart
# 3. 配置 Caddyfile
sudo nano /etc/caddy/Caddyfile
# 将里面的内容全部替换为:
fly.test12345.cfd:2053 {
handle_path /my-secret-panel/* {
reverse_proxy 127.0.0.1:10086
}
# (可选) 为根目录设置一个伪装页面
# 当访问根目录或其他路径时,显示 "File not found"
handle {
respond "File not found" 404
}
}
# Ctrl+O 确定保存,然后Ctrl+X退出
# 4. 重启 Caddy
sudo systemctl reload caddy

到此结束,可以使用https://fly.test12345.cfd:2053/my-secret-panel/看到登录界面了。

当然,你不设置这个prefix也可以,其实本身marzban就为你做了一层入口上的伪装(一个普通的web页面),但出于慎重以及GFW特征考虑,我觉得还是加上比较好。

这样,你就可以使用订阅链接的功能了。

4.1 不想使用Caddy想使用Nginx?#

注意,当前内容与4的内容冲突,如果希望使用nginx不想用caddy,才需要看这个。

获取 API Token:

  1. 在 Cloudflare 后台,点击右上角头像 -> My Profile(配置文件) -> 左侧 API Tokens(API 令牌。
  2. 点击 Create Token (创建账户API令牌)。
  3. 选择模板 Edit zone DNS(编辑区域 DNS)。
  4. Zone Resources(区域资源)里,选择 Specific zone(特定区域),然后选择你那个用来翻墙的域名。
  5. 生成 Token。

获取 Account ID: 左侧栏-> 账户主页,进入后在内容页你会发现:你的邮箱/用户名右边有三个点,点击就会有一个复制 **Account ID(账户 ID)**的选项

Terminal window
export CF_Token="这里填申请到的API Token"
export CF_Account_ID="Account ID"
# 这两个export会在关闭terminal后失效,如果在关闭terminal后想要需要执行下面的命令,务必要把export重新设置一遍
~/.acme.sh/acme.sh --issue --dns dns_cf -d fly.test12345.cfd --force
## 等待执行完毕

还是上面提到的env文件内,自己修改:

  • UVICORN_PORT: 修改为你想绑定的端口,这里假定为8000,后面出现的8000默认都是这个值。

使用Nginx反向代理到2053端口设置子链接,Cloudflare也能够正常转发。

这条路径下,HTTPS的证书交给Nginx挂载。

在服务器目录下,创建一个目录docker-setting:

Terminal window
mkdir -p ~/docker-setting/nginx
mkdir -p ~/docker-setting/certs
sudo nano ~/docker-setting/docker-compose.yml

将下面的代码黏贴:

docker-compose.yml
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
- "2053:2053"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./certs:/etc/letsencrypt:ro
- ./var/www/html:/var/www/html:ro
extra_hosts: # 让 Nginx 能访问宿主机的端口
- "host.docker.internal:host-gateway"
restart: unless-stopped
Terminal window
cd ~/docker-setting
# 创建一个临时容器(不需要启动)
docker create --name nginx-tmp nginx:alpine
# 拷整个 /etc/nginx 出来(包含 nginx.conf、conf.d、mime.types 等)
docker cp nginx-tmp:/etc/nginx ~/docker-setting/
docker cp nginx-tmp:/var/www/html ~/docker-setting/
# 删除临时容器
docker rm nginx-tmp
# 将https证书放入到cert下
# 复制证书进入目录
sudo cp $HOME/.acme.sh/fly.test12345.cfd_ecc/fullchain.cer ~/docker-setting/certs/certificate.crt
sudo cp $HOME/.acme.sh/fly.test12345.cfd_ecc/fly.test12345.cfd.key ~/docker-setting/certs/private.key
#删除掉默认的配置避免干扰
rm -f ~/docker-setting/nginx/conf.d/default.conf

创建一个叫做marzban.conf的文件,路径已经在下方给出。

~/docker-setting/nginx/conf.d/marzban.conf
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80; #如果你开启80,则使用这一块配置,否则不需要填写。
server_name panel.example.com; # 改成你的域名
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 2053 ssl http2;
server_name panel.example.com; # 记得改成你的域名
ssl_certificate /etc/letsencrypt/certificate.crt;
ssl_certificate_key /etc/letsencrypt/private.key;
# 建议的 TLS 设置(精简版)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
# 可选:HSTS(确认站点全站 https 再开)
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 可选:访问 / 时跳转到 /security-panel/
#location = / {
# return 301 /security-panel/;
#}
location /security-panel/ {
proxy_pass http://host.docker.internal:8000/; # 注意这个结尾的 /
proxy_http_version 1.1;
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 Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-Prefix /security-panel; #注意/security-panel要跟前面保持一致,不能有结尾的 /,你改了的话得一起改,
}
# 可选:不允许直接访问根路径下其它内容
# location / { return 404; }
}

最后,启动nginx容器即可

Terminal window
docker-compose up -d

5. 特定服务使用特定ip访问#

访问某些网站的时候,需要纯净的家宽IP避免一些问题。

可以参考我加的规则去仿写,具体可以查看下面配置文件中的outboundTag项,在我的场景中,我需要使用美国家宽ip保证我的ip纯净度,避免LLM官方给我的模型掺水降智。

这里的dest不要照抄,跟前面一样,请使用合适自己的dest

{
"log": {
"loglevel": "warning"
},
"routing": {
"rules": [
{
"ip": [
"geoip:private"
],
"outboundTag": "BLOCK",
"type": "field"
},
{
"type": "field",
"domain": [
"domain:openai.com",
"domain:chatgpt.com",
"domain:chat.com",
"domain:sora.com",
"domain:oaistatic.com",
"domain:api.openai.com",
"domain:platform.openai.com",
"domain:files.oaiusercontent.com",
"domain:anthropic.com",
"domain:claude.ai",
"domain:claudeusercontent.com",
"domain:api.anthropic.com",
"domain:statsig.anthropic.com",
"domain:gemini.google.com",
"domain:bard.google.com",
"domain:aistudio.google.com",
"domain:makersuite.google.com",
"domain:generativelanguage.googleapis.com",
"domain:geller-pa.googleapis.com",
"domain:alkalicore-pa.clients6.google.com",
"domain:cursor.sh",
"domain:cursor.com",
"domain:api2.cursor.sh",
"domain:api3.cursor.sh",
"domain:api4.cursor.sh",
"domain:api5.cursor.sh",
"domain:repo42.cursor.sh",
"domain:us-asia.gcpp.cursor.sh",
"domain:us-eu.gcpp.cursor.sh",
"domain:us-only.gcpp.cursor.sh",
"domain:grok.com",
"domain:x.ai",
"domain:perplexity.ai",
"domain:poe.com",
"domain:groq.com"
],
"outboundTag": "US-HOME"
},
{
"type": "field",
"ip": [
"160.79.104.0/23",
"209.249.57.0/24"
],
"outboundTag": "US-HOME"
}
]
},
"inbounds": [
{
"tag": "VLESS TCP REALITY",
"listen": "0.0.0.0",
"port": 443,
"protocol": "vless",
"settings": {
"clients": [],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"tcpSettings": {},
"security": "reality",
"realitySettings": {
"show": false,
"dest": "developer.apple.com:443",
"xver": 0,
"serverNames": [
"developer.apple.com"
],
"privateKey": "",
"shortIds": [
""
]
}
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
}
},
{
"tag": "Shadowsocks TCP",
"listen": "0.0.0.0",
"port": 1080,
"protocol": "shadowsocks",
"settings": {
"clients": [],
"network": "tcp,udp"
}
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "DIRECT"
},
{
"protocol": "blackhole",
"tag": "BLOCK"
},
{
"tag": "US-HOME",
"protocol": "对应的协议,可以是http、也可以是socks",
"settings": {
"servers": [
{
"address": "你的家宽地址",
"port": "实际端口",
"users": [
{
"user": "家宽用户名(如果需要可以设置,看你怎么接入)",
"pass": "家宽密码(如果需要可以设置,看你怎么接入)"
}
]
}
]
}
}
]
}
购买并配置 Linux VPS 以搭建个人网络服务
https://blog.astro777.cfd/posts/guide/setting-up-your-vps/
作者
ASTRO
发布于
2025-12-30
许可协议
CC BY-NC-SA 4.0