# Momentry 系統服務安裝與管理指南
## 概述
本文檔記錄 momentry 系統所需的所有服務,包括安裝步驟、健康檢查和管理命令。
**重要**: 請勿使用 `brew services` 命令管理服務,否則可能導致 .plist 檔案還原為預設狀態,造成系統異常。請使用 `launchctl` 命令進行管理。
---
## 服務清單
| 服務名稱 | 安裝方式 | 用途 | 狀態 |
|----------|----------|------|-------|
| PostgreSQL | Homebrew | 影片元資料儲存 | 已安裝 |
| Redis | Homebrew | 快取與工作佇列 | 已安裝 |
| Ollama | Homebrew | 本地 LLM 推論 | 已安裝 |
| Caddy | Homebrew | 網頁伺服器 (可選) | 已安裝 |
| Gitea | 手動安裝 | Git 服務 | 已安裝 |
| Grafana | Homebrew | 監控儀表板 | 已安裝 |
| Kafka | 手動安裝 | 訊息佇列 (可選) | 已安裝 |
| MariaDB | Homebrew | 資料庫 (可選) | 已安裝 |
| Netdata | Homebrew | 系統監控 | 已安裝 |
| PHP | Homebrew | Web 後端 | 已安裝 |
| Prometheus | Homebrew | 指標收集 | 已安裝 |
| SeaweedFS | 手動安裝 | 分散式儲存 (可選) | 已安裝 |
| SFTPGo | 手動安裝 | SFTP 服務 | 已安裝 |
| n8n | Homebrew | 工作流自動化 | 已安裝 |
---
## 必要服務 (Momentry 核心)
### 1. PostgreSQL
#### 安裝
```bash
# 檢查是否已安裝
brew list postgresql@18 2>/dev/null || echo "Not installed"
# 安裝 PostgreSQL 18
brew install postgresql@18
```
#### 初始化資料庫
```bash
# 初始化資料庫 (如尚未初始化)
initdb /usr/local/var/postgresql@18
# 建立 momentry 資料庫
createdb -U accusys momentry
```
#### 開機自動啟動
```bash
# 建立 plist 檔案
sudo tee /Library/LaunchDaemons/com.momentry.postgresql.plist > /dev/null <<'EOF'
Label
com.momentry.postgresql
ProgramArguments
/opt/homebrew/opt/postgresql@18/bin/pg_ctl
-D
/opt/homebrew/var/postgresql@18
-l
/opt/homebrew/var/postgresql@18/logfile
start
RunAtLoad
KeepAlive
WorkingDirectory
/opt/homebrew/var/postgresql@18
UserName
accusys
EOF
# 載入服務
sudo launchctl load /Library/LaunchDaemons/com.momentry.postgresql.plist
```
#### 管理命令
```bash
# 啟動
sudo launchctl load /Library/LaunchDaemons/com.momentry.postgresql.plist
# 停止
sudo launchctl unload /Library/LaunchDaemons/com.momentry.postgresql.plist
# 重新載入
sudo launchctl unload /Library/LaunchDaemons/com.momentry.postgresql.plist
sudo launchctl load /Library/LaunchDaemons/com.momentry.postgresql.plist
```
#### 健康檢查
```bash
# 方法 1: 使用 pg_isready
pg_isready -h localhost -p 5432 -U accusys
# 方法 2: 連線測試
psql -U accusys -h localhost -d momentry -c "SELECT 1;"
# 方法 3: 檢查程序
pgrep -f "postgres.*postgresql@18"
```
---
### 2. Redis
#### 安裝
```bash
# 檢查是否已安裝
brew list redis 2>/dev/null || echo "Not installed"
# 安裝 Redis
brew install redis
```
#### 設定密碼
```bash
# 編輯 Redis 設定檔
vim /opt/homebrew/etc/redis.conf
# 找到 requirepass 行,修改為:
requirepass accusys
# 或使用環境變數方式啟動
```
#### 開機自動啟動
```bash
# 建立 plist 檔案
sudo tee /Library/LaunchDaemons/com.momentry.redis.plist > /dev/null <<'EOF'
Label
com.momentry.redis
UserName
accusys
WorkingDirectory
/Users/accusys/momentry/var/redis
ProgramArguments
/opt/homebrew/opt/redis/bin/redis-server
/opt/homebrew/etc/redis.conf
EnvironmentVariables
REDIS_PASSWORD
accusys
RunAtLoad
KeepAlive
StandardOutPath
/Users/accusys/momentry/log/redis.log
StandardErrorPath
/Users/accusys/momentry/log/redis.error.log
EOF
# 載入服務
sudo launchctl load /Library/LaunchDaemons/com.momentry.redis.plist
```
#### 管理命令
```bash
# 啟動
sudo launchctl load /Library/LaunchDaemons/com.momentry.redis.plist
# 停止
sudo launchctl unload /Library/LaunchDaemons/com.momentry.redis.plist
# 重啟
sudo launchctl unload /Library/LaunchDaemons/com.momentry.redis.plist
sudo launchctl load /Library/LaunchDaemons/com.momentry.redis.plist
# 查看狀態
launchctl list | grep com.momentry.redis
# 查看日誌
tail -f /Users/accusys/momentry/log/redis.log
tail -f /Users/accusys/momentry/log/redis.error.log
```
#### 健康檢查
```bash
# 方法 1: 使用 redis-cli ping
redis-cli -a accusys ping
# 輸出應為: PONG
# 方法 2: 檢查密碼認證
redis-cli -a accusys AUTH accusys
# 方法 3: 檢查程序
pgrep -f redis-server
# 方法 4: 檢查連線數
redis-cli -a accusys INFO clients
```
---
### 3. Ollama
#### 安裝
```bash
# 檢查是否已安裝
which ollama || echo "Not installed"
# 安裝 Ollama
brew install ollama
```
#### 模型下載
```bash
# 下載 Mistral (LLM)
ollama pull mistral:latest
# 下載 Embedding 模型
ollama pull nomic-embed-text:latest
# 驗證模型
ollama list
```
#### 開機自動啟動
```bash
# 建立 plist 檔案
sudo tee /Library/LaunchDaemons/com.momentry.ollama.plist > /dev/null <<'EOF'
Label
com.momentry.ollama
UserName
accusys
WorkingDirectory
/Users/accusys/momentry/var/ollama
ProgramArguments
/opt/homebrew/bin/ollama
serve
EnvironmentVariables
OLLAMA_HOST
0.0.0.0:11434
OLLAMA_MODELS
/Users/accusys/momentry/var/ollama/models
RunAtLoad
KeepAlive
StandardOutPath
/Users/accusys/momentry/log/ollama.log
StandardErrorPath
/Users/accusys/momentry/log/ollama.error.log
EOF
# 載入服務
sudo launchctl load /Library/LaunchDaemons/com.momentry.ollama.plist
```
#### 管理命令
```bash
# 啟動
sudo launchctl load /Library/LaunchDaemons/com.momentry.ollama.plist
# 停止
sudo launchctl unload /Library/LaunchDaemons/com.momentry.ollama.plist
# 重啟
sudo launchctl unload /Library/LaunchDaemons/com.momentry.ollama.plist
sudo launchctl load /Library/LaunchDaemons/com.momentry.ollama.plist
# 查看狀態
launchctl list | grep com.momentry.ollama
# 查看日誌
tail -f /Users/accusys/momentry/log/ollama.log
tail -f /Users/accusys/momentry/log/ollama.error.log
```
#### 健康檢查
```bash
# 方法 1: API 測試
curl -s http://localhost:11434/api/tags | jq '.models[].name'
# 方法 2: 檢查程序
pgrep -f ollama
# 方法 3: 列出模型
ollama list
```
---
### 4. n8n (工作流自動化)
#### 安裝
```bash
# 檢查是否已安裝
which n8n || echo "Not installed"
# 安裝 n8n
brew install n8n
```
#### 開機自動啟動
```bash
# 複製 plist 到 LaunchDaemons 目錄
sudo cp /Users/accusys/momentry_core_0.1/momentry_runtime/plist/com.momentry.n8n.main.plist /Library/LaunchDaemons/
sudo cp /Users/accusys/momentry_core_0.1/momentry_runtime/plist/com.momentry.n8n.worker.plist /Library/LaunchDaemons/
# 載入服務
sudo launchctl load /Library/LaunchDaemons/com.momentry.n8n.main.plist
sudo launchctl load /Library/LaunchDaemons/com.momentry.n8n.worker.plist
```
#### 管理命令
```bash
# 啟動
sudo launchctl load /Library/LaunchDaemons/com.momentry.n8n.main.plist
sudo launchctl load /Library/LaunchDaemons/com.momentry.n8n.worker.plist
# 停止
sudo launchctl unload /Library/LaunchDaemons/com.momentry.n8n.main.plist
sudo launchctl unload /Library/LaunchDaemons/com.momentry.n8n.worker.plist
```
#### 健康檢查
```bash
# 方法 1: API 測試
curl -s http://localhost:5678/
# 方法 2: 檢查程序
ps aux | grep n8n | grep -v grep
# 方法 3: 檢查端口
lsof -i :5678
lsof -i :5690
```
---
## 可選服務
### 4. Caddy (網頁伺服器)
```bash
# 安裝
brew install caddy
# 開機啟動
cp /opt/homebrew.mxcl.caddy.plist /Library/LaunchDaemons/
sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.caddy.plist
# 健康檢查
curl -s https://localhost:2019/config/ | head -5
```
### 5. Grafana (監控)
```bash
# 安裝
brew install grafana
# 開機啟動
cp /opt/homebrew.mxcl.grafana.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/homebrew.mxcl.grafana.plist
# 健康檢查
curl -s http://localhost:3000/api/health | jq '.'
```
### 6. Prometheus (監控)
```bash
# 安裝
brew install prometheus
# 開機啟動
cp /opt/homebrew.mxcl.prometheus.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/homebrew.mxcl.prometheus.plist
# 健康檢查
curl -s http://localhost:9090/-/healthy
```
### 7. Netdata (系統監控)
```bash
# 安裝
brew install netdata
# 開機啟動
sudo brew services start netdata
# 健康檢查
curl -s http://localhost:19999/api/v1/info | jq '.version'
```
---
## 統一健康檢查腳本
建立 `/Users/accusys/momentry_core_0.1/scripts/health_check.sh`:
```bash
#!/bin/bash
# Momentry 系統健康檢查腳本
echo "========================================"
echo "Momentry 系統健康檢查"
echo "========================================"
echo ""
# 顏色定義
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
check_service() {
local name=$1
local check_cmd=$2
if eval "$check_cmd" > /dev/null 2>&1; then
echo -e "${GREEN}✓${NC} $name"
return 0
else
echo -e "${RED}✗${NC} $name"
return 1
fi
}
total=0
passed=0
# 1. PostgreSQL
total=$((total + 1))
check_service "PostgreSQL (localhost:5432)" "pg_isready -h localhost -p 5432 -U accusys" && passed=$((passed + 1))
# 2. Redis
total=$((total + 1))
check_service "Redis (localhost:6379)" "redis-cli -a accusys ping" && passed=$((passed + 1))
# 3. Ollama
total=$((total + 1))
check_service "Ollama (localhost:11434)" "curl -s http://localhost:11434/api/tags > /dev/null" && passed=$((passed + 1))
# 4. n8n
total=$((total + 1))
check_service "n8n (localhost:5678)" "curl -s http://localhost:5678/ > /dev/null" && passed=$((passed + 1))
# 5. Grafana (如果安裝)
if command -v grafana-server > /dev/null 2>&1; then
total=$((total + 1))
check_service "Grafana (localhost:3000)" "curl -s http://localhost:3000/api/health > /dev/null" && passed=$((passed + 1))
fi
# 6. Prometheus (如果安裝)
if command -v prometheus > /dev/null 2>&1; then
total=$((total + 1))
check_service "Prometheus (localhost:9090)" "curl -s http://localhost:9090/-/healthy > /dev/null" && passed=$((passed + 1))
fi
# 7. Netdata (如果安裝)
if command -v netdata > /dev/null 2>&1; then
total=$((total + 1))
check_service "Netdata (localhost:19999)" "curl -s http://localhost:19999/api/v1/info > /dev/null" && passed=$((passed + 1))
fi
echo ""
echo "========================================"
echo "結果: $passed/$total 服務正常"
echo "========================================"
if [ $passed -eq $total ]; then
exit 0
else
exit 1
fi
```
使用方式:
```bash
chmod +x scripts/health_check.sh
./scripts/health_check.sh
```
---
## 服務管理速查表
### 啟動服務
```bash
# PostgreSQL (需要 root 權限)
sudo launchctl load /Library/LaunchDaemons/com.momentry.postgresql.plist
# Redis, Ollama (需要 root 權限)
sudo launchctl load /Library/LaunchDaemons/com.momentry.redis.plist
sudo launchctl load /Library/LaunchDaemons/com.momentry.ollama.plist
# n8n (需要 root 權限)
sudo launchctl load /Library/LaunchDaemons/com.momentry.n8n.main.plist
sudo launchctl load /Library/LaunchDaemons/com.momentry.n8n.worker.plist
```
### 停止服務
```bash
# PostgreSQL
sudo launchctl unload /Library/LaunchDaemons/com.momentry.postgresql.plist
# Redis, Ollama
sudo launchctl unload /Library/LaunchDaemons/com.momentry.redis.plist
sudo launchctl unload /Library/LaunchDaemons/com.momentry.ollama.plist
# n8n
sudo launchctl unload /Library/LaunchDaemons/com.momentry.n8n.main.plist
sudo launchctl unload /Library/LaunchDaemons/com.momentry.n8n.worker.plist
```
### 查詢服務狀態
```bash
# 查看所有服務
launchctl list | grep -E "(postgres|redis|ollama|n8n|grafana|prometheus)"
# 查看特定服務
launchctl list | grep com.momentry
```
---
## 故障排除
### PostgreSQL 問題
```bash
# 查看日誌
tail -f /opt/homebrew/var/postgresql@18/logfile
# 重新初始化
pg_ctl -D /opt/homebrew/var/postgresql@18 stop
rm -rf /opt/homebrew/var/postgresql@18
initdb -D /opt/homebrew/var/postgresql@18
# 重建資料庫
dropdb momentry
createdb -U accusys momentry
```
### Redis 問題
```bash
# 查看日誌
tail -f /opt/homebrew/var/log/redis.log
# 測試連線
redis-cli -a accusys DEBUG SLEEP 1
# 重新整理 ACL
redis-cli -a accusys FLUSHALL
```
### Ollama 問題
```bash
# 查看日誌
tail -f ~/.ollama/logs/server.log
# 重新下載模型
ollama pull mistral:latest
ollama pull nomic-embed-text:latest
# 檢查 GPU 使用情況
ollama list
```
---
## 自動化腳本
建立 `/Users/accusys/momentry_core_0.1/scripts/service_manager.sh`:
```bash
#!/bin/bash
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PLIST_DIR="$SCRIPT_DIR/../momentry_runtime/plist"
action=${1:-start}
service=${2:-all}
start_postgresql() {
echo "Starting PostgreSQL..."
sudo launchctl load /Library/LaunchDaemons/com.momentry.postgresql.plist 2>/dev/null || \
echo "PostgreSQL plist not found, skipping..."
}
start_redis() {
echo "Starting Redis..."
launchctl load ~/Library/LaunchAgents/com.momentry.redis.plist 2>/dev/null || \
echo "Redis plist not found, skipping..."
}
start_ollama() {
echo "Starting Ollama..."
launchctl load ~/Library/LaunchAgents/com.momentry.ollama.plist 2>/dev/null || \
echo "Ollama plist not found, skipping..."
}
stop_postgresql() {
echo "Stopping PostgreSQL..."
sudo launchctl unload /Library/LaunchDaemons/com.momentry.postgresql.plist 2>/dev/null || true
}
stop_redis() {
echo "Stopping Redis..."
launchctl unload ~/Library/LaunchAgents/com.momentry.redis.plist 2>/dev/null || true
}
stop_ollama() {
echo "Stopping Ollama..."
launchctl unload ~/Library/LaunchAgents/com.momentry.ollama.plist 2>/dev/null || true
}
case $action in
start)
case $service in
all)
start_postgresql
start_redis
start_ollama
;;
postgresql|pgsql|pg)
start_postgresql
;;
redis)
start_redis
;;
ollama)
start_ollama
;;
*)
echo "Unknown service: $service"
exit 1
;;
esac
;;
stop)
case $service in
all)
stop_ollama
stop_redis
stop_postgresql
;;
postgresql|pgsql|pg)
stop_postgresql
;;
redis)
stop_redis
;;
ollama)
stop_ollama
;;
*)
echo "Unknown service: $service"
exit 1
;;
esac
;;
restart)
$0 stop $service
sleep 2
$0 start $service
;;
status)
echo "Service Status:"
echo "==============="
launchctl list | grep -E "(postgres|redis|ollama)" || echo "No services found"
;;
*)
echo "Usage: $0 {start|stop|restart|status} [service]"
echo "Services: all, postgresql, redis, ollama"
exit 1
;;
esac
```
---
## 附錄: 服務對應表
| 服務 | Port | 使用者 | plist 位置 |
|------|------|--------|-------------|
| PostgreSQL | 5432 | accusys | /Library/LaunchDaemons/ |
| Redis | 6379 | accusys | /Library/LaunchDaemons/ |
| Ollama | 11434 | accusys | /Library/LaunchDaemons/ |
| n8n Main | 5678 | accusys | /Library/LaunchDaemons/ |
| n8n Worker | 5690-5691 | accusys | /Library/LaunchDaemons/ |
| Grafana | 3000 | accusys | /Library/LaunchDaemons/ |
| Prometheus | 9090 | accusys | /Library/LaunchDaemons/ |
| Caddy | 2019 | root | /Library/LaunchDaemons/ |
| Netdata | 19999 | root | /Library/LaunchDaemons/ |