部署小智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 服务名

标签: none

评论已关闭