August 18, 2026

使用vps自建meting-Api

meting

起因

我的 Hugo 博客用 APlayer + MetingJS 做音乐播放器,依赖第三方接口 api.injahow.cn 来解析网易云/QQ音乐的歌曲数据。某天播放器不出现了,控制台突然报错,按F12页面显示:

Fatal error: Uncaught RedisException: MISCONF Redis is configured to save RDB snapshots, but it's currently unable to persist to disk...

原因不是博客代码的问题,而是 api.injahow.cn 这台第三方服务器自己的 Redis 数据库出了故障——磁盘写入失败,导致 Redis 拒绝执行任何写操作(包括接口用来做访问限流的计数功能),整个接口跟着崩溃,不过现在我要让音乐接口 “死者复生” ,看我的操作。

1.换下各种公共接口

既然是别人的meting服务器出问题了,找到了以下音乐解析器接口,我决定换以下四个公共接口:

meting-api.imsyy.top:直接连接失败(ERR_CONNECTION_CLOSED)。

meting-api-omega.vercel.app:数据能正常显示,可惜vercel域名被墙。

meting.mikus.ink:数据正常,但被 CORS 策略拦截

meting.jinghuashang.cn:实测请求带参数后没有返回预期的 JSON 数据,不可用。

既然都有问题,我决定下一步。

2.部署meting-api服务

这里只需要:

一台能ping通的vps、一个域名。

打开你的vps(比如xshell、putty等登录终端),进行以下操作。

2-1.装docker

curl -fsSL https://get.docker.com | sh

其实我这里早装了。

验证方式是

docker -v

显示版本号安装成功。

2-2.安装拉取meting-api

docker run -d --name meting-api -p 3000:3000 --restart always intemd/meting-api:latest

2-3.验证本地是否能跑起来

curl "http://127.0.0.1:3000/api?server=netease&type=playlist&id=7640699765"

因为因为 API 实际路径是 /api,所以做了调整,输出为:

