2025-12-03 06:33:05
PigeonPod是一款可以将YouTube的任意频道、播放列表转换成播客的程序,支持自托管。开始部署前,你需要创建一个YouTube Data API v3的API key。创建步骤可参考这里。
安装Docker和NGINX:
apt -y update apt -y install curl nginx python3-certbot-nginx curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh
创建目录新建compose文件:
mkdir /opt/pigeon-pod && cd /opt/pigeon-pod && nano docker-compose.yml
写入如下内容(将pigeonpod.example.com替换成你的域名):
services:
pigeon-pod:
image: ghcr.io/aizhimou/pigeon-pod:latest
restart: unless-stopped
container_name: pigeon-pod
ports:
- '127.0.0.1:8834:8080'
environment:
- 'PIGEON_BASE_URL=https://pigeonpod.example.com'
- 'PIGEON_AUDIO_FILE_PATH=/data/audio/'
- 'PIGEON_COVER_FILE_PATH=/data/cover/'
- 'SPRING_DATASOURCE_URL=jdbc:sqlite:/data/pigeon-pod.db' # set to your database path
volumes:
- data:/data
volumes:
data:
启动:
docker compose up -d
配置NGINX反向代理:
nano /etc/nginx/sites-available/pigeonpod
写入如下内容(将pigeonpod.example.com替换成你的域名):
server {
listen 80;
server_name pigeonpod.example.com;
client_max_body_size 0;
location / {
proxy_pass http://127.0.0.1:8834;
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;
}
}
启用站点:
ln -s /etc/nginx/sites-available/pigeonpod /etc/nginx/sites-enabled/pigeonpod
签发SSL证书:
certbot --nginx --email [email protected] --agree-tos --no-eff-email
访问pigeonpod.example.com,默认的管理员账号:root,密码:Root@123
登录进去,添加你刚创建的YouTube Data API Key:
效果:
2025-12-02 10:29:06
我第一眼看到这个名字还以为是锐速,卧槽文艺复兴了??说起来还挺怀念那段时间的,那段时间是折腾小鸡最快乐的时候,现在已经电子阳痿了。。完全提不起兴趣,今年黑5,总共消费0元= =
找了台灵车落地鸡试了一下,没想到药效出乎意料的好,本来晚高峰只能跑0.几MBps的鸡,吃上这个后能跑150MBps了,白天能跑150MBps的,现在能跑650MBps了。。
LotSpeed作者一共提供了3个版本,我全部都试了一遍,发现zeta-tcp版本的效果最好,所以这里我就只记录下zeta-tcp版本的配置步骤。
系统我使用的是Debian13,先更新系统、重启,确保系统当前运行的内核是最新版:
apt update apt full-upgrade
安装需要用到的软件包:
apt install build-essential git apt install linux-headers-$(uname -r)
克隆项目存储库、编译lotspeed内核模块:
git clone -b zeta-tcp https://github.com/uk0/lotspeed.git cd lotspeed make
安装lotspeed内核模块:
cp lotspeed.ko /lib/modules/$(uname -r)/kernel/net/ipv4/ depmod -a
加载lotspeed内核模块:
modprobe lotspeed
确保加载成功:
lsmod | grep lotspeed
[可选]配置开机自动加载lotspeed内核模块:
echo "lotspeed" >> /etc/modules-load.d/lotspeed.conf
这个开机自动加载配不配其实不重要,因为只要你后续把拥塞控制算法设置成lotspeed,系统就会自动加载lotspeed内核模块。配置这个的效果就是即便你的系统拥塞控制算法不是lotspeed,系统也自动加载lotspeed内核模块。换句话说就是无论你用不用这个模块,系统都先给你加载起来。
设置拥塞控制算法为lotspeed:
nano /etc/sysctl.d/10-lotspeed.conf
写入如下内容:
net.ipv4.tcp_congestion_control = lotspeed net.ipv4.tcp_no_metrics_save = 1
使其生效:
sysctl --system
查看拥塞控制算法是否生效:
sysctl net.ipv4.tcp_congestion_control
这样就配置好了,注意不要随意更新系统内核,如果内核更新了,你就需要重新编译一遍,作者要是能搞个dkms出来就好了。
2025-11-11 06:33:55
如果你因为种种原因不想再使用各类基于mihomo内核的GUI客户端了,那么可以尝试一下直接用裸核,裸核除了第一次配置的时候会麻烦一点(搓配置文件),后续使用是很爽的。
openSUSE Tumbleweed是我主要使用的Linux发行版,实际上下面的这些配置步骤应该适用于大部分使用systemd的Linux系统。
下载mihomo内核/解压/给执行权限:
wget https://github.com/MetaCubeX/mihomo/releases/download/v1.19.16/mihomo-linux-amd64-v3-go123-v1.19.16.gz gzip -d mihomo-linux-amd64-v3-go123-v1.19.16.gz sudo chmod +x mihomo-linux-amd64-v3-go123-v1.19.16
重命名并移动到/usr/local/bin:
sudo mv mihomo-linux-amd64-v3-go123-v1.19.16 /usr/local/bin/mihomo
创建运行时的目录和配置文件:
sudo mkdir /etc/mihomo sudo nano /etc/mihomo/config.yaml
我的配置如下:
mixed-port: 7890
allow-lan: true
tcp-concurrent: true
find-process-mode: strict
mode: rule
log-level: info
ipv6: false
keep-alive-interval: 30
unified-delay: true
profile:
store-selected: true
store-fake-ip: false
external-controller: 127.0.0.1:9090
external-controller-cors:
allow-origins:
- '*'
allow-private-network: true
secret: "89641937"
external-ui: "./ui"
external-ui-name: zashboard
external-ui-url: "https://github.com/Zephyruso/zashboard/archive/refs/heads/gh-pages.zip"
tun:
enable: true
stack: mixed
auto-route: true
auto-redirect: false
auto-detect-interface: true
dns-hijack:
- any:53
strict-route: true
mtu: 1500
dns:
enable: true
cache-algorithm: arc
prefer-h3: false
use-hosts: true
use-system-hosts: true
listen: 127.0.0.1:6868
ipv6: false
enhanced-mode: redir-host
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://cloudflare-dns.com/dns-query
- https://dns.google/dns-query
proxy-server-nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
direct-nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
respect-rules: true
sniffer:
enable: true
force-dns-mapping: true
parse-pure-ip: true
sniff:
HTTP:
ports:
- 80
- 8080-8880
override-destination: true
TLS:
ports:
- 443
- 8443
proxies:
- name: proxy1
type: vless
server: 89.64.19.37
port: 443
network: tcp
udp: true
tls: true
servername: www.cloudflare.com
reality-opts:
public-key: xxxx
short-id: "xxxx"
client-fingerprint: chrome
uuid: uuid
packet-encoding: xudp
flow: xtls-rprx-vision
- name: proxy2
type: ss
server: 89.64.19.37
port: 8080
network: tcp
udp: true
password: xxxx
cipher: chacha20-ietf-poly1305
proxy-groups:
- name: 🌍 VPN
icon: https://cdn.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Hijacking.png
type: select
proxies:
- ⚡️ Fastest
- 🎲 Random
- proxy1
- proxy2
- name: ⚡️ Fastest
icon: https://cdn.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Auto.png
type: url-test
tolerance: 150
url: https://cp.cloudflare.com/generate_204
interval: 300
proxies:
- proxy1
- proxy2
- name: 🎲 Random
icon: https://cdn.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Filter.png
type: fallback
url: https://cp.cloudflare.com/generate_204
interval: 300
proxies:
- proxy1
- proxy2
rule-providers:
torrent-trackers:
type: http
behavior: domain
format: mrs
url: https://github.com/legiz-ru/mihomo-rule-sets/raw/main/other/torrent-trackers.mrs
path: ./rule-sets/torrent-trackers.mrs
interval: 86400
proxy: ⚡️ Fastest
torrent-clients:
type: http
behavior: classical
format: yaml
url: https://github.com/legiz-ru/mihomo-rule-sets/raw/main/other/torrent-clients.yaml
path: ./rule-sets/torrent-clients.yaml
interval: 86400
proxy: ⚡️ Fastest
geosite-cn:
type: http
behavior: domain
format: mrs
url: https://github.com/MetaCubeX/meta-rules-dat/raw/meta/geo/geosite/cn.mrs
path: ./rule-sets/geosite-cn.mrs
interval: 86400
proxy: ⚡️ Fastest
geoip-cn:
type: http
behavior: ipcidr
format: mrs
url: https://github.com/MetaCubeX/meta-rules-dat/raw/meta/geo/geoip/cn.mrs
path: ./rule-sets/geoip-cn.mrs
interval: 86400
proxy: ⚡️ Fastest
geosite-private:
type: http
behavior: domain
format: mrs
url: https://github.com/MetaCubeX/meta-rules-dat/raw/meta/geo/geosite/private.mrs
path: ./rule-sets/geosite-private.mrs
interval: 86400
proxy: ⚡️ Fastest
geoip-private:
type: http
behavior: ipcidr
format: mrs
url: https://github.com/MetaCubeX/meta-rules-dat/raw/meta/geo/geoip/private.mrs
path: ./rule-sets/geoip-private.mrs
interval: 86400
proxy: ⚡️ Fastest
rules:
- RULE-SET,torrent-clients,DIRECT
- RULE-SET,torrent-trackers,DIRECT
- RULE-SET,geosite-private,DIRECT
- RULE-SET,geosite-cn,DIRECT
- RULE-SET,geoip-private,DIRECT
- RULE-SET,geoip-cn,DIRECT
- MATCH,🌍 VPN
简单说下这个配置的效果:
1.使用zashboard作为Web控制面板,访问:http://127.0.0.1:9090/ui/zashboard/ 密码:89641937
2.DNS模式使用realip+嗅探。(我不喜欢用FakeIP)我用了很多测试DNS泄露的网站均没有检测到漏(没有在本机抓包验证,不能百分百肯定,应该是不会漏=-=)
3.我自己的使用习惯是Tun,所以默认启用Tun模式,如果要使用系统代理也可以用端口7890。
4.分流规则全部使用rule-set,并且规则很简单,没有搞一大堆乱七八糟的规则在里面,除了geosite/geoip外,就只加了和bt下载相关的(个人使用习惯:下小姐姐必备)
5.出站代理的只配置了vless/ss,仅用作演示。如果你要添加其他协议的节点请参考官方的“出站代理”文档
我自己是不使用公共机场服务的,所有的节点都是自建,所以上面的配置没有涉及到proxy-providers(代理集合或者叫代理供应商)但是我最近一直在使用remnawavepanel,所以也可以把remnawavepanel提供的订阅链接配置上:
proxy-providers:
remnawave:
type: http
url: "https://sub.example.com/xxxx"
path: ./proxy_providers/remnawave.yaml
interval: 3600
size-limit: 0
然后在proxy-groups里面使用刚才配置的proxy-providers:
proxy-groups:
- name: 🌍 VPN
icon: https://cdn.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Hijacking.png
type: select
proxies:
- ⚡️ Fastest
- 🎲 Random
- proxy1
- proxy2
use:
- remnawave
- name: ⚡️ Fastest
icon: https://cdn.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Auto.png
type: url-test
tolerance: 150
url: https://cp.cloudflare.com/generate_204
interval: 300
proxies:
- proxy1
- proxy2
use:
- remnawave
- name: 🎲 Random
icon: https://cdn.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Filter.png
type: fallback
url: https://cp.cloudflare.com/generate_204
interval: 300
proxies:
- proxy1
- proxy2
use:
- remnawave
创建systemd服务:
sudo nano /etc/systemd/system/mihomo.service
写入如下配置:
[Unit] Description=mihomo Daemon, Another Clash Kernel. After=network.target NetworkManager.service systemd-networkd.service iwd.service [Service] Type=simple LimitNPROC=500 LimitNOFILE=1000000 CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SYS_TIME CAP_SYS_PTRACE CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SYS_TIME CAP_SYS_PTRACE CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE Restart=always ExecStartPre=/usr/bin/sleep 1s ExecStart=/usr/local/bin/mihomo -d /etc/mihomo ExecReload=/bin/kill -HUP $MAINPID [Install] WantedBy=multi-user.target
启动并设置开机自启:
sudo systemctl enable --now mihomo
效果:
2025-11-10 10:03:09
AppFlowy是Notion的开源替代品,你可以简单理解成这就是一个笔记软件。然后官方提供了一个自托管(self-host)版本:AppFlowy-Cloud,可以部署在自己的服务器上,无需使用官方的付费服务。
其实我半年前就部署过一次,试用了一会儿,当时就觉得这个程序的客户端UI真的太粗糙了,就没用下去,也懒得写文章记录部署的步骤,这回又故地重游了一次属于是。。心里想着半年过去了,这程序会不会变好一些?结果你猜怎么着?越来越拉了。。说句实话,我觉得这个AppFlowy-Cloud不值得我花这么长时间去部署,看看这个自托管版本的限制就知道了:
AI功能直接不让用,用户数量也限制只允许1个。。还有一堆其他的限制。。想赚钱能理解,但是你搞个自托管的版本限制成这个屌样,未免也有点太那啥了吧。。最TM骚的是这些限制在部署前找不到任何地方有说明,这是我部署好了后在管理员后台看到的。。你要在醒目的位置标明这些限制我压根就不会去部署了。
替大伙节约时间了,你看到这里可能就已经和我有一样的感受了,估计你也没有部署的欲望了,这东西不花钱真的就像一个大号的文本编辑器。。而且还有很多未知BUG,我刚部署的时候管理员后台直接报错打不开,隔了两天pull了个新的镜像后又能打开了(估计是他们修了BUG)但是还有一个问题是文件上传,只要上传的文件体积稍微大一点(10MB左右)就上传失败。。
遭老罪咯,花这么多时间去折腾这么个玩意,这个程序单说部署步骤也是同类产品中最繁琐的。。我的建议是花钱可以考虑,不花钱就别用了,自托管?搞笑的兄弟!我说的都是非常中肯的评价,好就是好,不好就是不好。
如果你想和我一起受罪,请开始准备工作:
1.一个域名A记录解析到:appflowy.example.com
2.系统的内存至少1GB,以下是我部署的全部服务内存占用情况,供参考:
3.系统的以下端口不能被其他程序占用,其中80/443端口用于给主机的NGINX反向代理:
80/443/3000/3001/8000/9999/9000/9001
我使用的系统是Debian13,安装NGINX/Docker:
apt -y update apt -y install curl nginx python3-certbot-nginx curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh
克隆AppFlowy-Cloud项目仓库:
cd /opt git clone https://github.com/AppFlowy-IO/AppFlowy-Cloud cd AppFlowy-Cloud
复制一份环境变量配置文件编辑:
cp deploy.env .env nano .env
需要修改的内容如下,全部写好了注释。其他没有在这里列出的内容可以保持默认值不做修改:
# 设置你的AppFlowy域名 FQDN=appflowy.example.com # 使用TLS SCHEME=https WS_SCHEME=wss # 数据库密码 POSTGRES_PASSWORD=dbpassword # MinIO的管理员账号密码,也用作s3存储桶的访问凭据 AWS_ACCESS_KEY=admin AWS_SECRET=miniopassword # AppFlowy管理员账号密码 [email protected] GOTRUE_ADMIN_PASSWORD=appflowyadminpassword # 使用命令openssl rand -hex 32生成 GOTRUE_JWT_SECRET=0a7a5b32d2a28f51a1250d4d68e68aa7133e033b17eeb7a6e2a0d2ab5cb62cdb # 关闭自动验证用户账户 GOTRUE_MAILER_AUTOCONFIRM=false # 关闭用户注册功能 GOTRUE_DISABLE_SIGNUP=true # GOTRUE的SMTP配置: GOTRUE_SMTP_HOST=mail.example.com GOTRUE_SMTP_PORT=587 GOTRUE_SMTP_USER=smtp GOTRUE_SMTP_PASS=smtppassword [email protected] # AppFlowy的SMTP配置: APPFLOWY_MAILER_SMTP_HOST=mail.example.com APPFLOWY_MAILER_SMTP_PORT=587 APPFLOWY_MAILER_SMTP_USERNAME=smtp [email protected] APPFLOWY_MAILER_SMTP_PASSWORD=smtppassword APPFLOWY_MAILER_SMTP_TLS_KIND=opportunistic # "none" "wrapper" "required" "opportunistic" # AI配置 AI_OPENAI_API_KEY=sk-proj-xxxxx AI_OPENAI_API_SUMMARY_MODEL=gpt-4o-mini # 性能优化 APPFLOWY_COLLABORATE_MULTI_THREAD=true # PGadmin的管理员账号密码 [email protected] PGADMIN_DEFAULT_PASSWORD=pgadminpassword
由于我使用外部(主机)的NGINX来反向代理AppFlowy,所以需要编辑compose文件:
nano docker-compose.yml
注释或者删掉compose内的NGINX配置:
services:# nginx: # restart: on-failure # image: nginx # ports: # - ${NGINX_PORT:-80}:80 # Disable this if you are using TLS # - ${NGINX_TLS_PORT:-443}:443 # volumes: # - ./nginx/nginx.conf:/etc/nginx/nginx.conf # - ./nginx/ssl/certificate.crt:/etc/nginx/ssl/certificate.crt # - ./nginx/ssl/private_key.key:/etc/nginx/ssl/private_key.key
将其他服务的端口暴露出来,为安全起见这里全部配置成只监听在本地(127.0.0.1):
services:
...
minio:
restart: on-failure
...
ports:
- "127.0.0.1:9000:9000"
- "127.0.0.1:9001:9001"
...
gotrue:
restart: on-failure
...
ports:
- "127.0.0.1:9999:9999"
...
appflowy_cloud:
restart: on-failure
...
ports:
- "127.0.0.1:8000:8000"
...
admin_frontend:
restart: on-failure
...
ports:
- "127.0.0.1:3000:3000"
...
appflowy_web:
restart: on-failure
...
ports:
- "127.0.0.1:3001:80"
启动:
docker compose up -d
新建NGINX站点配置文件:
nano /etc/nginx/sites-available/appflowy
写入如下内容:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name appflowy.example.com;
client_max_body_size 0;
underscores_in_headers on;
access_log /var/log/nginx/appflowy_access.log;
error_log /var/log/nginx/appflowy_error.log;
set $appflowy_cloud_backend "http://127.0.0.1:8000";
set $gotrue_backend "http://127.0.0.1:9999";
set $admin_frontend_backend "http://127.0.0.1:3000";
set $appflowy_web_backend "http://127.0.0.1:3001";
set $minio_backend "http://127.0.0.1:9001";
set $minio_api_backend "http://127.0.0.1:9000";
set $minio_internal_host "minio:9000";
# GoTrue
location /gotrue/ {
proxy_pass $gotrue_backend;
rewrite ^/gotrue(/.*)$ $1 break;
# Allow headers like redirect_to to be handed over to the gotrue
# for correct redirecting
proxy_set_header Host $http_host;
proxy_pass_request_headers on;
}
# WebSocket
location /ws {
proxy_pass $appflowy_cloud_backend;
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_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400s;
}
location /api {
proxy_pass $appflowy_cloud_backend;
proxy_set_header X-Request-Id $request_id;
proxy_set_header Host $http_host;
location ~* ^/api/workspace/([a-zA-Z0-9_-]+)/publish$ {
proxy_pass $appflowy_cloud_backend;
proxy_request_buffering off;
client_max_body_size 256M;
}
# AppFlowy-Cloud
location /api/chat {
proxy_pass $appflowy_cloud_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
chunked_transfer_encoding on;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 600s;
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
}
location /api/import {
proxy_pass $appflowy_cloud_backend;
# Set headers
proxy_set_header X-Request-Id $request_id;
proxy_set_header Host $http_host;
# Timeouts
proxy_read_timeout 600s;
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
# Disable buffering for large file uploads
proxy_request_buffering off;
proxy_buffering off;
proxy_cache off;
client_max_body_size 2G;
}
}
# Minio Web UI
location /minio/ {
proxy_pass $minio_backend;
rewrite ^/minio/(.*) /$1 break;
proxy_set_header Host $http_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-NginX-Proxy true;
## This is necessary to pass the correct IP to be hashed
real_ip_header X-Real-IP;
proxy_connect_timeout 300s;
## To support websockets in MinIO versions released after January 2023
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Some environments may encounter CORS errors (Kubernetes + Nginx Ingress)
# Uncomment the following line to set the Origin request to an empty string
# proxy_set_header Origin '';
chunked_transfer_encoding off;
}
location /minio-api/ {
proxy_pass $minio_api_backend;
# Set the host to internal host because the presigned url was signed against the internal host
proxy_set_header Host $minio_internal_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;
rewrite ^/minio-api/(.*) /$1 break;
proxy_connect_timeout 300s;
proxy_http_version 1.1;
proxy_set_header Connection "";
chunked_transfer_encoding off;
}
# Admin Frontend
location /console {
proxy_pass $admin_frontend_backend;
proxy_set_header X-Scheme $scheme;
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;
}
# AppFlowy Web
location / {
proxy_pass $appflowy_web_backend;
proxy_set_header X-Scheme $scheme;
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;
}
}
启用站点:
ln -s /etc/nginx/sites-available/appflowy /etc/nginx/sites-enabled/appflowy
签发SSL证书:
certbot --nginx --email [email protected] --agree-tos --no-eff-email
三个WebUI将在如下网址提供访问:
# AppFlowy Web UI https://appflowy.example.com # AppFlowy管理员后台 https://appflowy.example.com/console # MinIO Web UI https://appflowy.example.com/minio
1.使用GOTRUE_ADMIN_EMAIL/GOTRUE_ADMIN_PASSWORD既可以登录AppFlowy Web UI也可以登录AppFlowy管理员后台。
2.使用AWS_ACCESS_KEY/AWS_SECRET可以登录MinIO Web UI。
效果:
2025-11-10 09:59:32
我之前在找OpenCloud的同类软件时就得知了这个CryptPad,部署试了一下,说句很中肯的评价:不如OpenCloud好用。CryptPad除了端到端加密功能以外,其他方面都不如OpenCloud。
CryptPad虽然有一个网盘的功能,这里面也确实可以上传各种格式的文件,但是不能上传大文件(>300MB),基本上大文件都是上传失败。我看了一下issue,作者应该是把这个程序的定位就定在文档编辑、团队协作,网盘只是一个附带的小功能,只支持上传一些小文件,作为文档编辑、团队协作功能的一种补充。
如果你的需求主要是编辑文档,并且对数据有很高的安全要求,那么CryptPad非常适合,如果你是想搭建网盘存储各种各样的文件,那就不要用了CryptPad,纯折磨。。但话又说回来了OpenCloud一样也能编辑文档,而且还用的是Collabora(CODE)套件。。
准备工作:
1.添加两个A记录域名解析:
cryptpad.example.com sandbox-cryptpad.example.com
安装Docker和NGINX:
apt -y update apt -y install curl nginx python3-certbot-nginx curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh
创建目录新建compose文件:
mkdir /opt/cryptpad && cd /opt/cryptpad && nano docker-compose.yml
写入如下内容:
services:
cryptpad:
image: "cryptpad/cryptpad:version-2025.6.0"
hostname: cryptpad
restart: unless-stopped
environment:
- CPAD_MAIN_DOMAIN=https://cryptpad.example.com
- CPAD_SANDBOX_DOMAIN=https://sandbox-cryptpad.example.com
- CPAD_CONF=/cryptpad/config/config.js
- CPAD_INSTALL_ONLYOFFICE=yes
volumes:
- ./data/blob:/cryptpad/blob
- ./data/block:/cryptpad/block
- ./customize:/cryptpad/customize
- ./data/data:/cryptpad/data
- ./data/files:/cryptpad/datastore
- ./onlyoffice-dist:/cryptpad/www/common/onlyoffice/dist
- ./onlyoffice-conf:/cryptpad/onlyoffice-conf
ports:
- "127.0.0.1:3000:3000"
- "127.0.0.1:3003:3003"
ulimits:
nofile:
soft: 1000000
hard: 1000000
还需要创建如下目录并修改所有者权限:
mkdir -p data/{blob,block,data,files} customize onlyoffice-dist onlyoffice-conf
chown -R 4001:4001 data customize onlyoffice-dist onlyoffice-conf
启动:
docker compose up -d
配置NGINX反向代理:
nano /etc/nginx/sites-available/cryptpad
写入如下内容:
server {
listen 80;
listen [::]:80;
server_name cryptpad.example.com sandbox-cryptpad.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10G;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
}
location ^~ /cryptpad_websocket {
proxy_pass http://127.0.0.1:3003;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
}
}
启用站点:
ln -s /etc/nginx/sites-available/cryptpad /etc/nginx/sites-enabled/cryptpad
签发SSL证书:
certbot --nginx --email [email protected] --agree-tos --no-eff-email
访问cryptpad.example.com创建管理员账号:
配置站点标题等信息:
选择支持的应用程序,保持默认全选即可:
可选关闭注册(后续在管理面板可以控制开启):
这里需要注意:即便关闭了用户注册,CryptPad默认情况下还是允许匿名(访客)用户使用,当然功能有一定限制。
如果你要彻底禁用匿名(访客)用户使用你的实例,需要在customize目录内新建一个自定义配置文件:
nano /opt/cryptpad/customize/application_config.js
写入如下内容:
// SPDX-FileCopyrightText: 2023 XWiki CryptPad Teamand contributors // // SPDX-License-Identifier: AGPL-3.0-or-later /* * You can override the configurable values from this file. * The recommended method is to make a copy of this file (/customize.dist/application_config.js) in a 'customize' directory (/customize/application_config.js). * If you want to check all the configurable values, you can open the internal configuration file but you should not change it directly (/common/application_config_internal.js) */ (() => { const factory = (AppConfig) => { // Example: If you want to remove the survey link in the menu: // AppConfig.surveyURL = ""; // To inform users of the support ticket panel which languages your admins speak: //AppConfig.supportLanguages = [ 'en', 'fr' ]; AppConfig.registeredOnlyTypes = AppConfig.availablePadTypes; return AppConfig; }; // Do not change code below if (typeof(module) !== 'undefined' && module.exports) { module.exports = factory( require('../www/common/application_config_internal.js') ); } else if ((typeof(define) !== 'undefined' && define !== null) && (define.amd !== null)) { define(['/common/application_config_internal.js'], factory); } })();
修改文件所有者权限:
chown 4001:4001 /opt/cryptpad/customize/application_config.js
使自定义配置生效:
docker compose down docker compose up -d
这个文件application_config_internal.js提供了所有可自定义配置的内容。
如果你还要自定义别的配置,把application_config_internal.js里面的内容加到application_config.js里面即可。
还有一个问题,默认CryptPad只允许上传单个20MB大小的文件,如果觉得这个值太小想修改的话,这里需要挂载另外一个config.example.js配置文件到容器内。
不要直接挂载Github仓库里面默认的config.example.js,你需要进入当前运行的容器内,复制出容器正在使用的config.js:
docker compose exec -it cryptpad /bin/bash cat config/config.js
在这个配置文件内有两个与上传大小相关的配置项,根据自己的需要修改:
maxUploadSize: 20 * 1024 * 1024, # 20MB premiumUploadSize: 100 * 1024 * 1024, # 100MB
创建目录和config.js,将改好的配置内容写到config.js内:
mkdir /opt/cryptpad/config && nano /opt/cryptpad/config/config.js
编辑compose文件挂载config.js:
services:
cryptpad:
image: "cryptpad/cryptpad:version-2025.6.0"
...
environment:
...
- CPAD_CONF=/cryptpad/config/config.js
volumes:
...
- ./config/config.js:/cryptpad/config/config.js
修改权限:
chown -R 4001:4001 /opt/cryptpad/config
使配置生效:
docker compose down docker compose up -d
另一个更简单的办法是直接更改容器正在使用的config.js,然后重启容器:
docker compose restart
但请注意这种修改不是永久生效的,一旦容器被删除配置也会失效。最好还是使用上述挂载的方式。
其实改不改意义不大,哪怕改成10GB,传大文件最终也是上传失败,文章之前就说过了上传>300MB的文件大概率上传失败,可能程序设计的有缺陷吧,或者说作者就是只打算支持小文件上传。。
转到CryptPad管理员界面,在用户存储这里,可以修改所有用户的默认存储大小,也可以指定修改某一个用户的存储大小,注意这个存储大小与用户可以上传的单个文件大小不相关,这里的存储大小指的是用户网盘的总容量:
但是根据CryptPad论坛的这个帖子可以得知,maxUploadSize是用于所有默认用户的单个文件上传大小限制,如果给一个特定用户设置了存储大小,那么这个特定用户的单个文件上传大小就变成了用premiumUploadSize来限制。
2025-10-22 11:33:23
我在Github上找到了几个WHMCS对接ConvoyPanel的模块,我全部都试了一遍,这些模块不是这有点问题就是那有点问题。。只有这一个功能是完全正常的:https://github.com/simple-taipei/convoy-for-whmcs。但实际上这个模块也不能做到开箱即用,需要魔改一下WHMCS的产品配置页面。
由于ConvoyPanel的API对创建虚拟机时使用的ROOT密码要求非常严格,至少8位,且要包含一个大写字母,一个小写字母,一个数字,一个特殊符号。而WHMCS默认的ROOT密码输入框没有对用户输入的密码进行强度校验,这导致用户如果输入了一个强度不达标的密码,虚拟机就无法创建成功。
为了解决这个问题,我用AI写了一个WHMCS的Hook,实现的功能就是校验用户输入的ROOT密码是否满足ConvoyPanel的条件,如果不满足条件则阻止表单提交,直到用户输入的ROOT密码满足条件才能下单购买。我顺便还让AI写了一个隐藏WHMCS产品配置页面的NS1/NS2输入框,并填充默认值的Hook。有需要的可以直接从我博客下载。
密码强度校验:validate_rootpw
隐藏NS1/NS2输入框:hidden_nsprefix
使用方法也很简单,把这些PHP文件放到这个目录下:
/var/www/whmcs/includes/hooks
修改文件所有者权限:
chown -R www-data:www-data /var/www/whmcs/includes/hooks/validate_rootpw.php chown -R www-data:www-data /var/www/whmcs/includes/hooks/hidden_nsprefix.php
效果就是这样,用户购买时只需要输入虚拟机的Hostname和ROOT密码:
目前只测试过WHMCS默认的Standard Cart订单模板,其他的模板能不能用不清楚,不能用的话让AI改一下应该也不难。。但是请注意哈,这两个Hook文件都只是做了简单的前端校验,后端是没有校验的,也就是说用户如果懂点技术的话是可以直接篡改(绕过)这些功能的。当然我觉得不会有人那么无聊吧,让设置高强度的密码不要,要去用弱密码然后机子被人黑=-=
现在就可以来配置模块了,在WHMCS如下路径创建一个目录:
mkdir /var/www/whmcs/modules/servers/convoy
把模块克隆到本地:
git clone https://github.com/simple-taipei/convoy-for-whmcs.git cd convoy-for-whmcs
把模块文件都复制到对应的目录下:
cp convoy.php /var/www/whmcs/modules/servers/convoy cp -r lib /var/www/whmcs/modules/servers/convoy cp -r templates /var/www/whmcs/modules/servers/convoy
修改目录所有者权限:
chown -R www-data:www-data /var/www/whmcs/modules/servers/convoy
[可选]如果想要产品开通后,虚拟机自动开机可以编辑convoy.php:
nano /var/www/whmcs/modules/servers/convoy/convoy.php
把这个配置改成true:
'start_on_completion' => true
转到WHMCS后台,先添加一个组,再添加一个服务:
点击如图所示按钮进入完整的配置页面:
Name随便起一个,Hostname填写你的ConvoyPanel域名(不要带http/https前缀),IP Address填写ConvoyPanel所在服务器的公网IP。Password填写ConvoyPanel面板生成的Token,端口使用443,其他没有提到的配置项全部保持默认值不做修改,点击测试连接,确保能够正常连接到ConvoyPanel:
ConvoyPanel创建Token:
转到WHMCS的Products/Services页面,先创建一个产品组,再创建一个产品:
产品类型一定要选择Server/VPS,因为我们刚才的Hook都是针对的这个模板页面,你用其他的就达不到预期效果:
转到模块设置页面,参考下图来配置VPS产品的具体规格,如CPU、内存、硬盘、流量等:
这里面需要注意是Node ID这个ID在ConvoyPanel的如下页面可以找到:
还有Template UUID:
到这里就全部配置完成了,现在可以测试一下用户下单购买以及开通的情况,用户可以在WHMCS通过SSO登录到ConvoyPanel的虚拟机控制面板:
一切正常:
到这里这篇文章就写的差不多了,当然如果想正式营业的话还需要对接一个支付接口,oneman常用的接口不用多说了,肯定是易支付。。易支付可以自己搭,也可以用别人的,俗称平台。用别人的易支付风险很大,因为这些平台随时都可能跑路,做的都是些“你懂的”的业务。。最好还是自己搭一个。。这里就不多说了。。