# 🚀 Настройка собственного сервера обновлений для Umbrix Это руководство поможет вам настроить систему обновлений для приватного распространения APK/IPA файлов до публикации в магазинах. ## 📋 Варианты реализации ### Вариант 1: Простой JSON файл на хостинге (самое простое) Создайте файл `latest.json` на любом веб-сервере: ```json { "version": "2.5.8", "build_number": "258", "is_prerelease": false, "download_url": "https://your-server.com/downloads/umbrix-2.5.8.apk", "release_notes": "Что нового:\n- Исправлены ошибки подключения\n- Улучшена стабильность\n- Новый дизайн главной страницы", "published_at": "2026-01-16T10:00:00Z" } ``` **Где разместить:** - ✅ Netlify / Vercel (бесплатно) - ✅ GitHub Pages (можно сделать приватный репозиторий) - ✅ Ваш VPS сервер - ✅ Firebase Hosting **В constants.dart установите:** ```dart static const customUpdateServerUrl = "https://your-site.netlify.app/latest.json"; static const useCustomUpdateServer = true; ``` --- ### Вариант 2: Node.js API сервер (рекомендуемый) #### Установка ```bash mkdir umbrix-update-server cd umbrix-update-server npm init -y npm install express cors ``` #### server.js ```javascript const express = require('express'); const cors = require('cors'); const app = express(); app.use(cors()); app.use(express.json()); // Конфигурация версий const releases = { stable: { version: "2.5.8", build_number: "258", is_prerelease: false, download_url: "https://your-storage.com/umbrix-2.5.8.apk", release_notes: "Стабильная версия с исправлениями", published_at: new Date().toISOString() }, beta: { version: "2.6.0-beta.1", build_number: "260", is_prerelease: true, download_url: "https://your-storage.com/umbrix-2.6.0-beta.1.apk", release_notes: "Бета-версия с новыми функциями", published_at: new Date().toISOString() } }; // Endpoint для получения последней версии app.get('/api/updates/latest', (req, res) => { const includePrerelease = req.query.include_prerelease === 'true'; const release = includePrerelease ? releases.beta : releases.stable; console.log(`Update check: prerelease=${includePrerelease}`); res.json(release); }); // Аналитика (опционально) app.post('/api/updates/analytics', (req, res) => { const { current_version, device_info } = req.body; console.log('Update analytics:', { current_version, device_info }); res.json({ success: true }); }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Update server running on port ${PORT}`); }); ``` #### Запуск ```bash node server.js ``` #### Deploy на Render.com (бесплатно) 1. Создайте аккаунт на [Render.com](https://render.com) 2. Подключите GitHub репозиторий 3. Создайте Web Service 4. Render автоматически задеплоит ваш сервер **В constants.dart установите:** ```dart static const customUpdateServerUrl = "https://your-app.onrender.com/api/updates/latest"; static const useCustomUpdateServer = true; ``` --- ### Вариант 3: Firebase Cloud Functions (продвинутый) #### functions/index.js ```javascript const functions = require('firebase-functions'); const admin = require('firebase-admin'); admin.initializeApp(); exports.getLatestVersion = functions.https.onRequest(async (req, res) => { // CORS res.set('Access-Control-Allow-Origin', '*'); try { const db = admin.firestore(); const doc = await db.collection('app_updates').doc('latest').get(); if (!doc.exists) { return res.status(404).json({ error: 'Version not found' }); } res.json(doc.data()); } catch (error) { console.error('Error:', error); res.status(500).json({ error: 'Internal server error' }); } }); ``` **Плюсы Firebase:** - ✅ Автоматическое масштабирование - ✅ Бесплатный SSL - ✅ Встроенная аналитика - ✅ База данных Firestore для хранения версий --- ## 📦 Где хранить APK файлы ### 1. Firebase Storage (рекомендуемый) ```bash # Установка Firebase CLI npm install -g firebase-tools firebase login # Загрузка APK firebase storage:upload umbrix-2.5.8.apk /releases/umbrix-2.5.8.apk ``` **Получение публичной ссылки:** ```javascript // Генерация signed URL (действителен 7 дней) const { getStorage } = require('firebase-admin/storage'); const bucket = getStorage().bucket(); const file = bucket.file('releases/umbrix-2.5.8.apk'); const [url] = await file.getSignedUrl({ action: 'read', expires: Date.now() + 7 * 24 * 60 * 60 * 1000 }); ``` ### 2. AWS S3 / DigitalOcean Spaces ```bash # Пример с AWS CLI aws s3 cp umbrix-2.5.8.apk s3://your-bucket/releases/umbrix-2.5.8.apk --acl public-read ``` ### 3. Собственный сервер ```bash # Nginx конфигурация location /downloads/ { alias /var/www/downloads/; autoindex off; # Защита паролем (опционально) auth_basic "Restricted"; auth_basic_user_file /etc/nginx/.htpasswd; } ``` --- ## 🔒 Безопасность ### 1. Базовая аутентификация (Basic Auth) ```dart // В DioHttpClient добавьте заголовки final response = await httpClient.get>( url, options: Options( headers: { 'Authorization': 'Basic ${base64Encode(utf8.encode('username:password'))}', }, ), ); ``` ### 2. API ключ ```dart // В constants.dart static const updateServerApiKey = "your-secret-api-key"; // В запросе headers: { 'X-API-Key': Constants.updateServerApiKey, } ``` ### 3. JWT токен (самый безопасный) ```javascript // На сервере const jwt = require('jsonwebtoken'); function verifyToken(req, res, next) { const token = req.headers['authorization']?.split(' ')[1]; if (!token) return res.status(403).json({ error: 'No token' }); jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => { if (err) return res.status(401).json({ error: 'Invalid token' }); req.userId = decoded.userId; next(); }); } app.get('/api/updates/latest', verifyToken, (req, res) => { // ... }); ``` --- ## 🎯 Пошаговая инструкция (быстрый старт) ### Шаг 1: Создайте JSON файл Создайте файл `latest.json`: ```json { "version": "2.5.8", "build_number": "258", "is_prerelease": false, "download_url": "https://github.com/your-org/your-repo/releases/download/v2.5.8/umbrix-2.5.8.apk", "release_notes": "Первая версия", "published_at": "2026-01-16T10:00:00Z" } ``` ### Шаг 2: Разместите на GitHub Pages ```bash # В приватном репозитории создайте ветку gh-pages git checkout -b gh-pages git add latest.json git commit -m "Add update info" git push origin gh-pages # В Settings → Pages включите GitHub Pages для ветки gh-pages ``` ### Шаг 3: Обновите константы в приложении В файле `lib/core/model/constants.dart`: ```dart static const customUpdateServerUrl = "https://your-username.github.io/your-repo/latest.json"; static const useCustomUpdateServer = true; ``` ### Шаг 4: Соберите и протестируйте ```bash flutter build apk --release # Установите на устройство и проверьте обновления в разделе "О программе" ``` --- ## 📱 Автоматизация через GitHub Actions Создайте `.github/workflows/release.yml`: ```yaml name: Build and Deploy APK on: push: tags: - 'v*' jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Flutter uses: subosito/flutter-action@v2 - name: Build APK run: flutter build apk --release - name: Upload to storage run: | # Загрузка APK на ваш сервер curl -X POST -F "file=@build/app/outputs/flutter-apk/app-release.apk" \ https://your-server.com/api/upload - name: Update version info run: | # Обновление latest.json echo '{ "version": "${{ github.ref_name }}", "build_number": "${{ github.run_number }}", "download_url": "https://your-server.com/downloads/${{ github.ref_name }}.apk", "published_at": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'" }' > latest.json # Загрузка на сервер curl -X PUT -d @latest.json https://your-server.com/api/latest ``` --- ## ❓ FAQ **Q: Как переключиться обратно на GitHub?** A: В `constants.dart` установите `useCustomUpdateServer = false` **Q: Можно ли использовать оба варианта?** A: Да, можно добавить fallback логику в `app_update_repository.dart` **Q: Как защитить от несанкционированного доступа?** A: Используйте API ключи, JWT токены или базовую аутентификацию **Q: Нужен ли HTTPS?** A: Да, обязательно! Иначе Android не разрешит загрузку --- ## 🎉 Готово! Теперь у вас есть полностью функциональная система обновлений для приватного распространения APK файлов. **Следующие шаги:** 1. ✅ Выберите вариант размещения 2. ✅ Обновите `Constants.customUpdateServerUrl` 3. ✅ Загрузите APK на сервер 4. ✅ Протестируйте обновление 5. ✅ Настройте автоматизацию через CI/CD