Files
umbrix/UPDATE_SERVER_SETUP.md
Umbrix Developer 76a374950f feat: mobile-like window size and always-visible stats
- Changed window size to mobile phone format (400x800)
- Removed width condition for ActiveProxyFooter - now always visible
- Added run-umbrix.sh launch script with icon copying
- Stats cards now display on all screen sizes
2026-01-17 13:09:20 +03:00

10 KiB
Raw Permalink Blame History

🚀 Настройка собственного сервера обновлений для Umbrix

Это руководство поможет вам настроить систему обновлений для приватного распространения APK/IPA файлов до публикации в магазинах.

📋 Варианты реализации

Вариант 1: Простой JSON файл на хостинге (самое простое)

Создайте файл latest.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 установите:

static const customUpdateServerUrl = "https://your-site.netlify.app/latest.json";
static const useCustomUpdateServer = true;

Вариант 2: Node.js API сервер (рекомендуемый)

Установка

mkdir umbrix-update-server
cd umbrix-update-server
npm init -y
npm install express cors

server.js

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}`);
});

Запуск

node server.js

Deploy на Render.com (бесплатно)

  1. Создайте аккаунт на Render.com
  2. Подключите GitHub репозиторий
  3. Создайте Web Service
  4. Render автоматически задеплоит ваш сервер

В constants.dart установите:

static const customUpdateServerUrl = "https://your-app.onrender.com/api/updates/latest";
static const useCustomUpdateServer = true;

Вариант 3: Firebase Cloud Functions (продвинутый)

functions/index.js

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 (рекомендуемый)

# Установка Firebase CLI
npm install -g firebase-tools
firebase login

# Загрузка APK
firebase storage:upload umbrix-2.5.8.apk /releases/umbrix-2.5.8.apk

Получение публичной ссылки:

// Генерация 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

# Пример с AWS CLI
aws s3 cp umbrix-2.5.8.apk s3://your-bucket/releases/umbrix-2.5.8.apk --acl public-read

3. Собственный сервер

# Nginx конфигурация
location /downloads/ {
    alias /var/www/downloads/;
    autoindex off;
    
    # Защита паролем (опционально)
    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

🔒 Безопасность

1. Базовая аутентификация (Basic Auth)

// В DioHttpClient добавьте заголовки
final response = await httpClient.get<Map<String, dynamic>>(
  url,
  options: Options(
    headers: {
      'Authorization': 'Basic ${base64Encode(utf8.encode('username:password'))}',
    },
  ),
);

2. API ключ

// В constants.dart
static const updateServerApiKey = "your-secret-api-key";

// В запросе
headers: {
  'X-API-Key': Constants.updateServerApiKey,
}

3. JWT токен (самый безопасный)

// На сервере
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:

{
  "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

# В приватном репозитории создайте ветку 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:

static const customUpdateServerUrl = "https://your-username.github.io/your-repo/latest.json";
static const useCustomUpdateServer = true;

Шаг 4: Соберите и протестируйте

flutter build apk --release
# Установите на устройство и проверьте обновления в разделе "О программе"

📱 Автоматизация через GitHub Actions

Создайте .github/workflows/release.yml:

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