- 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
10 KiB
🚀 Настройка собственного сервера обновлений для 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 (бесплатно)
- Создайте аккаунт на Render.com
- Подключите GitHub репозиторий
- Создайте Web Service
- 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 файлов.
Следующие шаги:
- ✅ Выберите вариант размещения
- ✅ Обновите
Constants.customUpdateServerUrl - ✅ Загрузите APK на сервер
- ✅ Протестируйте обновление
- ✅ Настройте автоматизацию через CI/CD