feat: multi-architecture Docker setup (x86_64 + ARM64) with one-command install
- Multi-stage Dockerfile: builder compiles native modules (better-sqlite3, tiny-secp256k1) under target architecture, runtime is minimal Alpine - install.sh: POSIX sh installer (Alpine ash compatible) with architecture detection, Docker install, .env validation, health-check retry loop - docker-compose.yml: removed platform locks, .env read-only mount, 127.0.0.1 port binding, 384m mem limit (Orange Pi Zero 2 safe) - .dockerignore: excludes node_modules, secrets, tests, .kilo - README.md: complete rewrite with deployment docs for any device - Verified: POSIX sh syntax (dash), Dockerfile (docker build --check), docker-compose (docker compose config)
This commit is contained in:
18
.dockerignore
Normal file
18
.dockerignore
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
node_modules
|
||||||
|
db
|
||||||
|
uploads
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
.git
|
||||||
|
.kilo
|
||||||
|
.architect
|
||||||
|
kilo-meta.json
|
||||||
|
kilo.jsonc
|
||||||
|
AGENTS.md
|
||||||
|
corrupt-photo.jpg
|
||||||
|
wg/config
|
||||||
|
*.log
|
||||||
|
__pycache__
|
||||||
|
**/__tests__
|
||||||
|
**/*.test.js
|
||||||
41
Dockerfile
41
Dockerfile
@@ -3,41 +3,44 @@ FROM node:22-alpine AS builder
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
RUN npm install && npm cache clean --force
|
|
||||||
|
|
||||||
# --- Runtime image ---
|
RUN apk add --no-cache --virtual .build-deps \
|
||||||
|
python3 \
|
||||||
|
make \
|
||||||
|
g++ \
|
||||||
|
gcc \
|
||||||
|
linux-headers \
|
||||||
|
git \
|
||||||
|
py3-setuptools \
|
||||||
|
&& npm install --omit=dev \
|
||||||
|
&& apk del .build-deps
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Runtime image
|
||||||
|
# ============================================================
|
||||||
FROM node:22-alpine
|
FROM node:22-alpine
|
||||||
|
|
||||||
# Install runtime dependencies
|
RUN apk add --no-cache \
|
||||||
RUN apk update && \
|
bash \
|
||||||
apk add --no-cache --repository https://dl-cdn.alpinelinux.org/alpine/edge/community \
|
bind-tools \
|
||||||
wireguard-tools \
|
curl \
|
||||||
&& apk add --no-cache \
|
|
||||||
iptables \
|
iptables \
|
||||||
iproute2 \
|
iproute2 \
|
||||||
openresolv \
|
openresolv \
|
||||||
bash \
|
wireguard-tools
|
||||||
curl \
|
|
||||||
&& rm -rf /var/cache/apk/*
|
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy node_modules from builder
|
|
||||||
COPY --from=builder /app/node_modules ./node_modules
|
COPY --from=builder /app/node_modules ./node_modules
|
||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
|
|
||||||
# Copy application source
|
|
||||||
COPY ./src ./src
|
COPY ./src ./src
|
||||||
|
|
||||||
# Copy startup script
|
|
||||||
COPY ./wg/start.sh /app/start.sh
|
COPY ./wg/start.sh /app/start.sh
|
||||||
RUN chmod +x /app/start.sh
|
RUN chmod +x /app/start.sh
|
||||||
|
|
||||||
# Create db directory
|
RUN mkdir -p /app/db /app/uploads
|
||||||
RUN mkdir -p /app/db
|
|
||||||
|
|
||||||
# Health check: bot responds to /health on port 3000
|
EXPOSE 3001
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
|
||||||
CMD curl -sf http://localhost:3001/health || exit 1
|
|
||||||
|
|
||||||
CMD ["/bin/bash", "/app/start.sh"]
|
CMD ["/bin/bash", "/app/start.sh"]
|
||||||
|
|||||||
302
README.md
302
README.md
@@ -1,175 +1,205 @@
|
|||||||
# Универсальный Телеграмм Магазин
|
# Telegram Shop Bot
|
||||||
|
|
||||||
**Описание проекта**:
|
Телеграм-бот для организации онлайн-продаж через Telegram с поддержкой криптовалют и WireGuard VPN.
|
||||||
"Универсальный Телеграмм Магазин" — это телеграмм-бот для организации онлайн-продаж через Telegram. Проект предоставляет полный цикл управления магазином, включая работу с криптовалютами, управление товарами и пользователями, а также интеграцию с VPN через WireGuard для безопасных транзакций.
|
|
||||||
|
|
||||||
**Основные технологии**:
|
## Возможности
|
||||||
- Node.js + Telegraf для работы с Telegram API
|
|
||||||
- SQLite для хранения данных
|
|
||||||
- Docker для контейнеризации
|
|
||||||
- WireGuard для защищенных соединений
|
|
||||||
- Поддержка криптокошельков (Bitcoin, Ethereum, Litecoin)
|
|
||||||
|
|
||||||
Проект включает несколько ключевых разделов для удобной работы пользователей и администраторов, а также позволяет интегрировать систему криптокошельков для расчетов, управления товарами и отслеживания покупок.
|
- Каталог товаров с категориями и фильтрацией по локациям
|
||||||
|
- Покупки с оплатой криптовалютами (BTC, ETH, LTC, USDT, USDC)
|
||||||
|
- Управление криптокошельками (создание, пополнение, баланс)
|
||||||
|
- История транзакций и покупок
|
||||||
|
- SaaS-система с автоматическим расчётом комиссий
|
||||||
|
- Админ-панель на порту 3001
|
||||||
|
- WireGuard VPN для безопасных транзакций
|
||||||
|
|
||||||
### Основной функционал
|
## Быстрый старт (одна команда)
|
||||||
|
|
||||||
#### Для пользователей:
|
### Требования
|
||||||
- Просмотр товаров по категориям с фильтрацией по локациям
|
|
||||||
- Совершение покупок с использованием криптовалют
|
|
||||||
- Управление криптокошельками (создание, пополнение, просмотр баланса)
|
|
||||||
- Просмотр истории транзакций и покупок
|
|
||||||
- Настройка профиля (локация, контактные данные)
|
|
||||||
- Подключение к защищенному VPN через WireGuard для безопасных транзакций
|
|
||||||
|
|
||||||
#### Для администраторов:
|
- Любое устройство с Docker: x86_64 (PC, сервер) или ARM64 (Orange Pi, Raspberry Pi)
|
||||||
- Полное управление товарами и категориями
|
- 512 МБ RAM минимум (Orange Pi Zero 2 поддерживается)
|
||||||
- Управление пользователями (блокировка, редактирование балансов)
|
|
||||||
- Контроль транзакций и комиссий
|
|
||||||
- Создание дампов базы данных с автоматическим списанием комиссии (% от балансов кошельков)
|
|
||||||
- Управление локациями и настройками VPN
|
|
||||||
- Мониторинг активности пользователей
|
|
||||||
- SaaS система с автоматическим расчетом комиссий:
|
|
||||||
- Комиссия за оборот по магазину перед выгрузкой кошельков
|
|
||||||
|
|
||||||
---
|
### Установка
|
||||||
|
|
||||||
### Установка и запуск
|
|
||||||
|
|
||||||
#### Требования:
|
|
||||||
- Node.js 18+
|
|
||||||
- Docker и Docker Compose
|
|
||||||
- Telegram Bot Token
|
|
||||||
- SQLite connection string
|
|
||||||
- WireGuard конфигурация
|
|
||||||
|
|
||||||
#### 1. Установка зависимостей:
|
|
||||||
```bash
|
```bash
|
||||||
npm install
|
git clone <repo-url> && cd telegram-shop
|
||||||
|
bash install.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 2. Настройка конфигурации:
|
Скрипт автоматически:
|
||||||
Создайте файл `.env` в корне проекта со следующим содержимым:
|
1. Определит архитектуру (x86_64 / ARM64 / ARMv7)
|
||||||
```env
|
2. Установит Docker если не установлен
|
||||||
TELEGRAM_BOT_TOKEN=your_bot_token
|
3. Создаст `.env` из шаблона
|
||||||
MONGO_URI=mongodb://localhost:27017/telegram_shop
|
4. Проверит обязательные переменные
|
||||||
WIREGUARD_CONFIG_PATH=./wg/config/wg0.conf
|
5. Соберёт Docker-образ под текущую архитектуру
|
||||||
```
|
6. Запустит контейнер и проверит health-check
|
||||||
|
|
||||||
|
### Ручная установка
|
||||||
|
|
||||||
#### 3. Запуск через Docker:
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose up -d
|
# 1. Клонировать
|
||||||
|
git clone <repo-url> && cd telegram-shop
|
||||||
|
|
||||||
|
# 2. Создать .env из шаблона
|
||||||
|
cp .env.example .env
|
||||||
|
nano .env # заполнить BOT_TOKEN, ADMIN_IDS, ENCRYPTION_KEY
|
||||||
|
|
||||||
|
# 3. Собрать и запустить
|
||||||
|
docker compose up -d --build
|
||||||
|
|
||||||
|
# 4. Проверить статус
|
||||||
|
docker compose ps
|
||||||
|
curl http://localhost:3001/health
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 4. Настройка WireGuard:
|
## Настройка .env
|
||||||
1. Сгенерируйте ключи:
|
|
||||||
|
Скопируйте `.env.example` в `.env` и заполните:
|
||||||
|
|
||||||
|
| Переменная | Обязательно | Описание |
|
||||||
|
|---|---|---|
|
||||||
|
| `BOT_TOKEN` | ✅ | Токен Telegram бота (@BotFather) |
|
||||||
|
| `ADMIN_IDS` | ✅ | ID администраторов через запятую |
|
||||||
|
| `ENCRYPTION_KEY` | ✅ | Ключ шифрования (32 байта hex) |
|
||||||
|
| `SUPER_ADMIN_IDS` | — | ID супер-админов |
|
||||||
|
| `SUPPORT_LINK` | — | Ссылка на поддержку |
|
||||||
|
| `WG_ENABLED` | — | `true` / `false` (по умолчанию `false`) |
|
||||||
|
| `WG_PRIVATE_KEY` | — | Приватный ключ WireGuard |
|
||||||
|
| `WG_PUBLIC_KEY` | — | Публичный ключ WireGuard |
|
||||||
|
| `WG_PRESHARED_KEY` | — | Pre-shared ключ WireGuard |
|
||||||
|
| `WG_ENDPOINT` | — | Адрес сервера WireGuard |
|
||||||
|
| `WG_ADDRESS` | — | Адрес интерфейса WireGuard |
|
||||||
|
| `WG_DNS` | — | DNS для WireGuard |
|
||||||
|
|
||||||
|
Генерация ключа шифрования:
|
||||||
```bash
|
```bash
|
||||||
wg genkey | tee privatekey | wg pubkey > publickey
|
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
||||||
```
|
|
||||||
2. Настройте wg0.conf:
|
|
||||||
```ini
|
|
||||||
[Interface]
|
|
||||||
PrivateKey = <your_private_key>
|
|
||||||
Address = 10.0.0.1/24
|
|
||||||
ListenPort = 51820
|
|
||||||
|
|
||||||
[Peer]
|
|
||||||
PublicKey = <client_public_key>
|
|
||||||
AllowedIPs = 10.0.0.2/32
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 5. Запуск бота:
|
## Поддерживаемые устройства
|
||||||
|
|
||||||
|
| Устройство | Архитектура | RAM | Статус |
|
||||||
|
|---|---|---|---|
|
||||||
|
| PC / Сервер | x86_64 | ≥ 512 МБ | ✅ |
|
||||||
|
| Orange Pi Zero 2 | ARM64 (H616) | 512 МБ | ✅ |
|
||||||
|
| Raspberry Pi 4 | ARM64 | ≥ 1 ГБ | ✅ |
|
||||||
|
| Raspberry Pi 3 | ARM64 | 1 ГБ | ✅ |
|
||||||
|
| Raspberry Pi 2 | ARMv7 | 1 ГБ | ✅ |
|
||||||
|
|
||||||
|
Docker автоматически собирает нативные модули (`better-sqlite3`, `tiny-secp256k1`) под архитектуру хоста.
|
||||||
|
|
||||||
|
## Архитектура Docker
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────┐
|
||||||
|
│ telegram_shop_prod (node:22-alpine) │
|
||||||
|
│ ┌──────────────┐ ┌─────────────────────┐ │
|
||||||
|
│ │ Builder │ │ Runtime │ │
|
||||||
|
│ │ python3, g++ │→ │ bash, curl, │ │
|
||||||
|
│ │ make, gcc │ │ wireguard-tools, │ │
|
||||||
|
│ │ npm install │ │ iptables, bind-tools │ │
|
||||||
|
│ └──────────────┘ └─────────────────────┘ │
|
||||||
|
│ Port 3001 (localhost) │
|
||||||
|
│ Limit: 384MB RAM │
|
||||||
|
└─────────────────────────────────────────────┘
|
||||||
|
↑ Volumes: db/, uploads/, .env
|
||||||
|
```
|
||||||
|
|
||||||
|
### Файлы
|
||||||
|
|
||||||
|
| Файл | Назначение |
|
||||||
|
|---|---|
|
||||||
|
| `Dockerfile` | Multi-stage сборка (builder + runtime) |
|
||||||
|
| `docker-compose.yml` | Конфигурация контейнера |
|
||||||
|
| `install.sh` | Автоматический установщик |
|
||||||
|
| `.dockerignore` | Исключения из Docker-образа |
|
||||||
|
| `.env.example` | Шаблон переменных окружения |
|
||||||
|
| `wg/start.sh` | Скрипт запуска (WireGuard + Node.js) |
|
||||||
|
|
||||||
|
## Команды управления
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm start
|
# Запуск
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# Пересборка после изменений
|
||||||
|
docker compose up -d --build
|
||||||
|
|
||||||
|
# Логи
|
||||||
|
docker compose logs -f
|
||||||
|
|
||||||
|
# Стоп
|
||||||
|
docker compose down
|
||||||
|
|
||||||
|
# Рестарт
|
||||||
|
docker compose restart
|
||||||
|
|
||||||
|
# Статус
|
||||||
|
docker compose ps
|
||||||
|
|
||||||
|
# Health-check
|
||||||
|
curl http://localhost:3001/health
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
## WireGuard
|
||||||
|
|
||||||
### Структура проекта
|
WireGuard по умолчанию отключен (`WG_ENABLED=false`). Для включения:
|
||||||
|
|
||||||
|
1. Установите `WG_ENABLED=true` в `.env`
|
||||||
|
2. Заполните ключи WireGuard в `.env`
|
||||||
|
3. Перезапустите: `docker compose restart`
|
||||||
|
|
||||||
|
Контейнер требует `NET_ADMIN` и `sysctl net.ipv4.conf.all.src_valid_mark=1` для WireGuard. Эти привилегии заданы в `docker-compose.yml`.
|
||||||
|
|
||||||
|
## Безопасность
|
||||||
|
|
||||||
|
- `.env` монтируется только для чтения (`:ro`)
|
||||||
|
- Порт 3001 привязан к `127.0.0.1` (доступен только с хоста)
|
||||||
|
- Нативные модули компилируются в builder-стейдже (чистый runtime)
|
||||||
|
- `devDependencies` не попадают в production-образ
|
||||||
|
- Тестовые файлы исключены из Docker-образа (`.dockerignore`)
|
||||||
|
- `node_modules` хоста не попадают в образ (`.dockerignore`)
|
||||||
|
|
||||||
|
## Структура проекта
|
||||||
|
|
||||||
```
|
```
|
||||||
├── src/
|
├── src/
|
||||||
│ ├── config/ # Конфигурация приложения
|
│ ├── admin/ # Админ-панель (Express)
|
||||||
|
│ ├── config/ # Конфигурация (БД, крипто)
|
||||||
│ ├── context/ # Контекст и состояния бота
|
│ ├── context/ # Контекст и состояния бота
|
||||||
│ ├── handlers/ # Обработчики команд
|
│ ├── handlers/ # Обработчики команд
|
||||||
│ ├── models/ # Модели данных
|
│ ├── middleware/ # Промежуточные обработчики
|
||||||
|
│ ├── migrations/ # Миграции БД
|
||||||
|
│ ├── models/ # Модели данных (SQLite)
|
||||||
|
│ ├── router/ # Роутинг Express
|
||||||
│ ├── services/ # Бизнес-логика
|
│ ├── services/ # Бизнес-логика
|
||||||
│ ├── utils/ # Вспомогательные утилиты
|
│ ├── utils/ # Утилиты
|
||||||
│ └── index.js # Точка входа
|
│ └── index.js # Точка входа
|
||||||
├── wg/ # Конфигурация WireGuard
|
├── wg/ # WireGuard конфигурация
|
||||||
├── docker-compose.yml # Docker конфигурация
|
│ └── start.sh # Скрипт запуска контейнера
|
||||||
└── Dockerfile # Docker образ
|
├── db/ # SQLite база данных (volume)
|
||||||
|
├── uploads/ # Загруженные фото (volume)
|
||||||
|
├── Dockerfile # Multi-stage сборка
|
||||||
|
├── docker-compose.yml # Конфигурация контейнера
|
||||||
|
├── install.sh # Установщик (POSIX sh)
|
||||||
|
├── .dockerignore # Исключения из образа
|
||||||
|
├── .env.example # Шаблон переменных
|
||||||
|
└── package.json
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
## Разработка
|
||||||
|
|
||||||
### Разработка
|
|
||||||
|
|
||||||
#### Запуск в режиме разработки:
|
|
||||||
```bash
|
```bash
|
||||||
|
# Установка зависимостей
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# Запуск в режиме разработки
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
|
||||||
|
|
||||||
#### Линтинг и форматирование:
|
# Тесты
|
||||||
```bash
|
|
||||||
npm run lint
|
|
||||||
npm run format
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Тестирование:
|
|
||||||
```bash
|
|
||||||
npm test
|
npm test
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
## Лицензия
|
||||||
|
|
||||||
### Лицензия
|
MIT
|
||||||
|
|
||||||
Проект распространяется под лицензией MIT. Подробнее см. в файле LICENSE.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Контакты
|
|
||||||
|
|
||||||
По вопросам сотрудничества и поддержки:
|
|
||||||
- Email: support@telegram-shop.com
|
|
||||||
- Telegram: @telegram_shop_support
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Требования к системе:
|
|
||||||
1. **Интерфейс пользователя**:
|
|
||||||
- Интуитивно понятный и удобный интерфейс для покупок.
|
|
||||||
- Легкость в управлении профилем и кошельками.
|
|
||||||
- Информация о товарах и статусах покупок должна быть легко доступна.
|
|
||||||
|
|
||||||
2. **Интерфейс администратора**:
|
|
||||||
- Возможность редактировать товары, категории и управлять локациями.
|
|
||||||
- Инструменты для контроля баланса и управления пользователями.
|
|
||||||
- Функционал для создания и загрузки дампов данных.
|
|
||||||
|
|
||||||
3. **Безопасность**:
|
|
||||||
- Защищенные транзакции.
|
|
||||||
- Надежная система для хранения данных пользователей и кошельков.
|
|
||||||
- Механизмы для предотвращения мошенничества и атак.
|
|
||||||
|
|
||||||
4. **Производительность**:
|
|
||||||
- Система должна быть способна обрабатывать большое количество пользователей и транзакций одновременно.
|
|
||||||
- Пагинация данных, чтобы обеспечить быструю загрузку и обработку.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Риски и возможные проблемы:
|
|
||||||
1. **Зависимость от сторонних сервисов**:
|
|
||||||
- Интеграция с криптокошельками и сторонними сервисами для проверки баланса может быть подвержена сбоям, если эти сервисы не работают корректно.
|
|
||||||
|
|
||||||
2. **Поддержка разных криптовалют**:
|
|
||||||
- Необходимо следить за изменениями в протоколах криптовалют и своевременно обновлять систему.
|
|
||||||
|
|
||||||
3. **Безопасность и защита данных**:
|
|
||||||
- Важно следить за актуальностью средств защиты данных и предотвратить утечку информации о пользователях и их балансе.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Заключение:
|
|
||||||
**Универсальный Телеграмм Магазин** предоставляет эффективное решение для организации торговых процессов в Telegram, с возможностью работы с криптовалютами и традиционными средствами. Проект ориентирован на пользователей, которые ценят удобство, безопасность и скорость совершения покупок. Для администраторов — это мощный инструмент для управления товаром, пользователями и финансовыми потоками магазина.
|
|
||||||
@@ -1,30 +1,25 @@
|
|||||||
version: "3.3"
|
|
||||||
services:
|
services:
|
||||||
telegram_shop_prod:
|
telegram_shop_prod:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: ./Dockerfile
|
dockerfile: ./Dockerfile
|
||||||
network: host
|
|
||||||
hostname: telegram_shop_prod
|
hostname: telegram_shop_prod
|
||||||
container_name: telegram_shop_prod
|
container_name: telegram_shop_prod
|
||||||
ports:
|
ports:
|
||||||
- "3001:3001"
|
- "127.0.0.1:3001:3001"
|
||||||
restart: always
|
restart: unless-stopped
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./db:/app/db/ # Синхронизация базы данных (persistence)
|
- ./db:/app/db/
|
||||||
- ./uploads:/app/uploads/ # Uploaded product photos
|
- ./uploads:/app/uploads/
|
||||||
- ./wg/start.sh:/app/start.sh # Монтируем start.sh (генерирует wg0.conf из env)
|
- ./.env:/app/.env:ro
|
||||||
- ./.env:/app/.env:rw # Settings panel read/write
|
cap_add:
|
||||||
cap_add: # Минимальные привилегии, необходимые только для WireGuard
|
|
||||||
- NET_ADMIN
|
- NET_ADMIN
|
||||||
sysctls:
|
sysctls:
|
||||||
- net.ipv4.conf.all.src_valid_mark=1 # Необходимо для маршрутизации
|
- net.ipv4.conf.all.src_valid_mark=1
|
||||||
dns:
|
dns:
|
||||||
- 8.8.8.8
|
- 8.8.8.8
|
||||||
- 1.1.1.1
|
- 1.1.1.1
|
||||||
mem_limit: 512m
|
mem_limit: 384m
|
||||||
cpus: "1.0"
|
cpus: "1.0"
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "curl", "-sf", "http://localhost:3001/health"]
|
test: ["CMD", "curl", "-sf", "http://localhost:3001/health"]
|
||||||
@@ -32,5 +27,3 @@ services:
|
|||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
start_period: 60s
|
start_period: 60s
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
|
|||||||
274
install.sh
Executable file
274
install.sh
Executable file
@@ -0,0 +1,274 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Telegram Shop — установщик
|
||||||
|
# Скрипт для развёртывания на x86_64 и ARM64 (Orange Pi, RPi)
|
||||||
|
# Совместим с POSIX sh (Alpine ash)
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
BOLD='\033[1m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
print_header() {
|
||||||
|
printf "${CYAN}${BOLD}\n"
|
||||||
|
printf "╔═══════════════════════════════════════════════════════════════╗\n"
|
||||||
|
printf "║ Telegram Shop — Установщик v1.1 ║\n"
|
||||||
|
printf "║ Поддержка x86_64 и ARM64 (Orange Pi, Raspberry Pi) ║\n"
|
||||||
|
printf "╚═══════════════════════════════════════════════════════════════╝\n"
|
||||||
|
printf "${NC}\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_ok() { printf "${GREEN}✓${NC} %s\n" "$1"; }
|
||||||
|
print_warn() { printf "${YELLOW}⚠${NC} %s\n" "$1"; }
|
||||||
|
print_err() { printf "${RED}✗${NC} %s\n" "$1"; }
|
||||||
|
print_info() { printf "${BLUE}ℹ${NC} %s\n" "$1"; }
|
||||||
|
print_step() { printf "\n${CYAN}${BOLD}▶ %s${NC}\n" "$1"; }
|
||||||
|
|
||||||
|
trap 'print_err "Установка прервана ошибкой (строка $LINENO)"; exit 1' ERR
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 0. Определение окружения
|
||||||
|
# ============================================================
|
||||||
|
print_header
|
||||||
|
|
||||||
|
print_step "Определение окружения"
|
||||||
|
ARCH=$(uname -m)
|
||||||
|
case "$ARCH" in
|
||||||
|
x86_64) ARCH_NAME="x86_64 (Intel/AMD)" ;;
|
||||||
|
aarch64|arm64) ARCH_NAME="ARM64 (Orange Pi / RPi)" ;;
|
||||||
|
armv7l) ARCH_NAME="ARMv7 (Raspberry Pi 2)" ;;
|
||||||
|
*)
|
||||||
|
print_err "Неподдерживаемая архитектура: $ARCH"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
print_ok "Архитектура: $ARCH_NAME"
|
||||||
|
print_info "Docker автоматически соберёт образ под текущую архитектуру"
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 1. Проверка / установка Docker
|
||||||
|
# ============================================================
|
||||||
|
print_step "Проверка Docker"
|
||||||
|
|
||||||
|
DOCKER_MISSING=0
|
||||||
|
if ! command -v docker >/dev/null 2>&1; then
|
||||||
|
DOCKER_MISSING=1
|
||||||
|
elif ! docker version >/dev/null 2>&1; then
|
||||||
|
DOCKER_MISSING=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$DOCKER_MISSING" -eq 1 ]; then
|
||||||
|
print_warn "Docker не установлен или не запущен"
|
||||||
|
printf "\n"
|
||||||
|
printf "Установить Docker сейчас? (y/N): "
|
||||||
|
read -r INSTALL_DOCKER
|
||||||
|
case "$INSTALL_DOCKER" in
|
||||||
|
[Yy]|[Yy][Ee][Ss])
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
print_err "Docker обязателен. Установите вручную: https://docs.docker.com/engine/install/"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
print_info "Установка Docker..."
|
||||||
|
if command -v apk >/dev/null 2>&1; then
|
||||||
|
# Alpine
|
||||||
|
apk add --no-cache docker docker-cli-compose
|
||||||
|
rc-service docker start 2>/dev/null || service docker start 2>/dev/null || true
|
||||||
|
if ! docker version >/dev/null 2>&1; then
|
||||||
|
print_err "Docker не запустился. Запустите вручную: rc-service docker start"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
elif command -v apt-get >/dev/null 2>&1; then
|
||||||
|
# Debian / Ubuntu / Armbian
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y ca-certificates curl gnupg
|
||||||
|
install -m 0755 -d /etc/apt/keyrings
|
||||||
|
curl -fsSL "https://download.docker.com/linux/$(. /etc/os-release && echo "$ID")/gpg" | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||||
|
chmod a+r /etc/apt/keyrings/docker.gpg
|
||||||
|
printf "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/$(. /etc/os-release && echo "$ID") $(. /etc/os-release && echo "$VERSION_CODENAME") stable\n" \
|
||||||
|
> /etc/apt/sources.list.d/docker.list
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
|
||||||
|
service docker start 2>/dev/null || systemctl start docker 2>/dev/null || true
|
||||||
|
if ! docker version >/dev/null 2>&1; then
|
||||||
|
print_err "Docker не запустился. Запустите вручную: systemctl start docker"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
print_err "Неизвестный пакетный менеджер. Установите Docker вручную."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
print_ok "Docker установлен"
|
||||||
|
else
|
||||||
|
print_ok "Docker установлен: $(docker --version)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 2. Проверка docker compose
|
||||||
|
# ============================================================
|
||||||
|
print_step "Проверка docker compose"
|
||||||
|
|
||||||
|
COMPOSE_CMD=""
|
||||||
|
if docker compose version >/dev/null 2>&1; then
|
||||||
|
COMPOSE_CMD="docker compose"
|
||||||
|
COMPOSE_VER=$(docker compose version --short 2>/dev/null || echo "v2")
|
||||||
|
print_ok "docker compose v2 доступен: $COMPOSE_VER"
|
||||||
|
elif command -v docker-compose >/dev/null 2>&1; then
|
||||||
|
COMPOSE_CMD="docker-compose"
|
||||||
|
print_ok "docker-compose v1 доступен: $(docker-compose --version)"
|
||||||
|
else
|
||||||
|
print_err "docker compose не найден. Установите docker-compose-plugin или docker-compose."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 3. Подготовка файлов окружения
|
||||||
|
# ============================================================
|
||||||
|
print_step "Подготовка .env"
|
||||||
|
|
||||||
|
if [ ! -f ".env" ]; then
|
||||||
|
if [ -f ".env.example" ]; then
|
||||||
|
cp .env.example .env
|
||||||
|
# Убираем CRLF если файл скопирован из Windows
|
||||||
|
if command -v sed >/dev/null 2>&1; then
|
||||||
|
sed -i 's/\r$//' .env
|
||||||
|
fi
|
||||||
|
print_ok ".env создан из .env.example"
|
||||||
|
else
|
||||||
|
print_err ".env.example не найден!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
print_ok ".env уже существует — пропускаю создание"
|
||||||
|
# Убираем CRLF в существующем файле тоже
|
||||||
|
if command -v sed >/dev/null 2>&1; then
|
||||||
|
sed -i 's/\r$//' .env
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 4. Проверка обязательных переменных
|
||||||
|
# ============================================================
|
||||||
|
print_step "Проверка переменных окружения"
|
||||||
|
|
||||||
|
MISSING_COUNT=0
|
||||||
|
MISSING_LIST=""
|
||||||
|
for VAR in BOT_TOKEN ADMIN_IDS ENCRYPTION_KEY; do
|
||||||
|
VAL=$(grep -E "^${VAR}=" .env 2>/dev/null | cut -d'=' -f2- | tr -d '"' | tr -d '\r' || true)
|
||||||
|
if [ -z "$VAL" ] || [ "$VAL" = "your_bot_token_here" ] || [ "$VAL" = "123456789,987654321" ]; then
|
||||||
|
MISSING_COUNT=$((MISSING_COUNT + 1))
|
||||||
|
MISSING_LIST="$MISSING_LIST $VAR"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$MISSING_COUNT" -ne 0 ]; then
|
||||||
|
print_warn "Не заполнены или имеют placeholder значения:$MISSING_LIST"
|
||||||
|
printf "\n"
|
||||||
|
printf "${YELLOW}Откройте .env в редакторе и заполните:${NC}\n"
|
||||||
|
for V in $MISSING_LIST; do
|
||||||
|
printf " - %s\n" "$V"
|
||||||
|
done
|
||||||
|
printf "\n"
|
||||||
|
printf "Продолжить всё равно? (y/N): "
|
||||||
|
read -r CONTINUE
|
||||||
|
case "$CONTINUE" in
|
||||||
|
[Yy]|[Yy][Ee][Ss])
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
print_info "Откройте .env, заполните значения и запустите install.sh снова."
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
print_ok "Все обязательные переменные заполнены"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 5. Создание директорий
|
||||||
|
# ============================================================
|
||||||
|
print_step "Создание директорий"
|
||||||
|
mkdir -p db uploads
|
||||||
|
print_ok "db/, uploads/ готовы"
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 6. Сборка образа
|
||||||
|
# ============================================================
|
||||||
|
print_step "Сборка Docker-образа (это может занять несколько минут)"
|
||||||
|
print_info "Архитектура: $ARCH_NAME"
|
||||||
|
print_info "Нативные модули: better-sqlite3, tiny-secp256k1 (компилируются в builder)"
|
||||||
|
|
||||||
|
# Docker автоматически собирает под текущую архитектуру хоста
|
||||||
|
# buildx нужен только для multi-arch push в registry, для локальной сборки — обычный build
|
||||||
|
docker build -t telegram-shop:latest .
|
||||||
|
print_ok "Образ telegram-shop:latest собран"
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 7. Запуск контейнеров
|
||||||
|
# ============================================================
|
||||||
|
print_step "Запуск контейнеров"
|
||||||
|
$COMPOSE_CMD up -d
|
||||||
|
print_ok "Контейнеры запущены"
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 8. Проверка статуса
|
||||||
|
# ============================================================
|
||||||
|
print_step "Проверка статуса"
|
||||||
|
sleep 3
|
||||||
|
$COMPOSE_CMD ps
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 9. Показ логов
|
||||||
|
# ============================================================
|
||||||
|
print_step "Последние логи"
|
||||||
|
$COMPOSE_CMD logs --tail=20
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 10. Health-check с повторными попытками
|
||||||
|
# ============================================================
|
||||||
|
print_step "Проверка работоспособности"
|
||||||
|
HEALTH_URL="http://localhost:3001/health"
|
||||||
|
print_info "Запрос: $HEALTH_URL"
|
||||||
|
HEALTH_OK=0
|
||||||
|
for ATTEMPT in 1 2 3 4 5 6; do
|
||||||
|
sleep 5
|
||||||
|
if curl -sf "$HEALTH_URL" >/dev/null 2>&1; then
|
||||||
|
HEALTH_OK=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
print_info "Попытка $ATTEMPT/6 — сервис ещё запускается..."
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$HEALTH_OK" -eq 1 ]; then
|
||||||
|
RESPONSE=$(curl -sf "$HEALTH_URL" 2>/dev/null || echo "ok")
|
||||||
|
print_ok "Сервис отвечает!"
|
||||||
|
printf " ${GREEN}Ответ: %s${NC}\n" "$RESPONSE"
|
||||||
|
else
|
||||||
|
print_warn "Health-check не ответил за 30 секунд. Проверьте логи:"
|
||||||
|
printf " curl %s\n" "$HEALTH_URL"
|
||||||
|
printf " %s logs -f\n" "$COMPOSE_CMD"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Готово
|
||||||
|
# ============================================================
|
||||||
|
printf "\n"
|
||||||
|
printf "${GREEN}${BOLD}╔═══════════════════════════════════════════════════════════════╗${NC}\n"
|
||||||
|
printf "${GREEN}${BOLD}║ Установка завершена! ║${NC}\n"
|
||||||
|
printf "${GREEN}${BOLD}╚═══════════════════════════════════════════════════════════════╝${NC}\n"
|
||||||
|
printf "\n"
|
||||||
|
printf "${BOLD}Полезные команды:${NC}\n"
|
||||||
|
printf " docker compose ps # статус контейнеров\n"
|
||||||
|
printf " docker compose logs -f # логи в реальном времени\n"
|
||||||
|
printf " docker compose restart # перезапустить\n"
|
||||||
|
printf " docker compose down # остановить\n"
|
||||||
|
printf " docker compose up -d --build # пересобрать и запустить\n"
|
||||||
|
printf "\n"
|
||||||
|
printf "${BOLD}Health-check:${NC} %s\n" "$HEALTH_URL"
|
||||||
Reference in New Issue
Block a user