panel-build-and-deploy
Админская панель: запуск и выкладка
duck-obsidian-panel — это frontend-часть админки. Она собирается как static site и отдаётся через Nginx.
Панель сама не запускает shell-команды. Она ходит в backend API, а API уже вызывает gardenctl.
Локальный запуск
git clone git@github.com:leo-mmmmmmm/duck-obsidian-panel.git
cd duck-obsidian-panel
npm ci
npm run dev
Проверка типов:
npm run typecheck
Production build:
npm run build
После static export должен появиться:
out/
Сборка на сервере
cd /home/supervisor/leonid_projects/duck-obsidian-panel
npm ci
npm run build
Выложить static export:
sudo rm -rf /var/www/duck-obsidian-panel
sudo mkdir -p /var/www/duck-obsidian-panel
sudo cp -a out/. /var/www/duck-obsidian-panel/
Nginx для панели
Панель отдаётся как static files, а /api/* проксируется на backend API:
server {
listen 80;
server_name admin.obsidians.otc.guru;
root /var/www/duck-obsidian-panel;
index index.html;
auth_basic "Duck Garden Admin";
auth_basic_user_file /etc/nginx/.htpasswd-duck-admin;
location /api/ {
proxy_pass http://127.0.0.1:3017/api/;
proxy_http_version 1.1;
proxy_connect_timeout 60s;
proxy_send_timeout 900s;
proxy_read_timeout 900s;
send_timeout 900s;
proxy_set_header Authorization "Bearer PASTE_DUCK_PANEL_TOKEN_HERE";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /health {
proxy_pass http://127.0.0.1:3017/health;
}
location / {
try_files $uri $uri/ /index.html;
}
}
Активировать:
sudo ln -sf /etc/nginx/sites-available/admin.obsidians.otc.guru /etc/nginx/sites-enabled/admin.obsidians.otc.guru
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d admin.obsidians.otc.guru
Basic Auth для человека
sudo apt-get install -y apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd-duck-admin leonid
Это защита входа в админку через браузер.
Bearer token между Nginx и API
Backend API читает token из:
/etc/duck-garden-panel.env
Создать token:
TOKEN="$(openssl rand -hex 32)"
echo "$TOKEN"
В env-файле:
PORT=3017
DUCK_PANEL_TOKEN=long-random-token
DUCK_RUNNER_DIR=/home/supervisor/leonid_projects/duck-obsidian/.deploy
DUCK_GARDENS_BASE_DIR=/home/supervisor/leonid_projects/obsidians
DUCK_GARDEN_DOMAIN_ROOT=obsidians.otc.guru
DUCK_GARDEN_GITHUB_OWNER=leo-mmmmmmm
DUCK_GARDEN_ENGINE_VERSION=1.0.18
DUCK_GARDEN_PORT_START=8089
DUCK_GARDEN_PORT_END=8999
DUCK_CERTBOT_EMAIL=leo.mikhaylov.2000@gmail.com
DUCK_GARDEN_AUTO_HTTPS=true
DUCK_GITHUB_TOKEN=
Этот же token должен быть в Nginx:
proxy_set_header Authorization "Bearer long-random-token";
Браузер не должен знать DUCK_PANEL_TOKEN. Его подставляет только Nginx.
Проверить API из сервера
TOKEN="$(sudo awk -F= '$1=="DUCK_PANEL_TOKEN"{print $2}' /etc/duck-garden-panel.env)"
curl -s \
-H "Authorization: Bearer $TOKEN" \
http://127.0.0.1:3017/api/gardens
Ожидаемо:
{
"items": []
}
или список gardens.
Service API
Проверить:
sudo systemctl status duck-garden-panel-api --no-pager
sudo journalctl -u duck-garden-panel-api -n 100 --no-pager
Перезапустить:
sudo systemctl restart duck-garden-panel-api
Частые проблемы
401 Unauthorized
API не получил правильный Bearer token.
Проверить напрямую:
TOKEN="$(sudo awk -F= '$1=="DUCK_PANEL_TOKEN"{print $2}' /etc/duck-garden-panel.env)"
curl -s \
-H "Authorization: Bearer $TOKEN" \
http://127.0.0.1:3017/api/gardens
Если напрямую работает, а через домен нет — проверить proxy_set_header Authorization в Nginx.
504 Gateway Time-out
Создание garden или rebuild могут идти дольше стандартного timeout.
В location /api/ должны быть длинные timeouts:
proxy_connect_timeout 60s;
proxy_send_timeout 900s;
proxy_read_timeout 900s;
send_timeout 900s;
После изменения:
sudo nginx -t
sudo systemctl reload nginx
Next build падает из-за backup .tsx
Проверить:
find . -name "*.old.tsx" -o -name "*.backup.tsx" -o -name "*.bak.tsx"
Backup-файлы нужно вынести из проекта или удалить.
Дальше: backend API панели.