Files
obsidian-vault/family/how-to/kraken-portainer-access.md
T

245 lines
8.4 KiB
Markdown
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.
# Kraken — Portainer Access & Cloudflared SSH Tunnel
> Статус: ⏳ cloudflared pending — ждём CF Tunnel token от Alex
## Portainer
| Параметр | Значение |
|---|---|
| URL | `http://localhost:9000` |
| Auth header | `X-API-Key: ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g=` |
| Endpoint ID | уточнить через `GET /api/endpoints` (обычно `1` для local Docker) |
### Portainer API — Quick Reference
```bash
BASE=http://localhost:9000
KEY="ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g="
EP=1 # endpoint ID
# Список endpoints (узнать EP)
curl -s -H "X-API-Key: $KEY" $BASE/api/endpoints | jq '[.[].Id]'
# Список контейнеров
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 -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
"$BASE/api/endpoints/$EP/docker/containers/create?name=<NAME>" \
-d '<JSON>'
# Запустить контейнер
curl -s -X POST -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/<ID>/start"
# Логи
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
# 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", "echo hello from host > /host/tmp/test.txt && echo DONE"],
"HostConfig": {
"Binds": ["/:/host"],
"AutoRemove": false
}
}' | jq -r '.Id')
# 2. Запустить
curl -s -X POST -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/$ID/start"
# 3. Подождать завершения (1-2 сек) и забрать логи
sleep 2
curl -s -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/$ID/logs?stdout=1&stderr=1"
# 4. Удалить
curl -s -X DELETE -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/$ID"
```
> ⚠️ `AutoRemove: false` — обязательно, иначе контейнер удалится до того как получишь логи
> ⚠️ Используй `alpine`, не `alpine/git` и подобные — у них есть ENTRYPOINT, `sh -c` не сработает
---
## Cloudflared — деплой
### Шаг 1 — Получить CF Tunnel token (делает Alex вручную)
1. Открыть [Cloudflare Zero Trust → Networks → Tunnels](https://one.dash.cloudflare.com/)
2. **Create a tunnel** → Cloudflared → назвать `kraken`
3. На шаге "Install connector": скопировать команду вида:
```
cloudflared service install eyJ...
```
Нас интересует только токен — длинная строка после `service install`
4. Сохранить токен — вписать в эту заметку ниже
**CF Tunnel Token:**
```
<ВСТАВИТЬ СЮДА ТОКЕН ПОСЛЕ СОЗДАНИЯ ТОННЕЛЯ>
```
### Шаг 2 — Создать docker-compose.yml через alpine
Используем alpine-контейнер с bind `/:/host` для записи файла:
```bash
BASE=http://localhost:9000
KEY="ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g="
EP=1
TOKEN="<CF_TUNNEL_TOKEN>"
COMPOSE_B64=$(echo "services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
command: [\"tunnel\", \"--no-autoupdate\", \"run\"]
environment:
- TUNNEL_TOKEN=${TOKEN}
network_mode: host" | base64 | tr -d '\n')
ID=$(curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
"$BASE/api/endpoints/$EP/docker/containers/create?name=alpine-setup-$$" \
-d "{
\"Image\": \"alpine\",
\"Cmd\": [\"sh\", \"-c\", \"mkdir -p /host/home/kraken/cloudflared && echo ${COMPOSE_B64} | base64 -d > /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"
```
### Шаг 3 — Поднять cloudflared контейнер через Portainer API
```bash
BASE=http://localhost:9000
KEY="ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g="
EP=1
TOKEN="<CF_TUNNEL_TOKEN>"
# Создать контейнер
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')
# Запустить
curl -s -X POST -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/$CID/start"
echo "Container ID: $CID"
```
### Шаг 4 — Проверить логи
```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?all=true" | 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"
```
Ожидаем в логах:
```
INF Registered tunnel connection connIndex=0 ... protocol=http2
INF Connection ... registered connIndex=0
INF Connection ... registered connIndex=1
...
```
Если видишь все 4 соединения — туннель активен.
### Шаг 5 — Обновить статус в этой заметке
Заменить `⏳ cloudflared pending` в заголовке на `✅ cloudflared запущен`.
---
## Что делает Alex после запуска (вручную в CF Zero Trust)
После того как cloudflared запущен и туннель появился как **Active** в Zero Trust:
1. Открыть туннель `kraken` → **Edit** → вкладка **Public Hostname** → **Add a public hostname**
2. Добавить поддомен SSH:
- Subdomain: `ssh`
- Domain: `kraken.qentra.top` (создать заранее в DNS)
- Service type: **SSH**
- URL: `localhost:22`
3. Сохранить — DNS запись создаётся автоматически
Повторить для других сервисов если нужно:
- `omv.kraken.qentra.top` → HTTP → `localhost:80` (OMV Web UI)
- `portainer.kraken.qentra.top` → HTTP → `localhost:9000`
> ⚠️ Аналогично тому как настраивался `zulip.qentra.top` на Eagle:
> токен получается при создании тоннеля в Zero Trust → вставляется в `TUNNEL_TOKEN`
---
## SSH-доступ через Cloudflare Tunnel (с Eagle)
После настройки поддомена добавить в `~/.ssh/config` на Eagle:
```
Host ssh.kraken.qentra.top
ProxyCommand cloudflared access ssh --hostname %h
User kraken
IdentityFile ~/.ssh/id_rsa
StrictHostKeyChecking no
```
Затем:
```bash
ssh ssh.kraken.qentra.top
```
> `cloudflared` на Eagle уже есть (используется для `zulip.qentra.top`)
---
## Связанные заметки
- [[openmediavault-rpi5]] — настройка Kraken (Docker, Hermes, структура папок)
- [[truenas-infrastructure]] — Taiga (аналогичный Portainer API подход)
- [[obsidian-sync]] — синхронизация vault