部署小智AI到公网
作者:Harrandi 发布时间:May 14, 2026 分类:Linux
记录一下,也或许有人用得到。
参考https://github.com/xinnan-tech/xiaozhi-esp32-server/issues/791
1.克隆项目,https://github.com/xinnan-tech/xiaozhi-esp32-server
参考文件夹docs内的Deployment_all.md,
xiaozhi-esp32-server-redis和voiceprint-api我使用了docker其余没 用.
先搞定本地的部署,测试正常后配置公网。
2.去CF增加一个A记录如xiaozhi,地址填当前你服务器公网地址然后获取域名ID(不是ZONE ID)后面用得到:
curl --request GET --url "https://api.cloudflare.com/client/v4/zones/你的ZONE ID/dns_records?name=xiaozhi.yours.org&type=A" --header "Authorization: Bearer 你的APItoken" --header "Content-Type: application/json"
为域名申请letsencrypt证书:
略麻烦,因为我用动态域名,我也尝试了tunnel,工作不正常,只能用动态域名+直接开放端口。
登录 Cloudflare 控制台,进入 My Profile → API Tokens
点击 Create Token → 选择 Create Custom Token
配置权限(如Zone Zone Read; Zone DNS Edit)
选择Specific zone,即要用的域名.
在 TTL (time to live) 区域设置:
Start date (notBefore):可选,设置 Token 何时开始生效。不填则创建后立即生效
End date (notAfter):建议设置,Token 到此时间后自动失效。不填则永不过期
用 DNS-01 申请 SSL 证书:
# 安装 certbot 和 cloudflare dns 插件
sudo apt install certbot python3-certbot-dns-cloudflare
# 创建 API Token 配置文件(把 TOKEN 换成你的)
echo 'dns_cloudflare_api_token = 你的CloudflareAPIToken' | sudo tee /etc/cloudflare.ini
sudo chmod 600 /etc/cloudflare.ini
# 申请证书
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/cloudflare.ini \
-d xiaozhi.yours.org
创建一个动态IP更新脚本命名cf-ddns.sh:
#!/bin/bash
# ===配置区=============
CLOUDFLARE_API_TOKEN="你的APItoken"
ZONE_ID="你的ZoneID"
DNS_RECORD_ID="你的域名ID"
DNS_RECORD_NAME="xiaozhi.yours.org"
DNS_RECORD_TYPE="A"
# =====下方无需改动======
# curl 和 jq 的完整路径(cron 需要,没有的话需要安装)
CURL="/usr/bin/curl"
JQ="/usr/bin/jq"
# 获取当前公网 IP
IP=$($CURL -s ifconfig.me)
# 获取 Cloudflare 上当前记录的 IP
CURRENT_IP=$($CURL -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$DNS_RECORD_ID" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" | $JQ -r '.result.content')
# 比较是否需要更新
if [[ "$IP" == "$CURRENT_IP" ]]; then
echo "$(date): IP 未变化,跳过更新 ($IP)"
exit 0
fi
# IP 变化了,执行更新
echo "$(date): IP 从 $CURRENT_IP 变为 $IP,开始更新..."
$CURL -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$DNS_RECORD_ID" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" \
--data '{
"type": "'"$DNS_RECORD_TYPE"'",
"name": "'"$DNS_RECORD_NAME"'",
"content": "'"$IP"'",
"ttl": 120,
"proxied": false
}'
echo "$(date): 更新完成 -> $IP"
将这个脚本加入cron并输出日志注意权限:
chmod +x ~/cf-ddns.sh # 给执行权限
crontab -e # 编辑定时任务
*/5 * * * * /yourpath/cf-ddns.sh >> /home/you/ddns-error.log
3.配置Nginx反代,参考顶部链接内的服务器基础参数。
我的根目录是智控台(必须,我尝试子目录访问总是有小问题),digital-human就是之前的测试页面,为方便使用digital-human所以全部使用https,如需保留http删除nginx配置第一块sever_name下的return行。
登陆修改智控台内server.fronted_url为
https://xiaozhi.yours.org:8443,
server.websocket 地址wss://xiaozhi.yours.org:8443/xiaozhi/v1/
OTA地址 https://xiaozhi.yours.org:8443/xiaozhi/ota/
部署web:
cd ~/xiaozhi-esp32-server/main/manager-web
npm run build
cp -r dist/* /var/www/manager-web/
权限设置:
sudo chown -R www-data:www-data /var/www/manager-web
sudo find /var/www/manager-web -type d -exec chmod 755 {} \;
sudo find /var/www/manager-web -type f -exec chmod 644 {} \;
# 重载 Nginx
nginx -s reload
我的nginx配置:
server {
listen 8080 ;
server_name yours.org;
return 301 https://$host:8443$request_uri; #如使用http删除此行
location / {
root /var/www/manage-web;
index index.html index.htm;
try_files $uri $uri/ =404;
}
location /xiaozhi/v1/ {
proxy_pass http://192.168.10.12:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /xiaozhi/ota/ {
proxy_pass http://192.168.10.12:8002;
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;
}
}
server {
listen 8443 ssl;
server_name yours.org;
ssl_certificate /etc/letsencrypt/live/xiaozhi.yours.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xiaozhi.yours.org/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
root /var/www/manager-web/;
index index.html;
try_files $uri $uri/ =404;
}
location /digital-human {
root /var/www/;
index index.html index.htm;
try_files $uri $uri/ =404;
}
location /xiaozhi/v1/ {
proxy_pass http://192.168.10.12:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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_read_timeout 3600s;
}
location /xiaozhi/ota/ {
proxy_pass http://192.168.10.12:8002;
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;
}
location /xiaozhi/ {
proxy_pass http://127.0.0.1:8002;
proxy_set_header Host $host;
proxy_connect_timeout 15;
proxy_send_timeout 15;
proxy_read_timeout 15;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
因为我三个组件不是docker部署,所以用systemctl管理:
打包manager-api:
# 进入 manager-api 项目根目录(有 pom.xml 的地方)
cd /path/to/manager-api
# 用 Maven 打包
mvn clean package -DskipTests
创建systemctl:
sudo nano /etc/systemd/system/manager-api.service
[Unit]
Description=Xiaozhi Manager API Service
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/home/yours/xiao-zhi-server/main/manager-api
ExecStart=/usr/bin/java -jar /home/yours/xiao-zhi-server/main/manager-api/target/xiaozhi-esp32-api.jar
Restart=always
RestartSec=10
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
创建SERVER的systemctl:
[Unit]
Description=Xiaozhi ESP32 Server
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/home/yours/xiao-zhi-server/main/xiaozhi-server
ExecStart=/home/yours/miniconda3/envs/xiaozhi-esp32-server/bin/python app.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
创建MCP的systemctl:
[Unit]
Description=Xiaozhi MCP Server Service
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/home/yours/xiao-zhi-server/mcp-endpoint-server
ExecStart=/home/yours/miniconda3/envs/mcp-endpoint-server/bin/python main.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
启动或查询或自动它们:
sudo systemctl daemon-reload
sudo systemctl start 服务名
sudo systemctl enable 服务名
sudo systemctl status 服务名

评论已关闭