Podman部署Radicale+InfCloud笔记
Podman 部署 Radicale + InfCloud 完整笔记
一、环境说明
- 服务器配置:2核2G 云服务器
- 后端服务:Radicale (CalDAV/CardDAV 服务器)
- 前端界面:InfCloud (网页日历客户端)
- 容器工具:Podman
二、Radicale 部署
2.1 创建目录结构
mkdir -p ~/radicale/{config,data}
cd ~/radicale2.2 创建 Radicale 配置文件
创建 config 文件:
[server]
hosts = 0.0.0.0:5232
[auth]
type = htpasswd
htpasswd_filename = /data/users
htpasswd_encryption = bcrypt
[storage]
filesystem_folder = /data/collections
[web]
type = radicale.web.internal
[headers]
Access-Control-Allow-Origin = https://你的前端域名
Access-Control-Allow-Methods = GET, POST, OPTIONS, PROPFIND, PROPPATCH, REPORT, PUT, MOVE, DELETE, LOCK, UNLOCK
Access-Control-Allow-Headers = User-Agent, Authorization, Content-type, Depth, If-match, If-None-Match, Lock-Token, Timeout, Destination, Overwrite, Prefer, X-client, X-Requested-With
Access-Control-Expose-Headers = Etag, Preference-Applied
Access-Control-Allow-Credentials = true2.3 创建 docker-compose.yml
version: '3.8'
services:
radicale:
image: tomsquest/docker-radicale:latest
container_name: radicale
restart: unless-stopped
ports:
- "5232:5232"
volumes:
- ./config:/config/config:ro
- ./data:/data
environment:
- TZ=Asia/Shanghai
mem_limit: 256m
cpus: 0.52.4 启动并创建用户
# 启动服务
podman-compose up -d
# 创建用户(宿主机需安装 apache2-utils)
sudo apt install apache2-utils -y
htpasswd -B -c ./data/users zadmin
# 或直接在容器内创建
podman exec radicale htpasswd -B -c /data/users zadmin
# 重启服务
podman-compose restart radicale
# 查看日志
podman-compose logs radicale三、InfCloud 部署
3.1 拉取镜像并运行
# 创建配置目录
mkdir -p ~/infcloud/config
# 运行容器
podman run -d \
--name intelligent_kepler \
-p 8080:80 \
-v ~/infcloud/config:/srv/infcloud/config:ro \
waja/infcloud:latest3.2 复制配置文件
# 从容器复制默认配置
podman cp intelligent_kepler:/srv/infcloud/config/config.js ~/infcloud/config/config.js
# 或直接创建配置文件
cat > ~/infcloud/config/config.js << 'EOF'
var globalNetworkCheckSettings = {
href: "https://你的Radicale域名/",
timeOut: 90000,
lockTimeOut: 10000,
checkContentType: true,
settingsAccount: true,
delegation: true,
additionalResources: [],
hrefLabel: null,
forceReadOnly: null,
ignoreAlarms: false,
backgroundCalendars: []
};
var globalInterfaceLanguage = 'zh_CN';
var globalTimeZone = 'Asia/Shanghai';
var globalUseHtml5Cache = false; // 禁用缓存便于调试
var globalDebugMode = true;
EOF
# 重启容器
podman restart intelligent_kepler四、Caddy 反向代理配置
4.1 Caddyfile 配置
# Radicale 后端 API
zrili.aab.com {
reverse_proxy radicale:5232
}
# InfCloud 前端界面
zprili.aab.com {
reverse_proxy intelligent_kepler:80
}4.2 统一域名方案(推荐,避免跨域)
zri.aab.com {
# InfCloud 前端
handle / {
reverse_proxy infcloud:80
}
# Radicale 后端 API
handle /caldav/* {
reverse_proxy radicale:5232
}
# Radicale 管理界面
handle /.web/* {
reverse_proxy radicale:5232
}
}4.3 重载配置
sudo systemctl reload caddy五、常见问题与解决方案
5.1 CORS 跨域问题
错误信息:
Access to XMLHttpRequest at 'https://...' from origin 'https://...' has been blocked by CORS policy解决方案:确保 Radicale 配置中包含完整的 CORS 头,特别是 X-client:
Access-Control-Allow-Headers = User-Agent, Authorization, Content-type, Depth, If-match, If-None-Match, Lock-Token, Timeout, Destination, Overwrite, Prefer, X-client, X-Requested-With5.2 配置文件语法错误
错误信息:
config.js:335 Uncaught SyntaxError: Unexpected token ':'解决方案:
- 检查是否有多余的逗号
- 检查是否使用中文标点
- 确保变量使用
var声明
5.3 URL 拼接错误
错误信息:
REPORT https://zadmin@zrili.aab.comzadmin/解决方案:
- 确保
href末尾有斜杠:https://domain/ - 清除浏览器缓存和 AppCache
- 设置
globalUseHtml5Cache = false
5.4 清除 HTML5 AppCache
Chrome/Edge:
- 访问
chrome://appcache-internals/ - 找到对应站点,点击 Remove
强制刷新:
- 右键点击刷新按钮 → 「清空缓存并硬性重新加载」
5.5 容器内命令找不到
问题:htpasswd: command not found
解决方案:
# 使用完整路径
podman exec radicale /usr/bin/htpasswd -B -c /data/users zadmin
# 或使用 Python 生成密码
podman exec radicale python3 -c "import bcrypt; print(bcrypt.hashpw(b'password', bcrypt.gensalt()).decode())"六、备选方案:CalDavZAP
如果 InfCloud 问题难以解决,可以使用 CalDavZAP:
6.1 部署 CalDavZAP
# 创建目录
mkdir -p ~/caldavzap && cd ~/caldavzap
# 下载并解压
wget https://www.inf-it.com/CalDavZAP_0.13.1.zip
unzip CalDavZAP_0.13.1.zip
rm CalDavZAP_0.13.1.zip
# 配置
cp config.js.example config.js
sed -i "s|var globalNetworkCheckSettings = {.*|var globalNetworkCheckSettings = { href: 'https://你的Radicale域名',|" config.js
# 使用 Nginx 容器托管
podman run -d \
--name caldavzap \
-p 8082:80 \
-v $(pwd):/usr/share/nginx/html:ro \
nginx:alpine6.2 访问地址
http://你的服务器IP:8082七、常用命令速查
7.1 容器管理
# 查看容器状态
podman ps -a
# 查看日志
podman logs radicale
podman logs intelligent_kepler
# 进入容器
podman exec -it radicale /bin/sh
podman exec -it intelligent_kepler /bin/sh
# 重启容器
podman restart radicale intelligent_kepler
# 停止并删除
podman stop radicale intelligent_kepler
podman rm radicale intelligent_kepler7.2 网络测试
# 从容器内测试连通性
podman exec intelligent_kepler wget -O- http://radicale:5232/
# 带认证测试
curl -u zadmin:密码 https://你的域名/.web/
# 检查 CORS 头
curl -I https://你的域名/.web/ | grep -i "access-control"7.3 配置文件检查
# 查看 Radicale 配置
cat ~/radicale/config
# 查看 InfCloud 配置
cat ~/infcloud/config/config.js
# 查看用户文件
cat ~/radicale/data/users八、架构最佳实践
8.1 推荐架构(无跨域问题)
统一域名: https://calendar.example.com
├── / → InfCloud 前端
├── /caldav/* → Radicale API
└── /.web/* → Radicale 管理界面8.2 跨域架构(需配置 CORS)
├── https://frontend.example.com → InfCloud 前端
└── https://backend.example.com → Radicale API8.3 安全建议
- 始终使用 HTTPS(Caddy 自动提供)
- 使用 bcrypt 加密密码(
htpasswd_encryption = bcrypt) - 限制容器资源:
mem_limit: 256m,cpus: 0.5 - 添加安全选项:
security_opt: no-new-privileges:true - 定期备份数据目录:
~/radicale/data/
九、故障排查清单
- [ ] Radicale 容器是否运行:
podman ps | grep radicale - [ ] 用户文件是否存在:
podman exec radicale cat /data/users - [ ] CORS 头是否完整(包含
X-client) - [ ]
config.js中href是否正确(末尾有斜杠) - [ ] 浏览器缓存是否清除(包括 AppCache)
- [ ] 两个容器是否在同一网络
- [ ] Caddy 配置是否正确重载
- [ ] 域名 DNS 是否解析到正确 IP
- [ ] 防火墙端口是否开放(80, 443, 5232)