Skip to main content

nixos-config

nixos-config 오퍼레이터의 운영 면 — oracle/nuc/laptop/thinkpad 멀티 디바이스 NixOS + oracle에 사는 OpenClaw 봇 런타임을 실제로 손볼 때. AGENTS.md가 '현재 상태', NEXT.md가 '할 일', ROADMAP.md가 '이력'을 담는다면 이 스킬은 그 문서들이 front-load 못 하는 운영 반사신경을 담는다: 자리(디바이스) 인식 먼저, run.sh 엔트리, oracle/openclaw 분리 원칙, rebuild/rollback, OpenClaw 업그레이드(Dockerfile FROM 한 줄 + doctor read-only), 공개면 변경 시 서빙 URL 전수 검수(caddy 8-세트 + CF Tunnel + Tailscale Serve), 봇 스킬 심볼릭 배포, 커밋/스탬프/git-hooks 규율. 트리거: 'nixos-config', 'nixos-rebuild', 'rebuild', 'switch', 'rollback', 'flake update', 'oracle', 'openclaw', '봇 업그레이드', 'caddy', 'claw', 'control ui', 'geworfen', 'authelia', 'agenda 안돼', '디바이스', 'run.sh', '롤백', 'nixos 정리', 'tailscale', '터널', '안드로이드 앱', '앱이 안 붙어', 'trustedProxies', '403', '페어링'.

الانتقال إلى التثبيت

معلومات المصدر

