---
name: mac mini — доступ (LAN preferred, upterm fallback)
description: Как подключаться к mac mini оператора. С 2026-06-24 — из ЛЮБОЙ сети через Tailscale (ssh -p 2222 cebers_mini@100.84.177.25); в LAN — прямой SSH по .local; upterm — старый fallback.
type: reference
originSessionId: 6620ea3d-79ed-46e4-b5ea-65828f0cc0b8
---
**Хост:** mac mini, hostname `Cebers-mini.local` (mDNS) → `Cebers-mini.local` (на 2026-05-17), Darwin 25.x arm64, пользователь `cebers_mini`. Дом `/Users/cebers_mini`. Проекты в `~/Services/`.

**С 2026-06-24 — РАБОТАЕТ ИЗ ЛЮБОЙ СЕТИ через Tailscale (предпочтительно, бесплатно).** Обе машины в tailnet `tail2f8be2.ts.net` (аккаунт `cebersdev@`): мини = `cebers-mini` = **`100.84.177.25`**, ноут = `macbook-air-cebers` = `100.88.104.126`. Команда из любой сети:
```
ssh -i ~/.ssh/id_ed25519 -p 2222 cebers_mini@100.84.177.25 'cmd'
```
Порт **2222** (НЕ 22!): на мини tailscaled-ops в userspace-режиме отдаёт SSH через `tailscale serve --tcp 2222 → 127.0.0.1:22` (приватно в tailnet, ключевой вход в OpenSSH). Порт 22 на tailnet-IP занят встроенным Tailscale SSH (баннер `SSH-2.0-Tailscale`, дефолтная ACL `check` → неинтерактивный ssh виснет — НЕ использовать 22). Funnel ops_dashboard (8787/8080/8443) не тронут. scp/rsync тоже через `-P 2222 ...@100.84.177.25`.
- **На ноуте Tailscale обязан быть поднят:** `tailscale status` (CLI `/usr/local/bin/tailscale`); если «stopped» → `open -a Tailscale && tailscale up` (вход не нужен, креды сохранены). GUI-приложение macsys, login-item автозапуск.
- **⚠️ Грабли «симметричный NAT → DERP-блэкхол» (2026-06-26, потратили время):** на некоторых сетях у ноута симметричный NAT (`tailscale netcheck` → `MappingVariesByDestIP: true`) — прямой WireGuard-канал сам НЕ встаёт, весь трафик идёт через дальний DERP-релей (Хельсинки/Франкфурт ~340мс). На релее крупные пакеты блэкхолятся: `nc -z 100.84.177.25 2222` (мелкий SYN) проходит ИЛИ `tailscale ping` отвечает `via DERP`, **а сам SSH виснет на обмене ключами** (и 2222, и 22). Диагноз: `tailscale ping --c 10 100.84.177.25` — если все pong'и `via DERP(...)` и `direct connection not established`, это оно. **Фикс: пробить NAT — `tailscale ping --c 10 100.84.177.25` (долбить, пока не появится `pong ... via <ПУБЛИЧНЫЙ_IP>:port` вместо DERP); после этого `tailscale status` покажет ноут `active; direct ...` и SSH (2222 и 22) сразу заработает.** Это НЕ Hiddify и НЕ route-heal — сеть/NAT.
- **CLI на самом mini (не как в старой записи):** рабочий бинарь — `/opt/homebrew/bin/tailscale` (обёртка `/usr/local/bin/tailscale` БИТАЯ — указывает на несуществующий `…/Tailscale.app/…`, GUI-приложения на mini НЕТ). Демон один — homebrew-tailscaled (launchd `com.cebers.tailscaled-ops`), userspace, кастомный сокет; он же = узел 100.84.177.25 + встроенный Tailscale SSH (наш вход = его `be-child ssh`). Дефолтный `/var/run/tailscaled.socket` ПУСТ. Для serve/status на mini: `tailscale --socket=/Users/cebers_mini/Services/ops_dashboard/tailscale/tailscaled.sock serve status`. Serve-проброс 2222→`127.0.0.1:22` цел, Remote Login On, sshd на `*:22` — со стороны mini чинить нечего.
- **Порт 22 (Tailscale SSH) — рабочий, но требует web-reauth (check-режим ACL):** при `ssh -p 22` выдаёт `Tailscale SSH requires an additional check. To authenticate, visit: https://login.tailscale.com/a/...` и виснет. Оператор открывает ссылку в браузере под своим Tailscale-аккаунтом → вход на 22 проходит. Для неинтерактива предпочтительнее 2222 (ключевой, без reauth).
- **Грабли macOS (решено авто-хилером):** на ноуте Hiddify (VPN, `utun5`, `198.18.0.1`) перехватывает маршрутизацию, а маршрут Tailscale `100.64/10 → utun8` становится IFSCOPE (игнорируется) → трафик на `100.x` уходит в Hiddify и SSH виснет. Фикс: глобальный маршрут `100.64.0.0/10 → tailscale-utun` + **LaunchDaemon `com.cebers.ts-route-heal`** (`/usr/local/bin/ts-route-heal.sh`, каждые 60с, лог `/var/log/ts-route-heal.log`) держит его на актуальном Tailscale-интерфейсе. Трогает ТОЛЬКО `100.64/10` (диапазон только Tailscale) — на Hiddify/интернет/сервисы повлиять не может. Если SSH по tailnet вдруг таймаутит — `route -n get 100.84.177.25` должен дать `utun8`; если нет, запусти `sudo /bin/bash /usr/local/bin/ts-route-heal.sh`.

