Files
obsidian-vault/family/how-to/kraken-portainer-access.md
T
2026-05-29 09:01:25 +00:00

298 lines
11 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
> Статус: ✅ cloudflared запущен (прямой токен)
## Portainer
| Параметр | Значение |
|---|---|
| URL | `http://localhost:9000` |
| Auth header | `X-API-Key: ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g=` |
| Endpoint ID | уточнить: `curl -s -H "X-API-Key: ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g=" http://localhost:9000/api/endpoints | jq '[.[].Id]'` (обычно `1`) |
### Portainer API — Quick Reference
```bash
BASE=http://localhost:9000
KEY="ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g="
EP=1
# Список контейнеров
curl -s -H "X-API-Key: $KEY" "$BASE/api/endpoints/$EP/docker/containers/json?all=true" \
| jq '[.[] | {name: .Names[0], status: .Status, image: .Image}]'
# Логи контейнера
curl -s -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/<ID>/logs?stdout=1&stderr=1&tail=50"
# Удалить контейнер
curl -s -X DELETE -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/<ID>"
```
### Временный Alpine-контейнер (выполнить команду на хосте)
Для разовых задач — alpine с bind `/:/host`:
```bash
BASE=http://localhost:9000
KEY="ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g="
EP=1
ID=$(curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
"$BASE/api/endpoints/$EP/docker/containers/create?name=alpine-tmp-$$" \
-d '{
"Image": "alpine",
"Cmd": ["sh", "-c", "YOUR_COMMAND_HERE && echo DONE"],
"HostConfig": {"Binds": ["/:/host"], "AutoRemove": false}
}' | jq -r '.Id')
curl -s -X POST -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/$ID/start"
sleep 2
curl -s -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/$ID/logs?stdout=1&stderr=1"
curl -s -X DELETE -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/$ID"
```
> ⚠️ `AutoRemove: false` — обязательно, иначе контейнер удалится до получения логов
> ⚠️ Использовать `alpine`, не `alpine/git` — у git-образа свой ENTRYPOINT
---
## Cloudflared — деплой (выполняет Кракен)
CF Tunnel уже создан Alex'ом (`kraken` в Zero Trust), hostname настроен: `kraken.qentra.top → SSH → localhost:22`.
**CF Tunnel Token:**
```
eyJhIjoiZjE...TnpFNU5USTNNREl4WkRVeCJ9
```
### Шаг 1 — Убедиться что EP = 1
```bash
curl -s -H "X-API-Key: ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g=" \
http://localhost:9000/api/endpoints | jq '[.[].Id]'
```
Если не `1` — запомнить реальный ID и использовать его вместо `1` в шагах ниже.
### Шаг 2 — Создать и запустить cloudflared контейнер
```bash
BASE=http://localhost:9000
KEY="ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g="
EP=1
TOKEN="eyJhIjoiZjE0YTM3NWQ3NmU1ZTU4M2IzNjZhMDJhYjUyNDZiNDciLCJ0IjoiMmRkZDJiMjgtNjYwYy00NjQ0LTk1Y2ItY2Y1ZTQzNTBhMTA1IiwicyI6Ik5HVTRZalZtTURVdFptSm1OeTAwWVdGakxUaGlaamd0WmpFMFlUazVOekt3WTJWaCJ9"
CID=$(curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
"$BASE/api/endpoints/$EP/docker/containers/create?name=cloudflared" \
-d "{
\"Image\": \"cloudflare/cloudflared:latest\",
\"Cmd\": [\"tunnel\", \"--no-autoupdate\", \"run\"],
\"Env\": [\"TUNNEL_TOKEN=$TOKEN\"],
\"HostConfig\": {
\"RestartPolicy\": {\"Name\": \"unless-stopped\"},
\"NetworkMode\": \"host\"
}
}" | jq -r '.Id')
echo "Container ID: $CID"
curl -s -X POST -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/$CID/start"
echo "Started."
```
### Шаг 3 — Проверить логи
```bash
BASE=http://localhost:9000
KEY="ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g="
EP=1
CID=$(curl -s -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/json" \
| jq -r '.[] | select(.Names[] | contains("cloudflared")) | .Id')
curl -s -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/$CID/logs?stdout=1&stderr=1&tail=30" \
| strings
```
Ожидаем:
```
INF Registered tunnel connection connIndex=0 ... protocol=http2
INF Registered tunnel connection connIndex=1 ...
INF Registered tunnel connection connIndex=2 ...
INF Registered tunnel connection connIndex=3 ...
```
Все 4 соединения = туннель активен. Если видишь `ERR` — проверить токен.
### Шаг 4 — Сохранить compose-файл (опционально, для удобства в будущем)
```bash
BASE=http://localhost:9000
KEY="ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g="
EP=1
TOKEN="eyJhIjoiZjE0YTM3NWQ3NmU1ZTU4M2IzNjZhMDJhYjUyNDZiNDciLCJ0IjoiMmRkZDJiMjgtNjYwYy00NjQ0LTk1Y2ItY2Y1ZTQzNTBhMTA1IiwicyI6Ik5HVTRZalZtTURVdFptSm1OeTAwWVdGakxUaGlaamd0WmpFMFlUazVOekt3WTJWaCJ9"
COMPOSE="services:\n cloudflared:\n image: cloudflare/cloudflared:latest\n container_name: cloudflared\n restart: unless-stopped\n command: [\"tunnel\", \"--no-autoupdate\", \"run\"]\n environment:\n - TUNNEL_TOKEN=$TOKEN\n network_mode: host"
ID=$(curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
"$BASE/api/endpoints/$EP/docker/containers/create?name=alpine-cf-setup" \
-d "{
\"Image\": \"alpine\",
\"Cmd\": [\"sh\", \"-c\", \"mkdir -p /host/home/kraken/cloudflared && printf '$COMPOSE' > /host/home/kraken/cloudflared/docker-compose.yml && echo DONE\"],
\"HostConfig\": {\"Binds\": [\"/:/host\"], \"AutoRemove\": false}
}" | jq -r '.Id')
curl -s -X POST -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/$ID/start"
sleep 2
curl -s -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/$ID/logs?stdout=1&stderr=1"
curl -s -X DELETE -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/$ID"
```
### Шаг 5 — Создать скилл по внешнему доступу
```bash
mkdir -p /opt/data/skills/devops/kraken-external-access
cat > /opt/data/skills/devops/kraken-external-access/SKILL.md << 'SKILLEOF'
---
name: kraken-external-access
category: devops
description: Внешний доступ к Kraken через Cloudflare Tunnel — SSH с Eagle, Portainer API, управление cloudflared.
triggers:
- "доступ к кракену снаружи"
- "ssh к кракену с орла"
- "управление docker на кракене удалённо"
- "cloudflared крякен"
---
# Kraken — External Access via Cloudflare Tunnel
## SSH с Eagle (уже настроено в ~/.ssh/config на Eagle)
```bash
ssh kraken.qentra.top
```
## Portainer API
```bash
BASE=http://localhost:9000
KEY="ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g="
EP=1
# Список контейнеров
curl -s -H "X-API-Key: $KEY" "$BASE/api/endpoints/$EP/docker/containers/json?all=true" \
| jq '[.[] | {name: .Names[0], status: .Status}]'
```
## Управление cloudflared
```bash
# Статус + логи
CID=$(curl -s -H "X-API-Key: $KEY" "$BASE/api/endpoints/$EP/docker/containers/json" \
| jq -r '.[] | select(.Names[] | contains("cloudflared")) | .Id')
curl -s -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/$CID/logs?stdout=1&stderr=1&tail=30" | strings
# Рестарт
curl -s -X POST -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/$CID/restart"
```
## Питфолы
- `network_mode: host` — cloudflared видит все локальные порты Кракена напрямую
- `restart: unless-stopped` — при падении поднимается автоматически
- Токен в env `TUNNEL_TOKEN` — не менять без пересоздания контейнера
- Статус туннеля: https://one.dash.cloudflare.com/ → Networks → Tunnels → kraken
- Если туннель не поднимается — искать `ERR` в логах cloudflared
## Связанные заметки
- `family/how-to/kraken-portainer-access.md` — полная инструкция по деплою
- `family/how-to/openmediavault-rpi5.md` — структура Docker на Кракене
SKILLEOF
echo "Скилл создан."
```
> ⚠️ `/opt/data/` — HDD-volume, скилл переживёт rebuild образа
### Временный запуск cloudflared с прямым токеном (только для диагностики)
**Внимание:** Этот метод передает токен напрямую в `Cmd` контейнера. Это **небезопасно** для постоянного использования, но использовался для устранения проблем с монтированием файлов `credentials.json` и `config.yaml`.
Контейнер `cloudflared-access-debug-direct-token` с ID `8d9b3f7cec6fe6e1622f3a4c920733e9c322dfc936165b005bc22a0348c489a4` запущен с прямым токеном.
```bash
BASE=http://localhost:9000
KEY="ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g="
EP=3
TOKEN="eyJhIjoiZjE0YTM3NWQ3NmU1ZTU4M2IzNjZhMDJhYjUyNDZiNDciLCJ0IjoiMGVlNWIxNmQtYTNmMC00ZjEzLWJjMzQtMmE4ODFhMGE0NDBhIiwicyI6Ik5qYzNZekV5T1dNdE56TTFOUzAwWkdVM0xUa3dNakl0TnpFNU5USTNNREl4WkRVeCJ9" # Временный токен
CID=$(curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
"$BASE/api/endpoints/$EP/docker/containers/create?name=cloudflared-access-debug-direct-token" \
-d "{\"Image\": \"cloudflare/cloudflared:latest\", \"Cmd\": [\"tunnel\", \"run\", \"--token\", \"$TOKEN\"], \"HostConfig\": {\"RestartPolicy\": {\"Name\":\"unless-stopped\"}, \"NetworkMode\":\"host\"}}" | jq -r '.Id')
curl -s -X POST -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/$CID/start"
```
Заменить первую строку `> Статус: ⏳ cloudflared pending deploy` на `> Статус: ✅ cloudflared запущен (прямой токен)`.
---
## SSH-доступ с Eagle
Reverse SSH tunnel через VPS (порт 2223). Работает без CF Access Application.
`~/.ssh/config` на Eagle:
```
Host kraken.qentra.top
HostName 91.207.28.205
Port 2223
User kraken
IdentityFile ~/.ssh/id_rsa
StrictHostKeyChecking no
```
Подключение: `ssh kraken.qentra.top`
### Как это работает
Кракен держит постоянный reverse SSH tunnel на VPS `91.207.28.205`:
- systemd-сервис `kraken-tunnel.service` (autossh, autostart, restart always)
- VPS слушает порт 2223 → перенаправляет на `localhost:22` Кракена
- Ключ: `/home/kraken/.ssh/id_ed25519`
Управление туннелем на Кракене:
```bash
sudo systemctl status kraken-tunnel
sudo systemctl restart kraken-tunnel
sudo journalctl -u kraken-tunnel -n 20
```
Проверить порт на VPS:
```bash
ssh root@91.207.28.205 "ss -tlnp | grep 2223"
```
---
## Связанные заметки
- [[openmediavault-rpi5]] — настройка Kraken (Docker, Hermes, структура папок)
- [[truenas-infrastructure]] — Taiga (аналогичный Portainer API подход)
- [[obsidian-sync]] — синхронизация хранилища.