Compare commits
7 Commits
fe540f7674
...
ea50e56278
| Author | SHA1 | Date | |
|---|---|---|---|
| ea50e56278 | |||
| 9eef595003 | |||
| 73b0564d8e | |||
| c2cb6c0801 | |||
| 514a1e991e | |||
| 88f1bb5fe2 | |||
| 6844c24b77 |
@@ -12,7 +12,8 @@ prev_session_id: 2026-08-10-admin-pi-inbox-monitor
|
|||||||
|
|
||||||
- Gitea 1.27.1 + postgres 16, чистые контейнеры (`/volume1/docker/gitea/`), БД на volume1 (не SSD — требование). Админ `kreknin` (pass kreknin/gitea).
|
- Gitea 1.27.1 + postgres 16, чистые контейнеры (`/volume1/docker/gitea/`), БД на volume1 (не SSD — требование). Админ `kreknin` (pass kreknin/gitea).
|
||||||
- Traefik на kreknin починен: лежал с 07-31 (restart policy был `no`) → `restart: unless-stopped`. Проброс 80/443→8000/4443 добавлен в GUI Keenetic (API KeeneticOS Viva закрыт для curl — только GUI).
|
- Traefik на kreknin починен: лежал с 07-31 (restart policy был `no`) → `restart: unless-stopped`. Проброс 80/443→8000/4443 добавлен в GUI Keenetic (API KeeneticOS Viva закрыт для curl — только GUI).
|
||||||
- **ОСТАЛОСЬ: DNS-override на Keenetic** — «Домашняя сеть → Доменные имена»: `git.kreknin.site → 192.168.1.43`, `kreknin.site → 192.168.1.43`. NAT loopback у Алексея сломан (из его LAN внешние адреса не открываются) — без этой записи он сам не зайдёт на свой gitea. Проверить с его LAN.
|
- **Gitea на kreknin ЗАКРЫТ ПОЛНОСТЬЮ** (2026-08-12): https://git.kreknin.site/ работает и снаружи (LE-серт), и из LAN Алексея. **DNS-override сделан через RCI API** (концепт `.wiki/concepts/keenetic-rci-api.md`): `ip host git.kreknin.site/kreknin.site → 192.168.1.43`. KeeneticOS 5.1.3 hairpin НЕ чинит — DNS-override это решение. Правила порт-форвардинга в 5.x лежат в `ip.static` (to-host=MAC).
|
||||||
|
- **Из LAN 443 занят встроенным nginx DSM** → reverse proxy `git.kreknin.site:443 → proxy_pass https://127.0.0.1:4443` (traefik) в `server.ReverseProxy.conf` w3conf. LE-серт для nginx — извлечён из traefik acme.json + **автосинк**: `/volume1/scripts/acme-nginx-sync.sh` + cron 15 мин (ротация сама). DSM-пароль не нужен (root SSH).
|
||||||
- Пароль Keenetic: `pass kreknin/keenetic` (t3r1a4k314).
|
- Пароль Keenetic: `pass kreknin/keenetic` (t3r1a4k314).
|
||||||
- Keenetic отваливался на провайдере (не свет) — монитор-расширение сработал, удалён после завершения.
|
- Keenetic отваливался на провайдере (не свет) — монитор-расширение сработал, удалён после завершения.
|
||||||
|
|
||||||
|
|||||||
62
.wiki/concepts/keenetic-rci-api.md
Normal file
62
.wiki/concepts/keenetic-rci-api.md
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
---
|
||||||
|
title: Keenetic RCI API (KeeneticOS 4.x/5.x) — как автоматизировать
|
||||||
|
type: concept
|
||||||
|
tags: [keenetic, router, rci, api, nat, dns, hairpin]
|
||||||
|
related: [[kreknin-synology]]
|
||||||
|
updated: 2026-08-12
|
||||||
|
---
|
||||||
|
|
||||||
|
# Keenetic RCI API
|
||||||
|
|
||||||
|
Автоматизация KeeneticOS (проверено на **Viva 5.1.3**, release 5.01.C.3.0-1, stable). Новые веб-панели (Angular) закрыли старый `/api/auth`-digest + `/api/rci/`, но есть живой RCI через `/rci/`.
|
||||||
|
|
||||||
|
## Auth (интерактивный метод, как панель)
|
||||||
|
|
||||||
|
1. `GET /auth` → `401` + заголовки `X-NDM-Challenge` + `X-NDM-Realm` (+ кука `*.kpd*`).
|
||||||
|
2. `POST /auth` с JSON `{"login":"admin","password":ENC}`, заголовок `x-ndw2-interactive: 1`, куки из шага 1.
|
||||||
|
- `ENC = sha256hex( CHALLENGE + md5hex( login + ":" + realm + ":" + password ) )` (lowercase hex).
|
||||||
|
- `realm` — весь заголовок целиком (например `Keenetic Viva`, с пробелом).
|
||||||
|
3. Дальше все запросы **с кукой** из шага 1 (curl `-b jar`). Кука живёт ~5 мин (Max-Age=300) — перед серией запросов перелогинься.
|
||||||
|
|
||||||
|
## Чтение (GET, кука)
|
||||||
|
|
||||||
|
- `GET /rci/show/version` — версия OS
|
||||||
|
- `GET /rci/show/interface` — интерфейсы; `GET /rci/show/sc/interface/<id>` — конфиг интерфейса
|
||||||
|
- `GET /rci/show/sc/ip` — конфиг ip: `route`, `dhcp`, `dhcp/host`, `static` (!!), `nat` (только список интерфейсов), `http`, `conntrack`…
|
||||||
|
- `GET /rci/show/ip/nat` — ТЕКУЩИЕ NAT-сессии (не правила)
|
||||||
|
- `GET /rci/show/ip/hotspot` — устройства (known hosts)
|
||||||
|
|
||||||
|
**Правила переадресации (порт-форвардинг) в 5.x лежат в `ip.static`** (!!, не `nat`):
|
||||||
|
```json
|
||||||
|
{ "interface": "GigabitEthernet1", "protocol": "tcp", "port": "443",
|
||||||
|
"to-port": "4443", "to-host": "22:06:7c:20:00:43", "comment": "gitea-https" }
|
||||||
|
```
|
||||||
|
`to-host` = **MAC-адрес** целевого устройства, `to-port` = внутренний порт (опционально, если ≠ внешнему).
|
||||||
|
|
||||||
|
## Запись — CLI-parser (POST, кука)
|
||||||
|
|
||||||
|
`POST /rci/` телом **массивом** `[{"parse":"<cli-команда>"}, …]` — как в командной строке Keenetic. В конце обязательно `{"parse":"save"}`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -b $JAR -H 'Content-Type: application/json' -X POST http://192.168.1.1/rci/ \
|
||||||
|
-d '[{"parse":"ip host git.kreknin.site 192.168.1.43"},
|
||||||
|
{"parse":"ip host kreknin.site 192.168.1.43"},
|
||||||
|
{"parse":"save"}]'
|
||||||
|
```
|
||||||
|
|
||||||
|
Полезные команды:
|
||||||
|
- `ip host <domain> <ip>` — статичная DNS-запись (hosts override); `no ip host <domain>` — удалить
|
||||||
|
- `save` — сохранить конфиг (обязательно в конце батча)
|
||||||
|
- (для NAT-правил в 5.x — разбираться отдельно; в 5.x GUI их кладёт в `ip.static`)
|
||||||
|
|
||||||
|
## NAT loopback (hairpin)
|
||||||
|
|
||||||
|
**Keenetic (Viva, 5.1.3) hairpin НЕ работает** (проверено: из LAN внешний адрес не открывается, даже после обновления OS; провайдер не виноват — WAN IP белый 195.19.90.188). Рабочее решение — **DNS-override** на роутере (записи `host` выше): клиенты LAN резолвят `git.kreknin.site` → `192.168.1.43` напрямую. Годится для любого числа сервисов (общий traefik).
|
||||||
|
|
||||||
|
## Gotchas
|
||||||
|
|
||||||
|
- Старый `/api/auth` (digest) и `/api/rci/*` на новых прошивках **не работают** (отдают SPA). Путь RCI — `/rci/` без `/api/`.
|
||||||
|
- Кука в curl-куки-файле начинается с `#HttpOnly_` — не фильтруй `grep -v '^#'`, если хочешь её увидеть.
|
||||||
|
- `POST /rci/` с `{"path": ...}` (не массивом) — работает, но для чтения; для записи нужен массив parse-команд.
|
||||||
|
- Примеры кода: [gist ancientGlider/e72cdaa2…](https://gist.github.com/ancientGlider/e72cdaa2daf0af5f8d80f53fea4666be), [noksa/gokeenapi](https://github.com/noksa/gokeenapi) (Go, CLI: routes/DNS-records/DNS-routing/WireGuard).
|
||||||
|
- Официальная CLI-справка Keenetic: [support.keenetic.com — CLI](https://support.keenetic.com/hero/kn-1012/en/18480-command-line-interface--cli-.html) (порт-форвардинг, firewall, DNS, VPN-разделы).
|
||||||
@@ -125,7 +125,9 @@ USB **2TB WD20EARX** (sdq) отформатирован в один btrfs, см
|
|||||||
- **Домен:** `https://git.kreknin.site/` — LE-серт (traefik httpChallenge, выписан 2026-08-12), redirect http→https.
|
- **Домен:** `https://git.kreknin.site/` — LE-серт (traefik httpChallenge, выписан 2026-08-12), redirect http→https.
|
||||||
- **Traefik** (v2.6.6, порты 8000/4443/8080): лежал с 07-31 (restart policy был `no`, упал на инциденте) — починен: `restart: unless-stopped`. **Урок: traefik без restart policy после ребута не поднимается.**
|
- **Traefik** (v2.6.6, порты 8000/4443/8080): лежал с 07-31 (restart policy был `no`, упал на инциденте) — починен: `restart: unless-stopped`. **Урок: traefik без restart policy после ребута не поднимается.**
|
||||||
- **Проброс на Keenetic:** 80→192.168.1.43:8000, 443→192.168.1.43:4443 (правила в панели, сделал vitya/Алексей в GUI — KeeneticOS Viva API закрыт для curl-автоматизации).
|
- **Проброс на Keenetic:** 80→192.168.1.43:8000, 443→192.168.1.43:4443 (правила в панели, сделал vitya/Алексей в GUI — KeeneticOS Viva API закрыт для curl-автоматизации).
|
||||||
- **NAT loopback у Алексея СЛОМАН** (из его LAN внешние адреса не открываются): нужен DNS-override в Keenetic — «Домашняя сеть → Доменные имена»: `git.kreknin.site → 192.168.1.43`, `kreknin.site → 192.168.1.43`. Статус: добавлено/нет — проверить с LAN.
|
- **NAT loopback у Алексея СЛОМАН** — **РЕШЕНО (2026-08-12)**: KeeneticOS 5.1.3 hairpin не чинит (проверено). Двойное решение:
|
||||||
|
1. **DNS-override на Keenetic** (RCI): `git.kreknin.site`/`kreknin.site` → `192.168.1.43` (ip host через POST /rci/ parse)
|
||||||
|
2. **Reverse proxy на DSM nginx**: 443 занят встроенным nginx DSM → добавлен server block `git.kreknin.site:443 → proxy_pass https://127.0.0.1:4443` (traefik), файл `/usr/local/etc/nginx/sites-available/0a73bdfc-…w3conf` (server.ReverseProxy.conf) + `nginx -s reload`. ⚠️ Важно: traefik на 4443 — TLS-entrypoint, поэтому `proxy_pass https://` + `proxy_ssl_verify off` + `proxy_ssl_name git.kreknin.site` (HTTP на 4443 даёт 404). **LE-серт в nginx**: извлечён из traefik `/volume1/docker/traefik/letsencrypt/acme.json` (base64 из Certificate/Key) → `/usr/local/etc/nginx/ssl_git_kreknin.{pem,key}` (LE, до 2026-11-10). DSM-пароль НЕ нужен (root SSH). **Автосинк**: `/volume1/scripts/acme-nginx-sync.sh` + cron `/etc/cron.d/acme-nginx-sync` (каждые 15 мин) — при ротации traefik-серта сам копирует в nginx и делает reload. Лог: `/var/tmp/acme-nginx-sync.log`.
|
||||||
- **Keenetic admin-пароль:** `pass kreknin/keenetic` (t3r1a4k314; 3steaks1eGG — НЕ для роутера).
|
- **Keenetic admin-пароль:** `pass kreknin/keenetic` (t3r1a4k314; 3steaks1eGG — НЕ для роутера).
|
||||||
- Установка через web-форму падала (xorm nil-pointer panic на sqlite) → обход: `INSTALL_LOCK=true` в [security] + CLI `admin user create`. Gitea CLI: `docker exec -u 1026:100 gitea gitea --config /data/gitea/conf/app.ini admin user ...` (новый синтаксис `admin user create`, не `create-user`).
|
- Установка через web-форму падала (xorm nil-pointer panic на sqlite) → обход: `INSTALL_LOCK=true` в [security] + CLI `admin user create`. Gitea CLI: `docker exec -u 1026:100 gitea gitea --config /data/gitea/conf/app.ini admin user ...` (новый синтаксис `admin user create`, не `create-user`).
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever
|
|||||||
- [windows-recovery-host](entities/windows-recovery-host.md) — Windows Recovery Host (рабочий PC пользователя)
|
- [windows-recovery-host](entities/windows-recovery-host.md) — Windows Recovery Host (рабочий PC пользователя)
|
||||||
|
|
||||||
## Concepts
|
## Concepts
|
||||||
|
- [keenetic-rci-api](concepts/keenetic-rci-api.md) — KeeneticOS RCI API: auth, чтение конфига, запись через CLI-parser, DNS-override против сломанного hairpin
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- [admin-api-embed-pilonuxt](concepts/admin-api-embed-pilonuxt.md) — admin-api embedded in pilonuxt /admin/api, stack 25 retired (2026-08-05)
|
- [admin-api-embed-pilonuxt](concepts/admin-api-embed-pilonuxt.md) — admin-api embedded in pilonuxt /admin/api, stack 25 retired (2026-08-05)
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
## [2026-08-12] implement | UPDATE entities/kreknin-synology.md — автосинк LE-серта: acme-nginx-sync.sh (cron 15 мин) ротирует серт git.kreknin.site из traefik acme.json в nginx DSM автоматически.
|
||||||
|
## [2026-08-12] implement | UPDATE entities/kreknin-synology.md — LE-серт git.kreknin.site (из traefik acme.json) подложен в nginx DSM reverse proxy. Из LAN: валидный LE + Gitea, без DSM-пароля (root SSH).
|
||||||
|
## [2026-08-12] implement | UPDATE entities/kreknin-synology.md — reverse proxy git.kreknin.site:443 → traefik:4443 на DSM nginx (server.ReverseProxy.conf w3conf + reload). Из LAN git.kreknin.site → Gitea (DNS-override + proxy), снаружи LE-серт. Осталось: LE-серт в DSM для git.kreknin.site (из LAN, без предупреждения).
|
||||||
|
## [2026-08-12] implement | NEW concepts/keenetic-rci-api.md — разобрана автоматизация KeeneticOS 5.1.3 (RCI: GET /rci/show/*, POST /rci/ массив parse-команд). Через API добавлены DNS-записи git.kreknin.site/kreknin.site → 192.168.1.43 (решение сломанного hairpin). Проверено с LAN: всё 200. Правила порт-форвардинга в 5.x лежат в ip.static (to-host=MAC).
|
||||||
## [2026-08-12] implement | UPDATE entities/kreknin-synology.md — Gitea 1.27.1 + postgres 16 на kreknin (для Алексея), traefik починен (restart policy), LE-серт git.kreknin.site, проброс 80/443→8000/4443 на Keenetic. KeeneticOS Viva API закрыт — правила в GUI. NAT loopback сломан → нужен DNS-override git.kreknin.site→192.168.1.43. Пароли: pass kreknin/keenetic + pass kreknin/gitea.
|
## [2026-08-12] implement | UPDATE entities/kreknin-synology.md — Gitea 1.27.1 + postgres 16 на kreknin (для Алексея), traefik починен (restart policy), LE-серт git.kreknin.site, проброс 80/443→8000/4443 на Keenetic. KeeneticOS Viva API закрыт — правила в GUI. NAT loopback сломан → нужен DNS-override git.kreknin.site→192.168.1.43. Пароли: pass kreknin/keenetic + pass kreknin/gitea.
|
||||||
# Wiki op-log
|
# Wiki op-log
|
||||||
|
|
||||||
|
|||||||
24
AGENTS.md
Normal file
24
AGENTS.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# AGENTS.md (canon)
|
||||||
|
# Agent instructions. Each line is a trigger for an installed skill.
|
||||||
|
|
||||||
|
talk like a caveman
|
||||||
|
use project wiki
|
||||||
|
use task management system
|
||||||
|
check across all projects
|
||||||
|
pull remote before work
|
||||||
|
session handoff: read on start, write on end
|
||||||
|
follow project discipline
|
||||||
|
delegate to interns when allowed
|
||||||
|
recommend, don't menu
|
||||||
|
we're on Windows
|
||||||
|
|
||||||
|
# Secrets rule
|
||||||
|
|
||||||
|
Все креды (SSH, БД, panel, BA) лежат в `pass` (password-store). **Перед поиском доступов — `pass ls` / `pass show <path>`, а не grep по вики или `~/.ssh/config`.**
|
||||||
|
Серверы СТО Стайер: `stostayer/client` (`new.stostayer.ru:20435` — машина клиента, файлы 1С в `/var/from_1c/`), `stostayer/rusonyx`, `stostayer/client-wireguard`.
|
||||||
|
|
||||||
|
# VDS ops rule
|
||||||
|
|
||||||
|
Все docker-compose stacks на VDS управляются через Portainer (`https://portainer.vds.kzntsv.site`).
|
||||||
|
`ssh + docker compose up -d` на VDS — anti-pattern. См. [`portainer-stack-management-vds`](.wiki/concepts/portainer-stack-management-vds.md) для migration script + gotchas.
|
||||||
|
Исключения: `traefik` + `portainer` (management plane, ad-hoc compose).
|
||||||
25
CLAUDE.md
25
CLAUDE.md
@@ -1,24 +1,3 @@
|
|||||||
# CLAUDE.md
|
# CLAUDE.md — legacy pointer
|
||||||
# Agent instructions. Each line is a trigger for an installed skill.
|
|
||||||
|
|
||||||
talk like a caveman
|
Canon is `AGENTS.md`. Read `AGENTS.md` — it contains all project instructions.
|
||||||
use project wiki
|
|
||||||
use task management system
|
|
||||||
check across all projects
|
|
||||||
pull remote before work
|
|
||||||
session handoff: read on start, write on end
|
|
||||||
follow project discipline
|
|
||||||
delegate to interns when allowed
|
|
||||||
recommend, don't menu
|
|
||||||
we're on Windows
|
|
||||||
|
|
||||||
# Secrets rule
|
|
||||||
|
|
||||||
Все креды (SSH, БД, panel, BA) лежат в `pass` (password-store). **Перед поиском доступов — `pass ls` / `pass show <path>`, а не grep по вики или `~/.ssh/config`.**
|
|
||||||
Серверы СТО Стайер: `stostayer/client` (`new.stostayer.ru:20435` — машина клиента, файлы 1С в `/var/from_1c/`), `stostayer/rusonyx`, `stostayer/client-wireguard`.
|
|
||||||
|
|
||||||
# VDS ops rule
|
|
||||||
|
|
||||||
Все docker-compose stacks на VDS управляются через Portainer (`https://portainer.vds.kzntsv.site`).
|
|
||||||
`ssh + docker compose up -d` на VDS — anti-pattern. См. [`portainer-stack-management-vds`](.wiki/concepts/portainer-stack-management-vds.md) для migration script + gotchas.
|
|
||||||
Исключения: `traefik` + `portainer` (management plane, ad-hoc compose).
|
|
||||||
|
|||||||
Reference in New Issue
Block a user