From 955282e58757161d5a4acc53e5afb01fbb717ab9 Mon Sep 17 00:00:00 2001 From: M5Max128 Date: Wed, 27 May 2026 01:12:37 +0800 Subject: [PATCH] docs: add LaunchDaemon architecture reference for M5Max128/M5Max48 collaboration --- .../DESIGN/LaunchDaemon_Config_M5Max128.md | 421 ++++++++++++++++++ 1 file changed, 421 insertions(+) create mode 100644 docs_v1.0/DESIGN/LaunchDaemon_Config_M5Max128.md diff --git a/docs_v1.0/DESIGN/LaunchDaemon_Config_M5Max128.md b/docs_v1.0/DESIGN/LaunchDaemon_Config_M5Max128.md new file mode 100644 index 0000000..2cafac2 --- /dev/null +++ b/docs_v1.0/DESIGN/LaunchDaemon_Config_M5Max128.md @@ -0,0 +1,421 @@ +--- +title: LaunchDaemon Architecture (M5Max128 Reference) +version: 1.0 +date: 2026-05-27 +author: M5Max128 +status: reference +--- + +# LaunchDaemon Architecture Reference + +> **Scope**: M5Max128 local configuration (resource-managed binaries) +> **Note**: M5Max48 uses build-from-source approach via start_momentry.sh. Both approaches are valid and independent. + +## Overview + +| Machine | Approach | Status | +|---------|----------|--------| +| M5Max128 | LaunchDaemon + resource binaries | Reference document | +| M5Max48 | start_momentry.sh + build from source | Main branch | + +## Architecture Principles + +``` +/Library/LaunchDaemons/ (system-level, boot before login) + ├── com.momentry.postgresql.plist (P1, no dependency) + ├── com.momentry.redis.plist (P1, no dependency) + ├── com.momentry.qdrant.plist (P2, no dependency) + ├── com.momentry.mongodb.plist (P2, no dependency) + └── com.momentry.gitea.plist (P3, depends on PostgreSQL) + +Experimental services: + └── com.momentry.startup.plist (LLM, Embedding, Playground, etc.) +``` + +## Key Design Points + +### 1. Binary Location + +All binaries are resource-managed under `/Users/accusys/momentry_resources/bin/`: + +| Service | Binary Path | +|---------|-------------| +| PostgreSQL | `/Users/accusys/pgsql/18.3/bin/postgres` | +| Redis | `/Users/accusys/momentry_resources/bin/redis-server` | +| Qdrant | `/Users/accusys/momentry_resources/bin/qdrant` | +| MongoDB | `/Users/accusys/momentry_resources/bin/mongod` | +| Gitea | `/Users/accusys/momentry_resources/bin/gitea` | + +### 2. Root Boot → User Execution + +LaunchDaemons run at boot (root), but use `UserName` key to switch to user: + +```xml +UserName +accusys +``` + +### 3. Unified Log Path + +All logs go to `/Users/accusys/momentry/logs/`: + +```xml +StandardOutPath +/Users/accusys/momentry/logs/.log + +StandardErrorPath +/Users/accusys/momentry/logs/.error.log +``` + +## Plist Templates + +### PostgreSQL + +```xml + + + + + Label + com.momentry.postgresql + + UserName + accusys + + WorkingDirectory + /Users/accusys/momentry/var/postgresql + + ProgramArguments + + /Users/accusys/pgsql/18.3/bin/postgres + -D + /Users/accusys/momentry/var/postgresql + + + RunAtLoad + + + KeepAlive + + + StandardOutPath + /Users/accusys/momentry/logs/postgresql.log + + StandardErrorPath + /Users/accusys/momentry/logs/postgresql.error.log + + +``` + +### Redis (ACL Authentication) + +```xml + + + + + Label + com.momentry.redis + + UserName + accusys + + WorkingDirectory + /Users/accusys/momentry/var/redis + + ProgramArguments + + /Users/accusys/momentry_resources/bin/redis-server + --port + 6379 + --bind + 0.0.0.0 + --aclfile + /Users/accusys/momentry/etc/redis/users.acl + --dir + /Users/accusys/momentry/var/redis + --logfile + /Users/accusys/momentry/logs/redis.log + + + RunAtLoad + + + KeepAlive + + + StandardOutPath + /Users/accusys/momentry/logs/redis.log + + StandardErrorPath + /Users/accusys/momentry/logs/redis.error.log + + +``` + +### Redis ACL File + +Location: `/Users/accusys/momentry/etc/redis/users.acl` + +``` +user default on sanitize-payload ~* &* +@all >accusys +user accusys on sanitize-payload ~* &* +@all >accusys +``` + +**Redis 8.x Authentication**: +```bash +# Old (deprecated): redis-cli -a accusys ping +# New (recommended): redis-cli --user default --pass accusys ping +``` + +### Qdrant + +```xml + + + + + Label + com.momentry.qdrant + + UserName + accusys + + WorkingDirectory + /Users/accusys/momentry/var/qdrant/ + + ProgramArguments + + /Users/accusys/momentry_resources/bin/qdrant + + + EnvironmentVariables + + QDRANT__STORAGE__STORAGE_PATH + /Users/accusys/momentry/var/qdrant/ + QDRANT__SERVICE__HOST + 0.0.0.0 + QDRANT__SERVICE__HTTP_PORT + 6333 + HOME + /Users/accusys + + + RunAtLoad + + + KeepAlive + + + StandardOutPath + /Users/accusys/momentry/logs/qdrant.log + + StandardErrorPath + /Users/accusys/momentry/logs/qdrant.error.log + + +``` + +### MongoDB + +```xml + + + + + Label + com.momentry.mongodb + + UserName + accusys + + ProgramArguments + + /Users/accusys/momentry_resources/bin/mongod + --dbpath + /Users/accusys/momentry/var/mongodb + --logpath + /Users/accusys/momentry/logs/mongodb.log + --port + 27017 + --bind_ip + 0.0.0.0 + + + RunAtLoad + + + KeepAlive + + + StandardOutPath + /Users/accusys/momentry/logs/mongodb.log + + StandardErrorPath + /Users/accusys/momentry/logs/mongodb.error.log + + WorkingDirectory + /Users/accusys/momentry/var/mongodb + + +``` + +### Gitea (with Wrapper Script) + +```xml + + + + + Label + com.momentry.gitea + + UserName + accusys + + WorkingDirectory + /Users/accusys/momentry/var/gitea + + ProgramArguments + + /Users/accusys/momentry_core/scripts/start_gitea.sh + + + EnvironmentVariables + + HOME + /Users/accusys + GITEA_WORK_DIR + /Users/accusys/momentry/var/gitea + + + RunAtLoad + + + KeepAlive + + + StandardOutPath + /Users/accusys/momentry/logs/gitea.log + + StandardErrorPath + /Users/accusys/momentry/logs/gitea.error.log + + +``` + +## Wrapper Script: start_gitea.sh + +Gitea depends on PostgreSQL. Wrapper script ensures PostgreSQL is ready: + +```bash +#!/bin/bash + +PG_BIN="/Users/accusys/pgsql/18.3/bin" +GITEA_BIN="/Users/accusys/momentry_resources/bin/gitea" +GITEA_CONFIG="/Users/accusys/momentry/etc/gitea/app.ini" + +MAX_WAIT=60 +WAITED=0 + +# Wait for PostgreSQL +while ! "$PG_BIN/pg_isready" -q 2>/dev/null; do + if [ $WAITED -ge $MAX_WAIT ]; then + echo "ERROR: PostgreSQL not ready after $MAX_WAIT seconds" + exit 1 + fi + sleep 2 + WAITED=$((WAITED + 2)) +done + +# Start Gitea +"$GITEA_BIN" web --config "$GITEA_CONFIG" +``` + +## Install Script: install_launchdaemons.sh + +```bash +#!/bin/bash + +PLIST_DIR="/Users/accusys/momentry_core/momentry_runtime/plist" +DAEMON_DIR="/Library/LaunchDaemons" +LOG_DIR="/Users/accusys/momentry/logs" + +mkdir -p "$LOG_DIR" + +DAEMONS=( + "com.momentry.postgresql" + "com.momentry.redis" + "com.momentry.qdrant" + "com.momentry.mongodb" + "com.momentry.gitea" +) + +for daemon in "${DAEMONS[@]}"; do + plist_name="${daemon}.plist" + src="${PLIST_DIR}/${plist_name}" + dest="${DAEMON_DIR}/${plist_name}" + + if launchctl list "$daemon" >/dev/null 2>&1; then + sudo launchctl unload -w "$dest" 2>/dev/null + fi + + sudo cp "$src" "$dest" + sudo chown root:wheel "$dest" + sudo chmod 644 "$dest" + sudo launchctl load -w "$dest" +done +``` + +## Comparison: M5Max128 vs M5Max48 + +| Aspect | M5Max128 | M5Max48 | +|--------|----------|---------| +| **Approach** | LaunchDaemon (system-level) | start_momentry.sh (user script) | +| **Binaries** | Resource-managed (`momentry_resources/bin/`) | Build from source (`services/*/target/`) | +| **PostgreSQL data** | `/Users/accusys/momentry/var/postgresql` | `/Users/accusys/pgsql/data` | +| **Redis auth** | ACL file (`users.acl`) | `--requirepass` (deprecated) | +| **LLM path** | Resource binary | `/Users/accusys/llama/bin/` | +| **Gitea** | Independent LaunchDaemon | Not in startup script | +| **MongoDB** | Independent LaunchDaemon | Not in startup script | + +## Installation Steps (M5Max128) + +```bash +# 1. Ensure directories exist +mkdir -p /Users/accusys/momentry/logs +mkdir -p /Users/accusys/momentry/var/{postgresql,redis,qdrant,mongodb,gitea} + +# 2. Install LaunchDaemons (requires sudo) +sudo /Users/accusys/momentry_core/scripts/install_launchdaemons.sh + +# 3. Verify services +/Users/accusys/pgsql/18.3/bin/pg_isready +/Users/accusys/momentry_resources/bin/redis-cli --user default --pass accusys ping +curl http://localhost:6333/healthz +curl http://localhost:3000/ + +# 4. Reboot test +sudo reboot + +# 5. Post-reboot verification +launchctl list | grep com.momentry +``` + +## Notes + +1. **Independence**: M5Max128's LaunchDaemons do not conflict with M5Max48's startup script. Each machine has its own approach. + +2. **Resource Management**: M5Max128 uses pre-built binaries from `momentry_resources/bin/`, avoiding build dependencies. + +3. **Redis ACL**: Redis 8.x uses ACL authentication, not `--requirepass`. This is the modern approach. + +4. **Gitea Wrapper**: Essential because Gitea depends on PostgreSQL. The wrapper ensures PostgreSQL is ready before starting Gitea. + +--- + +## Version History + +| Version | Date | Author | Changes | +|---------|------|--------|---------| +| 1.0 | 2026-05-27 | M5Max128 | Initial reference document | \ No newline at end of file