Compare commits
34 Commits
f7d0ce2137
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 9e218fe87d | |||
| 5b1191b398 | |||
| 1a878d5e98 | |||
| 134a142774 | |||
| 0d25cbe8b8 | |||
| d3e783f512 | |||
|
|
e2cbac051a | ||
| 43e271733b | |||
|
|
20e1f3fa6c | ||
|
|
d4f3a10d0d | ||
| ec5f55a897 | |||
| cfaf1e8f45 | |||
| 0f31a7eee6 | |||
| f2a00f328f | |||
| 1ab4f4412d | |||
| 7c043afd4f | |||
|
|
7b2415eeda | ||
| b1220f1d2e | |||
| d953f87c92 | |||
| 1ee7afb4b9 | |||
| ae1cf8f430 | |||
|
|
0569bd5a0f | ||
|
|
5919c0123e | ||
| 06b25a17f9 | |||
| feb25cf4ad | |||
| 4b89753c3e | |||
|
|
885ae70062 | ||
| 79c8a9fea9 | |||
|
|
8e890ebfd2 | ||
|
|
f3c859a1d8 | ||
| eb90e621cc | |||
| 33f6c34d36 | |||
| 04cb863bd9 | |||
| 976bedbdbd |
@@ -35,9 +35,7 @@
|
||||
"useInternalPlugins": false
|
||||
},
|
||||
"Работа": "LiPcCase",
|
||||
"Интеграция СУП": "🤢",
|
||||
"Мама": "👩👦",
|
||||
"Другое": "📔",
|
||||
"Личное": "🧑",
|
||||
"Япония": "🎎"
|
||||
}
|
||||
126
BPMSoft CRM — RAG поиск по коду.md
Normal file
126
BPMSoft CRM — RAG поиск по коду.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# BPMSoft CRM — RAG поиск по коду
|
||||
|
||||
Семантический поиск по кодовой базе проекта `C:\Work\BPMSoft\crm`.
|
||||
Стек: **Qdrant** (векторная БД) + **Ollama nomic-embed-text** (эмбеддинги) + **MCP сервер** для Claude Code + **веб-интерфейс**.
|
||||
|
||||
---
|
||||
|
||||
## Инфраструктура
|
||||
|
||||
| Компонент | Адрес | Описание |
|
||||
| ---------------- | --------------------------------- | ------------------------ |
|
||||
| Qdrant | `http://localhost:6333` | Векторная БД, Docker |
|
||||
| Qdrant Dashboard | `http://localhost:6333/dashboard` | Веб-интерфейс Qdrant |
|
||||
| Ollama | `http://localhost:11434` | Локальные эмбеддинги |
|
||||
| Веб-поиск | `http://localhost:8765` | Интерфейс поиска по коду |
|
||||
|
||||
Файлы проекта: `C:\Work\BPMSoft\crm\.rag\`
|
||||
|
||||
---
|
||||
|
||||
## Команды
|
||||
|
||||
### Запустить Qdrant (Docker)
|
||||
```bash
|
||||
docker start qdrant
|
||||
```
|
||||
> Контейнер настроен на `restart=always` — стартует автоматически вместе с Docker.
|
||||
|
||||
### Запустить веб-интерфейс поиска
|
||||
```bash
|
||||
python C:\Work\BPMSoft\crm\.rag\search_server.py
|
||||
```
|
||||
Открыть в браузере: `http://localhost:8765`
|
||||
|
||||
### Инкрементальное обновление индекса (только изменённые файлы)
|
||||
```bash
|
||||
python C:\Work\BPMSoft\crm\.rag\index_incremental.py
|
||||
```
|
||||
Запускать после изменения/добавления файлов в проекте. Работает быстро — обрабатывает только изменённые файлы.
|
||||
|
||||
### Полная переиндексация (редко, при крупных изменениях)
|
||||
```bash
|
||||
python C:\Work\BPMSoft\crm\.rag\index_codebase.py --reindex
|
||||
```
|
||||
> Занимает несколько часов — пересоздаёт всю коллекцию с нуля.
|
||||
|
||||
---
|
||||
|
||||
## Что индексируется
|
||||
|
||||
### C# (`BPMSoft.Configuration`)
|
||||
- Методы, конструкторы → тип `method`
|
||||
- Классы, структуры → тип `class` / `struct`
|
||||
- Интерфейсы → тип `interface`
|
||||
- Enum'ы → тип `enum`
|
||||
- XML doc-комментарии включены в контекст
|
||||
|
||||
### JavaScript (`BPMSoft.Configuration`)
|
||||
- ExtJS BPMSoft схемы (`/Schemas/*.js`) → тип `extjs_schema`
|
||||
- Методы внутри схем → тип `extjs_method`
|
||||
- Mixins схем → тип `extjs_mixins`
|
||||
- Angular/src файлы (`/Files/src/js/`) → `function`, `js_class`, `js_method`
|
||||
- Autogenerated JS платформы (`/Autogenerated/Src/`)
|
||||
|
||||
### Исключено из индекса
|
||||
- `SvnPackages/` — SVN пакеты
|
||||
- `node_modules/`, `bin/`, `obj/`, `dist/`
|
||||
- `*.min.js` — минифицированные файлы
|
||||
- Angular build cache `/.nx/`
|
||||
|
||||
---
|
||||
|
||||
## MCP сервер для Claude Code
|
||||
|
||||
Зарегистрирован автоматически. Доступные инструменты:
|
||||
|
||||
| Инструмент | Описание |
|
||||
|------------|----------|
|
||||
| `search_codebase` | Семантический поиск по запросу |
|
||||
| `find_symbol` | Поиск класса/метода по имени |
|
||||
| `find_in_namespace` | Все символы в namespace или по пути |
|
||||
|
||||
### Регистрация вручную (если слетела)
|
||||
```bash
|
||||
claude mcp add --transport stdio crm-rag -- cmd /c python C:\Work\BPMSoft\crm\.rag\mcp_server.py
|
||||
```
|
||||
|
||||
### Проверить статус
|
||||
```bash
|
||||
claude mcp list
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Файлы
|
||||
|
||||
```
|
||||
C:\Work\BPMSoft\crm\.rag\
|
||||
├── index_codebase.py # Полная индексация
|
||||
├── index_incremental.py # Инкрементальное обновление
|
||||
├── mcp_server.py # MCP сервер для Claude Code
|
||||
├── search_server.py # Веб-сервер поиска (FastAPI)
|
||||
├── search_ui.html # Интерфейс поиска
|
||||
├── file_hashes.json # Хеши файлов для инкрементальной индексации
|
||||
└── qdrant_storage/ # Данные Qdrant (Docker volume)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Зависимости Python
|
||||
|
||||
```bash
|
||||
pip install qdrant-client tree-sitter tree-sitter-c-sharp tree-sitter-javascript requests fastapi uvicorn mcp
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Управление Docker контейнером
|
||||
|
||||
```bash
|
||||
docker ps | grep qdrant # статус
|
||||
docker stop qdrant # остановить
|
||||
docker start qdrant # запустить
|
||||
docker logs qdrant # логи
|
||||
docker restart qdrant # перезапустить
|
||||
```
|
||||
0
Companies.md
Normal file
0
Companies.md
Normal file
202
Dev/Cosmo Studio.md
Normal file
202
Dev/Cosmo Studio.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# Cosmo Studio — Пиксельный офис агентов
|
||||
|
||||
> Веб-дашборд в реальном времени: Cosmo, Люся и Claude Coding как пиксельные персонажи в виртуальном офисе.
|
||||
|
||||
## Концепция
|
||||
|
||||
Открываешь браузер → видишь офис. Я пишу тебе ответ → мой персонаж печатает за компьютером. Агент закончил работу → идёт на диван в зону отдыха. Люся думает → её персонаж чешет голову.
|
||||
|
||||
**Стек:**
|
||||
- Frontend: React + Canvas 2D (пиксель-арт офис)
|
||||
- Backend: Node.js + WebSocket (мост между OpenClaw и браузером)
|
||||
- Хостинг: VM Сервисы → `studio.digital-home.site`
|
||||
- Спрайты: из репозитория AgentRoom (MIT лицензия)
|
||||
|
||||
---
|
||||
|
||||
## Этапы
|
||||
|
||||
### Этап 0 — Подготовка (1-2 дня)
|
||||
|
||||
**0.1 Открыть OpenClaw API для VM Сервисов**
|
||||
- Сейчас `gateway.bind = "lan"` — уже слушает на LAN интерфейсе (192.168.31.103:18789)
|
||||
- VM Сервисы (192.168.31.60) должна быть в той же сети → проверить пинг
|
||||
- Если не достучаться: включить `gateway.bind = "lan"` явно + проверить firewall
|
||||
- Аутентификация: токен уже настроен в конфиге
|
||||
|
||||
**0.2 Скачать спрайты из AgentRoom**
|
||||
Репозиторий: https://github.com/liuyixin-louis/agentroom
|
||||
Нужные файлы:
|
||||
- `agentroom-visual/public/assets/` — тайлсеты офиса (SkyOffice: FloorAndGround, Modern_Office)
|
||||
- `agentroom-visual/public/assets/characters/` — спрайты персонажей (JIK-A-4 Metro City)
|
||||
- Каждый персонаж: 4 направления × 3 кадра = 12 спрайтов (idle, walk, type)
|
||||
|
||||
**0.3 Назначить персонажей агентам**
|
||||
| Агент | Персонаж | Цвет |
|
||||
|-------|----------|------|
|
||||
| Cosmo (main) | Синий character | #3B82F6 |
|
||||
| Люся (wife) | Розовый character | #EC4899 |
|
||||
| Claude Coding | Зелёный character | #10B981 |
|
||||
| Claude Research | Фиолетовый character | #8B5CF6 |
|
||||
|
||||
---
|
||||
|
||||
### Этап 1 — OpenClaw Bridge (2-3 дня)
|
||||
|
||||
**Задача:** Node.js сервис на VM Сервисы, который подключается к OpenClaw WebSocket API и транслирует события агентов.
|
||||
|
||||
**Структура:** `/opt/digital-home/cosmo-studio/bridge/`
|
||||
|
||||
```
|
||||
bridge/
|
||||
├── index.js # WebSocket клиент к OpenClaw
|
||||
├── state.js # Состояние всех агентов
|
||||
├── server.js # WebSocket сервер → браузер
|
||||
└── parser.js # Разбор JSONL событий
|
||||
```
|
||||
|
||||
**Логика определения состояния агента:**
|
||||
|
||||
OpenClaw sessions API: `GET http://192.168.31.103:18789/sessions`
|
||||
WebSocket events: `ws://192.168.31.103:18789`
|
||||
|
||||
Из JSONL событий:
|
||||
```
|
||||
toolCall → agent = "typing" (пишет)
|
||||
toolResult → agent = "reading" (читает/думает)
|
||||
text block → agent = "sending" (отправляет)
|
||||
session idle → agent = "idle" (свободен)
|
||||
session running → agent = "working"
|
||||
```
|
||||
|
||||
**Состояния персонажа:**
|
||||
- `idle` → сидит за столом, анимация дыхания
|
||||
- `typing` → руки на клавиатуре, быстрая анимация
|
||||
- `thinking` → смотрит в экран, медленная анимация
|
||||
- `walking` → движется по офису (BFS pathfinding)
|
||||
- `break` → на диване в Break Room
|
||||
- `waiting` → speech bubble "⏳"
|
||||
|
||||
---
|
||||
|
||||
### Этап 2 — Офисный движок (3-4 дня)
|
||||
|
||||
**Задача:** React + Canvas 2D рендерер с тайлсетами и персонажами.
|
||||
|
||||
**Структура:** `/opt/digital-home/cosmo-studio/frontend/`
|
||||
|
||||
```
|
||||
src/
|
||||
├── engine/
|
||||
│ ├── Renderer.ts # Canvas 2D loop (requestAnimationFrame)
|
||||
│ ├── TilesetManager.ts # Загрузка и рендер тайлов
|
||||
│ ├── Character.ts # Спрайт + анимация + позиция
|
||||
│ ├── Pathfinding.ts # BFS по офисной сетке
|
||||
│ └── OfficeLayout.ts # Карта офиса (столы, диваны, зоны)
|
||||
├── components/
|
||||
│ ├── Office.tsx # Основной Canvas компонент
|
||||
│ ├── AgentCard.tsx # Карточка агента (статус, токены)
|
||||
│ └── EventFeed.tsx # Лента событий (последние действия)
|
||||
├── hooks/
|
||||
│ └── useAgentEvents.ts # WebSocket → состояния агентов
|
||||
└── App.tsx
|
||||
```
|
||||
|
||||
**Офисная карта (32×24 тайла, каждый 32px = 1024×768px):**
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ [💻 Desk Cosmo] [💻 Desk Люся] │ ← Work Room
|
||||
│ [💻 Desk Coding] [💻 Desk Res] │
|
||||
├─────────────────────────────────┤
|
||||
│ [🛋️ Couch] [🌱 Plant] [TV] │ ← Break Room
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Логика переходов:**
|
||||
- Агент стал `working` → персонаж идёт к своему столу (BFS)
|
||||
- Агент стал `idle` → персонаж идёт в Break Room
|
||||
- Агент `typing` → анимация печати
|
||||
- Два агента встретились → speech bubble "👋"
|
||||
|
||||
---
|
||||
|
||||
### Этап 3 — UI панели (1-2 дня)
|
||||
|
||||
**Боковая панель:**
|
||||
- Список агентов: имя + статус + текущее действие
|
||||
- Токены: потрачено сегодня, неделя
|
||||
- Последнее сообщение (первые 60 символов)
|
||||
|
||||
**Нижняя панель — лента событий:**
|
||||
```
|
||||
17:42 Cosmo → отвечает Даниилу (telegram)
|
||||
17:41 Coding → читает файл main.go
|
||||
17:40 Люся → обрабатывает heartbeat
|
||||
```
|
||||
|
||||
**Верхняя панель:**
|
||||
- Дата/время
|
||||
- Кнопка "Open in Telegram" → deep link
|
||||
- Индикатор здоровья системы
|
||||
|
||||
---
|
||||
|
||||
### Этап 4 — Деплой (1 день)
|
||||
|
||||
```yaml
|
||||
# /opt/digital-home/cosmo-studio/docker-compose.yml
|
||||
services:
|
||||
cosmo-studio:
|
||||
build: .
|
||||
ports:
|
||||
- "3400:3400"
|
||||
environment:
|
||||
- OPENCLAW_URL=ws://192.168.31.103:18789
|
||||
- OPENCLAW_TOKEN=${OPENCLAW_TOKEN}
|
||||
networks:
|
||||
- services_proxy
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
services_proxy:
|
||||
external: true
|
||||
```
|
||||
|
||||
NPM proxy host: `studio.digital-home.site` → `cosmo-studio:3400`
|
||||
|
||||
---
|
||||
|
||||
## Что нужно решить заранее
|
||||
|
||||
1. **OpenClaw WebSocket API** — какие именно события транслирует, нужно изучить документацию `/home/daniil/.npm-global/lib/node_modules/openclaw/docs`
|
||||
|
||||
2. **Firewall между VPS и VM Сервисы** — сейчас VM Сервисы не видит gateway. Вариант: открыть порт 18789 в ufw на VPS, или использовать SSH tunnel.
|
||||
|
||||
3. **Спрайты** — нужно клонировать репо и выбрать конкретные файлы из `agentroom-visual/public/assets/`
|
||||
|
||||
4. **Аутентификация дашборда** — добавить basic auth через NPM или JWT
|
||||
|
||||
---
|
||||
|
||||
## Оценка времени
|
||||
|
||||
| Этап | Работа |
|
||||
|------|--------|
|
||||
| 0. Подготовка | 1-2 дня |
|
||||
| 1. Bridge сервис | 2-3 дня |
|
||||
| 2. Офисный движок | 3-4 дня |
|
||||
| 3. UI панели | 1-2 дня |
|
||||
| 4. Деплой | 1 день |
|
||||
| **Итого** | **~2 недели** |
|
||||
|
||||
---
|
||||
|
||||
## Статус
|
||||
|
||||
- [ ] Этап 0: Подготовка
|
||||
- [ ] Этап 1: Bridge сервис
|
||||
- [ ] Этап 2: Офисный движок
|
||||
- [ ] Этап 3: UI панели
|
||||
- [ ] Этап 4: Деплой
|
||||
|
||||
*Создано: 2026-03-27*
|
||||
543
Dev/Flutter/Roadmap.md
Normal file
543
Dev/Flutter/Roadmap.md
Normal file
@@ -0,0 +1,543 @@
|
||||
---
|
||||
title: "Flutter & Dart Roadmap"
|
||||
date: 2026-03-26
|
||||
tags:
|
||||
- flutter
|
||||
- dart
|
||||
- mobile
|
||||
- roadmap
|
||||
- learning
|
||||
description: "Подробный план изучения Flutter и Dart для опытного разработчика (C#, Go, JS)"
|
||||
---
|
||||
|
||||
# 🚀 Flutter & Dart Roadmap
|
||||
|
||||
> **Цель:** Самостоятельно создавать мобильные приложения (iOS + Android)
|
||||
> **Опыт:** C#, Go, JavaScript — базовые концепции ООП, async, типизация уже знакомы
|
||||
> **Общая оценка:** ~120–160 часов / 3–4 месяца при 8–10 ч/неделю
|
||||
|
||||
---
|
||||
|
||||
## 📋 Оглавление
|
||||
|
||||
1. [[#Этап 1 — Dart за 1 неделю|Dart за 1 неделю]]
|
||||
2. [[#Этап 2 — Flutter основы|Flutter основы (2 недели)]]
|
||||
3. [[#Этап 3 — Навигация и архитектура|Навигация и архитектура (1.5 недели)]]
|
||||
4. [[#Этап 4 — State Management|State Management (2 недели)]]
|
||||
5. [[#Этап 5 — Работа с данными|Работа с данными (2 недели)]]
|
||||
6. [[#Этап 6 — UI мастерство|UI мастерство (1.5 недели)]]
|
||||
7. [[#Этап 7 — Нативные возможности|Нативные возможности (1 неделя)]]
|
||||
8. [[#Этап 8 — Тестирование и CI/CD|Тестирование и CI/CD (1 неделя)]]
|
||||
9. [[#Этап 9 — Публикация|Публикация в Store (1 неделя)]]
|
||||
10. [[#Этап 10 — Реальный проект|Реальный проект (4–6 недель)]]
|
||||
11. [[#Ресурсы — Каталог|Каталог ресурсов]]
|
||||
|
||||
---
|
||||
|
||||
## Этап 1 — Dart за 1 неделю
|
||||
|
||||
⏱ **~8–12 часов** | С опытом в C# и JS пойдёт быстро
|
||||
|
||||
Dart — типизированный язык, похожий на гибрид C# и TypeScript. Основные отличия: null safety, mixins, extensions, Futures/Streams (аналог Task/Promise).
|
||||
|
||||
### Что изучить
|
||||
|
||||
- [x] Синтаксис: переменные, типы, `final`/`const`, `late` ✅ 2026-03-26
|
||||
- [x] Null safety (`?`, `!`, `??`, `?.`) ✅ 2026-03-26
|
||||
- [ ] Классы, наследование, mixins, abstract classes
|
||||
- [ ] Extensions (привет, C# extension methods)
|
||||
- [ ] Enums (enhanced enums с методами — Dart 3)
|
||||
- [ ] Generics (знакомо из C#)
|
||||
- [ ] Collections: `List`, `Map`, `Set` + spread operator
|
||||
- [ ] `async`/`await`, `Future`, `Stream`
|
||||
- [ ] Pattern matching и sealed classes (Dart 3) — аналог switch expressions в C#
|
||||
- [ ] Records (аналог tuples/анонимных типов)
|
||||
- [ ] Error handling: `try`/`catch`/`on`
|
||||
|
||||
### Ресурсы
|
||||
|
||||
- [ ] 📖 [Dart Language Tour](https://dart.dev/language) — **главный ресурс**, пробежать за 3–4 часа
|
||||
- [ ] 📖 [Dart Codelabs](https://dart.dev/codelabs) — интерактивные упражнения
|
||||
- [ ] 🎮 [DartPad](https://dartpad.dev/) — онлайн-песочница для экспериментов
|
||||
- [ ] 📹 [Dart in 100 Seconds — Fireship](https://www.youtube.com/watch?v=NrO0CJCbYLA) — быстрый обзор
|
||||
- [ ] 📖 [Effective Dart](https://dart.dev/effective-dart) — стайл-гайд и идиомы
|
||||
|
||||
### 🛠 Мини-проект
|
||||
|
||||
**CLI-утилита на Dart** — парсер JSON/CSV, конвертер валют через API, или простой todo-list в терминале. Цель: потрогать язык руками.
|
||||
|
||||
```bash
|
||||
dart create my_cli_app
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Этап 2 — Flutter основы
|
||||
|
||||
⏱ **~16–20 часов / 2 недели**
|
||||
|
||||
### Что изучить
|
||||
|
||||
- [ ] Установка Flutter SDK + настройка IDE (VS Code / Android Studio)
|
||||
- [ ] Эмуляторы: Android (AVD) + iOS Simulator (если есть Mac)
|
||||
- [ ] Структура проекта Flutter: `lib/`, `pubspec.yaml`, `assets/`
|
||||
- [ ] **Widget tree** — всё является виджетом
|
||||
- [ ] `StatelessWidget` vs `StatefulWidget` + `setState()`
|
||||
- [ ] `BuildContext` и жизненный цикл виджетов
|
||||
- [ ] Основные виджеты: `Text`, `Container`, `Column`, `Row`, `Stack`, `ListView`, `GridView`
|
||||
- [ ] `Scaffold`, `AppBar`, `BottomNavigationBar`, `Drawer`
|
||||
- [ ] Layout: `Expanded`, `Flexible`, `SizedBox`, `Padding`, `Align`
|
||||
- [ ] Input: `TextField`, `Form`, `FormField`, валидация
|
||||
- [ ] Кнопки: `ElevatedButton`, `TextButton`, `IconButton`, `FloatingActionButton`
|
||||
- [ ] `Image`, `Icon`, работа с assets
|
||||
- [ ] Material Design 3 и `ThemeData`
|
||||
- [ ] **Hot Reload** — главная суперсила Flutter
|
||||
|
||||
### Ресурсы
|
||||
|
||||
- [ ] 📖 [Flutter Get Started](https://docs.flutter.dev/get-started) — офиц. туториал установки
|
||||
- [ ] 📖 [Flutter Widget Catalog](https://docs.flutter.dev/ui/widgets) — каталог виджетов с примерами
|
||||
- [ ] 📖 [Flutter Codelabs](https://docs.flutter.dev/codelabs) — пошаговые лабы от Google
|
||||
- [ ] 📹 [Flutter Crash Course for Beginners — Traversy Media](https://www.youtube.com/watch?v=1ukSR1GRtMU) — 1 час, быстрый старт
|
||||
- [ ] 📹 [Flutter Full Course — Mitch Koko](https://www.youtube.com/watch?v=TclK5gNM_PM) — от начала до продвинутого
|
||||
- [ ] 📹 [Flutter Widget of the Week — Google](https://www.youtube.com/playlist?list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG) — короткие видео по виджетам
|
||||
- [ ] 📖 [Flutter Layout Cheat Sheet](https://medium.com/flutter-community/flutter-layout-cheat-sheet-5363348d037e)
|
||||
|
||||
### 🛠 Пет-проект: Визитка / Портфолио
|
||||
|
||||
Простое приложение-визитка с несколькими экранами:
|
||||
- [ ] Главный экран с аватаром, именем, описанием
|
||||
- [ ] Страница с контактами (ссылки, email)
|
||||
- [ ] Тёмная/светлая тема
|
||||
|
||||
---
|
||||
|
||||
## Этап 3 — Навигация и архитектура
|
||||
|
||||
⏱ **~12–15 часов / 1.5 недели**
|
||||
|
||||
### Что изучить
|
||||
|
||||
- [ ] `Navigator` 1.0: `push`, `pop`, named routes
|
||||
- [ ] `Navigator` 2.0 и декларативная навигация
|
||||
- [ ] **go_router** — стандарт навигации в 2025+ (рекомендован Google)
|
||||
- [ ] Deep links и параметры в маршрутах
|
||||
- [ ] Вложенная навигация (Shell routes, tab navigation)
|
||||
- [ ] Передача данных между экранами
|
||||
- [ ] Структура проекта:
|
||||
- Feature-first vs Layer-first
|
||||
- Рекомендуемая: `lib/features/<name>/{data, domain, presentation}/`
|
||||
- [ ] Dependency Injection: `get_it` + `injectable`
|
||||
- [ ] Repository pattern (знакомо из C#)
|
||||
|
||||
### Ресурсы
|
||||
|
||||
- [ ] 📖 [go_router docs](https://pub.dev/packages/go_router) — офиц. документация
|
||||
- [ ] 📖 [Flutter Navigation Guide](https://docs.flutter.dev/ui/navigation) — гайд от Google
|
||||
- [ ] 📹 [go_router Tutorial — Andrea Bizzotto](https://codewithandrea.com/articles/flutter-navigation-gorouter-go-vs-push/) — подробный разбор
|
||||
- [ ] 📖 [Flutter App Architecture — Andrea Bizzotto](https://codewithandrea.com/articles/flutter-app-architecture-riverpod-introduction/) — feature-first структура
|
||||
- [ ] 📹 [Flutter Project Structure — Reso Coder](https://www.youtube.com/watch?v=KjE2IDphA_U)
|
||||
|
||||
### 🛠 Пет-проект: Мульти-экранное приложение
|
||||
|
||||
Приложение-справочник (рецепты / заметки / фильмы):
|
||||
- [ ] Список элементов → детальный экран
|
||||
- [ ] go_router с параметрами
|
||||
- [ ] Bottom navigation с 3+ табами
|
||||
- [ ] Поиск и фильтрация
|
||||
|
||||
---
|
||||
|
||||
## Этап 4 — State Management
|
||||
|
||||
⏱ **~16–20 часов / 2 недели** | Самая важная тема
|
||||
|
||||
### Подходы (от простого к сложному)
|
||||
|
||||
- [ ] `setState` — для локального состояния
|
||||
- [ ] `InheritedWidget` — как работает "магия" под капотом
|
||||
- [ ] **Provider** — простой и понятный (хорош для старта)
|
||||
- [ ] **Riverpod** ⭐ — эволюция Provider, **рекомендация 2025+**
|
||||
- Compile-safe, testable, не зависит от BuildContext
|
||||
- `ref.watch`, `ref.read`, `ref.listen`
|
||||
- Providers: `Provider`, `StateProvider`, `NotifierProvider`, `AsyncNotifierProvider`, `FutureProvider`, `StreamProvider`
|
||||
- [ ] **BLoC** — для больших enterprise-приложений
|
||||
- Events → BLoC → States
|
||||
- Знакомый паттерн если работал с Redux/MediatR
|
||||
- [ ] Когда что использовать:
|
||||
- Маленькое приложение → Riverpod
|
||||
- Большое/командное → BLoC
|
||||
- Прототип → setState + Provider
|
||||
|
||||
### Ресурсы
|
||||
|
||||
- [ ] 📖 [Flutter State Management Guide](https://docs.flutter.dev/data-and-backend/state-mgmt/intro) — офиц. обзор
|
||||
- [ ] 📖 [Riverpod Documentation](https://riverpod.dev/) — **начни с этого**
|
||||
- [ ] 📹 [Riverpod 2.0 — Complete Guide — Andrea Bizzotto](https://codewithandrea.com/articles/flutter-state-management-riverpod/) — лучший гайд
|
||||
- [ ] 📹 [Flutter Riverpod Tutorial — Vandad Nahavandipoor](https://www.youtube.com/watch?v=vtGCteFYs4M)
|
||||
- [ ] 📖 [BLoC Library](https://bloclibrary.dev/) — офиц. сайт с туториалами
|
||||
- [ ] 📹 [BLoC Tutorial — Reso Coder](https://www.youtube.com/watch?v=THCkkQ-V1-8)
|
||||
- [ ] 📖 [Provider Package](https://pub.dev/packages/provider) — документация
|
||||
|
||||
### 🛠 Пет-проект: Todo App (с архитектурой)
|
||||
|
||||
- [ ] CRUD задач с Riverpod
|
||||
- [ ] Фильтры: все / активные / завершённые
|
||||
- [ ] Persistence (SharedPreferences или Hive)
|
||||
- [ ] Clean Architecture: Data → Domain → Presentation
|
||||
- [ ] Unit-тесты для бизнес-логики
|
||||
|
||||
---
|
||||
|
||||
## Этап 5 — Работа с данными
|
||||
|
||||
⏱ **~16–20 часов / 2 недели**
|
||||
|
||||
### HTTP и API
|
||||
|
||||
- [ ] Пакет `http` — базовые запросы
|
||||
- [ ] **Dio** — продвинутый HTTP-клиент (interceptors, retry, cancel)
|
||||
- [ ] Сериализация JSON: `json_serializable` + `build_runner`
|
||||
- [ ] **Freezed** — генерация data-классов и union types
|
||||
- [ ] Обработка ошибок сети: `Result` pattern, `Either`
|
||||
- [ ] Retrofit (знакомо из .NET!) — генерация API-клиента
|
||||
|
||||
### Локальное хранение
|
||||
|
||||
- [ ] `SharedPreferences` — key-value (как LocalStorage)
|
||||
- [ ] **Hive** — быстрая NoSQL база
|
||||
- [ ] **Drift** (бывший Moor) — type-safe SQLite ORM
|
||||
- [ ] `sqflite` — SQLite напрямую
|
||||
- [ ] `flutter_secure_storage` — для токенов/паролей
|
||||
|
||||
### Firebase (бесплатный tier)
|
||||
|
||||
- [ ] Firebase Auth — аутентификация
|
||||
- [ ] Cloud Firestore — NoSQL база
|
||||
- [ ] Firebase Storage — файлы
|
||||
- [ ] Firebase Messaging (FCM) — push-нотификации
|
||||
- [ ] [FlutterFire](https://firebase.flutter.dev/) — офиц. плагины
|
||||
|
||||
### Ресурсы
|
||||
|
||||
- [ ] 📖 [Flutter Networking Guide](https://docs.flutter.dev/data-and-backend/networking)
|
||||
- [ ] 📖 [Dio Package](https://pub.dev/packages/dio) — документация
|
||||
- [ ] 📖 [Freezed Package](https://pub.dev/packages/freezed) — генерация моделей
|
||||
- [ ] 📖 [FlutterFire Docs](https://firebase.flutter.dev/) — Firebase для Flutter
|
||||
- [ ] 📹 [Flutter REST API Tutorial — Vandad](https://www.youtube.com/watch?v=CQuxU8JGJnQ)
|
||||
- [ ] 📹 [Firebase Flutter Course — freeCodeCamp](https://www.youtube.com/watch?v=wUSkeTaBonA) — 5+ часов
|
||||
- [ ] 📖 [Drift Documentation](https://drift.simonbinder.eu/docs/getting-started/)
|
||||
|
||||
### 🛠 Пет-проект: Погодное приложение
|
||||
|
||||
- [ ] Запрос к Open-Meteo или OpenWeatherMap API
|
||||
- [ ] Модели через `freezed` + `json_serializable`
|
||||
- [ ] Поиск города, текущая погода + прогноз на 5 дней
|
||||
- [ ] Кэширование последнего запроса в Hive
|
||||
- [ ] Pull-to-refresh
|
||||
- [ ] Красивый UI с анимациями погоды
|
||||
|
||||
---
|
||||
|
||||
## Этап 6 — UI мастерство
|
||||
|
||||
⏱ **~12–15 часов / 1.5 недели**
|
||||
|
||||
### Что изучить
|
||||
|
||||
- [ ] Animations: implicit (`AnimatedContainer`, `AnimatedOpacity`) и explicit (`AnimationController`, `Tween`)
|
||||
- [ ] Hero animations (переходы между экранами)
|
||||
- [ ] Custom Paint — рисование кастомных элементов
|
||||
- [ ] `Sliver` виджеты: `CustomScrollView`, `SliverAppBar`, `SliverList`, `SliverGrid`
|
||||
- [ ] Responsive design: `LayoutBuilder`, `MediaQuery`, `OrientationBuilder`
|
||||
- [ ] Adaptive UI: Material (Android) + Cupertino (iOS)
|
||||
- [ ] Custom widgets: composition vs inheritance
|
||||
- [ ] Themes и дизайн-система (typography, color schemes, spacing)
|
||||
- [ ] Пакеты для UI:
|
||||
- `flutter_animate` — декларативные анимации
|
||||
- `shimmer` — loading placeholders
|
||||
- `cached_network_image` — кэширование картинок
|
||||
- `flutter_svg` — SVG поддержка
|
||||
|
||||
### Ресурсы
|
||||
|
||||
- [ ] 📖 [Flutter Animations Guide](https://docs.flutter.dev/ui/animations)
|
||||
- [ ] 📹 [Flutter Animations Course — Flutter Official](https://www.youtube.com/watch?v=IVTjpW3W33s)
|
||||
- [ ] 📖 [Flutter Adaptive Design](https://docs.flutter.dev/ui/adaptive-responsive)
|
||||
- [ ] 📹 [Sliver Widgets — Flutter](https://www.youtube.com/watch?v=Mz3kHQxBjGg)
|
||||
- [ ] 📖 [Material 3 in Flutter](https://docs.flutter.dev/ui/design/material)
|
||||
|
||||
### 🛠 Пет-проект: Клон UI известного приложения
|
||||
|
||||
Выбери и воспроизведи UI (без бэкенда):
|
||||
- [ ] Spotify / Netflix / Twitter — карточки, списки, анимации
|
||||
- [ ] Кастомные анимации переходов
|
||||
- [ ] Адаптивный дизайн под разные размеры экрана
|
||||
- [ ] Тёмная и светлая темы
|
||||
|
||||
---
|
||||
|
||||
## Этап 7 — Нативные возможности
|
||||
|
||||
⏱ **~8–10 часов / 1 неделя**
|
||||
|
||||
### Что изучить
|
||||
|
||||
- [ ] Platform channels — вызов нативного кода (Swift/Kotlin)
|
||||
- [ ] Камера: `camera`, `image_picker`
|
||||
- [ ] Геолокация: `geolocator`, `geocoding`
|
||||
- [ ] Карты: `google_maps_flutter` или `flutter_map` (OpenStreetMap)
|
||||
- [ ] Push-уведомления: `firebase_messaging` + `flutter_local_notifications`
|
||||
- [ ] Permissions: `permission_handler`
|
||||
- [ ] Biometrics: `local_auth`
|
||||
- [ ] Deep links и Universal links
|
||||
- [ ] Sharing: `share_plus`
|
||||
- [ ] URL launcher: `url_launcher`
|
||||
|
||||
### Ресурсы
|
||||
|
||||
- [ ] 📖 [Flutter Platform Integration](https://docs.flutter.dev/platform-integration/platform-channels)
|
||||
- [ ] 📖 [pub.dev](https://pub.dev/) — поиск пакетов, проверяй likes и pub points
|
||||
- [ ] 📹 [Google Maps in Flutter — Johannes Milke](https://www.youtube.com/watch?v=Zz5hMvgiWmY)
|
||||
- [ ] 📖 [Flutter Camera Plugin](https://pub.dev/packages/camera)
|
||||
|
||||
### 🛠 Мини-проект: Приложение с картой
|
||||
|
||||
- [ ] Показать текущее местоположение на карте
|
||||
- [ ] Добавление маркеров / POI
|
||||
- [ ] Поиск мест
|
||||
- [ ] Разрешения runtime
|
||||
|
||||
---
|
||||
|
||||
## Этап 8 — Тестирование и CI/CD
|
||||
|
||||
⏱ **~8–10 часов / 1 неделя**
|
||||
|
||||
### Что изучить
|
||||
|
||||
- [ ] **Unit tests** — тестирование бизнес-логики и репозиториев
|
||||
- [ ] **Widget tests** — тестирование UI-компонентов
|
||||
- [ ] **Integration tests** — E2E тестирование на устройстве/эмуляторе
|
||||
- [ ] Mocking: `mocktail` или `mockito`
|
||||
- [ ] Golden tests — скриншот-тесты UI
|
||||
- [ ] Code coverage: `flutter test --coverage`
|
||||
- [ ] CI/CD:
|
||||
- GitHub Actions / Codemagic / Fastlane
|
||||
- Автоматическая сборка APK/IPA
|
||||
- Автоматическая публикация в stores
|
||||
|
||||
### Ресурсы
|
||||
|
||||
- [ ] 📖 [Flutter Testing Guide](https://docs.flutter.dev/testing) — офиц. документация
|
||||
- [ ] 📹 [Flutter Testing Tutorial — Reso Coder](https://www.youtube.com/watch?v=RDY6UYh-4dg)
|
||||
- [ ] 📖 [Codemagic CI/CD](https://docs.codemagic.io/flutter/getting-started/) — бесплатный tier для Flutter
|
||||
- [ ] 📖 [Mocktail Package](https://pub.dev/packages/mocktail)
|
||||
|
||||
### 🛠 Практика
|
||||
|
||||
- [ ] Написать тесты для Todo App из Этапа 4
|
||||
- [ ] Unit tests для API-слоя (mock HTTP)
|
||||
- [ ] Widget tests для ключевых экранов
|
||||
- [ ] Настроить CI pipeline (GitHub Actions)
|
||||
|
||||
---
|
||||
|
||||
## Этап 9 — Публикация
|
||||
|
||||
⏱ **~6–8 часов / 1 неделя**
|
||||
|
||||
### Google Play Store
|
||||
|
||||
- [ ] Создать аккаунт разработчика ($25 одноразово)
|
||||
- [ ] Подписать APK/AAB (keystore)
|
||||
- [ ] Скриншоты, описание, иконка
|
||||
- [ ] Privacy Policy (можно сгенерировать)
|
||||
- [ ] Загрузить в Google Play Console
|
||||
- [ ] Internal testing → Closed testing → Production
|
||||
|
||||
### Apple App Store
|
||||
|
||||
- [ ] Apple Developer Program ($99/год)
|
||||
- [ ] Certificates, Identifiers, Profiles
|
||||
- [ ] Archive и загрузка через Xcode / Transporter
|
||||
- [ ] App Store Connect: метаданные, скриншоты
|
||||
- [ ] TestFlight для бета-тестирования
|
||||
- [ ] Ревью Apple (строгие правила)
|
||||
|
||||
### Ресурсы
|
||||
|
||||
- [ ] 📖 [Flutter Deployment — Android](https://docs.flutter.dev/deployment/android)
|
||||
- [ ] 📖 [Flutter Deployment — iOS](https://docs.flutter.dev/deployment/ios)
|
||||
- [ ] 📹 [Publish Flutter App — Mitch Koko](https://www.youtube.com/watch?v=g0GNuoCOtaQ)
|
||||
- [ ] 📖 [Fastlane for Flutter](https://docs.flutter.dev/deployment/cd)
|
||||
|
||||
---
|
||||
|
||||
## Этап 10 — Реальный проект
|
||||
|
||||
⏱ **~40–60 часов / 4–6 недель** | Всё вместе
|
||||
|
||||
### План создания реального приложения
|
||||
|
||||
> Пример: **Personal Finance Tracker** (или любое приложение по интересу)
|
||||
|
||||
#### Фаза 1: Планирование (2–3 дня)
|
||||
- [ ] Определить MVP: 3–5 ключевых фич
|
||||
- [ ] Wireframes (можно в Figma — бесплатно)
|
||||
- [ ] Выбрать стек: Riverpod + go_router + Dio + Drift/Hive
|
||||
- [ ] Спроектировать data models
|
||||
|
||||
#### Фаза 2: Скелет (1 неделя)
|
||||
- [ ] Настроить проект с правильной структурой (feature-first)
|
||||
- [ ] Настроить DI (get_it + injectable)
|
||||
- [ ] Навигация (go_router)
|
||||
- [ ] Базовый UI каждого экрана (placeholder)
|
||||
- [ ] Тема и дизайн-система
|
||||
|
||||
#### Фаза 3: Core Features (2–3 недели)
|
||||
- [ ] Реализовать основную бизнес-логику
|
||||
- [ ] Подключить API / базу данных
|
||||
- [ ] State management для каждой фичи
|
||||
- [ ] Обработка ошибок и loading states
|
||||
- [ ] Offline-first: локальный кэш + синхронизация
|
||||
|
||||
#### Фаза 4: Polish (1 неделя)
|
||||
- [ ] Анимации и micro-interactions
|
||||
- [ ] Responsive дизайн
|
||||
- [ ] Обработка edge-cases
|
||||
- [ ] Performance: profiling с DevTools
|
||||
- [ ] Accessibility (семантика для screen readers)
|
||||
|
||||
#### Фаза 5: Launch (3–5 дней)
|
||||
- [ ] Написать unit + widget тесты (coverage >60%)
|
||||
- [ ] CI/CD pipeline
|
||||
- [ ] Подготовить store listing
|
||||
- [ ] Бета-тест через TestFlight / Internal Testing
|
||||
- [ ] Релиз 🚀
|
||||
|
||||
### Идеи для реальных проектов
|
||||
|
||||
| Проект | Чему научит |
|
||||
|--------|-------------|
|
||||
| 💰 Финансовый трекер | CRUD, графики, локальная БД, экспорт |
|
||||
| 📝 Заметки/Markdown | Редактор, файловая система, синхронизация |
|
||||
| 🏋️ Трекер тренировок | Таймеры, анимации, статистика |
|
||||
| 🍕 Доставка еды (клон) | Карты, API, корзина, навигация |
|
||||
| 📰 Новостной агрегатор | RSS, API, кэширование, push |
|
||||
| 🎵 Музыкальный плеер | Аудио, фоновое воспроизведение, UI |
|
||||
|
||||
---
|
||||
|
||||
## Ресурсы — Каталог
|
||||
|
||||
### 📖 Документация (читать первым делом)
|
||||
|
||||
| Ресурс | Описание |
|
||||
|--------|----------|
|
||||
| [dart.dev](https://dart.dev/) | Официальная документация Dart |
|
||||
| [docs.flutter.dev](https://docs.flutter.dev/) | Официальная документация Flutter |
|
||||
| [pub.dev](https://pub.dev/) | Репозиторий пакетов (как npm/nuget) |
|
||||
| [Flutter API Reference](https://api.flutter.dev/) | Полный API reference |
|
||||
| [Material 3 Guidelines](https://m3.material.io/) | Гайдлайны Material Design |
|
||||
|
||||
### 📹 YouTube каналы
|
||||
|
||||
| Канал | Описание |
|
||||
|-------|----------|
|
||||
| [Flutter Official](https://www.youtube.com/@flutterdev) | Widget of the Week, Decoding Flutter |
|
||||
| [Fireship](https://www.youtube.com/@Fireship) | Быстрые обзоры, "in 100 seconds" |
|
||||
| [Vandad Nahavandipoor](https://www.youtube.com/@VandadNP) | Google Developer Expert, подробные курсы |
|
||||
| [Reso Coder](https://www.youtube.com/@ResoCoder) | Clean Architecture, TDD, BLoC |
|
||||
| [Mitch Koko](https://www.youtube.com/@createdbykoko) | Практичные проекты от 0 до деплоя |
|
||||
| [Code With Andrea](https://www.youtube.com/@CodeWithAndrea) | Riverpod, архитектура, best practices |
|
||||
| [The Flutter Way](https://www.youtube.com/@TheFlutterWay) | Красивые UI клоны |
|
||||
| [dbestech](https://www.youtube.com/@daboratechltd) | Полные проекты с бэкендом |
|
||||
| [Johannes Milke](https://www.youtube.com/@JohannesMilke) | Короткие туториалы по конкретным фичам |
|
||||
| [freeCodeCamp](https://www.youtube.com/@freecodecamp) | Длинные полные курсы (37+ часов) |
|
||||
|
||||
### 📚 Бесплатные курсы и туториалы
|
||||
|
||||
| Ресурс | Описание |
|
||||
|--------|----------|
|
||||
| [Flutter Codelabs](https://docs.flutter.dev/codelabs) | Пошаговые лабы от Google |
|
||||
| [Dart Codelabs](https://dart.dev/codelabs) | Интерактивные упражнения по Dart |
|
||||
| [Flutter Apprentice (raywenderlich)](https://www.kodeco.com/flutter) | Бесплатные статьи и туториалы |
|
||||
| [Flutter Gems](https://fluttergems.dev/) | Каталог полезных пакетов по категориям |
|
||||
| [Awesome Flutter](https://github.com/Solido/awesome-flutter) | Кураторский список ресурсов на GitHub |
|
||||
| [Flutter Examples](https://github.com/nisrulz/flutter-examples) | Сотни примеров кода |
|
||||
| [It's All Widgets](https://itsallwidgets.com/) | Галерея Flutter-приложений с исходниками |
|
||||
|
||||
### 🧰 Инструменты
|
||||
|
||||
| Инструмент | Описание |
|
||||
|------------|----------|
|
||||
| [DartPad](https://dartpad.dev/) | Онлайн-песочница |
|
||||
| [Flutter DevTools](https://docs.flutter.dev/tools/devtools) | Профилирование, отладка, инспектор |
|
||||
| [Very Good CLI](https://github.com/VeryGoodOpenSource/very_good_cli) | Генератор проектов с best practices |
|
||||
| [Mason](https://github.com/felangel/mason) | Шаблоны кода (как Yeoman) |
|
||||
| [Widgetbook](https://www.widgetbook.io/) | Storybook для Flutter виджетов |
|
||||
|
||||
### 📦 Must-have пакеты
|
||||
|
||||
| Пакет | Категория | Описание |
|
||||
|-------|-----------|----------|
|
||||
| `riverpod` | State Management | Реактивное управление состоянием |
|
||||
| `go_router` | Навигация | Декларативный роутинг |
|
||||
| `dio` | Networking | HTTP-клиент |
|
||||
| `freezed` | Code Generation | Immutable модели |
|
||||
| `json_serializable` | Serialization | JSON ↔ Dart |
|
||||
| `hive` | Storage | NoSQL БД |
|
||||
| `drift` | Storage | SQLite ORM |
|
||||
| `get_it` | DI | Service locator |
|
||||
| `injectable` | DI | Кодогенерация для get_it |
|
||||
| `flutter_hooks` | UI | React-style hooks |
|
||||
| `cached_network_image` | UI | Кэширование картинок |
|
||||
| `flutter_svg` | UI | SVG поддержка |
|
||||
| `intl` | i18n | Локализация |
|
||||
| `mocktail` | Testing | Мокирование |
|
||||
|
||||
---
|
||||
|
||||
## 💡 Советы от опытного разработчика к опытному
|
||||
|
||||
1. **Не читай — делай.** С опытом в C#/Go/JS ты быстро схватишь синтаксис. Открывай DartPad, пиши код.
|
||||
|
||||
2. **Flutter ≠ React Native.** Здесь нет DOM. Всё — виджеты. Widget tree пересоздаётся каждый кадр (Flutter рендерит как игровой движок).
|
||||
|
||||
3. **`const` everywhere.** Flutter использует `const` конструкторы для оптимизации rebuilds. Привыкай.
|
||||
|
||||
4. **Riverpod > Provider** для новых проектов. Provider legacy, Riverpod — его автор переосмыслил подход.
|
||||
|
||||
5. **Не бойся кодогенерации.** `build_runner` — это норма. `freezed` + `json_serializable` сэкономят тонны boilerplate.
|
||||
|
||||
6. **Декомпозиция виджетов.** Если `build()` больше 50 строк — разбивай. Extract widget > extract method.
|
||||
|
||||
7. **DevTools — твой друг.** Widget Inspector, Performance, Network — используй с первого дня.
|
||||
|
||||
8. **Dart — это не JavaScript.** Null safety строгий. Sound typing. Не борись с системой типов — используй её.
|
||||
|
||||
---
|
||||
|
||||
## 📊 Timeline Summary
|
||||
|
||||
| Этап | Тема | Часы | Недели |
|
||||
|------|------|------|--------|
|
||||
| 1 | Dart | 8–12 | 1 |
|
||||
| 2 | Flutter основы | 16–20 | 2 |
|
||||
| 3 | Навигация и архитектура | 12–15 | 1.5 |
|
||||
| 4 | State Management | 16–20 | 2 |
|
||||
| 5 | Работа с данными | 16–20 | 2 |
|
||||
| 6 | UI мастерство | 12–15 | 1.5 |
|
||||
| 7 | Нативные возможности | 8–10 | 1 |
|
||||
| 8 | Тестирование | 8–10 | 1 |
|
||||
| 9 | Публикация | 6–8 | 1 |
|
||||
| 10 | Реальный проект | 40–60 | 4–6 |
|
||||
| **Итого** | | **~140–190** | **~17–19** |
|
||||
|
||||
> При 8–10 часах в неделю = **~4–5 месяцев** до первого приложения в store 🎯
|
||||
|
||||
---
|
||||
|
||||
*Создано: 2026-03-26 | Автор: Cosmo ✨*
|
||||
*Последнее обновление: 2026-03-26*
|
||||
12
Hysteria2.md
12
Hysteria2.md
@@ -1,12 +0,0 @@
|
||||
https://blitz.digital-home.site:443/eb4643570d60cb40ef62b5bc7c7b92c4/
|
||||
|
||||
19 - 100000 (ap +)
|
||||
20 - 150000 (изменение + - согласование идет) - 1 заявка
|
||||
21 - 120000 () - 1 заявка (нужно перевыпуск)
|
||||
22 - ... (успешный ответ) - 1 заявка успех, 2 заявку отправляем
|
||||
|
||||
Нужно перевыпустить (логическое - не изменяемое) - Да
|
||||
|
||||
Новая
|
||||
Зарегистрирована
|
||||
На изменении (изменение данных + согласование)
|
||||
92
Sing-box.md
Normal file
92
Sing-box.md
Normal file
@@ -0,0 +1,92 @@
|
||||
1. Конфиг
|
||||
```json
|
||||
{
|
||||
"log": {
|
||||
"level": "info"
|
||||
},
|
||||
"dns": {
|
||||
"servers": [
|
||||
{
|
||||
"tag": "google",
|
||||
"address": "https://8.8.8.8/dns-query",
|
||||
"address_strategy": "ipv4_only",
|
||||
"detour": "proxy"
|
||||
}
|
||||
],
|
||||
"strategy": "ipv4_only"
|
||||
},
|
||||
"inbounds": [
|
||||
{
|
||||
"type": "tun",
|
||||
"tag": "tun-in",
|
||||
"interface_name": "tun0",
|
||||
"address": "172.19.0.1/30",
|
||||
"mtu": 1400,
|
||||
"auto_route": true,
|
||||
"strict_route": false,
|
||||
"stack": "system",
|
||||
"route_exclude_address": [
|
||||
"192.168.31.0/24",
|
||||
"195.135.254.66/32",
|
||||
"100.64.0.0/10"
|
||||
]
|
||||
}
|
||||
],
|
||||
"outbounds": [
|
||||
{
|
||||
"type": "vless",
|
||||
"tag": "proxy",
|
||||
"server": "195.135.254.66",
|
||||
"server_port": 8888,
|
||||
"uuid": "96639c6e-553f-4389-95d6-e9e3e808f22f",
|
||||
"tls": {
|
||||
"enabled": true,
|
||||
"server_name": "www.microsoft.com",
|
||||
"utls": {
|
||||
"enabled": true,
|
||||
"fingerprint": "chrome"
|
||||
},
|
||||
"reality": {
|
||||
"enabled": true,
|
||||
"public_key": "da-vsnYvc3G8nSguWmo0ort1nWBWcFs2nWY_kAcdYjI",
|
||||
"short_id": "a1b2c3d4"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "direct",
|
||||
"tag": "direct"
|
||||
}
|
||||
],
|
||||
"route": {
|
||||
"rules": [
|
||||
{
|
||||
"protocol": "dns",
|
||||
"action": "hijack-dns"
|
||||
},
|
||||
{
|
||||
"ip_cidr": [
|
||||
"192.168.31.0/24",
|
||||
"100.64.0.0/10"
|
||||
],
|
||||
"outbound": "direct"
|
||||
}
|
||||
],
|
||||
"final": "proxy",
|
||||
"auto_detect_interface": true
|
||||
}
|
||||
}
|
||||
```
|
||||
2. Команды
|
||||
```sh
|
||||
sudo systemctl start sing-box\nsleep 3\ncurl --max-time 5 http://34.160.111.145 -H "Host: ifconfig.me"
|
||||
sudo ip route add 195.135.254.66/32 via 192.168.31.1 dev ens18 2>/dev/null true
|
||||
curl --max-time 5 ifconfig.me
|
||||
sudo systemctl restart sing-box\nsleep 2 sudo ip route add 195.135.254.66/32 via 192.168.31.1 dev ens18 2>/dev/null true\n sudo ip route add 100.64.0.0/10 via 192.168.31.1 dev ens18 2>/dev/null true\n sleep 3\n journalctl -u sing-box -n 10 --no-pager\n curl --max-time 5 ifconfig.me
|
||||
sudo iptables -t mangle -A POSTROUTING -o ens18 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1000\nsudo iptables -t mangle -A PREROUTING -i ens18 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1000\ncurl --max-time 5 http://34.160.111.145 -H "Host: ifconfig.me"
|
||||
sudo systemctl stop sing-box
|
||||
curl --max-time 5 http://34.160.111.145 -H "Host: ifconfig.me"
|
||||
sudo tcpdump -i ens18 -n 'host 195.135.254.66' -c 10 &\nsleep 1\ncurl --max-time 3 http://34.160.111.145 -H "Host: ifconfig.me"
|
||||
sudo systemctl start sing-box\nsleep 2\nsudo tcpdump -i ens18 -n 'host 195.135.254.66' -c 10 &\nsleep 1\ncurl --max-time 3 http://34.160.111.145 -H "Host: ifconfig.me"
|
||||
sudo systemctl stop sing-box
|
||||
```
|
||||
219
VPN/Marzban - план действий при блокировке.md
Normal file
219
VPN/Marzban - план действий при блокировке.md
Normal file
@@ -0,0 +1,219 @@
|
||||
# Marzban — план действий при блокировке
|
||||
|
||||
> Инфраструктура: VDS Рига `195.135.254.66`, панель `https://daniilvds.duckdns.org:2083/dashboard/`
|
||||
> Логин: `admin` / `Marzban2026!`
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Быстрая смена порта
|
||||
|
||||
### 1. Меняем порт в Marzban (xray конфиг)
|
||||
|
||||
Через браузер:
|
||||
```
|
||||
https://daniilvds.duckdns.org:2083/dashboard/
|
||||
→ Core Settings → Xray Config
|
||||
→ Меняем "port": 8888 на новый (например 9443)
|
||||
→ Save
|
||||
```
|
||||
|
||||
Или через API (с любой машины):
|
||||
```bash
|
||||
TOKEN=$(curl -s -X POST https://daniilvds.duckdns.org:2083/api/admin/token \
|
||||
-d "username=admin&password=Marzban2026!" \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" | python3 -c "import json,sys; print(json.load(sys.stdin)['access_token'])")
|
||||
|
||||
# Получить текущий конфиг
|
||||
curl -s https://daniilvds.duckdns.org:2083/api/core/config \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# Применить изменённый конфиг (меняешь port в JSON и применяешь)
|
||||
curl -s -X PUT https://daniilvds.duckdns.org:2083/api/core/config \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{ ... новый конфиг ... }'
|
||||
```
|
||||
|
||||
### 2. Пробрасываем новый порт в Docker
|
||||
|
||||
```bash
|
||||
ssh root@195.135.254.66
|
||||
|
||||
# Редактируем compose
|
||||
nano /opt/marzban/docker-compose.yml
|
||||
# Меняем "8888:8888" → "9443:9443"
|
||||
|
||||
cd /opt/marzban && docker compose up -d marzban
|
||||
```
|
||||
|
||||
### 3. Обновляем ключи пользователям
|
||||
|
||||
Ключи пользователей **обновляются автоматически** — порт меняется во всех ссылках.
|
||||
|
||||
Заходишь в панель → выбираешь пользователя → копируешь новую ссылку → отправляешь.
|
||||
|
||||
Или через API:
|
||||
```bash
|
||||
curl -s https://daniilvds.duckdns.org:2083/api/user/USERNAME \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
# В поле "links" будет актуальная ссылка с новым портом
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 👥 Управление пользователями
|
||||
|
||||
### Создать пользователя
|
||||
```bash
|
||||
curl -s -X POST https://daniilvds.duckdns.org:2083/api/user \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"username": "vasya",
|
||||
"proxies": {"vless": {}},
|
||||
"inbounds": {"VLESS_REALITY": []}
|
||||
}'
|
||||
```
|
||||
|
||||
### Получить ссылку пользователя
|
||||
```bash
|
||||
curl -s https://daniilvds.duckdns.org:2083/api/user/vasya \
|
||||
-H "Authorization: Bearer $TOKEN" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['links'][0])"
|
||||
```
|
||||
|
||||
### Удалить пользователя (отозвать доступ)
|
||||
```bash
|
||||
curl -s -X DELETE https://daniilvds.duckdns.org:2083/api/user/vasya \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
### Список всех пользователей
|
||||
```bash
|
||||
curl -s "https://daniilvds.duckdns.org:2083/api/users" \
|
||||
-H "Authorization: Bearer $TOKEN" | python3 -c "import json,sys; [print(u['username'], u['status']) for u in json.load(sys.stdin)['users']]"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔌 Добавить новый протокол (inbound)
|
||||
|
||||
Через **Core Settings → Xray Config** в панели добавляешь новый блок в `inbounds`.
|
||||
|
||||
### Shadowsocks (простой, хорошо работает через мобильный)
|
||||
```json
|
||||
{
|
||||
"tag": "SHADOWSOCKS",
|
||||
"listen": "0.0.0.0",
|
||||
"port": 8388,
|
||||
"protocol": "shadowsocks",
|
||||
"settings": {
|
||||
"clients": [],
|
||||
"network": "tcp,udp"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### VLESS + WebSocket + TLS (обходит DPI через CDN/Cloudflare)
|
||||
```json
|
||||
{
|
||||
"tag": "VLESS_WS",
|
||||
"listen": "0.0.0.0",
|
||||
"port": 8889,
|
||||
"protocol": "vless",
|
||||
"settings": {
|
||||
"clients": [],
|
||||
"decryption": "none"
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": "ws",
|
||||
"security": "none",
|
||||
"wsSettings": {
|
||||
"path": "/vpn"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
После добавления inbound — в настройках пользователя выбрать новый inbound.
|
||||
|
||||
---
|
||||
|
||||
## ⚡ Устойчивые порты (реже блокируют)
|
||||
|
||||
| Порт | Почему безопасен |
|
||||
|------|-----------------|
|
||||
| 443 | HTTPS — блокировка убьёт половину интернета |
|
||||
| 80 | HTTP — аналогично |
|
||||
| 2083 | cPanel SSL — используется хостингами |
|
||||
| 2087 | cPanel — аналогично |
|
||||
| 8443 | Альтернативный HTTPS |
|
||||
|
||||
**Переехать на 443:**
|
||||
1. Остановить Outline/shadowbox: `docker stop shadowbox`
|
||||
2. Сменить порт Marzban на 443 (через панель + compose)
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Полезные команды на сервере
|
||||
|
||||
```bash
|
||||
ssh root@195.135.254.66
|
||||
|
||||
# Статус контейнеров
|
||||
cd /opt/marzban && docker compose ps
|
||||
|
||||
# Логи Marzban
|
||||
docker logs marzban-marzban-1 --tail 50
|
||||
|
||||
# Логи Caddy (SSL)
|
||||
docker logs marzban-caddy-1 --tail 20
|
||||
|
||||
# Перезапуск Marzban
|
||||
docker compose restart marzban
|
||||
|
||||
# Перезапуск всего стека
|
||||
docker compose restart
|
||||
|
||||
# Обновить образ Marzban
|
||||
docker compose pull && docker compose up -d
|
||||
|
||||
# Занятые порты
|
||||
ss -tlnp | grep -E "8888|2053|443|80"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔑 Reality — что делать если начали детектировать
|
||||
|
||||
Reality маскируется под настоящий TLS-хендшейк к `www.microsoft.com`. Если заблокировали:
|
||||
|
||||
1. Сменить `dest` на другой популярный сайт (например `www.google.com:443` или `www.apple.com:443`)
|
||||
2. Сгенерировать новую пару ключей:
|
||||
```bash
|
||||
docker exec marzban-marzban-1 xray x25519
|
||||
```
|
||||
3. Обновить `privateKey`, `publicKey`, `shortIds` в Core Settings
|
||||
4. Все пользователи получат новые ссылки автоматически (pubkey меняется в ссылке)
|
||||
|
||||
---
|
||||
|
||||
## 📱 Приложения для клиентов
|
||||
|
||||
| Платформа | Приложение | Ссылка |
|
||||
|-----------|-----------|--------|
|
||||
| iOS | Karing | https://apps.apple.com/app/karing/id6472431552 |
|
||||
| Android | Hiddify | https://play.google.com/store/apps/details?id=app.hiddify.com |
|
||||
| Windows | Hiddify | https://github.com/hiddify/hiddify-app/releases/latest |
|
||||
| macOS | Hiddify | https://github.com/hiddify/hiddify-app/releases/latest |
|
||||
|
||||
---
|
||||
|
||||
## 📋 Страница для раздачи ключей
|
||||
|
||||
`https://vpn.digital-home.site/admin?key=mysecret2026`
|
||||
|
||||
Вставляешь vless:// ссылку из Marzban → получаешь ссылку на 24 часа для друга.
|
||||
|
||||
---
|
||||
|
||||
*Обновлено: 01.04.2026*
|
||||
111
Без названия 1.md
Normal file
111
Без названия 1.md
Normal file
@@ -0,0 +1,111 @@
|
||||
|
||||
```
|
||||
{
|
||||
"log": {
|
||||
"loglevel": "warning"
|
||||
},
|
||||
"routing": {
|
||||
"rules": [
|
||||
{
|
||||
"ip": [
|
||||
"geoip:cloudflare"
|
||||
],
|
||||
"outboundTag": "DIRECT",
|
||||
"type": "field"
|
||||
}
|
||||
]
|
||||
},
|
||||
"inbounds": [
|
||||
{
|
||||
"tag": "VLESS_REALITY",
|
||||
"listen": "0.0.0.0",
|
||||
"port": 2083,
|
||||
"protocol": "vless",
|
||||
"settings": {
|
||||
"clients": [],
|
||||
"decryption": "none"
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": "tcp",
|
||||
"security": "reality",
|
||||
"realitySettings": {
|
||||
"show": false,
|
||||
"dest": "www.apple.com:443",
|
||||
"xver": 0,
|
||||
"serverNames": [
|
||||
"www.apple.com"
|
||||
],
|
||||
"privateKey": "sIiJLOrd5kisiC4Fx3OXBKqEinrtYa5vt4CalThTvkI",
|
||||
"shortIds": [
|
||||
"fb8382e98f461945",
|
||||
"a1b2c3d4"
|
||||
]
|
||||
}
|
||||
},
|
||||
"sniffing": {
|
||||
"enabled": true,
|
||||
"destOverride": [
|
||||
"http",
|
||||
"tls"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"outbounds": [
|
||||
{
|
||||
"protocol": "freedom",
|
||||
"tag": "DIRECT"
|
||||
},
|
||||
{
|
||||
"protocol": "blackhole",
|
||||
"tag": "BLOCK"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
{
|
||||
"log": {
|
||||
"loglevel": "warning"
|
||||
},
|
||||
"routing": {
|
||||
"rules": [
|
||||
{
|
||||
"ip": [
|
||||
"geoip:private"
|
||||
],
|
||||
"outboundTag": "BLOCK",
|
||||
"type": "field"
|
||||
}
|
||||
]
|
||||
},
|
||||
"inbounds": [
|
||||
{
|
||||
"tag": "Shadowsocks TCP",
|
||||
"listen": "0.0.0.0",
|
||||
"port": 1080,
|
||||
"protocol": "shadowsocks",
|
||||
"settings": {
|
||||
"clients": [],
|
||||
"network": "tcp,udp"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outbounds": [
|
||||
{
|
||||
"protocol": "freedom",
|
||||
"tag": "DIRECT"
|
||||
},
|
||||
{
|
||||
"protocol": "blackhole",
|
||||
"tag": "BLOCK"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
id leadNumber creator
|
||||
```
|
||||
303
Без названия.md
Normal file
303
Без названия.md
Normal file
@@ -0,0 +1,303 @@
|
||||
cat .openclaw/openclaw.json 8.07s :daniil-openclaw
|
||||
{
|
||||
"meta": {
|
||||
"lastTouchedVersion": "2026.3.24",
|
||||
"lastTouchedAt": "2026-04-04T21:30:41.300Z"
|
||||
},
|
||||
"env": {
|
||||
"MOONSHOT_API_KEY": "sk-TOKEN"
|
||||
},
|
||||
"wizard": {
|
||||
"lastRunAt": "2026-03-31T11:19:16.350Z",
|
||||
"lastRunVersion": "2026.3.24",
|
||||
"lastRunCommand": "doctor",
|
||||
"lastRunMode": "local"
|
||||
},
|
||||
"auth": {
|
||||
"profiles": {
|
||||
"anthropic:default": {
|
||||
"provider": "anthropic",
|
||||
"mode": "token"
|
||||
}
|
||||
}
|
||||
},
|
||||
"acp": {
|
||||
"enabled": true,
|
||||
"dispatch": {
|
||||
"enabled": true
|
||||
},
|
||||
"backend": "acpx",
|
||||
"defaultAgent": "claude",
|
||||
"allowedAgents": [
|
||||
"codex",
|
||||
"claude",
|
||||
"opencode",
|
||||
"gemini"
|
||||
],
|
||||
"stream": {
|
||||
"coalesceIdleMs": 5000,
|
||||
"maxChunkChars": 16000
|
||||
},
|
||||
"runtime": {
|
||||
"ttlMinutes": 120
|
||||
}
|
||||
},
|
||||
"models": {
|
||||
"providers": {
|
||||
"moonshot": {
|
||||
"baseUrl": "https://api.moonshot.ai/v1",
|
||||
"apiKey": "${MOONSHOT_API_KEY}",
|
||||
"api": "openai-completions",
|
||||
"models": [
|
||||
{
|
||||
"id": "kimi-k2.5",
|
||||
"name": "Kimi K2.5",
|
||||
"reasoning": false,
|
||||
"input": [
|
||||
"text",
|
||||
"image"
|
||||
],
|
||||
"contextWindow": 262144,
|
||||
"maxTokens": 262144
|
||||
},
|
||||
{
|
||||
"id": "kimi-k2-thinking",
|
||||
"name": "Kimi K2 Thinking",
|
||||
"reasoning": true,
|
||||
"input": [
|
||||
"text"
|
||||
],
|
||||
"contextWindow": 262144,
|
||||
"maxTokens": 262144
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"model": {
|
||||
"primary": "anthropic/claude-sonnet-4-6",
|
||||
"fallbacks": [
|
||||
"anthropic/claude-haiku-4-5"
|
||||
]
|
||||
},
|
||||
"models": {
|
||||
"anthropic/claude-sonnet-4-6": {
|
||||
"alias": "Sonnet 4.6"
|
||||
},
|
||||
"anthropic/claude-opus-4-6": {
|
||||
"alias": "Opus 4.6"
|
||||
},
|
||||
"anthropic/claude-haiku-4-5": {
|
||||
"alias": "Haiku 4.5"
|
||||
},
|
||||
"openai/gpt-5.4-mini": {
|
||||
"alias": "GPT-5.4 Mini"
|
||||
},
|
||||
"openai/gpt-5.4": {
|
||||
"alias": "GPT-5.4"
|
||||
},
|
||||
"openai/gpt-5.4-pro": {
|
||||
"alias": "GPT-5.4 Pro"
|
||||
},
|
||||
"moonshot/kimi-k2.5": {
|
||||
"alias": "Kimi K2.5"
|
||||
}
|
||||
},
|
||||
"workspace": "/home/daniil/.openclaw/workspace",
|
||||
"compaction": {
|
||||
"mode": "safeguard"
|
||||
},
|
||||
"maxConcurrent": 4,
|
||||
"subagents": {
|
||||
"maxConcurrent": 8
|
||||
}
|
||||
},
|
||||
"list": [
|
||||
{
|
||||
"id": "main",
|
||||
"default": true,
|
||||
"name": "Cosmo",
|
||||
"workspace": "/home/daniil/.openclaw/workspace"
|
||||
},
|
||||
{
|
||||
"id": "wife",
|
||||
"name": "Ассистент",
|
||||
"workspace": "/home/daniil/.openclaw/workspace-wife"
|
||||
}
|
||||
]
|
||||
},
|
||||
"tools": {
|
||||
"web": {
|
||||
"search": {
|
||||
"enabled": true,
|
||||
"provider": "brave",
|
||||
"maxResults": 5
|
||||
}
|
||||
},
|
||||
"media": {
|
||||
"audio": {
|
||||
"enabled": true,
|
||||
"models": [
|
||||
{
|
||||
"provider": "groq",
|
||||
"model": "whisper-large-v3-turbo"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"exec": {
|
||||
"notifyOnExit": false
|
||||
}
|
||||
},
|
||||
"bindings": [
|
||||
{
|
||||
"agentId": "wife",
|
||||
"match": {
|
||||
"channel": "telegram",
|
||||
"accountId": "wife"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "route",
|
||||
"agentId": "main",
|
||||
"match": {
|
||||
"channel": "telegram",
|
||||
"accountId": "daniil",
|
||||
"peer": {
|
||||
"kind": "direct",
|
||||
"id": "398382229"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"messages": {
|
||||
"ackReactionScope": "group-mentions",
|
||||
"tts": {
|
||||
"auto": "inbound",
|
||||
"provider": "microsoft",
|
||||
"edge": {
|
||||
"enabled": true,
|
||||
"voice": "ru-RU-DmitryNeural",
|
||||
"lang": "ru-RU",
|
||||
"outputFormat": "audio-24khz-48kbitrate-mono-mp3"
|
||||
},
|
||||
"microsoft": {
|
||||
"enabled": true,
|
||||
"voice": "ru-RU-DmitryNeural",
|
||||
"lang": "ru-RU",
|
||||
"outputFormat": "audio-24khz-48kbitrate-mono-mp3",
|
||||
"pitch": "+0%",
|
||||
"rate": "+0%"
|
||||
}
|
||||
}
|
||||
},
|
||||
"commands": {
|
||||
"native": "auto",
|
||||
"nativeSkills": "auto",
|
||||
"restart": true,
|
||||
"ownerDisplay": "raw"
|
||||
},
|
||||
"hooks": {
|
||||
"internal": {
|
||||
"enabled": true,
|
||||
"entries": {
|
||||
"command-logger": {
|
||||
"enabled": true
|
||||
},
|
||||
"session-memory": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"channels": {
|
||||
"telegram": {
|
||||
"enabled": true,
|
||||
"dmPolicy": "pairing",
|
||||
"groupAllowFrom": [
|
||||
"398382229"
|
||||
],
|
||||
"groupPolicy": "allowlist",
|
||||
"streaming": "partial",
|
||||
"actions": {
|
||||
"reactions": true
|
||||
},
|
||||
"accounts": {
|
||||
"daniil": {
|
||||
"name": "Cosmo (Даниил)",
|
||||
"dmPolicy": "pairing",
|
||||
"botToken": "8527290610:TOKEN",
|
||||
"allowFrom": [
|
||||
"398382229"
|
||||
],
|
||||
"groupPolicy": "allowlist",
|
||||
"streaming": "off",
|
||||
"threadBindings": {
|
||||
"spawnAcpSessions": false
|
||||
}
|
||||
},
|
||||
"wife": {
|
||||
"name": "Бот жены",
|
||||
"dmPolicy": "allowlist",
|
||||
"botToken": "8351034602:TOKEN",
|
||||
"allowFrom": [
|
||||
"197366320"
|
||||
],
|
||||
"groupPolicy": "allowlist",
|
||||
"streaming": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"gateway": {
|
||||
"port": 18789,
|
||||
"mode": "local",
|
||||
"bind": "lan",
|
||||
"controlUi": {
|
||||
"allowedOrigins": [
|
||||
"http://localhost:18789",
|
||||
"http://127.0.0.1:18789",
|
||||
"http://192.168.31.103:18789",
|
||||
"http://192.168.31.95:18789"
|
||||
]
|
||||
},
|
||||
"auth": {
|
||||
"mode": "token",
|
||||
"token": "TOKEN"
|
||||
},
|
||||
"tailscale": {
|
||||
"mode": "off",
|
||||
"resetOnExit": false
|
||||
}
|
||||
},
|
||||
"skills": {
|
||||
"install": {
|
||||
"nodeManager": "npm"
|
||||
}
|
||||
},
|
||||
"plugins": {
|
||||
"entries": {
|
||||
"telegram": {
|
||||
"enabled": true
|
||||
},
|
||||
"brave": {
|
||||
"enabled": true,
|
||||
"config": {
|
||||
"webSearch": {
|
||||
"apiKey": "KEY"
|
||||
}
|
||||
}
|
||||
},
|
||||
"acpx": {
|
||||
"enabled": true,
|
||||
"config": {
|
||||
"permissionMode": "approve-all",
|
||||
"command": "/home/daniil/bin/acpx-wrapper.sh",
|
||||
"expectedVersion": "any"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
137
Дизайн-инспирация/Ultrahuman Ring PRO.md
Normal file
137
Дизайн-инспирация/Ultrahuman Ring PRO.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# Ultrahuman Ring PRO — Анализ дизайна и UX
|
||||
|
||||
> Источник: https://www.ultrahuman.com/global/ring-pro/
|
||||
> Сохранено: 2026-04-02
|
||||
> Цель: вдохновение для редизайна Pulse App
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Визуальный дизайн сайта
|
||||
|
||||
### Общий стиль
|
||||
- **Тёмная тема** как основная — почти чёрный фон (`#0a0a0a`, `#111`), текст белый
|
||||
- **Акцентный цвет** — насыщенный тёмно-зелёный / teal (`#00c896` примерно), используется для иконок, индикаторов, меток состояния
|
||||
- **Типографика** — крупные, жирные заголовки (видимо sans-serif, похоже на Inter/Neue Haas), огромный кегль на hero-секциях
|
||||
- **Контраст** — очень высокий, метрики выделяются большими цифрами на тёмном фоне
|
||||
|
||||
### Фотографии и визуалы
|
||||
- Телефон в руке — реалистичные 3D-рендеры, не скриншоты
|
||||
- Фоновые фото людей в движении — размытые, тёмные, атмосферные (оранжевые, синие градиенты)
|
||||
- Каждая функция — отдельная «карточка» с реальным скриншотом приложения + фото/паттерн на фоне
|
||||
- Использование градиентных blob-овалов как фоновых элементов (зелёные, синие, розовые свечения)
|
||||
|
||||
### Компоненты
|
||||
- **Таб-бар** внизу экрана телефона — горизонтальный, полупрозрачный тёмный фон, активный таб белый жирный
|
||||
- **Карточки метрик** — скруглённые углы, плотный padding, маленький лейбл сверху + большое число
|
||||
- **Индикаторы статуса** — цветные теги (зелёный «Excellent», красный «Needs attention»)
|
||||
- **Мини-графики** — sparkline прямо в карточке, тонкие линии
|
||||
- **Прогресс-бар** — тонкий, цветной (зелёный/красный)
|
||||
|
||||
---
|
||||
|
||||
## 📱 UX и структура приложения
|
||||
|
||||
### Навигация
|
||||
Четыре основных раздела в таб-баре:
|
||||
| Таб | Содержимое |
|
||||
|-----|-----------|
|
||||
| **Sleep** | Sleep Index, стадии сна, REM/Deep/Light, детальный timeline |
|
||||
| **Vitals** | HR, RHR, HRV, VO2 Max, Temp, Cardio Age |
|
||||
| **PowerPlugs** | Маркетплейс плагинов (Women's Health, Respiratory, Heart) |
|
||||
| **Longevity** | Ultra Age = Brain Age + Pulse Age + Blood Age |
|
||||
|
||||
### Ключевые экраны
|
||||
|
||||
#### Dashboard / Longevity
|
||||
- Центральный элемент — **большое число** (возраст: 32, с маркером "+3 years older")
|
||||
- Под ним — объяснение одной фразой: *"You're currently aging at a faster aging pace than expected for your age"*
|
||||
- Contributors: три субметрики (Brain Age 32, Pulse Age 28, Blood Age 31) с иконками
|
||||
|
||||
#### Sleep
|
||||
- Score крупно (74), под ним timeline-график сна по стадиям
|
||||
- Стадии: Awake, REM, Light Sleep, Deep Sleep — цветовая кодировка
|
||||
- Мини-гистограмма активности по ночи
|
||||
|
||||
#### Vitals
|
||||
- Сетка карточек 2×n
|
||||
- Каждая карточка: лейбл + значение + delta (`+2`) + статус (Within typical range) + мини-sparkline
|
||||
- Метрики: Heart Rate, Resting HR, HRV, VO2 Max, Temp Deviation, Cardio Age
|
||||
|
||||
#### PowerPlugs
|
||||
- App Store-стиль: карточки с gradient-обложками
|
||||
- Каждый плагин: иконка + название + категория + кнопка Get / Installed
|
||||
|
||||
---
|
||||
|
||||
## 💡 Фичи для вдохновения в Pulse
|
||||
|
||||
### Что можно взять напрямую
|
||||
|
||||
| Идея | Где в Pulse | Сложность |
|
||||
|------|------------|-----------|
|
||||
| **Readiness Score как центральный элемент** — большое число, одна фраза-объяснение | Health Dashboard | Низкая — данные уже есть |
|
||||
| **Contributors под скором** — разбивка на 3 субметрики (сон, HRV, RHR) | Health Dashboard | Низкая |
|
||||
| **Цветовые статусы** — Excellent / Good / Needs attention | Везде | Низкая |
|
||||
| **Sparkline в карточке** — мини-график прямо рядом с числом | Health, Финансы | Средняя |
|
||||
| **Tab-bar снизу** — Sleep / Vitals / Habits / Finance | Главная навигация | Низкая |
|
||||
| **Timeline сна** — гистограмма по часам с фазами | Sleep раздел | Средняя |
|
||||
| **Delta значений** — `+2 bpm vs yesterday` рядом с числом | Все метрики | Низкая |
|
||||
|
||||
### Концепции посложнее
|
||||
|
||||
| Идея | Описание | Сложность |
|
||||
|------|---------|-----------|
|
||||
| **"Biological Age" аналог** | Индекс долгосрочного здоровья на основе сна + HRV + активности | Высокая |
|
||||
| **PowerPlugs аналог** | Маркетплейс трекеров/модулей (привычки, финансы, здоровье) | Высокая |
|
||||
| **AI-объяснения** (как Jade) | *"Low glymphatic clearance is slowing mental recovery"* — причина + рекомендация | Высокая |
|
||||
| **Stress Rhythm** | Трекинг стресса по HRV в течение дня | Высокая (нет датчика) |
|
||||
|
||||
---
|
||||
|
||||
## 🖌️ Дизайн-система для адаптации в Pulse
|
||||
|
||||
### Цвета
|
||||
```
|
||||
Фон: #0d0d0d — #111111
|
||||
Карточки: #1a1a1a — #1e1e1e
|
||||
Акцент: #00c896 (teal/зелёный) — уже близко к нашему Deep Teal
|
||||
Хорошо: #00c896 green
|
||||
Внимание: #ff4d4d red
|
||||
Нейтральный: #888888 gray
|
||||
Текст: #ffffff primary, #aaaaaa secondary
|
||||
```
|
||||
|
||||
### Типографика
|
||||
- Заголовки: очень крупные (48px+), жирные, Inter или аналог
|
||||
- Метрики: 32–48px, bold
|
||||
- Лейблы: 10–12px, uppercase, letter-spacing
|
||||
- Описание: 14px, regular, серый
|
||||
|
||||
### Карточки
|
||||
```
|
||||
border-radius: 16–20px
|
||||
padding: 16–20px
|
||||
background: rgba(255,255,255,0.05) или #1e1e1e
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Приоритетный план для Pulse
|
||||
|
||||
**Фаза 1 (быстрые wins):**
|
||||
1. Редизайн Health Dashboard — большой Readiness Score + 3 contributors
|
||||
2. Добавить цветовые статусы к метрикам (Excellent / Needs attention)
|
||||
3. Delta значений (`+2 vs yesterday`) везде
|
||||
|
||||
**Фаза 2 (средний срок):**
|
||||
4. Sparklines в карточках метрик
|
||||
5. Timeline-график сна по фазам
|
||||
6. Tab-bar навигация (Sleep / Vitals / Habits / Finance)
|
||||
|
||||
**Фаза 3 (амбициозно):**
|
||||
7. AI-интерпретации метрик (Cosmo объясняет что значит HRV = 45)
|
||||
8. "Pulse Age" — агрегированный индекс здоровья
|
||||
|
||||
---
|
||||
|
||||
*Сохранено Cosmo, 02.04.2026*
|
||||
@@ -1,12 +0,0 @@
|
||||
| | 100 | 200 | 300 | 400 | 500 |
|
||||
| --------------- | ------------------ | ------------------ | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
|
||||
| Песни наоборот | Агутин - Аэропорты | Дима Билан - Держи | Звери - Районы кварталы | Корни - Ты узнаешь ее | Максим - Знаешь ли ты |
|
||||
| Продолжи песню | Мы увидим сзади | Из ярких лампочек | Все твои слова | Силы не жалей | Что любят гламур |
|
||||
| Вопросы от Дани | Она забыла его имя | Настольный теннис | Винни-пух | Кошка | 25 |
|
||||
| Сумерки | Белла | Эдвард Каллен | Бейсбол | В балетную студию в Фениксе | Что она упала с лестницы и вылетела через окно |
|
||||
| Чей плейлист | Ксюша | Даша | Света | Юля Шубина | Юля Мосина |
|
||||
| Поездки | 25 тысяч шагов | Изразцы | Альберт | Княгиня Ольга | 922 |
|
||||
| Факты о нас | 2 месяца | Даша Неберова | 1 год и 7 месяцев | Животные | Аллергия на текилу |
|
||||
| Универ | 1832 | Норильск | Информационные технологии графического проектирования | Препод по философии (Гурьев Евгений Павлович) | Разумнова Елена Альбертовна |
|
||||
| Профессия | | Канальный | Б.Н. Ельцин | Комитет по государственному контролю, использованию и охране памятников истории и культуры Санкт-Петербурга | 4 |
|
||||
| Наши встречи | Уэнсдей | Август 2023 года | Учебник по металлическим конструкциям | Для смысла | Вынуть батарейки из Дашиных часов в гостиной |
|
||||
337
Инфраструктура/pulse-api.md
Normal file
337
Инфраструктура/pulse-api.md
Normal file
@@ -0,0 +1,337 @@
|
||||
# pulse-api — Архитектура
|
||||
|
||||
**Репозиторий:** `https://git.digital-home.site/daniil/pulse-api`
|
||||
**Go module:** `github.com/daniil/homelab-api`
|
||||
**URL:** `https://api.digital-home.site`
|
||||
**Dev:** `http://192.168.31.60:8081`
|
||||
|
||||
## Общая архитектура
|
||||
|
||||
Классический Go REST API с разделением на слои:
|
||||
|
||||
```
|
||||
cmd/api/main.go ← точка входа, роутер, инициализация
|
||||
internal/
|
||||
config/ ← загрузка env-переменных
|
||||
repository/ ← работа с БД (SQL-запросы)
|
||||
service/ ← бизнес-логика
|
||||
handler/ ← HTTP-хендлеры (request/response)
|
||||
model/ ← структуры данных (Go structs + JSON)
|
||||
middleware/ ← JWT-аутентификация
|
||||
bot/ ← Telegram бот
|
||||
scheduler/ ← cron-задачи (напоминания)
|
||||
```
|
||||
|
||||
**Стек:**
|
||||
- Router: `go-chi/chi v5`
|
||||
- ORM: `jmoiron/sqlx` (raw SQL + named queries)
|
||||
- БД: PostgreSQL 16
|
||||
- JWT: `golang-jwt/jwt v5`
|
||||
- Telegram: `go-telegram-bot-api v5`
|
||||
- Cron: `robfig/cron v3`
|
||||
- Email: Resend API (`service/email.go`)
|
||||
- Крипто: `golang.org/x/crypto` (bcrypt для паролей)
|
||||
|
||||
## Структура папок
|
||||
|
||||
```
|
||||
pulse-api/
|
||||
├── cmd/api/main.go # Точка входа: роутер, DI, запуск
|
||||
├── internal/
|
||||
│ ├── bot/
|
||||
│ │ ├── bot.go # Инициализация, Start(), SendMessage()
|
||||
│ │ └── handlers.go # Команды и callback кнопки
|
||||
│ ├── config/
|
||||
│ │ └── config.go # Config struct + Load() из env
|
||||
│ ├── handler/
|
||||
│ │ ├── auth.go # Register, Login, Refresh, Me, VerifyEmail...
|
||||
│ │ ├── tasks.go # CRUD задач + complete/uncomplete
|
||||
│ │ ├── habits.go # CRUD привычек + логи + статистика
|
||||
│ │ ├── habit_freeze.go # Заморозка привычек
|
||||
│ │ ├── finance.go # Категории и транзакции финансов
|
||||
│ │ ├── savings.go # Накопления (категории, участники, планы)
|
||||
│ │ ├── interest.go # Начисление процентов
|
||||
│ │ ├── profile.go # Профиль пользователя
|
||||
│ │ └── health.go # GET /health
|
||||
│ ├── middleware/
|
||||
│ │ └── auth.go # JWT Bearer middleware
|
||||
│ ├── model/
|
||||
│ │ ├── user.go # User, RegisterRequest, LoginRequest...
|
||||
│ │ ├── task.go # Task, CreateTaskRequest...
|
||||
│ │ ├── habit.go # Habit, HabitLog, HabitStats...
|
||||
│ │ ├── habit_freeze.go # HabitFreeze
|
||||
│ │ ├── finance.go # FinanceCategory, FinanceTransaction...
|
||||
│ │ ├── savings.go # SavingsCategory, SavingsTransaction...
|
||||
│ │ └── email.go # Email templates
|
||||
│ ├── repository/
|
||||
│ │ ├── db.go # NewDB() + RunMigrations()
|
||||
│ │ ├── user.go # UserRepository
|
||||
│ │ ├── task.go # TaskRepository
|
||||
│ │ ├── habit.go # HabitRepository
|
||||
│ │ ├── habit_freeze.go # HabitFreezeRepository
|
||||
│ │ ├── finance.go # FinanceRepository
|
||||
│ │ ├── savings.go # SavingsRepository
|
||||
│ │ └── email_token.go # EmailTokenRepository
|
||||
│ ├── service/
|
||||
│ │ ├── auth.go # AuthService: register/login/JWT
|
||||
│ │ ├── habit.go # HabitService
|
||||
│ │ ├── task.go # TaskService
|
||||
│ │ ├── finance.go # FinanceService
|
||||
│ │ ├── interest.go # Начисление процентов
|
||||
│ │ └── email.go # EmailService (Resend)
|
||||
│ └── scheduler/
|
||||
│ └── scheduler.go # Cron-напоминания через Telegram
|
||||
├── docs/
|
||||
│ └── SAVINGS.md
|
||||
├── go.mod
|
||||
├── Dockerfile
|
||||
└── docker-compose.yml
|
||||
```
|
||||
|
||||
## API Эндпоинты
|
||||
|
||||
### Публичные (без авторизации)
|
||||
|
||||
| Метод | Путь | Описание |
|
||||
|-------|------|----------|
|
||||
| GET | `/health` | Health check |
|
||||
| POST | `/auth/register` | Регистрация: `{email, username, password}` |
|
||||
| POST | `/auth/login` | Логин: `{email, password}` → `{access_token, refresh_token, user}` |
|
||||
| POST | `/auth/refresh` | Обновление токена: `{refresh_token}` |
|
||||
| POST | `/auth/verify-email` | Подтверждение email: `{token}` |
|
||||
| POST | `/auth/resend-verification` | Повторная отправка: `{email}` |
|
||||
| POST | `/auth/forgot-password` | Сброс пароля: `{email}` |
|
||||
| POST | `/auth/reset-password` | Новый пароль: `{token, new_password}` |
|
||||
|
||||
### Авторизованные (Bearer JWT)
|
||||
|
||||
#### Аутентификация/Профиль
|
||||
|
||||
| Метод | Путь | Описание |
|
||||
|-------|------|----------|
|
||||
| GET | `/auth/me` | Текущий пользователь |
|
||||
| PUT | `/auth/me` | Обновить профиль |
|
||||
| PUT | `/auth/password` | Сменить пароль: `{old_password, new_password}` |
|
||||
| GET | `/profile` | Профиль |
|
||||
| PUT | `/profile` | Обновить профиль |
|
||||
|
||||
#### Задачи
|
||||
|
||||
| Метод | Путь | Описание |
|
||||
|-------|------|----------|
|
||||
| GET | `/tasks` | Список задач. Query: `?completed=true/false` |
|
||||
| GET | `/tasks/today` | Задачи на сегодня |
|
||||
| POST | `/tasks` | Создать: `{title, description?, icon?, color?, due_date?, priority?, reminder_time?, is_recurring?, recurrence_type?, recurrence_interval?, recurrence_end_date?}` |
|
||||
| GET | `/tasks/{id}` | Получить задачу |
|
||||
| PUT | `/tasks/{id}` | Обновить задачу |
|
||||
| DELETE | `/tasks/{id}` | Удалить задачу |
|
||||
| POST | `/tasks/{id}/complete` | Отметить выполненной |
|
||||
| POST | `/tasks/{id}/uncomplete` | Снять отметку |
|
||||
|
||||
#### Привычки
|
||||
|
||||
| Метод | Путь | Описание |
|
||||
|-------|------|----------|
|
||||
| GET | `/habits` | Список привычек |
|
||||
| POST | `/habits` | Создать: `{name, description?, color?, icon?, frequency, target_days?, target_count?, reminder_time?, start_date?}` |
|
||||
| GET | `/habits/{id}` | Получить привычку |
|
||||
| PUT | `/habits/{id}` | Обновить |
|
||||
| DELETE | `/habits/{id}` | Удалить |
|
||||
| POST | `/habits/{id}/log` | Отметить: `{date?, count?, note?}` |
|
||||
| GET | `/habits/{id}/logs` | История отметок |
|
||||
| DELETE | `/habits/{id}/logs/{logId}` | Удалить отметку |
|
||||
| GET | `/habits/stats` | Общая статистика |
|
||||
| GET | `/habits/{id}/stats` | Статистика привычки |
|
||||
| GET | `/habits/{id}/freezes` | Заморозки привычки |
|
||||
| POST | `/habits/{id}/freezes` | Создать заморозку |
|
||||
| DELETE | `/habits/{id}/freezes/{freezeId}` | Удалить заморозку |
|
||||
|
||||
#### Финансы
|
||||
|
||||
| Метод | Путь | Описание |
|
||||
|-------|------|----------|
|
||||
| GET | `/finance/categories` | Категории расходов/доходов |
|
||||
| POST | `/finance/categories` | Создать: `{name, emoji?, type, budget?, color?, sort_order?}` |
|
||||
| PUT | `/finance/categories/{id}` | Обновить |
|
||||
| DELETE | `/finance/categories/{id}` | Удалить |
|
||||
| GET | `/finance/transactions` | Транзакции. Query: `?month=&year=` |
|
||||
| POST | `/finance/transactions` | Создать: `{category_id, type, amount, description?, date}` |
|
||||
| PUT | `/finance/transactions/{id}` | Обновить |
|
||||
| DELETE | `/finance/transactions/{id}` | Удалить |
|
||||
| GET | `/finance/summary` | Сводка: баланс, доходы, расходы, по категориям |
|
||||
| GET | `/finance/analytics` | Аналитика: тренды по месяцам |
|
||||
|
||||
#### Накопления
|
||||
|
||||
| Метод | Путь | Описание |
|
||||
|-------|------|----------|
|
||||
| GET | `/savings/categories` | Категории накоплений |
|
||||
| POST | `/savings/categories` | Создать категорию |
|
||||
| GET | `/savings/categories/{id}` | Получить |
|
||||
| PUT | `/savings/categories/{id}` | Обновить |
|
||||
| DELETE | `/savings/categories/{id}` | Удалить |
|
||||
| GET | `/savings/categories/{id}/members` | Участники |
|
||||
| POST | `/savings/categories/{id}/members` | Добавить участника |
|
||||
| DELETE | `/savings/categories/{id}/members/{userId}` | Удалить участника |
|
||||
| GET | `/savings/categories/{id}/recurring-plans` | Регулярные планы |
|
||||
| POST | `/savings/categories/{id}/recurring-plans` | Создать план |
|
||||
| PUT | `/savings/recurring-plans/{planId}` | Обновить план |
|
||||
| DELETE | `/savings/recurring-plans/{planId}` | Удалить план |
|
||||
| GET | `/savings/transactions` | Транзакции накоплений |
|
||||
| POST | `/savings/transactions` | Создать транзакцию |
|
||||
| GET | `/savings/transactions/{id}` | Получить |
|
||||
| PUT | `/savings/transactions/{id}` | Обновить |
|
||||
| DELETE | `/savings/transactions/{id}` | Удалить |
|
||||
| GET | `/savings/stats` | Статистика |
|
||||
|
||||
## Модели данных
|
||||
|
||||
### User
|
||||
```go
|
||||
type User struct {
|
||||
ID int64
|
||||
Email string
|
||||
Username string
|
||||
PasswordHash string // bcrypt, в JSON скрыто
|
||||
EmailVerified bool
|
||||
TelegramChatID *int64 // nullable
|
||||
NotificationsEnabled bool
|
||||
Timezone string
|
||||
MorningReminderTime string // "09:00"
|
||||
EveningReminderTime string // "21:00"
|
||||
CreatedAt, UpdatedAt time.Time
|
||||
}
|
||||
```
|
||||
|
||||
### Task
|
||||
```go
|
||||
type Task struct {
|
||||
ID, UserID int64
|
||||
Title, Description string
|
||||
Icon, Color string
|
||||
DueDate *string // "2026-01-01"
|
||||
Priority int // 1=низкий, 2=средний, 3=высокий
|
||||
ReminderTime *string // "19:00"
|
||||
Completed bool // производное от CompletedAt
|
||||
// Повторяющиеся задачи:
|
||||
IsRecurring bool
|
||||
RecurrenceType *string // "daily", "weekly", "monthly"
|
||||
RecurrenceInterval int
|
||||
RecurrenceEndDate *string
|
||||
ParentTaskID *int64
|
||||
CreatedAt, UpdatedAt time.Time
|
||||
}
|
||||
```
|
||||
|
||||
### Habit
|
||||
```go
|
||||
type Habit struct {
|
||||
ID, UserID int64
|
||||
Name, Description string
|
||||
Color, Icon string
|
||||
Frequency string // "daily", "weekly", "custom"
|
||||
TargetDays []int // дни недели (0=вс...6=сб)
|
||||
TargetCount int
|
||||
ReminderTime *string // "19:00"
|
||||
StartDate *string
|
||||
IsArchived bool
|
||||
CreatedAt, UpdatedAt time.Time
|
||||
}
|
||||
|
||||
type HabitLog struct {
|
||||
ID, HabitID, UserID int64
|
||||
Date time.Time
|
||||
Count int
|
||||
Note string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
```
|
||||
|
||||
### FinanceCategory / FinanceTransaction
|
||||
```go
|
||||
type FinanceCategory struct {
|
||||
ID, UserID int64
|
||||
Name, Emoji string
|
||||
Type string // "income" | "expense"
|
||||
Budget *float64
|
||||
Color string
|
||||
SortOrder int
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type FinanceTransaction struct {
|
||||
ID, UserID, CategoryID int64
|
||||
Type string // "income" | "expense"
|
||||
Amount float64
|
||||
Description string
|
||||
Date time.Time
|
||||
CreatedAt time.Time
|
||||
CategoryName, CategoryEmoji string // из JOIN
|
||||
}
|
||||
```
|
||||
|
||||
## Аутентификация
|
||||
|
||||
- **JWT HS256** с двумя типами токенов: `access` (короткий) и `refresh` (длинный)
|
||||
- Middleware `Authenticate` парсит `Authorization: Bearer <token>`, проверяет `type == "access"`
|
||||
- UserID извлекается из claims и помещается в context: `GetUserID(ctx)`
|
||||
- Пароли хешируются bcrypt
|
||||
- Email-верификация при регистрации через Resend API
|
||||
- Password reset — одноразовые токены в таблице `email_tokens`
|
||||
|
||||
## Telegram Бот
|
||||
|
||||
**Команды:**
|
||||
| Команда | Действие |
|
||||
|---------|---------|
|
||||
| `/start` | Показать Chat ID (для привязки к аккаунту Pulse) |
|
||||
| `/tasks` | Список задач на сегодня с inline-кнопками |
|
||||
| `/habits` | Привычки на сегодня с inline-кнопками |
|
||||
| `/done <id>` или `/done_<id>` | Отметить задачу выполненной |
|
||||
| `/check <id>` или `/check_<id>` | Отметить привычку |
|
||||
| `/help` | Справка |
|
||||
|
||||
**Callback-кнопки:**
|
||||
- `donetask_<id>` — выполнить задачу
|
||||
- `deltask_<id>` — удалить задачу
|
||||
- `checkhabit_<id>` — отметить привычку сегодня
|
||||
- `checkhabit_<id>_yesterday` — отметить привычку за вчера
|
||||
|
||||
**Привязка:** пользователь вводит `/start`, получает Chat ID, вставляет его в настройки Pulse → `PUT /profile {telegram_chat_id: ...}`
|
||||
|
||||
## Scheduler (cron-напоминания)
|
||||
|
||||
`internal/scheduler/scheduler.go` — использует `robfig/cron`:
|
||||
- Утренние напоминания (время из настроек пользователя)
|
||||
- Вечерние напоминания
|
||||
- Напоминания о задачах по `reminder_time`
|
||||
- Напоминания о привычках по `reminder_time`
|
||||
|
||||
## Конфигурация (env переменные)
|
||||
|
||||
| Переменная | Описание | Default |
|
||||
|-----------|----------|---------|
|
||||
| `DATABASE_URL` | PostgreSQL DSN | `postgres://homelab:homelab@db:5432/homelab` |
|
||||
| `JWT_SECRET` | Секрет для JWT | `change-me-in-production` |
|
||||
| `PORT` | Порт сервера | `8080` |
|
||||
| `RESEND_API_KEY` | API ключ Resend (email) | — |
|
||||
| `FROM_EMAIL` | Email отправителя | `noreply@digital-home.site` |
|
||||
| `FROM_NAME` | Имя отправителя | `Homelab` |
|
||||
| `APP_URL` | Публичный URL приложения | `https://api.digital-home.site` |
|
||||
| `TELEGRAM_BOT_TOKEN` | Токен Telegram бота | — |
|
||||
|
||||
## Где искать что
|
||||
|
||||
| Задача | Файл |
|
||||
|--------|------|
|
||||
| Добавить новый эндпоинт | `handler/<domain>.go` + роут в `cmd/api/main.go` |
|
||||
| Изменить модель/таблицу | `model/<domain>.go` + `repository/db.go` (migrations) |
|
||||
| Логика уведомлений | `internal/scheduler/scheduler.go` |
|
||||
| Telegram команды | `internal/bot/handlers.go` |
|
||||
| Финансы (категории/транзакции) | `handler/finance.go`, `service/finance.go`, `repository/finance.go` |
|
||||
| Привычки | `handler/habits.go`, `service/habit.go`, `repository/habit.go` |
|
||||
| Задачи | `handler/tasks.go`, `service/task.go`, `repository/task.go` |
|
||||
| Накопления | `handler/savings.go`, `repository/savings.go` |
|
||||
| Email отправка | `service/email.go` |
|
||||
| JWT/Auth | `service/auth.go`, `middleware/auth.go` |
|
||||
| Конфиг | `config/config.go` |
|
||||
263
Инфраструктура/pulse-web.md
Normal file
263
Инфраструктура/pulse-web.md
Normal file
@@ -0,0 +1,263 @@
|
||||
# pulse-web — Архитектура
|
||||
|
||||
**Репозиторий:** `https://git.digital-home.site/daniil/pulse-web`
|
||||
**URL:** `https://pulse.digital-home.site`
|
||||
**Dev:** `http://192.168.31.60:5174`
|
||||
**Storybook:** `http://192.168.31.60:6006`
|
||||
|
||||
## Общая архитектура
|
||||
|
||||
React SPA (Single Page Application):
|
||||
|
||||
```
|
||||
src/
|
||||
api/ ← API-функции (axios, по доменам)
|
||||
store/ ← State management (Zustand)
|
||||
contexts/ ← React Context (тема)
|
||||
pages/ ← Страницы (маршруты)
|
||||
components/ ← Переиспользуемые компоненты
|
||||
main.jsx ← Точка входа (BrowserRouter + ThemeContext)
|
||||
App.jsx ← Роутер (Routes/Route)
|
||||
index.css ← Глобальные стили (Tailwind)
|
||||
```
|
||||
|
||||
**Стек:**
|
||||
- Framework: React 18
|
||||
- Bundler: Vite 5
|
||||
- Роутинг: React Router DOM 6
|
||||
- State: Zustand 4
|
||||
- HTTP: Axios (с interceptors для JWT refresh)
|
||||
- UI: Tailwind CSS 3
|
||||
- Анимации: Framer Motion 11
|
||||
- Иконки: Lucide React
|
||||
- Графики: Recharts 2
|
||||
- Утилиты дат: date-fns 3
|
||||
- Компонент-либа: Storybook 8
|
||||
- Тесты: Vitest + Testing Library
|
||||
|
||||
## Структура папок
|
||||
|
||||
```
|
||||
pulse-web/
|
||||
├── src/
|
||||
│ ├── api/
|
||||
│ │ ├── client.js # Axios instance + JWT interceptor
|
||||
│ │ ├── auth.js # (в store/auth.js)
|
||||
│ │ ├── tasks.js # tasksApi: list, today, create, complete...
|
||||
│ │ ├── habits.js # habitsApi: list, create, log, stats...
|
||||
│ │ ├── finance.js # financeApi: categories, transactions, summary
|
||||
│ │ ├── savings.js # savingsApi: categories, transactions, stats
|
||||
│ │ └── profile.js # profileApi: get, update
|
||||
│ ├── store/
|
||||
│ │ └── auth.js # useAuthStore (Zustand): user, login, logout
|
||||
│ ├── contexts/
|
||||
│ │ └── ThemeContext.jsx # ThemeProvider: light/dark, localStorage
|
||||
│ ├── pages/
|
||||
│ │ ├── Home.jsx # Главная страница (дашборд)
|
||||
│ │ ├── Tracker.jsx # Трекер (таб: привычки/задачи/статистика)
|
||||
│ │ ├── Habits.jsx # Страница привычек (встраивается в Tracker)
|
||||
│ │ ├── Tasks.jsx # Страница задач (встраивается в Tracker)
|
||||
│ │ ├── Stats.jsx # Статистика (встраивается в Tracker)
|
||||
│ │ ├── Finance.jsx # Финансы (таб: обзор/транзакции/аналитика/категории)
|
||||
│ │ ├── Savings.jsx # Накопления
|
||||
│ │ ├── Settings.jsx # Настройки пользователя
|
||||
│ │ ├── Login.jsx # Вход
|
||||
│ │ ├── Register.jsx # Регистрация
|
||||
│ │ ├── ForgotPassword.jsx # Сброс пароля
|
||||
│ │ ├── ResetPassword.jsx # Новый пароль (по токену из email)
|
||||
│ │ └── VerifyEmail.jsx # Подтверждение email
|
||||
│ ├── components/
|
||||
│ │ ├── Navigation.jsx # Нижняя навигация (fixed bottom)
|
||||
│ │ ├── CreateTaskModal.jsx
|
||||
│ │ ├── EditTaskModal.jsx
|
||||
│ │ ├── CreateHabitModal.jsx
|
||||
│ │ ├── EditHabitModal.jsx
|
||||
│ │ ├── LogHabitModal.jsx
|
||||
│ │ └── finance/
|
||||
│ │ ├── FinanceDashboard.jsx # Обзор месяца
|
||||
│ │ ├── TransactionList.jsx # Список транзакций
|
||||
│ │ ├── FinanceAnalytics.jsx # Графики трендов
|
||||
│ │ ├── CategoriesManager.jsx # Управление категориями
|
||||
│ │ └── AddTransactionModal.jsx
|
||||
│ ├── App.jsx # Routes + ProtectedRoute/PublicRoute
|
||||
│ ├── main.jsx # ReactDOM.render + Providers
|
||||
│ └── index.css # Tailwind + кастомные стили
|
||||
├── public/
|
||||
├── package.json
|
||||
├── vite.config.js
|
||||
├── tailwind.config.js
|
||||
├── nginx.conf
|
||||
└── Dockerfile
|
||||
```
|
||||
|
||||
## Страницы / Роуты
|
||||
|
||||
| Путь | Компонент | Защита | Описание |
|
||||
|------|-----------|--------|----------|
|
||||
| `/login` | `Login` | Public only | Форма входа |
|
||||
| `/register` | `Register` | Public only | Форма регистрации |
|
||||
| `/forgot-password` | `ForgotPassword` | Public only | Запрос сброса пароля |
|
||||
| `/verify-email` | `VerifyEmail` | Нет | Подтверждение email по токену |
|
||||
| `/reset-password` | `ResetPassword` | Нет | Установка нового пароля |
|
||||
| `/` | `Home` | Protected | Главная: дашборд |
|
||||
| `/tracker` | `Tracker` | Protected | Трекер привычек/задач/статистики |
|
||||
| `/habits` | → `/tracker` | Protected | Редирект на трекер |
|
||||
| `/tasks` | → `/tracker` | Protected | Редирект на трекер |
|
||||
| `/stats` | → `/tracker` | Protected | Редирект на трекер |
|
||||
| `/savings` | `Savings` | Protected | Накопления |
|
||||
| `/settings` | `Settings` | Protected | Настройки аккаунта |
|
||||
| `*` | → `/` | — | Любой неизвестный → главная |
|
||||
|
||||
### Tracker (вкладки)
|
||||
`/tracker` содержит 3 вкладки:
|
||||
1. **Привычки** — `Habits` компонент
|
||||
2. **Задачи** — `Tasks` компонент
|
||||
3. **Статистика** — `Stats` компонент
|
||||
|
||||
### Finance (вкладки)
|
||||
`/finance` (доступна через роутер если добавить) содержит 4 вкладки:
|
||||
1. **Обзор** — `FinanceDashboard`
|
||||
2. **Транзакции** — `TransactionList`
|
||||
3. **Аналитика** — `FinanceAnalytics`
|
||||
4. **Категории** — `CategoriesManager`
|
||||
|
||||
> ⚠️ Страница Finance рендерится, но **нет роута** в App.jsx. Доступ только если добавить `<Route path="/finance">`.
|
||||
|
||||
## Основные компоненты
|
||||
|
||||
| Компонент | Файл | Назначение |
|
||||
|-----------|------|------------|
|
||||
| `Navigation` | components/Navigation.jsx | Нижняя навбар (Главная, Трекер, Накопления, Настройки). Показывает Finance только для `user.id === 1` (owner) |
|
||||
| `ProtectedRoute` | App.jsx | Редиректит на `/login` если не авторизован |
|
||||
| `PublicRoute` | App.jsx | Редиректит на `/` если уже авторизован |
|
||||
| `FinanceDashboard` | finance/ | Обзор месяца: баланс, доходы/расходы, по категориям, дневной график |
|
||||
| `TransactionList` | finance/ | Список транзакций с фильтрацией |
|
||||
| `FinanceAnalytics` | finance/ | Recharts: тренды по месяцам |
|
||||
| `CategoriesManager` | finance/ | CRUD категорий |
|
||||
| `AddTransactionModal` | finance/ | Модал добавления транзакции |
|
||||
| `CreateTaskModal` | components/ | Создание задачи |
|
||||
| `EditTaskModal` | components/ | Редактирование задачи |
|
||||
| `CreateHabitModal` | components/ | Создание привычки |
|
||||
| `LogHabitModal` | components/ | Отметка привычки |
|
||||
|
||||
## API вызовы
|
||||
|
||||
### Axios Client (`src/api/client.js`)
|
||||
|
||||
```js
|
||||
const api = axios.create({ baseURL: VITE_API_URL })
|
||||
|
||||
// Request interceptor: добавляет Bearer токен из localStorage
|
||||
api.interceptors.request → Authorization: Bearer <access_token>
|
||||
|
||||
// Response interceptor: при 401 делает refresh и повторяет запрос
|
||||
api.interceptors.response → POST /auth/refresh → обновляет tokens в localStorage
|
||||
```
|
||||
|
||||
### API модули
|
||||
|
||||
```js
|
||||
// tasks.js
|
||||
tasksApi.list(completed?) → GET /tasks
|
||||
tasksApi.today() → GET /tasks/today
|
||||
tasksApi.create(data) → POST /tasks
|
||||
tasksApi.complete(id) → POST /tasks/{id}/complete
|
||||
tasksApi.uncomplete(id) → POST /tasks/{id}/uncomplete
|
||||
tasksApi.update(id, data) → PUT /tasks/{id}
|
||||
tasksApi.delete(id) → DELETE /tasks/{id}
|
||||
|
||||
// habits.js
|
||||
habitsApi.list() → GET /habits
|
||||
habitsApi.create(data) → POST /habits
|
||||
habitsApi.log(id, data) → POST /habits/{id}/log
|
||||
habitsApi.stats() → GET /habits/stats
|
||||
habitsApi.habitStats(id) → GET /habits/{id}/stats
|
||||
|
||||
// finance.js
|
||||
financeApi.getCategories() → GET /finance/categories
|
||||
financeApi.createCategory(data) → POST /finance/categories
|
||||
financeApi.getTransactions(m, y) → GET /finance/transactions?month=&year=
|
||||
financeApi.createTransaction(data) → POST /finance/transactions
|
||||
financeApi.getSummary(m, y) → GET /finance/summary
|
||||
financeApi.getAnalytics() → GET /finance/analytics
|
||||
|
||||
// savings.js
|
||||
savingsApi.getCategories() → GET /savings/categories
|
||||
savingsApi.createCategory(data) → POST /savings/categories
|
||||
savingsApi.getTransactions() → GET /savings/transactions
|
||||
savingsApi.getStats() → GET /savings/stats
|
||||
|
||||
// profile.js
|
||||
profileApi.get() → GET /profile
|
||||
profileApi.update(data) → PUT /profile
|
||||
```
|
||||
|
||||
## State Management
|
||||
|
||||
**Zustand** — единственный store: `src/store/auth.js`
|
||||
|
||||
```js
|
||||
useAuthStore = {
|
||||
user: null | User,
|
||||
isLoading: boolean,
|
||||
isAuthenticated: boolean,
|
||||
|
||||
initialize() // Вызывается в App.jsx useEffect: GET /auth/me
|
||||
login(email, password) // POST /auth/login, сохраняет tokens
|
||||
register(email, username, password)
|
||||
logout() // Чистит localStorage + state
|
||||
}
|
||||
```
|
||||
|
||||
**React Context:**
|
||||
- `ThemeContext` (`contexts/ThemeContext.jsx`) — dark/light mode, сохраняется в localStorage
|
||||
|
||||
**Нет Redux / React Query** — данные загружаются локально в компонентах через `useState + useEffect`.
|
||||
|
||||
## Основные зависимости
|
||||
|
||||
| Пакет | Версия | Назначение |
|
||||
|-------|--------|------------|
|
||||
| react | 18.2 | UI framework |
|
||||
| react-router-dom | 6.22 | Роутинг |
|
||||
| zustand | 4.5 | State management |
|
||||
| axios | 1.6 | HTTP клиент |
|
||||
| tailwindcss | 3.4 | CSS utility framework |
|
||||
| framer-motion | 11 | Анимации |
|
||||
| lucide-react | 0.312 | Иконки |
|
||||
| recharts | 2.12 | Графики |
|
||||
| date-fns | 3.3 | Утилиты дат |
|
||||
| clsx | 2.1 | Условные классы |
|
||||
| storybook | 8.5 | UI компонент-браузер (dev) |
|
||||
| vitest | 4 | Тесты |
|
||||
|
||||
## Конфигурация
|
||||
|
||||
| Env переменная | Описание | Default |
|
||||
|---------------|----------|---------|
|
||||
| `VITE_API_URL` | URL backend API | `https://api.digital-home.site` |
|
||||
|
||||
## Где искать что
|
||||
|
||||
| Задача | Файл |
|
||||
|--------|------|
|
||||
| **Новая страница** | `src/pages/NewPage.jsx` + роут в `App.jsx` + ссылка в `Navigation.jsx` |
|
||||
| **Новый компонент** | `src/components/NewComponent.jsx` |
|
||||
| **Новый API вызов** | `src/api/<domain>.js` (добавить метод) |
|
||||
| **Финансы: UI** | `src/pages/Finance.jsx`, `src/components/finance/` |
|
||||
| **Финансы: API** | `src/api/finance.js` |
|
||||
| **Привычки: UI** | `src/pages/Habits.jsx`, `CreateHabitModal`, `LogHabitModal` |
|
||||
| **Привычки: API** | `src/api/habits.js` |
|
||||
| **Задачи: UI** | `src/pages/Tasks.jsx`, `CreateTaskModal`, `EditTaskModal` |
|
||||
| **Задачи: API** | `src/api/tasks.js` |
|
||||
| **Авторизация** | `src/store/auth.js`, `src/pages/Login.jsx` |
|
||||
| **Глобальные стили** | `src/index.css` + `tailwind.config.js` |
|
||||
| **Темная тема** | `src/contexts/ThemeContext.jsx` |
|
||||
| **Нижняя навигация** | `src/components/Navigation.jsx` |
|
||||
|
||||
## Заметки
|
||||
|
||||
- `Finance` страница не добавлена в роутер и навигацию для обычных пользователей — только для owner (id=1)
|
||||
- Legacy роуты `/habits`, `/tasks`, `/stats` → редиректят на `/tracker`
|
||||
- Токены хранятся в `localStorage`: `access_token`, `refresh_token`
|
||||
- Auto-refresh токена при 401 ответе (в axios interceptor)
|
||||
112
Инфраструктура/Сервисы/README.md
Normal file
112
Инфраструктура/Сервисы/README.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# Сервисы VM 192.168.31.60
|
||||
|
||||
Все Docker-сервисы развёрнуты в `/opt/digital-home/` на VM Сервисы.
|
||||
Общая сеть: `services_proxy` (создана в `services/docker-compose.yml`).
|
||||
Внешний трафик: Nginx Proxy Manager → домены `*.digital-home.site`.
|
||||
|
||||
## Сводная таблица
|
||||
|
||||
| Сервис | Папка | Домен | Порты (внешние) | Статус |
|
||||
|--------|-------|-------|-----------------|--------|
|
||||
| Nginx Proxy Manager | services/ | — (точка входа) | 80, 81, 443 | ✅ Up |
|
||||
| Gitea | gitea/ | git.digital-home.site | — (NPM) | ✅ Up |
|
||||
| Gitea Runner | gitea-runner/ | — | — | ✅ Up |
|
||||
| Homepage | homepage/ | home.digital-home.site | — (NPM) | ✅ Up |
|
||||
| Jellyfin | media/ | — | — (NPM) | ✅ Up |
|
||||
| qBittorrent | media/ | — | 6881 | ❌ Stopped |
|
||||
| Nextcloud | nextcloud/ | cloud.digital-home.site | 5433 (db) | ✅ Up |
|
||||
| Immich | photo/ | — | — (NPM) | ✅ Up |
|
||||
| Portainer | portainer/ | portainer.digital-home.site | — (NPM) | ✅ Up |
|
||||
| Uptime Kuma | uptime-kuma/ | — | — (NPM) | ✅ Up |
|
||||
| Vaultwarden | vault/ | vault.digital-home.site | — (NPM) | ✅ Up |
|
||||
| Vikunja | vikunja/ | tasks.digital-home.site | — (NPM) | ✅ Up |
|
||||
| Menu Bot | bots/menu/ | — | — | ❓ Unknown |
|
||||
| Review Bot | review-bot/ | — | 3300 | ✅ Up |
|
||||
| Cosmo Studio | cosmo-studio/ | — | — (NPM) | ✅ Up |
|
||||
| Pulse API | homelab-api/ | api.digital-home.site | 8081 (dev) | ✅ Up |
|
||||
| Pulse Web | pulse-web/ | pulse.digital-home.site | 5174 (dev) | ✅ Up |
|
||||
| Storybook | storybook/ | — | 6006 | ✅ Up |
|
||||
| Health Webhook | health-webhook/ | health.digital-home.site | 3200 | ✅ Up |
|
||||
| IT Tools | it-tools/ | — | — (NPM) | ✅ Up |
|
||||
| Savings | savings/ | — | — (NPM) | ❌ Stopped |
|
||||
| AdventureLog | adventurelog/ | — | — | ❌ Stopped |
|
||||
| LangLearn | langlearn/ | — | — | ❌ Stopped |
|
||||
| Lingua Learn | lingua-learn/ | — | — | ❌ Stopped |
|
||||
| My Game (Своя Игра) | my-game/ | — | — | ❌ Stopped |
|
||||
| Japan App | japan-app/ | — | — | ❌ Stopped |
|
||||
| VPN Invite | vpn-invite/ | — | 3500 | ✅ Up |
|
||||
| VPN Router | vpn-router/ | — | host network | ❌ Stopped |
|
||||
| Webhook Deploy | webhook-deploy/ | — | 9000 | ❓ Unknown |
|
||||
|
||||
## Запущенные сервисы (docker ps)
|
||||
|
||||
Статус на момент документирования (02.04.2026):
|
||||
|
||||
```
|
||||
homelab-api Up 19 hours
|
||||
vpn-invite Up 21 hours
|
||||
cosmo-studio (x2) Up 3 days
|
||||
uptime-kuma Up 5 days (healthy)
|
||||
jellyfin Up 6 days (healthy)
|
||||
gitea-runner Up 6 days
|
||||
review-bot Up 6 days
|
||||
health-webhook Up 7 days
|
||||
pulse-web Up 12 days
|
||||
pulse-web-dev Up 4 weeks
|
||||
pulse-api-dev Up 4 weeks
|
||||
storybook Up 4 weeks
|
||||
nginx_proxy_manager Up 26 hours
|
||||
homelab-db Up 4 weeks (healthy)
|
||||
it-tools Up 4 weeks
|
||||
homepage Up 4 weeks (healthy)
|
||||
immich_server Up 4 weeks (healthy)
|
||||
immich_redis Up 4 weeks
|
||||
immich_postgres Up 4 weeks
|
||||
immich_ml Up 4 weeks (healthy)
|
||||
vikunja Up 4 weeks
|
||||
vikunja_db Up 4 weeks
|
||||
vaultwarden Up 4 weeks (healthy)
|
||||
portainer Up 4 weeks
|
||||
nextcloud_app Up 4 weeks
|
||||
nextcloud_db Up 4 weeks
|
||||
nextcloud_redis Up 4 weeks
|
||||
gitea Up 4 weeks
|
||||
```
|
||||
|
||||
## Архитектура сети
|
||||
|
||||
```
|
||||
Интернет
|
||||
↓
|
||||
Nginx Proxy Manager (80/443)
|
||||
↓ (services_proxy network)
|
||||
┌───────────────────────────────┐
|
||||
│ Все сервисы в одной сети │
|
||||
│ services_proxy │
|
||||
│ │
|
||||
│ git.* → gitea:3000 │
|
||||
│ home.* → homepage:3000 │
|
||||
│ cloud.* → nextcloud_app:80 │
|
||||
│ vault.* → vaultwarden:80 │
|
||||
│ tasks.* → vikunja:3456 │
|
||||
│ portainer.* → portainer:9000 │
|
||||
│ api.* → homelab-api:8080 │
|
||||
│ pulse.* → pulse-web:80 │
|
||||
│ health.* → health-webhook:3200│
|
||||
└───────────────────────────────┘
|
||||
```
|
||||
|
||||
## Паттерн добавления сервиса
|
||||
|
||||
```bash
|
||||
mkdir /opt/digital-home/<name>
|
||||
cd /opt/digital-home/<name>
|
||||
|
||||
# docker-compose.yml с сетью:
|
||||
networks:
|
||||
services_proxy:
|
||||
external: true
|
||||
|
||||
docker compose up -d
|
||||
# Добавить proxy host в NPM UI (порт 81)
|
||||
```
|
||||
38
Инфраструктура/Сервисы/adventurelog.md
Normal file
38
Инфраструктура/Сервисы/adventurelog.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# AdventureLog
|
||||
|
||||
## Назначение
|
||||
Приложение для логирования путешествий и приключений. Ведение дневника поездок с геолокацией.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| adventurelog-frontend | ghcr.io/seanmorley15/adventurelog-frontend:latest |
|
||||
| adventurelog-backend | ghcr.io/seanmorley15/adventurelog-backend:latest |
|
||||
| adventurelog-db | postgis/postgis:16-3.5 |
|
||||
|
||||
## Порты
|
||||
Нет внешних портов (через NPM).
|
||||
|
||||
## Volumes
|
||||
|
||||
| Volume | Контейнер | Путь контейнера | Содержимое |
|
||||
|--------|-----------|----------------|------------|
|
||||
| postgres_data | adventurelog-db | /var/lib/postgresql/data | БД PostGIS |
|
||||
| adventurelog_media | adventurelog-backend | /code/media/ | Медиа-файлы |
|
||||
|
||||
## Домен
|
||||
Через NPM (не указан явно).
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (external)
|
||||
- `default` (internal между frontend и backend)
|
||||
|
||||
## Env переменные
|
||||
Из `env_file: .env` (ключи неизвестны).
|
||||
|
||||
## Статус
|
||||
❌ **Не запущен** (не найден в `docker ps`)
|
||||
|
||||
## Заметки
|
||||
- Использует PostGIS (PostgreSQL с геопространственными расширениями)
|
||||
42
Инфраструктура/Сервисы/bots-menu.md
Normal file
42
Инфраструктура/Сервисы/bots-menu.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Menu Bot (bots/menu)
|
||||
|
||||
## Назначение
|
||||
Telegram-бот для отображения меню / навигации. Написан на Go.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| menu-bot | local build (Go) |
|
||||
|
||||
## Порты
|
||||
Нет внешних портов.
|
||||
|
||||
## Volumes
|
||||
|
||||
| Путь хоста | Путь контейнера | Содержимое |
|
||||
|-----------|----------------|------------|
|
||||
| ./data | /root/data | Данные бота |
|
||||
|
||||
## Домен
|
||||
Нет.
|
||||
|
||||
## Сети
|
||||
Нет явной сети (использует `env_file: .env`).
|
||||
|
||||
## Env переменные
|
||||
Из `.env` файла (ключи неизвестны — файл не читался).
|
||||
|
||||
## Статус
|
||||
❓ **Статус неизвестен** (не найден в `docker ps`)
|
||||
|
||||
## Структура проекта
|
||||
```
|
||||
bots/menu/
|
||||
├── cmd/ # Точка входа
|
||||
├── internal/ # Логика бота
|
||||
├── data/ # Данные
|
||||
├── Dockerfile
|
||||
├── docker-compose.yml
|
||||
└── go.mod
|
||||
```
|
||||
36
Инфраструктура/Сервисы/cosmo-studio.md
Normal file
36
Инфраструктура/Сервисы/cosmo-studio.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Cosmo Studio
|
||||
|
||||
## Назначение
|
||||
Web-интерфейс для OpenClaw AI-ассистента (Cosmo). Bridge-сервис соединяется с OpenClaw instance, frontend предоставляет UI для взаимодействия.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| cosmo-studio-bridge-1 | local build (Dockerfile) |
|
||||
| cosmo-studio-frontend-1 | local build (Dockerfile.frontend) |
|
||||
|
||||
## Порты
|
||||
|
||||
| Контейнер | Внутренний | Назначение |
|
||||
|-----------|-----------|------------|
|
||||
| bridge | 3401-3402 | WebSocket bridge |
|
||||
| frontend | 80 | Web UI |
|
||||
|
||||
## Volumes
|
||||
Нет persistent volumes (конфиг через env).
|
||||
|
||||
## Домен
|
||||
Через NPM (не указан явно).
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (external)
|
||||
- `internal` (bridge между bridge и frontend)
|
||||
|
||||
## Env переменные
|
||||
- `OPENCLAW_URL` (ws://192.168.31.103:18789)
|
||||
- `OPENCLAW_TOKEN`
|
||||
- `SSH_KEY_PATH`
|
||||
|
||||
## Статус
|
||||
✅ **Запущен** (Up 3 days)
|
||||
40
Инфраструктура/Сервисы/gitea-runner.md
Normal file
40
Инфраструктура/Сервисы/gitea-runner.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Gitea Actions Runner
|
||||
|
||||
## Назначение
|
||||
CI/CD runner для выполнения Gitea Actions workflows. Запускает задачи сборки, тестирования и деплоя при push/PR в Gitea.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| gitea-runner | gitea-runner-runner (local build) |
|
||||
|
||||
## Порты
|
||||
Нет внешних портов.
|
||||
|
||||
## Volumes
|
||||
|
||||
| Путь хоста | Путь контейнера | Содержимое |
|
||||
|-----------|----------------|------------|
|
||||
| /var/run/docker.sock | /var/run/docker.sock | Docker socket (для запуска контейнеров) |
|
||||
| runner_data | /data | Данные runner'а |
|
||||
| ./config.yaml | /config/config.yaml | Конфиг runner'а |
|
||||
|
||||
## Домен
|
||||
Нет.
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
- `GITEA_INSTANCE_URL`
|
||||
- `GITEA_RUNNER_REGISTRATION_TOKEN`
|
||||
- `GITEA_RUNNER_NAME`
|
||||
- `CONFIG_FILE`
|
||||
|
||||
## Статус
|
||||
✅ **Запущен** (Up 6 days)
|
||||
|
||||
## Заметки
|
||||
- `privileged: true` — нужно для запуска вложенных Docker-контейнеров в workflows
|
||||
- Подключается к Gitea по `http://gitea:3000`
|
||||
47
Инфраструктура/Сервисы/gitea.md
Normal file
47
Инфраструктура/Сервисы/gitea.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Gitea
|
||||
|
||||
## Назначение
|
||||
Self-hosted Git-хостинг. Хранит репозитории проектов (pulse-api, pulse-web, obsidian и другие). Поддерживает Gitea Actions для CI/CD.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| gitea | gitea/gitea:latest |
|
||||
|
||||
## Порты
|
||||
|
||||
| Внутренний | Протокол | Назначение |
|
||||
|-----------|---------|------------|
|
||||
| 3000 | HTTP | Web UI + API |
|
||||
| 22 | TCP | SSH для git |
|
||||
|
||||
(Порты открыты только в сети, внешний доступ через NPM)
|
||||
|
||||
## Volumes
|
||||
|
||||
| Путь хоста | Путь контейнера | Содержимое |
|
||||
|-----------|----------------|------------|
|
||||
| ./data | /data | Репозитории, конфиги, БД (SQLite) |
|
||||
| /etc/timezone | /etc/timezone | Временная зона (ro) |
|
||||
| /etc/localtime | /etc/localtime | Локальное время (ro) |
|
||||
|
||||
## Домен
|
||||
`https://git.digital-home.site`
|
||||
|
||||
## Сети
|
||||
- `gitea_backend` (internal)
|
||||
- `services_proxy` (external, для NPM)
|
||||
|
||||
## Env переменные
|
||||
- `USER_UID`
|
||||
- `USER_GID`
|
||||
- `GITEA__server__DOMAIN`
|
||||
- `GITEA__server__ROOT_URL`
|
||||
|
||||
## Статус
|
||||
✅ **Запущен** (Up 4 weeks)
|
||||
|
||||
## Связанные сервисы
|
||||
- `gitea-runner` — CI/CD runner для Gitea Actions
|
||||
- `review-bot` — AI ревью PR через webhook
|
||||
37
Инфраструктура/Сервисы/health-webhook.md
Normal file
37
Инфраструктура/Сервисы/health-webhook.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Health Webhook
|
||||
|
||||
## Назначение
|
||||
Webhook-сервис для проверки здоровья / health check инфраструктуры. Node.js сервис с JWT-авторизацией, возможно интеграция с email-уведомлениями через Resend.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| health-webhook | local build (Node.js) |
|
||||
|
||||
## Порты
|
||||
|
||||
| Внешний | Внутренний | Назначение |
|
||||
|---------|-----------|------------|
|
||||
| 3200 | 3200 | HTTP API |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Путь хоста | Путь контейнера | Содержимое |
|
||||
|-----------|----------------|------------|
|
||||
| ./data | /app/data | Данные сервиса |
|
||||
|
||||
## Домен
|
||||
`https://health.digital-home.site`
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
- `JWT_SECRET`
|
||||
- `NODE_ENV`
|
||||
- `RESEND_API_KEY`
|
||||
- `APP_URL`
|
||||
|
||||
## Статус
|
||||
✅ **Запущен** (Up 7 days)
|
||||
40
Инфраструктура/Сервисы/homepage.md
Normal file
40
Инфраструктура/Сервисы/homepage.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Homepage
|
||||
|
||||
## Назначение
|
||||
Стартовая страница / дашборд домашней лаборатории. Показывает все сервисы, их статусы, виджеты (погода, календарь и т.д.).
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| homepage | ghcr.io/gethomepage/homepage:latest |
|
||||
|
||||
## Порты
|
||||
|
||||
| Внутренний | Назначение |
|
||||
|-----------|------------|
|
||||
| 3000 | Web UI |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Путь хоста | Путь контейнера | Содержимое |
|
||||
|-----------|----------------|------------|
|
||||
| ./config | /app/config | YAML-конфиги (services, widgets, bookmarks) |
|
||||
| ./icons | /app/public/icons | Пользовательские иконки |
|
||||
| /var/run/docker.sock | /var/run/docker.sock | Docker socket (для статусов контейнеров, ro) |
|
||||
|
||||
## Домен
|
||||
`https://home.digital-home.site`
|
||||
|
||||
## Сети
|
||||
- `homepage_backend` (internal)
|
||||
- `services_proxy` (external, для NPM)
|
||||
|
||||
## Env переменные
|
||||
- `PUID`
|
||||
- `PGID`
|
||||
- `TZ`
|
||||
- `HOMEPAGE_ALLOWED_HOSTS`
|
||||
|
||||
## Статус
|
||||
✅ **Запущен** (Up 4 weeks, healthy)
|
||||
31
Инфраструктура/Сервисы/it-tools.md
Normal file
31
Инфраструктура/Сервисы/it-tools.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# IT Tools
|
||||
|
||||
## Назначение
|
||||
Коллекция онлайн-инструментов для разработчиков: конверторы форматов, генераторы, кодировщики, хэши и т.д.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| it-tools | corentinth/it-tools:latest |
|
||||
|
||||
## Порты
|
||||
|
||||
| Внутренний | Назначение |
|
||||
|-----------|------------|
|
||||
| 80 | Web UI (через NPM) |
|
||||
|
||||
## Volumes
|
||||
Нет.
|
||||
|
||||
## Домен
|
||||
Через NPM (не указан явно).
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
Нет.
|
||||
|
||||
## Статус
|
||||
✅ **Запущен** (Up 4 weeks)
|
||||
31
Инфраструктура/Сервисы/japan-app.md
Normal file
31
Инфраструктура/Сервисы/japan-app.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Japan App
|
||||
|
||||
## Назначение
|
||||
PWA-гид по Японии. Содержит список мест (92+), расписание поездки, карты.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| japan-app | local build |
|
||||
|
||||
## Порты
|
||||
Нет (через NPM).
|
||||
|
||||
## Volumes
|
||||
Нет.
|
||||
|
||||
## Домен
|
||||
Через NPM (не указан явно).
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
Нет.
|
||||
|
||||
## Статус
|
||||
❌ **Не запущен** (не найден в `docker ps`)
|
||||
|
||||
## Заметки
|
||||
- `watchtower.enable=false` — не обновляется автоматически
|
||||
39
Инфраструктура/Сервисы/langlearn.md
Normal file
39
Инфраструктура/Сервисы/langlearn.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# LangLearn
|
||||
|
||||
## Назначение
|
||||
Приложение для изучения языков. Go backend + React frontend с PostgreSQL.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| langlearn-backend | local build (Go) |
|
||||
| langlearn-frontend | local build (React) |
|
||||
| langlearn-db | postgres:16-alpine |
|
||||
|
||||
## Порты
|
||||
|
||||
| Контейнер | Внутренний | Назначение |
|
||||
|-----------|-----------|------------|
|
||||
| backend | 8080 | REST API (через NPM) |
|
||||
| frontend | — | Web UI (через NPM) |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Volume | Контейнер | Путь контейнера | Содержимое |
|
||||
|--------|-----------|----------------|------------|
|
||||
| pgdata | db | /var/lib/postgresql/data | БД |
|
||||
|
||||
## Домен
|
||||
Через NPM (не указан явно).
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (external)
|
||||
- `internal` (между backend и db)
|
||||
|
||||
## Env переменные
|
||||
- `DATABASE_URL`
|
||||
- `PORT`
|
||||
|
||||
## Статус
|
||||
❌ **Не запущен** (не найден в `docker ps`)
|
||||
34
Инфраструктура/Сервисы/lingua-learn.md
Normal file
34
Инфраструктура/Сервисы/lingua-learn.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Lingua Learn
|
||||
|
||||
## Назначение
|
||||
Приложение для изучения языков (альтернативная версия). Node.js backend + React frontend.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| lingua-learn-client | local build (React) |
|
||||
| lingua-learn-server | local build (Node.js) |
|
||||
| lingua-learn-db | postgres:16-alpine |
|
||||
|
||||
## Порты
|
||||
Нет внешних портов (через NPM).
|
||||
|
||||
## Volumes
|
||||
|
||||
| Volume | Контейнер | Путь контейнера | Содержимое |
|
||||
|--------|-----------|----------------|------------|
|
||||
| postgres_data | db | /var/lib/postgresql/data | БД |
|
||||
|
||||
## Домен
|
||||
Через NPM (не указан явно).
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
- `DATABASE_URL`
|
||||
- `NODE_ENV`
|
||||
|
||||
## Статус
|
||||
❌ **Не запущен** (не найден в `docker ps`)
|
||||
50
Инфраструктура/Сервисы/media.md
Normal file
50
Инфраструктура/Сервисы/media.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Media (Jellyfin + qBittorrent)
|
||||
|
||||
## Назначение
|
||||
Медиа-стек: скачивание торрентов (qBittorrent) и стриминг медиа-контента (Jellyfin).
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| jellyfin | jellyfin/jellyfin:latest |
|
||||
| qbittorrent | lscr.io/linuxserver/qbittorrent:latest |
|
||||
|
||||
## Порты
|
||||
|
||||
| Контейнер | Внешний | Внутренний | Назначение |
|
||||
|-----------|---------|-----------|------------|
|
||||
| qbittorrent | 6881 | 6881 | BitTorrent TCP |
|
||||
| qbittorrent | 6881/udp | 6881/udp | BitTorrent UDP |
|
||||
| jellyfin | — | 8096 | Web UI (через NPM) |
|
||||
| qbittorrent | — | 8080 | Web UI (через NPM) |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Путь хоста | Контейнер | Путь контейнера | Содержимое |
|
||||
|-----------|-----------|----------------|------------|
|
||||
| ./qbittorrent/config | qbittorrent | /config | Конфиг qBittorrent |
|
||||
| ./downloads | qbittorrent | /downloads | Загруженные файлы |
|
||||
| ./jellyfin/config | jellyfin | /config | Конфиг Jellyfin |
|
||||
| ./jellyfin/cache | jellyfin | /cache | Кэш Jellyfin |
|
||||
| ./downloads | jellyfin | /data/downloads | Медиа-файлы (ro) |
|
||||
| ../nextcloud/nextcloud_data/data | jellyfin | /data/nextcloud | Файлы Nextcloud (ro) |
|
||||
|
||||
## Домен
|
||||
Через NPM (не указан явно в конфиге).
|
||||
|
||||
## Сети
|
||||
- `media_backend` (internal)
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
- `PUID`, `PGID`, `TZ` (оба контейнера)
|
||||
- `WEBUI_PORT` (qbittorrent)
|
||||
|
||||
## Статус
|
||||
- ✅ jellyfin: **Запущен** (Up 6 days, healthy)
|
||||
- ❌ qbittorrent: **Не запущен**
|
||||
|
||||
## Заметки
|
||||
- Jellyfin имеет доступ к файлам Nextcloud через bind mount
|
||||
- Закомментированная секция GPU-транскодинга для Intel
|
||||
41
Инфраструктура/Сервисы/my-game-svoya-igra.md
Normal file
41
Инфраструктура/Сервисы/my-game-svoya-igra.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# My Game (Своя игра)
|
||||
|
||||
## Назначение
|
||||
Веб-версия игры "Своя Игра" (аналог Jeopardy). Node.js/Express backend + React frontend + MongoDB.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| svoya-igra-client | local build (React) |
|
||||
| svoya-igra-server | local build (Node.js) |
|
||||
| svoya-igra-mongodb | mongo:7 |
|
||||
|
||||
## Порты
|
||||
|
||||
| Контейнер | Внутренний | Назначение |
|
||||
|-----------|-----------|------------|
|
||||
| server | 3001 | REST API (через NPM) |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Volume | Контейнер | Путь контейнера | Содержимое |
|
||||
|--------|-----------|----------------|------------|
|
||||
| mongodb_data | mongodb | /data/db | MongoDB данные |
|
||||
| ./server/public | server | /app/public | Статичные файлы |
|
||||
|
||||
## Домен
|
||||
Через NPM (не указан явно).
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (external)
|
||||
- `internal` (между server и mongodb)
|
||||
|
||||
## Env переменные
|
||||
- `PORT`
|
||||
- `MONGODB_URI`
|
||||
- `NODE_ENV`
|
||||
- `CLIENT_URL`
|
||||
|
||||
## Статус
|
||||
❌ **Не запущен** (не найден в `docker ps`)
|
||||
49
Инфраструктура/Сервисы/nextcloud.md
Normal file
49
Инфраструктура/Сервисы/nextcloud.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Nextcloud
|
||||
|
||||
## Назначение
|
||||
Облачное хранилище файлов (self-hosted аналог Google Drive). Синхронизация файлов, фото, документов.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| nextcloud_app | nextcloud:latest |
|
||||
| nextcloud_db | postgres:15-alpine |
|
||||
| nextcloud_redis | redis:7-alpine |
|
||||
|
||||
## Порты
|
||||
|
||||
| Контейнер | Внешний | Внутренний | Назначение |
|
||||
|-----------|---------|-----------|------------|
|
||||
| nextcloud_db | 5433 | 5432 | PostgreSQL (для прямого доступа) |
|
||||
| nextcloud_app | — | 80 | Web UI (через NPM) |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Путь хоста | Контейнер | Путь контейнера | Содержимое |
|
||||
|-----------|-----------|----------------|------------|
|
||||
| ./db_data | nextcloud_db | /var/lib/postgresql/data | БД PostgreSQL |
|
||||
| ./redis_data | nextcloud_redis | /data | Redis данные |
|
||||
| ./nextcloud_data | nextcloud_app | /var/www/html | Файлы Nextcloud, данные пользователей |
|
||||
|
||||
## Домен
|
||||
`https://cloud.digital-home.site`
|
||||
|
||||
## Сети
|
||||
- `nextcloud_backend` (internal)
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
- `POSTGRES_HOST`, `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD`
|
||||
- `NEXTCLOUD_ADMIN_USER`, `NEXTCLOUD_ADMIN_PASSWORD`
|
||||
- `OVERWRITEPROTOCOL`, `OVERWRITEHOST`
|
||||
- `NEXTCLOUD_TRUSTED_PROXIES`, `TRUSTED_DOMAINS`
|
||||
- `REDIS_HOST`
|
||||
- `PHP_UPLOAD_LIMIT`, `PHP_MEMORY_LIMIT`
|
||||
|
||||
## Статус
|
||||
✅ **Все контейнеры запущены** (Up 4 weeks)
|
||||
|
||||
## Заметки
|
||||
- Файлы Nextcloud монтируются в Jellyfin и Immich для просмотра медиа
|
||||
- Лимит загрузки файлов: 2048 МБ
|
||||
50
Инфраструктура/Сервисы/photo-immich.md
Normal file
50
Инфраструктура/Сервисы/photo-immich.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Immich (photo)
|
||||
|
||||
## Назначение
|
||||
Self-hosted Google Photos альтернатива. Автозагрузка фото с телефона, ML-распознавание лиц и объектов, умный поиск.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| immich_server | ghcr.io/immich-app/immich-server:release |
|
||||
| immich_machine_learning | ghcr.io/immich-app/immich-machine-learning:release |
|
||||
| immich_redis | redis:7-alpine |
|
||||
| immich_postgres | tensorchord/pgvecto-rs:pg14-v0.2.0 |
|
||||
|
||||
## Порты
|
||||
|
||||
| Контейнер | Внутренний | Назначение |
|
||||
|-----------|-----------|------------|
|
||||
| immich_server | 2283 | Web UI (через NPM) |
|
||||
| immich_redis | 6379 | Redis |
|
||||
| immich_postgres | 5432 | PostgreSQL + pgvecto-rs |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Путь хоста | Контейнер | Путь контейнера | Содержимое |
|
||||
|-----------|-----------|----------------|------------|
|
||||
| ./upload | immich_server | /usr/src/app/upload | Загруженные фото |
|
||||
| ./model-cache | immich_ml | /cache | ML-модели |
|
||||
| ./pgdata | immich_postgres | /var/lib/postgresql/data | БД |
|
||||
| ../nextcloud/nextcloud_data/data | immich_server | /mnt/nextcloud | Файлы Nextcloud (ro) |
|
||||
| /etc/localtime | immich_server | /etc/localtime | Время (ro) |
|
||||
|
||||
## Домен
|
||||
Через NPM (не указан явно).
|
||||
|
||||
## Сети
|
||||
- `photo_backend` (internal)
|
||||
- `services_proxy` (external, только immich_server)
|
||||
|
||||
## Env переменные
|
||||
- `DB_HOSTNAME`, `DB_USERNAME`, `DB_PASSWORD`, `DB_DATABASE_NAME`
|
||||
- `REDIS_HOSTNAME`
|
||||
- `POSTGRES_PASSWORD`, `POSTGRES_USER`, `POSTGRES_DB`
|
||||
|
||||
## Статус
|
||||
✅ **Все контейнеры запущены** (Up 4 weeks, immich_server healthy)
|
||||
|
||||
## Заметки
|
||||
- Использует `pgvecto-rs` — PostgreSQL с расширением для векторного поиска (нужно для ML)
|
||||
- immich_machine_learning работает только во внутренней сети
|
||||
38
Инфраструктура/Сервисы/portainer.md
Normal file
38
Инфраструктура/Сервисы/portainer.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Portainer
|
||||
|
||||
## Назначение
|
||||
Web UI для управления Docker. Просмотр контейнеров, образов, volumes, сетей. Визуальный мониторинг всей Docker-инфраструктуры.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| portainer | portainer/portainer-ce:latest |
|
||||
|
||||
## Порты
|
||||
|
||||
| Внутренний | Назначение |
|
||||
|-----------|------------|
|
||||
| 8000 | Edge agent |
|
||||
| 9000 | HTTP Web UI |
|
||||
| 9443 | HTTPS Web UI |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Путь хоста | Путь контейнера | Содержимое |
|
||||
|-----------|----------------|------------|
|
||||
| /var/run/docker.sock | /var/run/docker.sock | Docker socket |
|
||||
| ./data | /data | Данные Portainer (пользователи, настройки) |
|
||||
|
||||
## Домен
|
||||
`https://portainer.digital-home.site`
|
||||
|
||||
## Сети
|
||||
- `portainer_backend` (internal)
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
Нет (кроме `security_opt: no-new-privileges:true`).
|
||||
|
||||
## Статус
|
||||
✅ **Запущен** (Up 4 weeks)
|
||||
49
Инфраструктура/Сервисы/pulse-api-homelab-api.md
Normal file
49
Инфраструктура/Сервисы/pulse-api-homelab-api.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Pulse API (homelab-api)
|
||||
|
||||
## Назначение
|
||||
Backend API для приложения Pulse — трекер привычек, задач, финансов, накоплений. Go REST API + Telegram бот.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| homelab-api | local build (Go) |
|
||||
| homelab-db | postgres:16-alpine |
|
||||
| pulse-api-dev | local build (dev instance, порт 8081) |
|
||||
|
||||
## Порты
|
||||
|
||||
| Контейнер | Внешний | Внутренний | Назначение |
|
||||
|-----------|---------|-----------|------------|
|
||||
| homelab-api | — | 8080 | REST API (через NPM → api.digital-home.site) |
|
||||
| pulse-api-dev | 8081 | 8080 | Dev-инстанс API |
|
||||
| homelab-db | — | 5432 | PostgreSQL |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Volume | Путь контейнера | Содержимое |
|
||||
|--------|----------------|------------|
|
||||
| postgres_data | /var/lib/postgresql/data | БД |
|
||||
|
||||
## Домен
|
||||
`https://api.digital-home.site`
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (external)
|
||||
- `internal` (между api и db)
|
||||
|
||||
## Env переменные
|
||||
- `DATABASE_URL`
|
||||
- `JWT_SECRET`
|
||||
- `PORT`
|
||||
- `RESEND_API_KEY`
|
||||
- `FROM_EMAIL`
|
||||
- `FROM_NAME`
|
||||
- `APP_URL`
|
||||
- `TELEGRAM_BOT_TOKEN`
|
||||
|
||||
## Статус
|
||||
✅ **Запущен** (homelab-api: Up 19 hours, homelab-db: Up 4 weeks, pulse-api-dev: Up 4 weeks)
|
||||
|
||||
## Подробная документация
|
||||
→ [[pulse-api]]
|
||||
36
Инфраструктура/Сервисы/pulse-web.md
Normal file
36
Инфраструктура/Сервисы/pulse-web.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Pulse Web
|
||||
|
||||
## Назначение
|
||||
Frontend React-приложение для Pulse. Трекер привычек, задач, финансов, накоплений.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| pulse-web | local build (React/Vite) |
|
||||
| pulse-web-dev | local build (dev instance, порт 5174) |
|
||||
|
||||
## Порты
|
||||
|
||||
| Контейнер | Внешний | Внутренний | Назначение |
|
||||
|-----------|---------|-----------|------------|
|
||||
| pulse-web | — | 80 | Prod (через NPM → pulse.digital-home.site) |
|
||||
| pulse-web-dev | 5174 | 80 | Dev-инстанс |
|
||||
|
||||
## Volumes
|
||||
Нет persistent volumes.
|
||||
|
||||
## Домен
|
||||
`https://pulse.digital-home.site`
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
- `VITE_API_URL`
|
||||
|
||||
## Статус
|
||||
✅ **Запущен** (pulse-web: Up 12 days, pulse-web-dev: Up 4 weeks)
|
||||
|
||||
## Подробная документация
|
||||
→ [[pulse-web]]
|
||||
46
Инфраструктура/Сервисы/review-bot.md
Normal file
46
Инфраструктура/Сервисы/review-bot.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Review Bot
|
||||
|
||||
## Назначение
|
||||
AI-бот для автоматического code review Pull Request'ов в Gitea. Получает вебхуки от Gitea, клонирует репозиторий, анализирует изменения через Anthropic Claude и оставляет комментарии.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| review-bot | local build (Node.js) |
|
||||
|
||||
## Порты
|
||||
|
||||
| Внешний | Внутренний | Назначение |
|
||||
|---------|-----------|------------|
|
||||
| 3300 | 3300 | HTTP webhook endpoint |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Volume | Путь контейнера | Содержимое |
|
||||
|--------|----------------|------------|
|
||||
| review-bot-logs | /var/log/review-bot | Логи ревью |
|
||||
|
||||
## Домен
|
||||
Нет (доступен только изнутри сети).
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
- `GITEA_URL`
|
||||
- `GITEA_TOKEN`
|
||||
- `WEBHOOK_SECRET`
|
||||
- `ANTHROPIC_URL` (прокси через AI-proxy на 192.168.31.103:3301)
|
||||
- `PROXY_KEY`
|
||||
- `LOG_FILE`
|
||||
- `CLONE_BASE_DIR`
|
||||
- `PORT`
|
||||
|
||||
## Статус
|
||||
✅ **Запущен** (Up 6 days)
|
||||
|
||||
## Заметки
|
||||
- Использует AI-proxy (`192.168.31.103:3301`) т.к. Anthropic API key работает только с основной машины OpenClaw
|
||||
- Вебхук настроен для репозиториев pulse-api и pulse-web
|
||||
- Директория для клонирования: `/tmp/review-bot-clones`
|
||||
52
Инфраструктура/Сервисы/savings.md
Normal file
52
Инфраструктура/Сервисы/savings.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Savings (семейные накопления)
|
||||
|
||||
## Назначение
|
||||
Приложение для совместного управления накоплениями. Go backend + React frontend. Поддержка категорий накоплений, участников, регулярных планов, начисления процентов.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| savings-backend | local build (Go) |
|
||||
| savings-frontend | local build (React) |
|
||||
|
||||
## Порты
|
||||
|
||||
| Контейнер | Внутренний | Назначение |
|
||||
|-----------|-----------|------------|
|
||||
| savings-backend | 9090 | REST API (через NPM) |
|
||||
| savings-frontend | — | Web UI (через NPM) |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Путь хоста | Контейнер | Путь контейнера | Содержимое |
|
||||
|-----------|-----------|----------------|------------|
|
||||
| ./savings.db | backend | /root/savings.db | SQLite БД |
|
||||
|
||||
## Домен
|
||||
Через NPM (не указан явно).
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
**Backend:**
|
||||
- `DB_NAME`, `DB_TYPE`
|
||||
- `JWT_SECRET`, `JWT_EXPIRES_IN`
|
||||
- `PORT`, `GIN_MODE`
|
||||
- `FRONTEND_URL`
|
||||
- `INTEREST_CALCULATION_ENABLED`, `INTEREST_CALCULATION_INTERVAL`
|
||||
- `SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`
|
||||
- `FROM_EMAIL`, `FROM_NAME`, `EMAIL_ENABLED`
|
||||
|
||||
**Frontend (build args):**
|
||||
- `REACT_APP_API_URL`
|
||||
- `REACT_APP_APP_NAME`
|
||||
- `REACT_APP_VERSION`
|
||||
|
||||
## Статус
|
||||
❌ **Не запущен** (не найден в `docker ps`)
|
||||
|
||||
## Заметки
|
||||
- Использует SQLite (не PostgreSQL) — данные в одном файле `savings.db`
|
||||
- Встроенный расчёт процентов по расписанию
|
||||
41
Инфраструктура/Сервисы/services-nginx-proxy-manager.md
Normal file
41
Инфраструктура/Сервисы/services-nginx-proxy-manager.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Nginx Proxy Manager (services)
|
||||
|
||||
## Назначение
|
||||
Обратный прокси-сервер. Управляет входящим трафиком (HTTP/HTTPS), SSL-сертификатами (Let's Encrypt), маршрутизирует запросы к контейнерам по доменам `*.digital-home.site`.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| nginx_proxy_manager | jc21/nginx-proxy-manager:latest |
|
||||
|
||||
## Порты
|
||||
|
||||
| Внешний | Внутренний | Назначение |
|
||||
|---------|-----------|------------|
|
||||
| 80 | 80 | HTTP |
|
||||
| 81 | 81 | Web UI (управление NPM) |
|
||||
| 443 | 443 | HTTPS |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Volume | Путь | Содержимое |
|
||||
|--------|------|------------|
|
||||
| ./data | /data | Конфиги прокси-хостов, БД |
|
||||
| ./letsencrypt | /etc/letsencrypt | SSL-сертификаты Let's Encrypt |
|
||||
|
||||
## Домен
|
||||
Нет (сам является точкой входа). UI доступен напрямую через порт 81.
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (создаётся здесь как `proxy`, используется всеми другими сервисами)
|
||||
|
||||
## Env переменные
|
||||
Нет конфигурационных env-переменных.
|
||||
|
||||
## Статус
|
||||
✅ **Запущен** (Up 26 hours)
|
||||
|
||||
## Заметки
|
||||
- Это корневой сервис инфраструктуры — все остальные подключаются к сети `services_proxy`
|
||||
- Управление через UI на порту 81 (только из локальной сети)
|
||||
31
Инфраструктура/Сервисы/storybook.md
Normal file
31
Инфраструктура/Сервисы/storybook.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Storybook
|
||||
|
||||
## Назначение
|
||||
Storybook для разработки UI-компонентов pulse-web. Изолированная среда для разработки и документирования React-компонентов.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| storybook | local build |
|
||||
|
||||
## Порты
|
||||
|
||||
| Внешний | Внутренний | Назначение |
|
||||
|---------|-----------|------------|
|
||||
| 6006 | 80 | Storybook UI |
|
||||
|
||||
## Volumes
|
||||
Нет.
|
||||
|
||||
## Домен
|
||||
Нет (доступен напрямую по порту 6006).
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
Нет.
|
||||
|
||||
## Статус
|
||||
✅ **Запущен** (Up 4 weeks)
|
||||
35
Инфраструктура/Сервисы/uptime-kuma.md
Normal file
35
Инфраструктура/Сервисы/uptime-kuma.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Uptime Kuma
|
||||
|
||||
## Назначение
|
||||
Мониторинг доступности сервисов. Следит за uptime всех хостов и URL, отправляет уведомления при падении.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| uptime-kuma | louislam/uptime-kuma:1 |
|
||||
|
||||
## Порты
|
||||
|
||||
| Внутренний | Назначение |
|
||||
|-----------|------------|
|
||||
| 3001 | Web UI (через NPM) |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Путь хоста | Путь контейнера | Содержимое |
|
||||
|-----------|----------------|------------|
|
||||
| ./data | /app/data | БД мониторинга (SQLite), конфиги |
|
||||
|
||||
## Домен
|
||||
Через NPM (не указан явно).
|
||||
|
||||
## Сети
|
||||
- `uptime_backend` (internal)
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
Нет.
|
||||
|
||||
## Статус
|
||||
✅ **Запущен** (Up 5 days, healthy)
|
||||
38
Инфраструктура/Сервисы/vault-vaultwarden.md
Normal file
38
Инфраструктура/Сервисы/vault-vaultwarden.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Vaultwarden (vault)
|
||||
|
||||
## Назначение
|
||||
Self-hosted менеджер паролей, совместимый с клиентами Bitwarden. Хранит пароли, заметки, карты в зашифрованном виде.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| vaultwarden | vaultwarden/server:latest |
|
||||
|
||||
## Порты
|
||||
|
||||
| Внутренний | Назначение |
|
||||
|-----------|------------|
|
||||
| 80 | Web UI (через NPM) |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Путь хоста | Путь контейнера | Содержимое |
|
||||
|-----------|----------------|------------|
|
||||
| ./data | /data | Зашифрованная БД паролей |
|
||||
|
||||
## Домен
|
||||
`https://vault.digital-home.site`
|
||||
|
||||
## Сети
|
||||
- `vault_backend` (internal)
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
- `DOMAIN`
|
||||
- `LOG_LEVEL`
|
||||
- `EXTENDED_LOGGING`
|
||||
- (закомментированы: `SIGNUPS_ALLOWED`, `ADMIN_TOKEN`, SMTP-настройки)
|
||||
|
||||
## Статус
|
||||
✅ **Запущен** (Up 4 weeks, healthy)
|
||||
48
Инфраструктура/Сервисы/vikunja.md
Normal file
48
Инфраструктура/Сервисы/vikunja.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# Vikunja
|
||||
|
||||
## Назначение
|
||||
Self-hosted менеджер задач (аналог Todoist/Trello). Используется для личных задач, проектов, канбан-досок.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| vikunja | vikunja/vikunja:latest |
|
||||
| vikunja_db | postgres:15-alpine |
|
||||
|
||||
## Порты
|
||||
|
||||
| Контейнер | Внутренний | Назначение |
|
||||
|-----------|-----------|------------|
|
||||
| vikunja | 3456 | Web UI (через NPM) |
|
||||
| vikunja_db | 5432 | PostgreSQL |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Путь хоста | Контейнер | Путь контейнера | Содержимое |
|
||||
|-----------|-----------|----------------|------------|
|
||||
| ./db | vikunja_db | /var/lib/postgresql/data | БД задач |
|
||||
| ./files | vikunja | /app/vikunja/files | Вложения к задачам |
|
||||
|
||||
## Домен
|
||||
`https://tasks.digital-home.site`
|
||||
|
||||
## Сети
|
||||
- `vikunja_backend` (internal)
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
- `VIKUNJA_DATABASE_TYPE`, `VIKUNJA_DATABASE_HOST`, `VIKUNJA_DATABASE_DATABASE`
|
||||
- `VIKUNJA_DATABASE_USER`, `VIKUNJA_DATABASE_PASSWORD`
|
||||
- `VIKUNJA_SERVICE_PUBLICURL`
|
||||
- `VIKUNJA_SERVICE_JWTSECRET`
|
||||
- `VIKUNJA_SERVICE_ENABLEREGISTRATION`
|
||||
- `VIKUNJA_SERVICE_ENABLETASKATTACHMENTS`
|
||||
- `VIKUNJA_SERVICE_TIMEZONE`
|
||||
|
||||
## Статус
|
||||
✅ **Запущен** (Up 4 weeks)
|
||||
|
||||
## Заметки
|
||||
- API токен для автоматизации: `tk_03787e3778789fd5bfaff0542a8dd9390aae0f82`
|
||||
- Проекты: Inbox(1), Личное(3), Dev(4), Япония(5), Финансы(6)
|
||||
37
Инфраструктура/Сервисы/vpn-invite.md
Normal file
37
Инфраструктура/Сервисы/vpn-invite.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# VPN Invite
|
||||
|
||||
## Назначение
|
||||
Сервис для управления приглашениями в VPN. Node.js приложение с SQLite.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| vpn-invite-vpn-invite-1 | node:20-alpine |
|
||||
|
||||
## Порты
|
||||
|
||||
| Внутренний | Назначение |
|
||||
|-----------|------------|
|
||||
| 3500 | HTTP API (через NPM) |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Volume | Путь контейнера | Содержимое |
|
||||
|--------|----------------|------------|
|
||||
| vpn-invite-data | /data | SQLite БД инвайтов |
|
||||
| ./ | /app | Код приложения |
|
||||
|
||||
## Домен
|
||||
Через NPM (не указан явно).
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
- `ADMIN_KEY`
|
||||
- `PORT`
|
||||
- `DB_PATH`
|
||||
|
||||
## Статус
|
||||
✅ **Запущен** (Up 21 hours)
|
||||
35
Инфраструктура/Сервисы/vpn-router.md
Normal file
35
Инфраструктура/Сервисы/vpn-router.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# VPN Router (sing-box)
|
||||
|
||||
## Назначение
|
||||
VPN-маршрутизатор на базе sing-box. Управляет VPN-трафиком, поддерживает разные протоколы.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| vpn-router | ghcr.io/sagernet/sing-box:v1.10.7 |
|
||||
|
||||
## Порты
|
||||
`network_mode: host` — использует все порты хоста напрямую.
|
||||
|
||||
## Volumes
|
||||
|
||||
| Путь хоста | Путь контейнера | Содержимое |
|
||||
|-----------|----------------|------------|
|
||||
| ./config | /etc/sing-box | Конфиг sing-box (config.json) |
|
||||
|
||||
## Домен
|
||||
Нет (работает на уровне сети).
|
||||
|
||||
## Сети
|
||||
`network_mode: host` (нет Docker-сетей).
|
||||
|
||||
## Env переменные
|
||||
Нет.
|
||||
|
||||
## Статус
|
||||
❌ **Не запущен** (не найден в `docker ps`)
|
||||
|
||||
## Заметки
|
||||
- `cap_add: NET_ADMIN` — нужно для управления сетевыми интерфейсами
|
||||
- Конфиг в `./config/config.json`
|
||||
40
Инфраструктура/Сервисы/webhook-deploy.md
Normal file
40
Инфраструктура/Сервисы/webhook-deploy.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Webhook Deploy
|
||||
|
||||
## Назначение
|
||||
Python-сервер для автоматического деплоя через вебхуки. Получает HTTP-запрос → запускает Docker Compose команды для обновления сервисов.
|
||||
|
||||
## Контейнеры
|
||||
|
||||
| Имя | Образ |
|
||||
|-----|-------|
|
||||
| deploy-webhook | python:3.12-alpine |
|
||||
|
||||
## Порты
|
||||
|
||||
| Внешний | Внутренний | Назначение |
|
||||
|---------|-----------|------------|
|
||||
| 9000 | 9000 | HTTP webhook endpoint |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Путь хоста | Путь контейнера | Содержимое |
|
||||
|-----------|----------------|------------|
|
||||
| ./server.py | /app/server.py | Python код сервера |
|
||||
| /var/run/docker.sock | /var/run/docker.sock | Docker socket |
|
||||
| /opt/digital-home | /opt/digital-home | Все проекты (для деплоя) |
|
||||
| /usr/bin/docker | /usr/bin/docker | Docker CLI бинарник |
|
||||
|
||||
## Домен
|
||||
Нет (внутренний доступ).
|
||||
|
||||
## Сети
|
||||
- `services_proxy` (external)
|
||||
|
||||
## Env переменные
|
||||
Нет (конфиг в `server.py`).
|
||||
|
||||
## Статус
|
||||
❓ **Статус неизвестен** (не найден в `docker ps`)
|
||||
|
||||
## Заметки
|
||||
- Имеет доступ к Docker socket и всем проектам — может деплоить любой сервис
|
||||
58
Квартира/Планирование инфраструктуры.md
Normal file
58
Квартира/Планирование инфраструктуры.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# 🏠 Планирование домашней инфраструктуры
|
||||
|
||||
## Текущий сетап
|
||||
- **Mini-PC** — Proxmox, VM с Docker-сервисами + OpenClaw
|
||||
- **Роутер** — Xiaomi Router AX3200
|
||||
- **Умный дом** — Aqara M100 хаб, Zigbee устройства, колонки Яндекс
|
||||
|
||||
## Схема сети (план)
|
||||
|
||||
```
|
||||
Роутер (коридор/гостиная)
|
||||
│
|
||||
└── Cat6 → Кабинет
|
||||
│
|
||||
Свитч
|
||||
├── Mini-PC (Proxmox)
|
||||
├── NAS (Synology DS223j)
|
||||
├── Мой комп
|
||||
└── Комп Светы
|
||||
|
||||
UPS в кабинете питает: свитч + mini-PC + NAS
|
||||
```
|
||||
|
||||
## 🛒 Список покупок
|
||||
|
||||
### 1. NAS + Диски (~46к₽)
|
||||
- **Synology DS223j** — ~28-30к₽
|
||||
- [Ситилинк](https://www.citilink.ru/product/setevoe-hranilische-nas-synology-ds223j-2-bay-nastolnyi-rtd1619b-2049554/)
|
||||
- 2 отсека, RAID 1, Synology DSM
|
||||
- Чисто хранилище: бэкапы, файлы, медиа
|
||||
- **2× WD Red Plus 6TB (WD60EFPX)** — ~8-9к₽ за штуку
|
||||
- [Ситилинк](https://www.citilink.ru/product/zhestkii-disk-wd-red-plus-wd60efpx-6tb-hdd-sata-iii-3-5-1970104/)
|
||||
- CMR, 5400 RPM, 256 МБ кеш, 24/7
|
||||
- RAID 1 = 6 ТБ полезного пространства
|
||||
|
||||
### 2. UPS / ИБП (~8-12к₽)
|
||||
- **APC Back-UPS 650-1000VA**
|
||||
- Защита от отключений электричества
|
||||
- Питает: mini-PC + NAS + свитч
|
||||
- 15-20 минут на корректное завершение
|
||||
|
||||
### 3. Свитч (~3к₽)
|
||||
- **TP-Link TL-SG108E** (8 портов, управляемый)
|
||||
- Гигабит, VLAN поддержка
|
||||
- Ставится в кабинет
|
||||
|
||||
### Итого: ~57-65к₽
|
||||
|
||||
## 📝 Заметки
|
||||
- NAS используется только как хранилище (SMB/NFS), Docker остаётся на VM
|
||||
- При переезде — один Cat6 кабель от роутера до кабинета
|
||||
- Wi-Fi с AX3200 покрывает телефоны, колонки, умный дом
|
||||
- Home Assistant на Proxmox свяжет Aqara + Яндекс
|
||||
|
||||
## Очерёдность
|
||||
1. NAS + диски — расширение хранилища
|
||||
2. UPS — защита данных
|
||||
3. Свитч — когда устройств станет >3 в кабинете
|
||||
24
Квартира/Сеть и доступы.md
Normal file
24
Квартира/Сеть и доступы.md
Normal file
@@ -0,0 +1,24 @@
|
||||
## Распределение сетевой нагрузки
|
||||
|
||||
- Перенести Tailscale с машины OpenClaw в отдельную ВМ для постоянного доступа к домашней сети (минимальный образ, будет только Tailscale)
|
||||
- Создать ВМ для sing-box, который всегда будет подключен к серверу Риги
|
||||
- Удалить с OpenClaw VM sing-box, переправлять трафик через SingBox VM
|
||||
|
||||
## Проверить после прибытия с отпуска
|
||||
|
||||
- Tailscale на Services VM (--accept-routes нужно выключить, так как из-за этого не удается выйти в доступ через SSH)
|
||||
-
|
||||
|
||||
## Улучшения
|
||||
|
||||
- Поставить NAS хранилище
|
||||
- Подумать о переносе каких-то сервисов в отдельную машину, чтобы распределить нагрузку
|
||||
- Установить ИБП
|
||||
- Создать уведомления в ТГ о доступности ВМ с ВПН-ами и сервисов, потому что может отключиться ВПН и нужно будет его включить
|
||||
- Создать правило перезапуска sing-box при сетевой ошибке или моргании сети
|
||||
- Создать правило перезапуска OpenClaw gateway после ошибки sing-box
|
||||
|
||||
## Проекты
|
||||
|
||||
- Отключить вкладку и правило добавления доходов/затрат
|
||||
-
|
||||
@@ -1,11 +0,0 @@
|
||||
Получить статистику по дням
|
||||
```bash
|
||||
npx ccusage@latest
|
||||
```
|
||||
|
||||
Получить статистику в режиме реального времени
|
||||
```bash
|
||||
npx ccusage@latest blocks --live
|
||||
```
|
||||
|
||||
Новый текст, чтобы оценить синхронизацию - ИЗМЕНИЛ
|
||||
@@ -1,20 +0,0 @@
|
||||
Найти процессы по порту
|
||||
```bash
|
||||
netstat -ano | findstr :9090 | findstr LISTENING
|
||||
```
|
||||
|
||||
Убить процесс
|
||||
```bash
|
||||
taskkill /PID 8768 /F
|
||||
|
||||
powershell.exe -Command "Stop-Process -Id 8768 -Force"
|
||||
```
|
||||
|
||||
Запустить npx приложение на порту
|
||||
```bash
|
||||
cd D:/Pet_projects/savings/react-app/savings-mobile && npx serve dist -p 3000
|
||||
```
|
||||
|
||||
```
|
||||
46U8w7EdHd6CBdrd3TyA
|
||||
```
|
||||
9
Личное/Tokens (API keys).md
Normal file
9
Личное/Tokens (API keys).md
Normal file
@@ -0,0 +1,9 @@
|
||||
```
|
||||
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```
|
||||
```
|
||||
OPENROUTER
|
||||
|
||||
```
|
||||
d4f4f27c-aa88-4f81-b24a-07da456b6c08:5a63fff139d294e29dfe0cabe970526a
|
||||
```
|
||||
FAL
|
||||
10
Личное/Игры.md
Normal file
10
Личное/Игры.md
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
https://s1.byrutorg.com/horizon-forbidden-west-complete-edition
|
||||
https://s1.byrutorg.com/horizon-zero-dawn-remastered
|
||||
https://s1.byrutorg.com/the-last-of-us-part-2
|
||||
https://s1.byrutorg.com/1-dying-light-2-stay-human
|
||||
https://s1.byrutorg.com/call-of-duty-black-ops-6
|
||||
https://s1.byrutorg.com/split-fiction
|
||||
https://s1.byrutorg.com/call-of-duty-ghosts-deluxe-edition
|
||||
https://s1.byrutorg.com/download/torrent/call_of_duty_modern_warfare/1-1-0-358
|
||||
https://s1.byrutorg.com/call-of-duty-black-ops-cold-war
|
||||
12
Личное/Смена VPN.md
Normal file
12
Личное/Смена VPN.md
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
Пользователи:
|
||||
- Даня +
|
||||
- Света +
|
||||
- Юлиана +
|
||||
- Виталя +
|
||||
- Коля +
|
||||
- Паша (Виталя) +
|
||||
- Юля Ш.
|
||||
- Юля М.
|
||||
- Даша
|
||||
- Ксюша +
|
||||
42
Планирование.md
Normal file
42
Планирование.md
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
Основной объект
|
||||
|
||||
Дата старта
|
||||
Дата завершения
|
||||
Период - Q1, Q2, ..., Year
|
||||
Родитель - Year
|
||||
|
||||
Деталь
|
||||
|
||||
Команда
|
||||
План (в млн)
|
||||
Основной объект
|
||||
|
||||
--------
|
||||
Q1 2026
|
||||
01.01.2026
|
||||
31.03.2026
|
||||
Q1 2026
|
||||
2026
|
||||
|
||||
Деталь
|
||||
|
||||
DFS | 20 | Q1 2026 | 50
|
||||
DTI | 30 | Q1 2026
|
||||
KPI | 20 | Q1 2026
|
||||
|
||||
-----
|
||||
|
||||
Q2 2026
|
||||
01.01.2026
|
||||
31.03.2026
|
||||
Q1 2026
|
||||
2026
|
||||
|
||||
Деталь
|
||||
|
||||
DFS | 20 | Q2 2026
|
||||
DTI | 30 | Q2 2026
|
||||
|
||||
2026
|
||||
DFS | 20+ 30 + 40 + 50 |
|
||||
@@ -1,16 +1,20 @@
|
||||
1. Проставить значение настройки "NrbErpHeadProject"
|
||||
2. Проставить значение настройки "NrbAsyncServiceUri"
|
||||
2. Проставить значение настройки "NrbAsyncServiceUri" `https://async.prod.plt.adsw.io/`
|
||||
3. Проставить значение настройки "NrbPresaleProjectServiceKey"
|
||||
4. Проставить значение настройки "NrbIsERPIntegrationEnabled"
|
||||
5. Проставить значение настройки "ServiceAccountName"
|
||||
6. Проставить значение настройки "ServiceAccountSecret"
|
||||
5. Проставить значение настройки "NrbOpenProjectUrl"
|
||||
6. Проставить значение настройки "NrbErpServiceSecret"
|
||||
7. Проверить настройку "GatewayURLKey"
|
||||
|
||||
Секреты
|
||||
Секреты CRM
|
||||
1. Dev CRM `20b6702d-a3f7-4dfa-baad-640da98b727c`
|
||||
2. Preprod CRM `347bf64d-8920-4de6-a0f1-654c2ab15fda`
|
||||
3. Prod CRM `24b9aef3-dffb-4f9e-9c5d-fa8a9802276f`
|
||||
|
||||
Cекреты ERP
|
||||
1. Dev `067d72e8-2728-493b-b7b0-4fa4c482d921`
|
||||
2. Prod `ff915955-844e-4a93-a933-c43cfc84adf4`
|
||||
|
||||
|
||||
Dev Private Gateway - `https://private-api-gateway-feature-itdev-1381.dev.plt.adsw.io/query`
|
||||
Dev Async - `https://async-feature-itdev-1381.dev.plt.adsw.io/`
|
||||
Reference in New Issue
Block a user