المستودع
junghan0611/nixos-config
آخر نشاط في المصدر
١٣ سبتمبر ٢٠٢٦ في ٠٣:١٩
لغة SKILL.md المكتشفة
الكورية
النجوم
٣
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
nixos-config
description
nixos-config 오퍼레이터의 운영 면 — oracle/nuc/laptop/thinkpad 멀티 디바이스 NixOS + oracle에 사는 OpenClaw 봇 런타임을 실제로 손볼 때. AGENTS.md가 '현재 상태', NEXT.md가 '할 일', ROADMAP.md가 '이력'을 담는다면 이 스킬은 그 문서들이 front-load 못 하는 운영 반사신경을 담는다: 자리(디바이스) 인식 먼저, run.sh 엔트리, oracle/openclaw 분리 원칙, rebuild/rollback, OpenClaw 업그레이드(Dockerfile FROM 한 줄 + doctor read-only), 공개면 변경 시 서빙 URL 전수 검수(caddy 8-세트 + CF Tunnel + Tailscale Serve), 봇 스킬 심볼릭 배포, 커밋/스탬프/git-hooks 규율. 트리거: 'nixos-config', 'nixos-rebuild', 'rebuild', 'switch', 'rollback', 'flake update', 'oracle', 'openclaw', '봇 업그레이드', 'caddy', 'claw', 'control ui', 'geworfen', 'authelia', 'agenda 안돼', '디바이스', 'run.sh', '롤백', 'nixos 정리', 'tailscale', '터널', '안드로이드 앱', '앱이 안 붙어', 'trustedProxies', '403', '페어링'.
user_invocable
true
# nixos-config — 오퍼레이터의 운영 면 Repo: `~/repos/gh/nixos-config` (심볼릭 → `/home/junghan/nixos-config`, 같은 real dir). 멀티 디바이스 NixOS(`oracle`/`nuc`/`laptop`/`thinkpad`) + **oracle에 사는 OpenClaw 봇 런타임**을 운영하는 자리. `AGENTS.md`(현재 상태)·`NEXT.md`(할 일)·`ROADMAP.md`(이력)이 *무엇/언제*를 담는다면, 이 스킬은 그 문서들이 못 담는 **매번 다시 당하는 운영 반사신경**을 담는다. > ⚠️ 이건 generic NixOS 문서가 아니다. **이 repo 오퍼레이터의 핸드북**이다. > 실사용자(가족 포함)가 oracle 봇에 의존한다 — oracle 작업은 service reliability 작업이다. ## 0. 자리 인식 먼저 (correctness starts here) 어느 디바이스인지 모르면 아무것도 하지 마라. SessionStart hook이 `device=`/`time_kst=`를 준다. 안 보이면: ```bash cat ~/.current-device TZ='Asia/Seoul' date '+%Y%m%dT%H%M%S' ``` `run.sh` normalization: `oracle-nixos` → `oracle` (첫 `-` 앞 토큰 = flake profile 이름). **핵심 분리 원칙**: `oracle`이 아니면 OpenClaw를 볼 필요가 없다. oracle/openclaw 작업이 아니면 `ORACLE.md`를 열지 마라 — `AGENTS.md`만으로 충분하다. ## 1. 문서 라우팅 — 뭘 열까 | 작업 맥락 | 펼칠 문서 | |---|---| | **OpenClaw 런타임 자체를 만짐** (봇 설정·heartbeat·cron·채널·배달·스키마) | → **`openclaw` 스킬** (`.claude/skills/openclaw/` — 같은 리포, 별개 스킬). 기억으로 찍지 말고 그 버전의 사실로 만지는 절차 | | OpenClaw 주제별 소스 좌표 (`src/…:줄`) | `docs/openclaw-reference-map.md` (v2026.8.2 기준, 미확인은 미확인이라 적힘) | | oracle 디바이스 또는 OpenClaw 관련 | `ORACLE.md` (ownership·model routing·env/secret·업그레이드·함정) | | thinkpad 로컬 AI (Ollama) | `THINKPAD.md` | | nuc/laptop 일반 NixOS | `AGENTS.md` + 표준 NixOS 흐름 | | OpenClaw 함정 카탈로그 | `docs/openclaw-gotchas.md` | | 지금 무슨 상태인가 | `AGENTS.md` (날짜 박히면 → ROADMAP로 이관 신호) | | 앞으로 할 일·후속 검증 | `NEXT.md` (끝난 항목 지우고 새 후속 추가) | | 어떻게 여기까지 왔나(버전·결정 이력) | `ROADMAP.md` | | 라이브 봇 런타임 SSOT | `~/openclaw/` (config/auth/workspaces — **커밋 금지**) | > **OpenClaw 축은 이 스킬이 지지 않는다.** 디바이스·rebuild·배포·커밋은 여기, > **런타임 내부는 `openclaw` 스킬**이다. 일부러 나눠놨다 — 한쪽을 안다고 다른 쪽을 > 안다고 생각하는 순간 옛 기억으로 라이브를 만지게 된다. ## 2. run.sh — 오퍼레이터 엔트리 사람+에이전트 공용 인터페이스. 이미 `run.sh` 경로가 있는 작업이면 중복 만들지 말고 확장하라. 범위: flake update, rebuild/switch/rollback, cleanup, Oracle service helper, OpenClaw tunnel/restart/status/pairing, skill deploy(`k)`). 상세 oracle helper는 `ORACLE.md` §7. `br` 쓰지 마라. rigid tracker 대신 **agenda 스탬프**를 쓴다(이 repo 선호). ## 3. 표준 rebuild / rollback (nuc/laptop/thinkpad) ```bash sudo nixos-rebuild switch --flake .#<profile> # profile = oracle|nuc|laptop|thinkpad ``` 문제 시 rollback: `run.sh` 또는 `sudo nixos-rebuild switch --rollback`. NixOS는 generation이 롤백 표면이다. 디스크 여유 부족하면(oracle 특히) 정리부터 — 먼저 `run.sh c)` safe로 재고, 여유가 부족할 때만 `run.sh C)` deep을 고른다. ## 4. oracle / openclaw 작업 (safety-critical) 라이브 truth = `~/openclaw/`. 공개 백업/레퍼런스 = `docker/openclaw/`, `docker/*`. 절대 secret/auth를 공개 repo로 새게 하지 마라. 자세한 건 `ORACLE.md`. 자주 쓰는 반사신경만: - **업그레이드는 두 종류다 — 먼저 어느 쪽인지 판정하라.** - **패치/마이너 (`X.Y-1 → X.Y-2` 등) = Dockerfile `FROM` 한 줄 bump**: `~/openclaw/Dockerfile` + `docker/openclaw/Dockerfile` 둘 다 `ghcr.io/openclaw/openclaw:X → :Y` + 업글 로그 주석 → 재빌드 → `up -d --force-recreate`. 플러그인은 stock(번들)이라 자동으로 따라옴. - **메이저 hop (7.1 → 8.1 같은 한 달치) = 한 줄 bump가 아니다.** 새 이미지는 **옛 state를 거부**한다 (agent DB v1 → v19). 게이트웨이를 **끄고** 오프라인으로 마이그레이션한 뒤 올린다: 백업 → 정지 → `doctor --fix` **직렬 반복**(lease를 잃으면 남은 DB를 건너뛴다) → 기동 → 검수. 실측 39분. 절차·함정 전문 = `docs/openclaw-gotchas.md` "8.1 컷오버" (2026-08-31). - **~~업글 후 `--fix` 금지~~ → 2026-08-31 폐기.** 그 금지는 gemini가 `google-gemini-cli/`였을 때의 방어였고, 8/27 Copilot 이관으로 겨눌 대상이 사라졌다. **8.1부터 `doctor --fix`는 필수**다 — agent DB 스키마를 올리는 건 doctor뿐이다. 단 **반드시 게이트웨이를 끈 상태**에서(라이브 writer가 있으면 "stopped-writer maintenance" 로 전부 skip), 그리고 **끝난 뒤 6봇 prefix를 재확인**한다. - **6봇 모델 prefix 전수 재확인** (gemini는 `github-copilot/gemini-3.7-flash` — `google*` 아님), claude-cli 봇 Anthropic auth GREEN, memory 4096d, `fallbacks` 빈 상태, catch-all 1번(8.1부터 `modelPolicy.allow` 배열 첫 항목 = `openai/gpt-5.6-terra`). - **모델은 claude-cli 봇이면 카탈로그 등록만으로 태운다** — `agentRuntime claude-cli`는 구독 API에서 모델을 동적 해결(예: Sonnet 5 = `anthropic/claude-sonnet-5` + primary, 재빌드 불필요). 서빙 미보장 모델을 primary로 박지 말 것(auto-fallback catch-all이 정체성 훼손). - **gemini는 DOWN 아니다 (2026-08-27~)** — 서빙 레일 = **`github-copilot/gemini-3.7-flash`**(Copilot 구독). 옛 "403 → agy 이관 대기 → DOWN 유지" 반사신경은 **화석이다**. Google 구독·gemini-cli·agy 안 쫓는다. api-key(`google/`) 폴백은 여전히 금지 — 그 키는 나노바나나 이미지 전용. ## 5. 반사신경 — 다시 당하지 말 것 - **공개면 변경 = 서빙 URL 전수 검수**: `docker/caddy/Caddyfile` 이든 gateway 설정이든 공개면을 건드렸으면 **caddy 8-세트 + 밖의 3개**를 한 번에 확인한다. 하나만 보고 넘기지 마라. (`docs/openclaw-gotchas.md` "caddy 변경 = 8-세트 검수" 참조) ```bash for h in agenda analytics ax claw comments forge ha map; do printf '%-28s %s\n' "$h" "$(curl -sS -m 12 -o /dev/null -w '%{http_code}' https://$h.junghanacs.com/)" done curl -sS -m 12 -o /dev/null -w 'aionsclubs %{http_code}\n' https://aionsclubs.org/ # CF Tunnel curl -sS -m 10 -o /dev/null -w 'tailnet %{http_code}\n' https://oracle.tailb0e905.ts.net/ # Tailscale Serve ``` **기대값을 알고 봐야 한다 — 200 이 아닌 게 셋이고 전부 정상이다** (2026-09-08 실측): | 기대 | 호스트 | 왜 | |---|---|---| | 200 | agenda · analytics · ax · forge · ha · aionsclubs · tailnet | | | **302** | claw · map | authelia forward_auth 게이트. 설계대로 | | **404** | comments | remark42 는 루트에 페이지가 없다. **장애 아님** — `/api/v1/ping` 이 `pong` 이면 정상 | caddy 밖의 두 경로(`aionsclubs.org` CF Tunnel, `oracle.tailb0e905.ts.net` Tailscale Serve)는 caddy 를 안 타므로 Caddyfile 검수에서 빠지기 쉽다. **세트에 넣어라.** - **계획 재부팅 뒤에는 재기동만 보고 끝내지 마라**: `systemctl --failed`·`docker ps`로 실패/health를 먼저 보고, `emacsclient -s server --eval '(+ 1 1)'`로 agenda의 호스트 socket을 확인한다. 이어 위 **8+3 URL 세트**와 `comments /api/v1/ping`, `./scripts/turnwatch.sh 24`를 통과해야 복구 완료다. caddy 443 선점과 emacs socket ownership은 과거에 재부팅에서만 드러난 레이스다. - **`/health` 200 은 게이트웨이가 멀쩡하다는 증거가 아니다**: `/health` 는 무인증 라우트라 proxy attribution·토큰 검사를 **건너뛴다**. 그래서 `/health` 는 200 인데 `/` 는 403 인 비대칭이 나오고, 이 비대칭 자체가 "네트워크·프로세스는 살아있고 **인증 계층**에서 막혔다"는 진단이다. 앱/UI 가 못 붙을 때 `/health` 만 보고 "게이트웨이 정상"이라 결론내지 마라 — **인증이 걸리는 `/` 를 같이 찍고, 403 이면 본문(JSON `type`)을 읽어라.** 본문이 원인을 이름으로 말해준다(`proxy_attribution_required` 등). - **도커 네트워크가 갈리면 `gateway.trustedProxies` 가 조용히 화석이 된다**: gateway 는 두 네트워크에 붙어 있다 — `proxy`(`172.18.0.0/16`, caddy 경로) 와 `openclaw-config_default`(`172.26.0.0/16`, 호스트 루프백 포워딩 = tailscale serve·SSH 터널). 후자는 compose IPAM으로 고정했고 `trustedProxies` 는 **`172.18.0.0/16` + `172.26.0.1/32`**다 (2026-09-13 실측). 남아 있을 수 있는 옛 `openclaw_default`/`172.19.0.0/16`를 다시 믿지 마라. compose project/default network를 다시 만들었으면 추측하지 말고 `docker inspect openclaw-gateway`와 컨테이너가 보는 소스 IP(`/proc/net/tcp`를 폴링하며 요청을 흘린다 — 전문은 gotchas)를 재측정한다. 넓히지 말고 `/32`로 좁게 더하고, **config 변경이므로 restart로 충분**. ⚠️ **대가를 알고 하라**: 도커 NAT 는 tailscale serve 와 호스트 루프백을 **같은 IP 로 뭉갠다.** 그 IP 를 신뢰하는 순간 `run.sh t)` SSH 터널로 Control UI 를 보던 길이 403 이 된다. `/32` 로도 분리되지 않는다. 대체는 tailnet URL 직행(thinkpad 도 tailnet 에 있다). - **claw.junghanacs.com = 인증 뒤에 원격 셸이 있는 유일한 vhost**: OpenClaw Control UI 공개면. 자물쇠 3겹(Authelia forward_auth → gateway token → device pairing)을 전부 유지한다. **`gateway.auth.mode`를 `trusted-proxy`로 바꾸지 마라** — gateway가 `proxy` 도커 네트에 붙어 있어 같은 네트 컨테이너가 18789로 직결(Authelia 우회)하므로, 그 순간 우회가 곧 인증 우회가 된다. Authelia claw 규칙은 **bypass → operator one_factor → deny catch-all 3단**(default가 one_factor라 catch-all 없으면 family가 통과). WS 재연결이 조용히 죽으면 F5. (`docs/openclaw-gotchas.md` claw 항목) - **ax.junghanacs.com = 첫 static vhost(관리 대상)**: 기존 6개는 `reverse_proxy`지만 ax는 백엔드 없이 caddy `file_server`가 `/srv/ax`(호스트 `docker-data/ax` ro 마운트)를 직접 서빙. web root는 junghan0611 repo `apply/ax make publish`가 채운다(재시작 불요, 즉시 라이브·leak gate 유일 관문). **compose 볼륨 추가/제거는 `restart` 아니라 `up -d --force-recreate`**. 향후 umami/remark는 정본에 스니펫으로(caddy 주입 금지). ax 요청은 이 레인이 대응. - **agenda 000 ≠ caddy**: `agenda.junghanacs.com`(geworfen)은 호스트 emacs `server` 데몬에 의존한다. 데몬 hang이면 caddy와 무관하게 agenda 000. `emacsclient -s server --eval '(+ 1 1)'` 타임아웃이면 데몬이 근인. 복구는 **geworfen 담당자에게 entwurf 핸드오프** — 호스트 데몬을 nixos-config에서 직접 만지지 마라. - **Caddyfile 편집 후 reload 아니라 `docker restart caddy`**: single-file bind-mount inode 함정 — atomic rename이 새 inode를 만들어 `caddy reload`가 "unchanged"로 무시한다. 재시작 후 `docker exec caddy grep <domain> /etc/caddy/Caddyfile`로 컨테이너가 새 내용을 보는지 확인. - **봇 스킬은 심볼릭 배포** — workspace 스킬을 sibling repo SSOT(예: butlercli)로 절대 심볼릭. 봇이 고친 게 SSOT로 흐르고 SSOT 수정이 봇에 즉시 반영(redeploy 불필요). 이중 마운트 덕에 `/home/junghan/...` 절대경로가 host·container 양쪽 resolve. (`NEXT.md` "스킬 심볼릭 배포") - **디스크 보수적으로** — oracle storage 빠듯. 압박의 첫 수는 `run.sh c)` safe(14일 generation 보존, docker·pnpm 제외) → 여유를 재측정하는 것이다. `run.sh C)` deep/docker prune은 그 다음 선택지다(`docker system df` 명목치 ≠ 실 회수량, builder prune이 본 회수원). safe의 `--yes`는 스크립트 확인만 넘긴다. root GC·journal 같은 `sudo` 단계는 비대화형에서 건너뛸 수 있으므로, 출력의 실패를 확인하고 필요하면 visible terminal에서 sudo 인증 후 처리한다. 현재 journal은 선언적 1GiB 상한으로 사후 진단 여지를 보존한다. - **restart vs recreate — "무엇을 바꿨느냐"로 가른다** (매번 까먹는 지점): - **env/mount 변경 → `up -d --force-recreate`**. `docker compose restart`는 기존 env 재사용, recreate만 새 env·볼륨 픽업. - **config 파일(`~/openclaw/config/openclaw.json`) 변경 → `docker compose restart openclaw-gateway`로 충분.** restart도 gateway 프로세스·manager cache·Node compile state를 콜드 리셋한다. config-only에 recreate는 과하다(느리고 불필요하게 더 깊은 콜드). recreate는 env/mount일 때만. - **restart/recreate 후 memory prewarm** — 콜드 첫 `memory_search`는 세션 전수 스캔(glg 808 files/211MB, ARM)으로 15s 하드타임아웃(`memory-core` tools.ts 하드코딩, config로 못 늘림)에 걸릴 수 있다. gateway healthy 뒤 각 봇에 `openclaw agent --agent <id> --session-key "agent:<id>:prewarm-$(date +%s)" --message '기억 검색' --timeout 60`을 (텔레그램 발송 없이) 한 번 돌려 **봇이 콜드를 대신 맞게** 하면 실제 유저는 웜만 만난다. 1차 방어는 인덱스 정비(dirty:no 유지 — family-turns 스킬 memory 섹션): 정비돼 있으면 콜드도 15s를 버틴다(2026-07-16 실측, 정비 후 콜드 3연속 성공). upstream PR로 timeout 늘리는 건 안 한다 — 운영으로 커버(GLG 결정). ## 6. 커밋 / 릴리즈 규율 - 커밋 전 `commit` 스킬, 릴리즈 전 `tag-release` 스킬. 로그 깨끗하게(“Generated with Claude”· Co-Authored-By 금지). 에이전트는 commit workflow에서만 커밋, **push는 GLG**. - **git-hooks 안전벽** (global `core.hooksPath`): 공개 repo(`junghan0611/*`·`junghanacs/*`) added line의 **정체성 용어** + 모든 repo의 **secret**를 차단. nixos-config는 공개 repo다 — 실제 이메일/비번/토큰을 커밋 다이어그램에 넣지 마라(실파일은 gitignore, 템플릿은 플레이스홀더). `AGENT_ALLOW_UNSAFE_COMMIT=1`·`--no-verify`·`core.hooksPath` 변경 **금지**(GLG 명시 예외만). - 막히면: hook 출력 읽고 → 다이어그램에서 용어/secret 제거(private은 `PRIVATE.md`/`.env.local` 또는 플레이스홀더) → 재스테이지 → 재시도. false positive 같으면 멈추고 hook 출력 그대로 보고. - push 후 agenda 스탬프(commit/release 스킬 규약). ## 7. 영속 사실이 사는 곳 (썩는 문서 말고) | 사실 | 집 | |---|---| | 현재 운영 상태 | `AGENTS.md` | | 다음 할 일·후속 검증 | `NEXT.md` (완료분은 지우고 ROADMAP으로 흘림) | | 버전·업그레이드·운영 결정 이력 | `ROADMAP.md` | | oracle/openclaw 핸드북 | `ORACLE.md` | | 반복되는 운영 함정 | `docs/openclaw-gotchas.md` | | 라이브 봇 런타임 change history | `~/openclaw/README.md` (커밋 안 되는 SSOT) | 이 스킬 자체(`.claude/skills/nixos-config/SKILL.md`)는 **양쪽 하네스가 읽는다**: Claude Code는 `.claude/skills/`를 네이티브로, pi는 `.pi/settings.json`의 `["../.claude/skills"]`로. 스킬을 고치면 두 하네스에 동시에 반영된다 — 커밋해서 다른 기기로도 펼친다.
عرض على GitHub