root@racknerd-6c465f:~# curl "http://127.0.0.1:3000/api?server=netease&type=playlist&id=7640699765"
[{"title":"Спокойная ночь","author":"Кино","pic":"https://p1.music.126.net/jrEDyug7ubULYf3UrXzHjg==/109951170416026069.jpg","url":"http://127.0.0.1:3000/api?server=netease&type=url&id=26710593","lrc":"http://127.0.0.1:3000/api?server=netease&type=lrc&id=26710593"}.......

代表成功。

3.申请免费域名

因为api接口需要域名解析到vps的ip,所以我选择的域名服务商是免费的DNSHE,这个域名是免费的,而且可以延长到十年内,自己随便填写一个记录名称前缀,记录内容就是你vps的ip。

image-20260818215429942

填好后保存退出,等解析完成一会儿会有用。

4.配置 Nginx 反向代理

4-1.先确定你的vps系统,如果你的系统是debian/ubuntu一类的,一般是conf.d结构。

先确定Nginx用的那种结构:

ls /etc/nginx/

显示输出为:

root@racknerd-6c465f:~# ls /etc/nginx/
conf.d  fastcgi_params  mime.types  modules  nginx.conf  scgi_params  uwsgi_params

确定Nginx为D结构后,接下来:

nano /etc/nginx/conf.d/meting.conf

写入:

server {
    listen 80;
    server_name your domian(your domian代表是你刚刚申请的域名,后面我都用这个代替我申请的域名);

    location / {
        proxy_pass http://127.0.0.1:3000;
        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;

        add_header 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' '*' always;
    }
}

不过中间出现了小插曲,解决了。对于初步搭建meting-api的不用管,保存退出:Ctrl+XY → 回车就行。

然后检测并重载:

cat /etc/nginx/conf.d/meting.conf

输出为:


root@racknerd-6c465f:~# nano /etc/nginx/conf.d/meting.conf
root@racknerd-6c465f:~# cat /etc/nginx/conf.d/meting.conf
server {
    listen 80;
    server_name your domian;
    location / {
        proxy_pass http://127.0.0.1:3000;
        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;
        add_header 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' '*' always;
    }
}

4-2.接下来检测并重载 Nginx

nginx -t
systemctl reload nginx

显示看到 syntax is oktest is successful 就继续。

测速接口:

curl "http://your domian/api?server=netease&type=playlist&id=7640699765"

输出为:

root@racknerd-6c465f:~# curl "http://your domian/api?server=netease&type=playlist&id=7640699765"
[{"title":"Спокойная ночь","author":"Кино","pic":"https://p1.music.126.net/jrEDyug7ubULYf3UrXzHjg==/109951170416026069.jpg"......

即为成功。

apt update
apt install certbot python3-certbot-nginx -y

安装并申请证书,输入:

certbot --nginx -d your domian

输出为:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/meting.tooyoungtoosimple.ccwu.cc/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/meting.tooyoungtoosimple.ccwu.cc/privkey.pem
   Your cert will expire on 2026-11-14. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:
   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

提示你的证书申请成功,而且有效期到 2026-11-14。

再次输入测试https:

curl "https://your domian/api?server=netease&type=playlist&id=7640699765"

输出为:

root@racknerd-6c465f:~# curl "https://your aomian/api?server=netease&type=playlist&id=7640699765"
[{"title":"Спокойная ночь","author":"Кино","pic":"https://p1.music.126.net/jrEDyug7ubULYf3UrXzHjg==/109951170416026069.jpg","url":"http://your aomian/api?server=netease&type=url&id=26710593","lrc":"http://your domian/api?server=netease&type=lrc&id=26710593"}

4-3.解决url和lrc的http问题

主接口本身返回成功了(说明 HTTPS 通了),但有个细节要注意:返回内容里嵌套的 urllrc 链接依然是 http:// 开头,不是 https://。这个项目有个特殊要求——它读取 X-Forwarded-Host 这个请求头来拼接返回链接里的协议和域名,而且格式比较特殊,需要写成 $scheme://$server_name 这样的形式,不是标准写法。

解决办法,编辑nano /etc/nginx/conf.d/meting.conf

    location / {
        proxy_pass http://127.0.0.1:3000;
        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;
        add_header 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' '*' always;
    }

proxy_set_header X-Forwarded-Proto $scheme; 这一行下面加一行:

        proxy_set_header X-Forwarded-Host $scheme://$server_name;

保存退出:Ctrl+XY → 回车

检测并重载

nginx -t
systemctl reload nginx

重新测试:

curl "https://your domian/api?server=netease&type=playlist&id=7640699765"

结果显示url和lrc都有https了,成功完成。

5.解决CORS 头问题

我修改好后f12网页端提示:

Access to fetch at 'https://your domian/api?server=netease&type=playlist&id=7640699765&auth=undefined&r=0.5812098791672832' from origin 'https://www.zaqizaba.xyz' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed. Have the server send the header with a valid value.

解决办法是,在Ngnix除掉这三行:

        add_header 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' '*' always;

变成:

    location / {
        proxy_pass http://127.0.0.1:3000;
        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 X-Forwarded-Host $scheme://$server_name;
    }

保存退出:Ctrl+XY → 回车

检测并重载

nginx -t
systemctl reload nginx

验证 CORS 头是否正常(只有一个了)

curl -I "https://your domian/api?server=netease&type=playlist&id=7640699765"

看输出里 Access-Control-Allow-Origin 这一行,应该只出现一次,值是单个 *,不是 *, *

改完之后再回浏览器测试一次播放器,应该就没有 CORS 报错了。

输出为:

curl -I "https://your domian/api?server=netease&type=playlist&id=7640699765"
HTTP/1.1 200 OK
Server: nginx/1.27.5
Date: Sun, 16 Aug 2026 15:07:31 GMT
Content-Type: application/json; charset=UTF-8
Connection: keep-alive
access-control-allow-origin: *

输出为一个 *显示为成功。

6.限制自建接口

毕竟我是自己搭建的自建api接口,不是公共免费接口。我这个接口部署在我的vps上,不可能让别人都用,不然vps的api接口请求消耗的流量费用我hold不住。

这里可以这样做。给接口加一个简单的 Referer 检查。就是 只有从我的博客页面发起的请求才放行,其他来源直接拒绝(403)。

编辑配置文件

nano /etc/nginx/conf.d/meting.conf

在 443 端口那个 server {} 块里(跟 listen 443 ssl; 同级,location / 外面),加上这两行:

    valid_referers none blocked www.zaqizaba.xyz zaqizaba.xyz;
    if ($invalid_referer) {
        return 403;
    }

完整的 443 server 块应该长这样:

server {
    server_name your domian;

    valid_referers none blocked www.zaqizaba.xyz zaqizaba.xyz;
    if ($invalid_referer) {
        return 403;
    }

    location / {
        proxy_pass http://127.0.0.1:3000;
        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 X-Forwarded-Host $scheme://$server_name;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/your domian/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/your domian/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

保存生效:

nginx -t
systemctl reload nginx

测试是不是成功;

curl -H "Referer: https://evil-site.com" "https://your domian/api?server=netease&type=playlist&id=7640699765"

显示:

:~# curl -H "Referer: https://evil-site.com" "https://your domian/api?server=netease&type=playlist&id=7640699765"
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.27.5</center>
</body>
</html>

代表成功403,只有从你自己博客发起的请求才放行,其他来源直接返回 403。测试验证:带假 Referer 的请求确实被正确拦截了。

大功告成!!!现在将music shortcodes的原来出问题的api公共音乐接口:

var meting_api='https://api.injahow.cn/api?server=:server&type=:type&id=:id&auth=:auth&r=:r';

换成你用vps自建的api音乐接口:

var meting_api='https://your domian/api?server=:server&type=:type&id=:id&auth=:auth&r=:r';

这样,自己用vps搭建的音乐api接口就不用受第三方的Redis 数据库故障困扰了,完全自己掌握,并且出问题还可以排查。

phoenix_illustration_wide

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。