**Альтернатива — прямой SSH в LAN** (когда оператор и mac mini в одной сети, чуть быстрее/проще):
```
ssh -i ~/.ssh/id_ed25519 cebers_mini@Cebers-mini.local
# или Cebers-mini.local через mDNS
```

**⚠️ IP меняется (DHCP) + ssh-резолв имени бывает капризным.** 2026-06-24: `192.168.0.107` стал недоступен, мини переехал на **192.168.0.109** (и .115). При этом `ssh Cebers-mini.local` падал с `Could not resolve hostname` (getaddrinfo), хотя `ping`/`dscacheutil` имя резолвили. **Если ssh по имени не идёт — узнать текущий IP и ходить по нему:** `dscacheutil -q host -a name cebers-mini.local` (или `ping -c1 cebers-mini.local`), затем `ssh -i ~/.ssh/id_ed25519 cebers_mini@<IP>`. Не залипать на .107.
Мой публичный `~/.ssh/id_ed25519.pub` уже в `~cebers_mini/.ssh/authorized_keys`. **scp и rsync работают** — это снимает все TTY-проблемы, описанные ниже про upterm. Используй `scp` для передачи файлов любого размера и с любыми байтами; не возись с base64+chunks, если не пришлось.

**Fallback — upterm (релейный SSH, https://upterm.dev):** оператор запускает `upterm host` на mac mini, выдаёт одноразовую команду вида `ssh <token>@uptermd.upterm.dev`. Это **shared-shell** — все клиенты видят один tty. Использовать только когда LAN недоступна или нужен публичный туннель.

**Мои ключи локально:**
- `~/.ssh/id_ed25519` — для прямого SSH в LAN (предпочтительно).
- `~/.ssh/id_ed25519_upterm6` — для upterm (одноразовые сессии). Существовали `id_ed25519_upterm[1..5]` для прошлых сессий — все ротированы оператором.

**Особенности upterm shared-shell (когда всё-таки приходится):**
- ssh нужен `-tt` (PTY обязателен; без него `Connection closed` сразу).
- Несколько параллельных агентов = несколько отдельных upterm-сессий на mac mini. Один shared-shell на двоих не работает (команды перемешиваются).
- Никакого `scp` — uptermd только релей. Транспорт файлов через `cat`/`base64`/`tar` внутри сессии — **ненадёжен**: при чанках >~150 байт TTY-буфер начинает терять/дублировать байты (наблюдал «echo loops» и off-by-N байт). `sha256` после транспорта обязателен.
- НЕ запускать `chsh`, `sudo`, `git config --global` — это окружение оператора.
- НЕ убивать `launchctl`-агенты без согласования.
- Для `git log` / `git diff` / `cat` больших файлов добавлять `--no-pager` (или `export PAGER=cat GIT_PAGER=cat LESS=FRX`), иначе откроется `less` и сессия зависнет.

**Хелпер для upterm:** `/Users/cebers/Разработки/upterm_run.sh '<cmd>'`. Отправляет команду через `script(1)` для PTY, ставит маркеры `===UR_START/END===`, чистит ANSI/CR и возвращает stdout. `UR_TIMEOUT=N` секунд — настройка таймаута. Для прямого SSH в LAN он **не нужен** — используй обычный `ssh ...`.

**Прокси:** все сетевые запросы **изнутри mac mini** идут через `http://127.0.0.1:2081` (xray). Исключения: `127.0.0.1,localhost`. Без него половина бота лежит. К самому mac mini из LAN — без прокси.

**Why:** прямой SSH работает, потому что mac mini в той же подсети, что и ноутбук, и `id_ed25519` уже добавлен в его authorized_keys. До 2026-05-17 пользовались только upterm — отсюда и описание про PTY/TTY-баг (актуально только для fallback).

**How to apply:** при просьбе «подключиться к mac mini» — сначала пробовать `ssh -i ~/.ssh/id_ed25519 cebers_mini@Cebers-mini.local 'cmd'`. Если `Permission denied` — спросить у оператора, в LAN ли мы сейчас, и если да, проверить `authorized_keys`. Если оператор пишет про upterm — переключаться на `upterm_run.sh`.
