Backend: - schedule_tenant: NC 新容器自動 pgsql 安裝 (_nc_db_check 全新容器處理) - schedule_tenant: NC 初始化加入 Redis + APCu memcache 設定 (修正 OIDC invalid_state) - schedule_tenant: 新租戶 KC realm 自動設定 accessCodeLifespan=600s (修正 authentication_expired) - schedule_account: NC Mail 帳號自動設定 (nc_mail_result/nc_mail_done_at) - schedule_account: NC 台灣國定假日行事曆自動訂閱 (CalDAV MKCALENDAR) - nextcloud_client: 新增 subscribe_calendar() CalDAV 訂閱方法 - settings: 新增系統設定 API (site_title/version/timezone/SSO/Keycloak) - models/result: 新增 nc_mail_result, nc_mail_done_at 欄位 - alembic: 遷移 002(system_settings) 003(keycloak_admin) 004(nc_mail_result) Frontend (Admin Portal): - 新增完整管理後台 (index/tenants/accounts/servers/schedules/logs/settings/system-status) - api.js: Keycloak JS Adapter SSO 整合 (PKCE/S256, fallback KC JS 來源, 自動 token 更新) - index.html: Promise.allSettled 取代 Promise.all,防止單一 API 失敗影響整頁 - 所有頁面加入 try/catch + toast 錯誤處理 - 新增品牌 LOGO 與 favicon Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
250 lines
4.5 KiB
Markdown
250 lines
4.5 KiB
Markdown
# Radicale CalDAV/CardDAV Server
|
||
|
||
Virtual MIS 日曆與聯絡人服務後端。
|
||
|
||
## 服務資訊
|
||
|
||
- **服務名稱**: Radicale CalDAV/CardDAV Server
|
||
- **容器名稱**: vmis-radicale
|
||
- **內部埠號**: 5232
|
||
- **外部埠號**: 5232 (開發環境)
|
||
- **認證方式**: HTTP Header (X-Remote-User) - 由 Keycloak OAuth2 整合
|
||
- **資料儲存**: File System (/data/collections)
|
||
|
||
## 功能
|
||
|
||
- ✅ CalDAV - 日曆同步 (RFC 4791)
|
||
- ✅ CardDAV - 聯絡人同步 (RFC 6352)
|
||
- ✅ HTTP Header 認證
|
||
- ✅ 多使用者支援
|
||
- ✅ Web 管理介面
|
||
|
||
## 目錄結構
|
||
|
||
```
|
||
radicale/
|
||
├── config/
|
||
│ └── config # Radicale 配置檔
|
||
├── data/ # 資料目錄(自動建立)
|
||
│ └── collections/ # 日曆與聯絡人資料
|
||
├── docker-compose.yml # Docker Compose 配置
|
||
└── README.md # 本文件
|
||
```
|
||
|
||
## 部署步驟
|
||
|
||
### 1. 建立資料目錄
|
||
|
||
```bash
|
||
mkdir -p data/collections
|
||
```
|
||
|
||
### 2. 設定權限
|
||
|
||
```bash
|
||
# 確保資料目錄權限正確(UID=1000, GID=1000)
|
||
sudo chown -R 1000:1000 data/
|
||
chmod -R 750 data/
|
||
```
|
||
|
||
### 3. 啟動服務
|
||
|
||
```bash
|
||
# 啟動
|
||
docker-compose up -d
|
||
|
||
# 查看日誌
|
||
docker-compose logs -f
|
||
|
||
# 停止
|
||
docker-compose down
|
||
```
|
||
|
||
### 4. 驗證服務
|
||
|
||
```bash
|
||
# 檢查服務狀態
|
||
docker-compose ps
|
||
|
||
# 測試連線
|
||
curl -I http://localhost:5232
|
||
|
||
# 預期回應: HTTP/1.1 200 OK
|
||
```
|
||
|
||
## 整合架構
|
||
|
||
### Virtual MIS 整合
|
||
|
||
```
|
||
Virtual MIS Backend
|
||
↓ caldav_service.py
|
||
Radicale (CalDAV/CardDAV)
|
||
↓ File System
|
||
/data/collections/
|
||
├── {username}/
|
||
│ ├── {calendar-uuid}/ # 日曆
|
||
│ └── {addressbook-uuid}/ # 通訊錄
|
||
```
|
||
|
||
### 認證流程
|
||
|
||
```
|
||
1. 使用者登入 Keycloak SSO
|
||
2. Virtual MIS Backend 取得 username
|
||
3. Backend 使用 X-Remote-User Header 呼叫 Radicale
|
||
4. Radicale 信任 Header,直接存取對應使用者資料
|
||
```
|
||
|
||
## 資料結構
|
||
|
||
### 日曆資料 (CalDAV)
|
||
|
||
```
|
||
/data/collections/{username}/{calendar-uuid}/
|
||
├── event-1.ics
|
||
├── event-2.ics
|
||
└── ...
|
||
```
|
||
|
||
### 聯絡人資料 (CardDAV)
|
||
|
||
```
|
||
/data/collections/{username}/{addressbook-uuid}/
|
||
├── contact-1.vcf
|
||
├── contact-2.vcf
|
||
└── ...
|
||
```
|
||
|
||
## 客戶端配置
|
||
|
||
### iOS / macOS
|
||
|
||
**日曆 (CalDAV)**:
|
||
```
|
||
伺服器: 10.1.0.254:5232 (開發環境)
|
||
使用者名稱: {Keycloak username}
|
||
密碼: (由 Backend 處理)
|
||
使用 SSL: 否 (開發環境) / 是 (正式環境)
|
||
```
|
||
|
||
**聯絡人 (CardDAV)**:
|
||
```
|
||
伺服器: 10.1.0.254:5232
|
||
使用者名稱: {Keycloak username}
|
||
密碼: (由 Backend 處理)
|
||
使用 SSL: 否 (開發環境) / 是 (正式環境)
|
||
```
|
||
|
||
### Android (DAVx⁵)
|
||
|
||
```
|
||
基礎 URL: http://10.1.0.254:5232/
|
||
使用者名稱: {Keycloak username}
|
||
密碼: (由 Backend 處理)
|
||
```
|
||
|
||
### Thunderbird
|
||
|
||
**日曆**:
|
||
```
|
||
位置: http://10.1.0.254:5232/{username}/{calendar-uuid}/
|
||
```
|
||
|
||
**聯絡人** (需要 CardBook 擴充套件):
|
||
```
|
||
URL: http://10.1.0.254:5232/{username}/{addressbook-uuid}/
|
||
```
|
||
|
||
## 監控與維護
|
||
|
||
### 查看日誌
|
||
|
||
```bash
|
||
# 即時日誌
|
||
docker-compose logs -f radicale
|
||
|
||
# 最近 100 行
|
||
docker-compose logs --tail=100 radicale
|
||
```
|
||
|
||
### 備份策略
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
# 備份腳本
|
||
BACKUP_DIR="/backups/radicale"
|
||
DATE=$(date +%Y%m%d_%H%M%S)
|
||
|
||
# 備份資料
|
||
tar -czf ${BACKUP_DIR}/radicale_data_${DATE}.tar.gz \
|
||
./data/
|
||
|
||
# 保留最近 30 天
|
||
find ${BACKUP_DIR} -name "radicale_data_*.tar.gz" -mtime +30 -delete
|
||
```
|
||
|
||
### 效能監控
|
||
|
||
```bash
|
||
# 查看儲存空間
|
||
du -sh data/
|
||
|
||
# 查看容器資源使用
|
||
docker stats vmis-radicale
|
||
```
|
||
|
||
## 故障排除
|
||
|
||
### 問題 1: 無法連線
|
||
|
||
**檢查**:
|
||
```bash
|
||
# 檢查容器狀態
|
||
docker-compose ps
|
||
|
||
# 檢查埠號占用
|
||
netstat -tulpn | grep 5232
|
||
|
||
# 檢查防火牆
|
||
sudo ufw status
|
||
```
|
||
|
||
### 問題 2: 認證失敗
|
||
|
||
**檢查**:
|
||
- X-Remote-User Header 是否正確傳遞
|
||
- Radicale 配置檔中 auth.type 是否為 http_x_remote_user
|
||
- Backend 呼叫時是否正確設定 Header
|
||
|
||
### 問題 3: 資料無法寫入
|
||
|
||
**檢查**:
|
||
```bash
|
||
# 檢查目錄權限
|
||
ls -la data/
|
||
|
||
# 修正權限
|
||
sudo chown -R 1000:1000 data/
|
||
chmod -R 750 data/
|
||
```
|
||
|
||
## 安全建議
|
||
|
||
1. **認證**: 使用 Keycloak SSO 統一認證
|
||
2. **網路隔離**: 僅允許 Backend 存取 Radicale
|
||
3. **HTTPS**: 正式環境必須使用 HTTPS
|
||
4. **備份**: 定期備份 data/ 目錄
|
||
5. **權限**: 嚴格控制檔案系統權限
|
||
|
||
## 參考文件
|
||
|
||
- [Radicale 官方文件](https://radicale.org/v3.html)
|
||
- [CalDAV 協議 (RFC 4791)](https://tools.ietf.org/html/rfc4791)
|
||
- [CardDAV 協議 (RFC 6352)](https://tools.ietf.org/html/rfc6352)
|
||
|
||
## 更新記錄
|
||
|
||
- **2026-03-02**: 建立 Radicale Docker Compose 配置
|
||
- **2026-03-02**: 整合 Virtual MIS Calendar & Contacts
|