Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c27dfbfba7 | ||
|
|
8d55a2629c | ||
|
|
67292b2697 | ||
|
|
491feb04ac | ||
|
|
0cc1d73e07 | ||
|
|
d74033605b | ||
|
|
796c223d44 | ||
|
|
95383d09fc |
2
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
|||||||
[submodule "libcore"]
|
[submodule "libcore"]
|
||||||
path = libcore
|
path = libcore
|
||||||
url = https://github.com/hiddify/hiddify-next-core
|
url = https://update.umbrix.net/vodorod/umbrix-libcore.git
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 6.3 KiB |
@@ -14,6 +14,7 @@ import 'package:umbrix/core/preferences/general_preferences.dart';
|
|||||||
import 'package:umbrix/core/preferences/preferences_migration.dart';
|
import 'package:umbrix/core/preferences/preferences_migration.dart';
|
||||||
import 'package:umbrix/core/preferences/preferences_provider.dart';
|
import 'package:umbrix/core/preferences/preferences_provider.dart';
|
||||||
import 'package:umbrix/features/app/widget/app.dart';
|
import 'package:umbrix/features/app/widget/app.dart';
|
||||||
|
import 'package:umbrix/features/app_update/notifier/app_update_notifier.dart';
|
||||||
import 'package:umbrix/features/auto_start/notifier/auto_start_notifier.dart';
|
import 'package:umbrix/features/auto_start/notifier/auto_start_notifier.dart';
|
||||||
import 'package:umbrix/features/common/custom_splash_screen.dart';
|
import 'package:umbrix/features/common/custom_splash_screen.dart';
|
||||||
import 'package:umbrix/features/deep_link/notifier/deep_link_notifier.dart';
|
import 'package:umbrix/features/deep_link/notifier/deep_link_notifier.dart';
|
||||||
@@ -153,6 +154,13 @@ Future<void> _performBootstrap(
|
|||||||
() => container.read(systemTrayNotifierProvider.future),
|
() => container.read(systemTrayNotifierProvider.future),
|
||||||
timeout: 1000,
|
timeout: 1000,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Автопроверка обновлений при запуске (отложенная)
|
||||||
|
_safeInit(
|
||||||
|
"auto check updates",
|
||||||
|
() => container.read(appUpdateNotifierProvider.notifier).checkSilently(),
|
||||||
|
timeout: 5000,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
abstract class Constants {
|
abstract class Constants {
|
||||||
static const appName = "Umbrix";
|
static const appName = "Umbrix";
|
||||||
static const githubUrl = "https://github.com/umbrix-app/umbrix";
|
static const githubUrl = "https://update.umbrix.net/vodorod/umbrix";
|
||||||
static const githubReleasesApiUrl = "https://api.github.com/repos/umbrix-app/umbrix/releases";
|
static const githubReleasesApiUrl = "https://update.umbrix.net/api/v1/repos/vodorod/umbrix/releases";
|
||||||
static const githubLatestReleaseUrl = "https://github.com/umbrix-app/umbrix/releases/latest";
|
static const githubLatestReleaseUrl = "https://update.umbrix.net/vodorod/umbrix/releases/latest";
|
||||||
static const appCastUrl = "http://localhost:8000/api/appcast.xml";
|
static const appCastUrl = "http://localhost:8000/api/appcast.xml";
|
||||||
static const telegramChannelUrl = "https://t.me/umbrix_app";
|
static const telegramChannelUrl = "https://t.me/umbrix_app";
|
||||||
static const privacyPolicyUrl = "https://umbrix.net/privacy.html";
|
static const privacyPolicyUrl = "https://umbrix.net/privacy.html";
|
||||||
@@ -18,12 +18,14 @@ abstract class Constants {
|
|||||||
// 🖥️ Для Linux десктопа используйте: "http://localhost:8000/api/appcast.xml"
|
// 🖥️ Для Linux десктопа используйте: "http://localhost:8000/api/appcast.xml"
|
||||||
// 📱 Для Android эмулятора используйте: "http://10.0.2.2:8000/api/appcast.xml"
|
// 📱 Для Android эмулятора используйте: "http://10.0.2.2:8000/api/appcast.xml"
|
||||||
// См. документацию в папке: update-server/README.md
|
// См. документацию в папке: update-server/README.md
|
||||||
static const customUpdateServerUrl = "http://localhost:8000/api/appcast.xml";
|
|
||||||
|
// ТЕСТ: Используем httpbin.org для демонстрации (возвращает тестовые данные)
|
||||||
|
static const customUpdateServerUrl = "https://httpbin.org/json";
|
||||||
|
|
||||||
// Использовать собственный сервер обновлений вместо GitHub
|
// Использовать собственный сервер обновлений вместо GitHub
|
||||||
// true = использовать customUpdateServerUrl (для приватного репозитория)
|
// true = использовать customUpdateServerUrl (для приватного репозитория)
|
||||||
// false = использовать GitHub Releases (для публичного репозитория)
|
// false = использовать GitHub Releases (для публичного репозитория)
|
||||||
static const useCustomUpdateServer = true;
|
static const useCustomUpdateServer = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const kAnimationDuration = Duration(milliseconds: 250);
|
const kAnimationDuration = Duration(milliseconds: 250);
|
||||||
|
|||||||
@@ -23,6 +23,20 @@ abstract class GithubReleaseParser {
|
|||||||
}
|
}
|
||||||
final preRelease = json["prerelease"] as bool;
|
final preRelease = json["prerelease"] as bool;
|
||||||
final publishedAt = DateTime.parse(json["published_at"] as String);
|
final publishedAt = DateTime.parse(json["published_at"] as String);
|
||||||
|
|
||||||
|
// Парсим assets
|
||||||
|
final List<ReleaseAsset> assets = [];
|
||||||
|
if (json["assets"] != null) {
|
||||||
|
for (final assetJson in json["assets"] as List) {
|
||||||
|
final asset = assetJson as Map<String, dynamic>;
|
||||||
|
assets.add(ReleaseAsset(
|
||||||
|
name: asset["name"] as String,
|
||||||
|
downloadUrl: asset["browser_download_url"] as String,
|
||||||
|
size: asset["size"] as int,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return RemoteVersionEntity(
|
return RemoteVersionEntity(
|
||||||
version: version,
|
version: version,
|
||||||
buildNumber: buildNumber,
|
buildNumber: buildNumber,
|
||||||
@@ -31,6 +45,7 @@ abstract class GithubReleaseParser {
|
|||||||
url: json["html_url"] as String,
|
url: json["html_url"] as String,
|
||||||
publishedAt: publishedAt,
|
publishedAt: publishedAt,
|
||||||
flavor: flavor,
|
flavor: flavor,
|
||||||
|
assets: assets,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,88 @@ class RemoteVersionEntity with _$RemoteVersionEntity {
|
|||||||
required String url,
|
required String url,
|
||||||
required DateTime publishedAt,
|
required DateTime publishedAt,
|
||||||
required Environment flavor,
|
required Environment flavor,
|
||||||
|
@Default([]) List<ReleaseAsset> assets,
|
||||||
}) = _RemoteVersionEntity;
|
}) = _RemoteVersionEntity;
|
||||||
|
|
||||||
String get presentVersion =>
|
String get presentVersion => flavor == Environment.prod ? version : "$version ${flavor.name}";
|
||||||
flavor == Environment.prod ? version : "$version ${flavor.name}";
|
|
||||||
|
/// Найти asset по расширению файла с умным определением
|
||||||
|
String? findAssetByExtension(String extension) {
|
||||||
|
try {
|
||||||
|
// Для Linux используем приоритет: .deb > .rpm > .AppImage
|
||||||
|
if (extension == '.deb' || extension == '.rpm' || extension == '.AppImage') {
|
||||||
|
final priorities = ['.deb', '.rpm', '.AppImage'];
|
||||||
|
|
||||||
|
for (final ext in priorities) {
|
||||||
|
try {
|
||||||
|
final asset = assets.firstWhere((asset) => asset.name.endsWith(ext));
|
||||||
|
return asset.downloadUrl;
|
||||||
|
} catch (_) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Для Windows - ищем .exe с приоритетом x64
|
||||||
|
if (extension == '.exe') {
|
||||||
|
// Сначала ищем x64 setup/installer
|
||||||
|
for (final pattern in ['x64', 'amd64', 'win64', 'setup', 'installer']) {
|
||||||
|
try {
|
||||||
|
final asset = assets.firstWhere(
|
||||||
|
(asset) => asset.name.toLowerCase().contains(pattern) && asset.name.endsWith('.exe'),
|
||||||
|
);
|
||||||
|
return asset.downloadUrl;
|
||||||
|
} catch (_) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если не нашли специфичный - берём любой .exe
|
||||||
|
try {
|
||||||
|
final asset = assets.firstWhere((asset) => asset.name.endsWith('.exe'));
|
||||||
|
return asset.downloadUrl;
|
||||||
|
} catch (_) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Для macOS - ищем .dmg
|
||||||
|
if (extension == '.dmg') {
|
||||||
|
// Сначала ищем universal или arm64 (для M1/M2)
|
||||||
|
for (final pattern in ['universal', 'arm64', 'apple-silicon']) {
|
||||||
|
try {
|
||||||
|
final asset = assets.firstWhere(
|
||||||
|
(asset) => asset.name.toLowerCase().contains(pattern) && asset.name.endsWith('.dmg'),
|
||||||
|
);
|
||||||
|
return asset.downloadUrl;
|
||||||
|
} catch (_) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если не нашли - берём любой .dmg
|
||||||
|
try {
|
||||||
|
final asset = assets.firstWhere((asset) => asset.name.endsWith('.dmg'));
|
||||||
|
return asset.downloadUrl;
|
||||||
|
} catch (_) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Для других расширений - прямой поиск
|
||||||
|
return assets.firstWhere((asset) => asset.name.endsWith(extension)).downloadUrl;
|
||||||
|
} catch (_) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ReleaseAsset with _$ReleaseAsset {
|
||||||
|
const factory ReleaseAsset({
|
||||||
|
required String name,
|
||||||
|
required String downloadUrl,
|
||||||
|
required int size,
|
||||||
|
}) = _ReleaseAsset;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,4 +84,21 @@ class AppUpdateNotifier extends _$AppUpdateNotifier with AppLogger {
|
|||||||
await _ignoreReleasePref.write(version.version);
|
await _ignoreReleasePref.write(version.version);
|
||||||
state = AppUpdateStateIgnored(version);
|
state = AppUpdateStateIgnored(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Тихая проверка обновлений (без изменения UI состояния если нет обновлений)
|
||||||
|
/// Используется при запуске приложения
|
||||||
|
Future<void> checkSilently() async {
|
||||||
|
loggy.debug("silent update check");
|
||||||
|
final result = await check();
|
||||||
|
|
||||||
|
// Если доступно обновление - показываем уведомление в tray
|
||||||
|
if (result is AppUpdateStateAvailable) {
|
||||||
|
_showUpdateNotification(result.versionInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showUpdateNotification(RemoteVersionEntity version) {
|
||||||
|
// TODO: Реализовать уведомление через system tray
|
||||||
|
loggy.info("new version available: ${version.version}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,19 @@ class NewVersionDialog extends HookConsumerWidget with PresLogger {
|
|||||||
|
|
||||||
static final _dialogKey = GlobalKey(debugLabel: 'new version dialog');
|
static final _dialogKey = GlobalKey(debugLabel: 'new version dialog');
|
||||||
|
|
||||||
|
/// Перезапуск приложения (кроссплатформенный метод)
|
||||||
|
void _restartApplication() {
|
||||||
|
final executable = Platform.resolvedExecutable;
|
||||||
|
loggy.info('Restarting application: $executable');
|
||||||
|
|
||||||
|
// Запускаем новый процесс и завершаем текущий
|
||||||
|
Process.start(executable, []).then((_) {
|
||||||
|
exit(0);
|
||||||
|
}).catchError((e) {
|
||||||
|
loggy.error('Failed to restart application', e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> show(BuildContext context) async {
|
Future<void> show(BuildContext context) async {
|
||||||
if (_dialogKey.currentContext == null) {
|
if (_dialogKey.currentContext == null) {
|
||||||
return showDialog(
|
return showDialog(
|
||||||
@@ -57,23 +70,103 @@ class NewVersionDialog extends HookConsumerWidget with PresLogger {
|
|||||||
downloadProgress.value = 0.0;
|
downloadProgress.value = 0.0;
|
||||||
|
|
||||||
final tempDir = await getTemporaryDirectory();
|
final tempDir = await getTemporaryDirectory();
|
||||||
|
|
||||||
|
// Определяем нужное расширение файла
|
||||||
String fileExt = '';
|
String fileExt = '';
|
||||||
if (Platform.isWindows)
|
if (Platform.isWindows)
|
||||||
fileExt = '.exe';
|
fileExt = '.exe';
|
||||||
else if (Platform.isMacOS)
|
else if (Platform.isMacOS)
|
||||||
fileExt = '.dmg';
|
fileExt = '.dmg';
|
||||||
else if (Platform.isLinux) fileExt = '.AppImage';
|
else if (Platform.isLinux) fileExt = '.deb';
|
||||||
|
|
||||||
|
// Ищем asset с нужным расширением
|
||||||
|
final downloadUrl = newVersion.findAssetByExtension(fileExt);
|
||||||
|
|
||||||
|
if (downloadUrl == null) {
|
||||||
|
if (context.mounted) {
|
||||||
|
CustomToast.error('Файл установки $fileExt не найден в релизе').show(context);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final savePath = '${tempDir.path}/umbrix-${newVersion.version}$fileExt';
|
final savePath = '${tempDir.path}/umbrix-${newVersion.version}$fileExt';
|
||||||
final file = File(savePath);
|
final file = File(savePath);
|
||||||
if (await file.exists()) await file.delete();
|
if (await file.exists()) await file.delete();
|
||||||
|
|
||||||
final dio = Dio();
|
final dio = Dio();
|
||||||
await dio.download(newVersion.url, savePath, onReceiveProgress: (received, total) {
|
await dio.download(downloadUrl, savePath, onReceiveProgress: (received, total) {
|
||||||
if (total != -1) downloadProgress.value = received / total;
|
if (total != -1) downloadProgress.value = received / total;
|
||||||
});
|
});
|
||||||
|
|
||||||
loggy.info('Update downloaded to: $savePath');
|
loggy.info('Update downloaded to: $savePath');
|
||||||
|
|
||||||
|
// Для Linux DEB - запускаем установку через системный установщик пакетов
|
||||||
|
if (Platform.isLinux && fileExt == '.deb') {
|
||||||
|
try {
|
||||||
|
// Пытаемся установить через pkexec apt install
|
||||||
|
final result = await Process.run('pkexec', ['apt', 'install', '-y', savePath]);
|
||||||
|
if (result.exitCode == 0) {
|
||||||
|
if (context.mounted) {
|
||||||
|
CustomToast.success('Обновление установлено! Приложение перезагрузится...').show(context);
|
||||||
|
context.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Автоматический перезапуск после небольшой задержки
|
||||||
|
Future.delayed(const Duration(seconds: 2), () {
|
||||||
|
_restartApplication();
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
loggy.warning('Failed to install via pkexec apt: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Для Windows EXE - запускаем тихую установку
|
||||||
|
if (Platform.isWindows && fileExt == '.exe') {
|
||||||
|
try {
|
||||||
|
if (context.mounted) {
|
||||||
|
CustomToast('Установка обновления...', type: AlertType.info).show(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запускаем установщик в тихом режиме с правами администратора
|
||||||
|
// /VERYSILENT - без UI, /SUPPRESSMSGBOXES - без диалогов
|
||||||
|
// /NORESTART - не перезагружать систему
|
||||||
|
final result = await Process.run(
|
||||||
|
'powershell',
|
||||||
|
[
|
||||||
|
'-Command',
|
||||||
|
'Start-Process',
|
||||||
|
'-FilePath',
|
||||||
|
'"$savePath"',
|
||||||
|
'-ArgumentList',
|
||||||
|
'"/VERYSILENT", "/SUPPRESSMSGBOXES", "/NORESTART"',
|
||||||
|
'-Verb',
|
||||||
|
'RunAs',
|
||||||
|
'-Wait'
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.exitCode == 0) {
|
||||||
|
if (context.mounted) {
|
||||||
|
CustomToast.success('Обновление установлено! Приложение перезагрузится...').show(context);
|
||||||
|
context.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Автоматический перезапуск после небольшой задержки
|
||||||
|
Future.delayed(const Duration(seconds: 2), () {
|
||||||
|
_restartApplication();
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
loggy.warning('Failed to install via PowerShell: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Для других платформ или если автоустановка не сработала - просто открываем файл
|
||||||
final result = await OpenFile.open(savePath);
|
final result = await OpenFile.open(savePath);
|
||||||
|
|
||||||
if (result.type != ResultType.done && context.mounted) {
|
if (result.type != ResultType.done && context.mounted) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: umbrix
|
name: umbrix
|
||||||
description: Cross Platform Multi Protocol Proxy Frontend.
|
description: Cross Platform Multi Protocol Proxy Frontend.
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
version: 1.7.0+170
|
version: 1.7.3+173
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.3.0 <4.0.0"
|
sdk: ">=3.3.0 <4.0.0"
|
||||||
|
|||||||
284
update-server/CODE_SIGNING_WINDOWS.md
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
# Подпись кода для Windows (Code Signing)
|
||||||
|
|
||||||
|
## Зачем нужен сертификат?
|
||||||
|
|
||||||
|
При установке `.exe` файла без цифровой подписи Windows показывает предупреждения:
|
||||||
|
- ⚠️ "Неизвестный издатель"
|
||||||
|
- ⚠️ "Windows защитила ваш компьютер"
|
||||||
|
- ⚠️ Windows Defender может блокировать файл
|
||||||
|
|
||||||
|
**С сертификатом:**
|
||||||
|
- ✅ "Проверенный издатель: Umbrix Team"
|
||||||
|
- ✅ Нет предупреждений SmartScreen
|
||||||
|
- ✅ Пользователи доверяют приложению
|
||||||
|
|
||||||
|
## Текущее состояние (БЕЗ сертификата)
|
||||||
|
|
||||||
|
Приложение **РАБОТАЕТ**, но:
|
||||||
|
1. При установке Windows показывает "Неизвестный издатель"
|
||||||
|
2. Пользователь должен нажать "Все равно запустить"
|
||||||
|
3. Антивирус может блокировать (ложное срабатывание)
|
||||||
|
|
||||||
|
**Для внутреннего использования это НОРМАЛЬНО** ✅
|
||||||
|
|
||||||
|
## Где получить сертификат?
|
||||||
|
|
||||||
|
### 1. Коммерческие сертификаты (EV Code Signing)
|
||||||
|
|
||||||
|
**Recommended:** Extended Validation (EV) - сразу доверие Windows
|
||||||
|
|
||||||
|
| Провайдер | Цена/год | Особенности |
|
||||||
|
|-----------|----------|-------------|
|
||||||
|
| **DigiCert** | $469-799 | Лучшая репутация, EV на USB токене |
|
||||||
|
| **Sectigo (Comodo)** | $399-599 | Популярный, хорошая поддержка |
|
||||||
|
| **GlobalSign** | $349-599 | Быстрое получение (1-2 дня) |
|
||||||
|
| **SSL.com** | $299-499 | Дешевле, но дольше проверка |
|
||||||
|
| **Certum** | €199-399 | Европейский, принимают криптовалюту |
|
||||||
|
|
||||||
|
**EV сертификат (Extended Validation):**
|
||||||
|
- ✅ Сразу доверие Windows SmartScreen
|
||||||
|
- ✅ Зелёная подпись "Проверенный издатель"
|
||||||
|
- ✅ Никаких предупреждений
|
||||||
|
- 📦 Выдается на USB токене (нельзя скопировать)
|
||||||
|
- ⏱️ Проверка документов 3-7 дней
|
||||||
|
|
||||||
|
**Обычный Code Signing (не EV):**
|
||||||
|
- ⚠️ Доверие нарастает со временем (нужно минимум 100-1000 установок)
|
||||||
|
- ⚠️ Первые месяцы будут предупреждения SmartScreen
|
||||||
|
- 💾 Файл .pfx/.p12 (можно хранить локально)
|
||||||
|
- ⏱️ Получение 1-2 дня
|
||||||
|
|
||||||
|
### 2. Требования для получения
|
||||||
|
|
||||||
|
**Документы:**
|
||||||
|
- Регистрация компании (ИНН, ОГРН, выписка из ЕГРЮЛ)
|
||||||
|
- ИЛИ ИП (ОГРНИП)
|
||||||
|
- ИЛИ личность физлица (паспорт, утилиты)
|
||||||
|
|
||||||
|
**Проверка:**
|
||||||
|
- Подтверждение номера телефона
|
||||||
|
- Email компании (домен должен совпадать)
|
||||||
|
- Банковские реквизиты
|
||||||
|
- Адрес офиса (могут позвонить или прислать письмо с кодом)
|
||||||
|
|
||||||
|
### 3. Процесс получения (DigiCert EV пример)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Заказ → 2-3 минуты (онлайн форма)
|
||||||
|
↓
|
||||||
|
2. Оплата → $799/год
|
||||||
|
↓
|
||||||
|
3. Проверка документов → 3-7 дней
|
||||||
|
- Загрузка ЕГРЮЛ/паспорта
|
||||||
|
- Подтверждение телефона
|
||||||
|
- Проверка адреса
|
||||||
|
↓
|
||||||
|
4. Отправка USB токена → 1-5 дней (DHL/FedEx)
|
||||||
|
↓
|
||||||
|
5. Установка драйверов → 10 минут
|
||||||
|
↓
|
||||||
|
6. Готово! Можно подписывать код
|
||||||
|
```
|
||||||
|
|
||||||
|
## Как подписать файл после получения сертификата
|
||||||
|
|
||||||
|
### С EV сертификатом (USB токен)
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# 1. Установить Windows SDK (включает signtool.exe)
|
||||||
|
# Скачать: https://developer.microsoft.com/windows/downloads/windows-sdk/
|
||||||
|
|
||||||
|
# 2. Подключить USB токен
|
||||||
|
|
||||||
|
# 3. Подписать EXE
|
||||||
|
$signtool = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\signtool.exe"
|
||||||
|
& $signtool sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 /a "umbrix-1.7.3-windows-setup.exe"
|
||||||
|
|
||||||
|
# Результат:
|
||||||
|
# Successfully signed: umbrix-1.7.3-windows-setup.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
### С обычным Code Signing (.pfx файл)
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# 1. Экспортировать сертификат в .pfx с паролем
|
||||||
|
|
||||||
|
# 2. Подписать EXE
|
||||||
|
$signtool = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\signtool.exe"
|
||||||
|
& $signtool sign /f "umbrix-cert.pfx" /p "PASSWORD" /tr http://timestamp.digicert.com /td sha256 /fd sha256 "umbrix-1.7.3-windows-setup.exe"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Проверка подписи
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Посмотреть информацию о подписи
|
||||||
|
$signtool verify /pa /v "umbrix-1.7.3-windows-setup.exe"
|
||||||
|
|
||||||
|
# Или через GUI: ПКМ → Свойства → Цифровые подписи
|
||||||
|
```
|
||||||
|
|
||||||
|
## Автоматизация с GitHub Actions
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Build & Sign Windows
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: ['v*']
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-windows:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Flutter
|
||||||
|
uses: subosito/flutter-action@v2
|
||||||
|
with:
|
||||||
|
flutter-version: '3.24.0'
|
||||||
|
|
||||||
|
- name: Build Windows
|
||||||
|
run: flutter build windows --release
|
||||||
|
|
||||||
|
- name: Build Installer
|
||||||
|
run: iscc windows/installer.iss
|
||||||
|
|
||||||
|
# Для EV сертификата - использовать self-hosted runner с USB токеном
|
||||||
|
# Для обычного - загрузить .pfx в GitHub Secrets
|
||||||
|
|
||||||
|
- name: Sign EXE
|
||||||
|
env:
|
||||||
|
CERT_PASSWORD: ${{ secrets.CERT_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
# Импорт .pfx из секрета
|
||||||
|
$cert = [Convert]::FromBase64String("${{ secrets.CERT_BASE64 }}")
|
||||||
|
[IO.File]::WriteAllBytes("cert.pfx", $cert)
|
||||||
|
|
||||||
|
# Подпись
|
||||||
|
$signtool = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\signtool.exe"
|
||||||
|
& $signtool sign /f cert.pfx /p $env:CERT_PASSWORD /tr http://timestamp.digicert.com /td sha256 /fd sha256 dist/umbrix-1.7.3-windows-setup.exe
|
||||||
|
|
||||||
|
# Удалить временный .pfx
|
||||||
|
Remove-Item cert.pfx
|
||||||
|
|
||||||
|
- name: Upload to Gitea
|
||||||
|
run: |
|
||||||
|
curl -X POST "https://update.umbrix.net/api/v1/repos/vodorod/umbrix/releases/assets" `
|
||||||
|
-H "Authorization: token ${{ secrets.GITEA_TOKEN }}" `
|
||||||
|
--data-binary "@dist/umbrix-1.7.3-windows-setup.exe"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Альтернативы (НЕ рекомендуется)
|
||||||
|
|
||||||
|
### 1. Self-Signed сертификат (для тестирования)
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Создать self-signed сертификат
|
||||||
|
$cert = New-SelfSignedCertificate -Type CodeSigningCert -Subject "CN=Umbrix Team" -CertStoreLocation Cert:\CurrentUser\My
|
||||||
|
|
||||||
|
# Экспортировать
|
||||||
|
$pwd = ConvertTo-SecureString -String "password123" -Force -AsPlainText
|
||||||
|
Export-PfxCertificate -Cert $cert -FilePath umbrix-selfsigned.pfx -Password $pwd
|
||||||
|
|
||||||
|
# Подписать
|
||||||
|
signtool sign /f umbrix-selfsigned.pfx /p password123 /fd sha256 umbrix-1.7.3.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
**⚠️ Проблемы:**
|
||||||
|
- Windows все равно показывает предупреждение
|
||||||
|
- Нужно вручную добавлять сертификат в доверенные
|
||||||
|
- НЕ работает на других компьютерах
|
||||||
|
- Только для внутреннего тестирования
|
||||||
|
|
||||||
|
### 2. Open Source Certificate (StartSSL, Let's Encrypt)
|
||||||
|
|
||||||
|
❌ **Не работает для Code Signing!**
|
||||||
|
- Let's Encrypt выдает только SSL/TLS (для HTTPS)
|
||||||
|
- Code Signing требует проверку юрлица
|
||||||
|
- Нет бесплатных Code Signing сертификатов
|
||||||
|
|
||||||
|
### 3. Использование osslsigncode (Linux подпись Windows файлов)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Установка на Linux
|
||||||
|
sudo apt install osslsigncode
|
||||||
|
|
||||||
|
# Подпись (с .pfx сертификатом)
|
||||||
|
osslsigncode sign \
|
||||||
|
-pkcs12 umbrix-cert.pfx \
|
||||||
|
-pass "PASSWORD" \
|
||||||
|
-ts http://timestamp.digicert.com \
|
||||||
|
-in umbrix-1.7.3-windows-setup.exe \
|
||||||
|
-out umbrix-1.7.3-windows-setup-signed.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
## Рекомендации для Umbrix
|
||||||
|
|
||||||
|
### Для разработки и тестирования (СЕЙЧАС):
|
||||||
|
✅ **Без сертификата** - просто предупреждение Windows
|
||||||
|
- Пользователи могут нажать "Все равно запустить"
|
||||||
|
- Работает для внутреннего использования
|
||||||
|
- Бесплатно
|
||||||
|
|
||||||
|
### Для публичного релиза (БУДУЩЕЕ):
|
||||||
|
✅ **DigiCert EV Code Signing** ($799/год)
|
||||||
|
- Сразу доверие Windows
|
||||||
|
- Нет предупреждений
|
||||||
|
- Профессиональный вид
|
||||||
|
- Рекомендуется для коммерческого продукта
|
||||||
|
|
||||||
|
### Для малого бюджета:
|
||||||
|
✅ **Certum Open Source Code Signing** (€199/год)
|
||||||
|
- Дешевле других
|
||||||
|
- Принимают криптовалюту
|
||||||
|
- Специальная цена для Open Source проектов
|
||||||
|
- Требуют ссылку на GitHub/GitLab
|
||||||
|
|
||||||
|
## Ссылки
|
||||||
|
|
||||||
|
**Покупка сертификатов:**
|
||||||
|
- DigiCert: https://www.digicert.com/signing/code-signing-certificates
|
||||||
|
- Sectigo: https://sectigo.com/ssl-certificates-tls/code-signing
|
||||||
|
- GlobalSign: https://www.globalsign.com/en/code-signing-certificate
|
||||||
|
- SSL.com: https://www.ssl.com/certificates/code-signing/
|
||||||
|
- Certum: https://en.sklep.certum.pl/data-safety/code-signing-certificates/
|
||||||
|
|
||||||
|
**Документация:**
|
||||||
|
- Microsoft Code Signing: https://learn.microsoft.com/windows/win32/seccrypto/cryptography-tools
|
||||||
|
- signtool.exe: https://learn.microsoft.com/windows-hardware/drivers/devtest/signtool
|
||||||
|
|
||||||
|
**Проверка репутации SmartScreen:**
|
||||||
|
- https://www.microsoft.com/en-us/wdsi/filesubmission
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
**Q: Можно ли работать без сертификата?**
|
||||||
|
A: Да! Приложение будет работать, но Windows покажет предупреждение "Неизвестный издатель". Для личного/внутреннего использования это OK.
|
||||||
|
|
||||||
|
**Q: Как быстро получить доверие SmartScreen с обычным сертификатом?**
|
||||||
|
A: Нужно минимум 100-1000 установок за 2-3 месяца. EV сертификат дает доверие сразу.
|
||||||
|
|
||||||
|
**Q: Можно ли использовать сертификат на Linux для подписи Windows файлов?**
|
||||||
|
A: Да, через `osslsigncode`. Но EV сертификаты на USB токене работают только на Windows.
|
||||||
|
|
||||||
|
**Q: Что дешевле - EV или обычный Code Signing?**
|
||||||
|
A: Обычный дешевле ($299 vs $799), но нужно ждать наработки репутации. EV дороже, но доверие сразу.
|
||||||
|
|
||||||
|
**Q: Сертификат для Umbrix - обязателен?**
|
||||||
|
A: Для закрытого тестирования - НЕТ. Для публичного релиза - ОЧЕНЬ ЖЕЛАТЕЛЬНО.
|
||||||
|
|
||||||
|
## Итого
|
||||||
|
|
||||||
|
**Текущая конфигурация обновлений:**
|
||||||
|
- ✅ Файл: `.exe` установщик (Inno Setup)
|
||||||
|
- ✅ Приоритет поиска: x64 → amd64 → win64 → setup → installer → любой .exe
|
||||||
|
- ✅ Установка: PowerShell с `/VERYSILENT /SUPPRESSMSGBOXES /NORESTART`
|
||||||
|
- ✅ Автоперезагрузка: через 2 секунды
|
||||||
|
- ⚠️ Сертификат: НЕТ (показывает предупреждение, но работает)
|
||||||
|
|
||||||
|
**Следующие шаги:**
|
||||||
|
1. Собрать Windows версию на машине с Windows
|
||||||
|
2. Создать Inno Setup установщик
|
||||||
|
3. Загрузить в Gitea релиз
|
||||||
|
4. Протестировать автообновление
|
||||||
|
5. (Опционально) Купить сертификат для публичного релиза
|
||||||
260
update-server/GITEA_SETUP.md
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
# 🚀 Установка Gitea для системы обновлений Umbrix
|
||||||
|
|
||||||
|
## 📋 Подготовка
|
||||||
|
|
||||||
|
### 1. Аренда VPS
|
||||||
|
**Минимальные требования:**
|
||||||
|
- RAM: 1GB (рекомендую 2GB для комфорта)
|
||||||
|
- CPU: 1 vCore
|
||||||
|
- SSD: 20GB
|
||||||
|
- OS: Ubuntu 22.04 / Debian 12
|
||||||
|
|
||||||
|
**Рекомендуемые провайдеры:**
|
||||||
|
- Hetzner Cloud (от €3.79/мес, 2GB RAM)
|
||||||
|
- DigitalOcean Droplet ($6/мес)
|
||||||
|
- Contabo VPS (от €4.99/мес, 4GB RAM)
|
||||||
|
|
||||||
|
### 2. Домены
|
||||||
|
Настройте DNS записи для:
|
||||||
|
```
|
||||||
|
git.umbrix.net → IP вашего сервера
|
||||||
|
git-mirror1.umbrix.net → IP сервера (или другой сервер)
|
||||||
|
git-mirror2.umbrix.net → IP сервера (или другой сервер)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. SSL сертификаты (Let's Encrypt)
|
||||||
|
```bash
|
||||||
|
# Установите certbot
|
||||||
|
sudo apt update && sudo apt install -y certbot
|
||||||
|
|
||||||
|
# Получите сертификаты для всех доменов
|
||||||
|
sudo certbot certonly --standalone -d git.umbrix.net
|
||||||
|
sudo certbot certonly --standalone -d git-mirror1.umbrix.net
|
||||||
|
sudo certbot certonly --standalone -d git-mirror2.umbrix.net
|
||||||
|
|
||||||
|
# Скопируйте в папку nginx/ssl/
|
||||||
|
sudo cp /etc/letsencrypt/live/git.umbrix.net/fullchain.pem nginx/ssl/
|
||||||
|
sudo cp /etc/letsencrypt/live/git.umbrix.net/privkey.pem nginx/ssl/
|
||||||
|
# Повторите для mirror1 и mirror2
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🐳 Установка Gitea
|
||||||
|
|
||||||
|
### 1. Установите Docker
|
||||||
|
```bash
|
||||||
|
# Удалите старые версии
|
||||||
|
sudo apt remove docker docker-engine docker.io containerd runc
|
||||||
|
|
||||||
|
# Установите Docker
|
||||||
|
curl -fsSL https://get.docker.com -o get-docker.sh
|
||||||
|
sudo sh get-docker.sh
|
||||||
|
|
||||||
|
# Добавьте пользователя в группу docker
|
||||||
|
sudo usermod -aG docker $USER
|
||||||
|
newgrp docker
|
||||||
|
|
||||||
|
# Установите Docker Compose
|
||||||
|
sudo apt install -y docker-compose
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Загрузите конфигурацию
|
||||||
|
```bash
|
||||||
|
# Создайте папку
|
||||||
|
mkdir -p ~/gitea-server
|
||||||
|
cd ~/gitea-server
|
||||||
|
|
||||||
|
# Скопируйте файлы:
|
||||||
|
# - gitea-docker-compose.yml → docker-compose.yml
|
||||||
|
# - nginx.conf → nginx/nginx.conf
|
||||||
|
|
||||||
|
# Создайте папки для SSL
|
||||||
|
mkdir -p nginx/ssl gitea/data gitea/postgres
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Настройте пароль БД
|
||||||
|
Отредактируйте `docker-compose.yml`:
|
||||||
|
```yaml
|
||||||
|
POSTGRES_PASSWORD=ваш_надёжный_пароль_здесь
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Запустите Gitea
|
||||||
|
```bash
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Первоначальная настройка
|
||||||
|
Откройте браузер: `https://git.umbrix.net`
|
||||||
|
|
||||||
|
**Настройки установки:**
|
||||||
|
- Database Type: `PostgreSQL`
|
||||||
|
- Host: `db:5432`
|
||||||
|
- Username: `gitea`
|
||||||
|
- Password: (ваш пароль из docker-compose.yml)
|
||||||
|
- Database Name: `gitea`
|
||||||
|
- SSH Server Domain: `git.umbrix.net`
|
||||||
|
- Gitea Base URL: `https://git.umbrix.net`
|
||||||
|
- **Отключите регистрацию** (только вы сможете создавать аккаунты)
|
||||||
|
|
||||||
|
## 📦 Создание репозитория и релиза
|
||||||
|
|
||||||
|
### 1. Создайте репозиторий
|
||||||
|
- Войдите в Gitea
|
||||||
|
- Нажмите "+" → "New Repository"
|
||||||
|
- Название: `umbrix`
|
||||||
|
- Visibility: `Public` (для обновлений)
|
||||||
|
|
||||||
|
### 2. Загрузите код (с локальной машины)
|
||||||
|
```bash
|
||||||
|
cd ~/dorod/hiddify-umbrix-v1.7.0
|
||||||
|
|
||||||
|
# Инициализируйте Git (если не инициализирован)
|
||||||
|
git init
|
||||||
|
git add .
|
||||||
|
git commit -m "Initial commit"
|
||||||
|
|
||||||
|
# Добавьте remote (замените на свой домен)
|
||||||
|
git remote add gitea https://git.umbrix.net/your-username/umbrix.git
|
||||||
|
|
||||||
|
# Запушьте код
|
||||||
|
git push -u gitea main
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Создайте релиз
|
||||||
|
**Через UI:**
|
||||||
|
1. Перейдите: Releases → New Release
|
||||||
|
2. Tag: `v1.7.3`
|
||||||
|
3. Title: `Umbrix v1.7.3`
|
||||||
|
4. Описание: (release notes)
|
||||||
|
5. Прикрепите файлы:
|
||||||
|
- `umbrix-1.7.3-linux-x86_64.deb`
|
||||||
|
- `umbrix-1.7.3-linux-x86_64.rpm`
|
||||||
|
- `Umbrix-1.7.3-linux-x86_64.AppImage`
|
||||||
|
|
||||||
|
**Через API:**
|
||||||
|
```bash
|
||||||
|
# Получите Access Token: Настройки → Applications → Generate Token
|
||||||
|
|
||||||
|
curl -X POST "https://git.umbrix.net/api/v1/repos/your-username/umbrix/releases" \
|
||||||
|
-H "Authorization: token YOUR_ACCESS_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"tag_name": "v1.7.3",
|
||||||
|
"name": "Umbrix v1.7.3",
|
||||||
|
"body": "## Что нового\n- Улучшена стабильность",
|
||||||
|
"draft": false,
|
||||||
|
"prerelease": false
|
||||||
|
}'
|
||||||
|
|
||||||
|
# Загрузите файлы релиза
|
||||||
|
curl -X POST "https://git.umbrix.net/api/v1/repos/your-username/umbrix/releases/ID/assets" \
|
||||||
|
-H "Authorization: token YOUR_ACCESS_TOKEN" \
|
||||||
|
-F "attachment=@dist/umbrix-1.7.3.deb"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Настройка Umbrix для Gitea
|
||||||
|
|
||||||
|
Отредактируйте `lib/core/model/constants.dart`:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
abstract class Constants {
|
||||||
|
static const appName = "Umbrix";
|
||||||
|
static const githubUrl = "https://git.umbrix.net/your-username/umbrix";
|
||||||
|
static const githubReleasesApiUrl = "https://git.umbrix.net/api/v1/repos/your-username/umbrix/releases";
|
||||||
|
static const githubLatestReleaseUrl = "https://git.umbrix.net/your-username/umbrix/releases/latest";
|
||||||
|
|
||||||
|
// ... остальное без изменений
|
||||||
|
static const useCustomUpdateServer = false; // Используем Gitea API
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Пересоберите:**
|
||||||
|
```bash
|
||||||
|
flutter build linux --release
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🌐 Стратегия зеркал (антиблокировка)
|
||||||
|
|
||||||
|
### Вариант 1: DNS Load Balancing
|
||||||
|
Несколько IP для одного домена:
|
||||||
|
```
|
||||||
|
git.umbrix.net → 1.2.3.4, 5.6.7.8, 9.10.11.12
|
||||||
|
```
|
||||||
|
|
||||||
|
### Вариант 2: Поддомены-зеркала
|
||||||
|
```dart
|
||||||
|
static const githubReleasesApiUrl = List<String>[
|
||||||
|
"https://git.umbrix.net/api/v1/repos/your-username/umbrix/releases",
|
||||||
|
"https://git-mirror1.umbrix.net/api/v1/repos/your-username/umbrix/releases",
|
||||||
|
"https://git-mirror2.umbrix.net/api/v1/repos/your-username/umbrix/releases",
|
||||||
|
];
|
||||||
|
|
||||||
|
// В app_update_repository.dart пробуем по очереди:
|
||||||
|
for (final url in Constants.githubReleasesApiUrl) {
|
||||||
|
try {
|
||||||
|
final response = await httpClient.get(url);
|
||||||
|
if (response.statusCode == 200) return response;
|
||||||
|
} catch (e) {
|
||||||
|
continue; // Пробуем следующее зеркало
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Вариант 3: Cloudflare + Workers
|
||||||
|
Прокси через Cloudflare Workers (обходит блокировки):
|
||||||
|
```javascript
|
||||||
|
// worker.js
|
||||||
|
export default {
|
||||||
|
async fetch(request) {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
const targetUrl = "https://git.umbrix.net" + url.pathname;
|
||||||
|
return fetch(targetUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Домен: `updates.umbrix.workers.dev`
|
||||||
|
|
||||||
|
## 📊 Мониторинг
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Логи Gitea
|
||||||
|
docker-compose logs -f gitea
|
||||||
|
|
||||||
|
# Статус
|
||||||
|
docker-compose ps
|
||||||
|
|
||||||
|
# Использование ресурсов
|
||||||
|
docker stats
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔄 Обновление Gitea
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose pull
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
## 💾 Бэкапы
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Бэкап данных Gitea
|
||||||
|
docker exec -u git gitea gitea dump -c /data/gitea/conf/app.ini
|
||||||
|
|
||||||
|
# Бэкап БД
|
||||||
|
docker exec gitea-db pg_dump -U gitea gitea > backup.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎉 Готово!
|
||||||
|
|
||||||
|
Теперь у вас:
|
||||||
|
- ✅ Свой GitHub-клон на домене `git.umbrix.net`
|
||||||
|
- ✅ API для проверки обновлений (совместим с GitHub API)
|
||||||
|
- ✅ Зеркала для обхода блокировок
|
||||||
|
- ✅ UI для управления релизами
|
||||||
|
|
||||||
|
**URL releases API:**
|
||||||
|
```
|
||||||
|
https://git.umbrix.net/api/v1/repos/your-username/umbrix/releases
|
||||||
|
```
|
||||||
|
|
||||||
|
Формат ответа идентичен GitHub API!
|
||||||
255
update-server/INSTALL_INSTRUCTIONS.md
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
# 🚀 Инструкция по установке Gitea на сервер 85.208.139.84
|
||||||
|
|
||||||
|
## Шаг 1: Подключение к серверу
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Подключитесь к серверу по SSH
|
||||||
|
ssh root@85.208.139.84
|
||||||
|
# или
|
||||||
|
ssh ваш_пользователь@85.208.139.84
|
||||||
|
```
|
||||||
|
|
||||||
|
## Шаг 2: Загрузка установочного скрипта
|
||||||
|
|
||||||
|
**Вариант A: Через scp (с локальной машины)**
|
||||||
|
```bash
|
||||||
|
cd ~/dorod/hiddify-umbrix-v1.7.0/update-server
|
||||||
|
scp install-gitea.sh root@85.208.139.84:/root/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Вариант B: Прямо на сервере (создать файл)**
|
||||||
|
```bash
|
||||||
|
# На сервере
|
||||||
|
nano install-gitea.sh
|
||||||
|
# Скопируйте содержимое файла install-gitea.sh
|
||||||
|
# Сохраните: Ctrl+O, Enter, Ctrl+X
|
||||||
|
```
|
||||||
|
|
||||||
|
**Вариант C: Через curl (самый простой)**
|
||||||
|
```bash
|
||||||
|
# На сервере, скопируйте файл в интернет и скачайте:
|
||||||
|
curl -O https://ваш-сервер/install-gitea.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Шаг 3: Запуск установки
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Сделайте скрипт исполняемым
|
||||||
|
chmod +x install-gitea.sh
|
||||||
|
|
||||||
|
# Запустите установку
|
||||||
|
sudo ./install-gitea.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Установка займёт **3-5 минут**.
|
||||||
|
|
||||||
|
## Шаг 4: Первоначальная настройка Gitea
|
||||||
|
|
||||||
|
1. Откройте браузер: **http://85.208.139.84:3000**
|
||||||
|
|
||||||
|
2. При первом входе увидите страницу установки:
|
||||||
|
|
||||||
|
**Database Settings:**
|
||||||
|
- Database Type: `PostgreSQL` ✓
|
||||||
|
- Host: `db:5432` ✓
|
||||||
|
- Username: `gitea` ✓
|
||||||
|
- Password: `gitea_secure_pass_2026` ✓
|
||||||
|
- Database Name: `gitea` ✓
|
||||||
|
|
||||||
|
**General Settings:**
|
||||||
|
- Site Title: `Umbrix Updates`
|
||||||
|
- Repository Root Path: `/data/git/repositories` ✓
|
||||||
|
- Git LFS Root Path: `/data/git/lfs` ✓
|
||||||
|
- Run As Username: `git` ✓
|
||||||
|
|
||||||
|
**Server and Third-Party Service Settings:**
|
||||||
|
- SSH Server Domain: `85.208.139.84` ✓
|
||||||
|
- SSH Server Port: `2222` ✓
|
||||||
|
- Gitea HTTP Listen Port: `3000` ✓
|
||||||
|
- Gitea Base URL: `http://85.208.139.84:3000` ✓
|
||||||
|
|
||||||
|
**Email Settings:** (можно пропустить)
|
||||||
|
|
||||||
|
**Administrator Account Settings:**
|
||||||
|
- Administrator Username: `admin` (или ваш логин)
|
||||||
|
- Password: (ваш надёжный пароль)
|
||||||
|
- Email: `admin@umbrix.net`
|
||||||
|
|
||||||
|
3. Нажмите **"Install Gitea"**
|
||||||
|
|
||||||
|
4. Дождитесь завершения установки (10-20 секунд)
|
||||||
|
|
||||||
|
5. Войдите с созданными учётными данными
|
||||||
|
|
||||||
|
## Шаг 5: Создание репозитория Umbrix
|
||||||
|
|
||||||
|
1. После входа нажмите **"+"** → **"New Repository"**
|
||||||
|
|
||||||
|
2. Заполните:
|
||||||
|
- Owner: `admin` (ваш пользователь)
|
||||||
|
- Repository Name: `umbrix`
|
||||||
|
- Description: `Umbrix VPN Application`
|
||||||
|
- Visibility: ☑ **Public** (важно для updates!)
|
||||||
|
- Initialize Repository: ☐ (пустой, заполним с локальной машины)
|
||||||
|
|
||||||
|
3. Нажмите **"Create Repository"**
|
||||||
|
|
||||||
|
## Шаг 6: Загрузка кода с локальной машины
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# На локальной машине
|
||||||
|
cd ~/dorod/hiddify-umbrix-v1.7.0
|
||||||
|
|
||||||
|
# Добавьте remote для Gitea
|
||||||
|
git remote add gitea http://85.208.139.84:3000/admin/umbrix.git
|
||||||
|
|
||||||
|
# Запушьте код
|
||||||
|
git push -u gitea main
|
||||||
|
# Введите: admin / ваш_пароль
|
||||||
|
```
|
||||||
|
|
||||||
|
## Шаг 7: Создание первого релиза
|
||||||
|
|
||||||
|
### Через UI:
|
||||||
|
|
||||||
|
1. Откройте: http://85.208.139.84:3000/admin/umbrix
|
||||||
|
2. Перейдите: **Releases** → **New Release**
|
||||||
|
3. Заполните:
|
||||||
|
- Tag version: `v1.7.3`
|
||||||
|
- Release Title: `Umbrix v1.7.3`
|
||||||
|
- Describe this release:
|
||||||
|
```
|
||||||
|
## 🚀 Что нового
|
||||||
|
- Улучшена стабильность подключения
|
||||||
|
- Исправлены ошибки
|
||||||
|
```
|
||||||
|
4. Прикрепите файлы (Drag & Drop):
|
||||||
|
- `dist/umbrix-1.7.3-linux.deb`
|
||||||
|
- `dist/umbrix-1.7.3-linux.rpm`
|
||||||
|
- `dist/Umbrix-1.7.3-linux.AppImage`
|
||||||
|
|
||||||
|
5. Нажмите **"Publish Release"**
|
||||||
|
|
||||||
|
### Через API (автоматизация):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Получите Access Token
|
||||||
|
# Gitea → Settings → Applications → Generate New Token
|
||||||
|
# Permissions: read:repository, write:repository
|
||||||
|
|
||||||
|
TOKEN="ваш_токен"
|
||||||
|
|
||||||
|
# Создайте релиз
|
||||||
|
curl -X POST "http://85.208.139.84:3000/api/v1/repos/admin/umbrix/releases" \
|
||||||
|
-H "Authorization: token $TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"tag_name": "v1.7.3",
|
||||||
|
"name": "Umbrix v1.7.3",
|
||||||
|
"body": "## Что нового\n- Улучшена стабильность",
|
||||||
|
"draft": false,
|
||||||
|
"prerelease": false
|
||||||
|
}'
|
||||||
|
|
||||||
|
# Загрузите файлы
|
||||||
|
RELEASE_ID=1 # ID из предыдущего ответа
|
||||||
|
|
||||||
|
curl -X POST "http://85.208.139.84:3000/api/v1/repos/admin/umbrix/releases/$RELEASE_ID/assets" \
|
||||||
|
-H "Authorization: token $TOKEN" \
|
||||||
|
-H "Content-Type: multipart/form-data" \
|
||||||
|
-F "attachment=@dist/umbrix-1.7.3-linux.deb"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Шаг 8: Настройка Umbrix для использования Gitea
|
||||||
|
|
||||||
|
Отредактируйте `lib/core/model/constants.dart`:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
abstract class Constants {
|
||||||
|
static const appName = "Umbrix";
|
||||||
|
static const githubUrl = "http://85.208.139.84:3000/admin/umbrix";
|
||||||
|
static const githubReleasesApiUrl = "http://85.208.139.84:3000/api/v1/repos/admin/umbrix/releases";
|
||||||
|
static const githubLatestReleaseUrl = "http://85.208.139.84:3000/admin/umbrix/releases/latest";
|
||||||
|
// ...
|
||||||
|
static const useCustomUpdateServer = false; // Используем Gitea API
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пересоберите:
|
||||||
|
```bash
|
||||||
|
flutter build linux --release
|
||||||
|
```
|
||||||
|
|
||||||
|
## Шаг 9: Тест проверки обновлений
|
||||||
|
|
||||||
|
1. Запустите пересобранное приложение
|
||||||
|
2. Откройте: **Настройки** → **О программе**
|
||||||
|
3. Нажмите **"Проверка обновлений"**
|
||||||
|
4. Должно показать: **"Доступно обновление до версии 1.7.3"**
|
||||||
|
|
||||||
|
## 📊 Управление сервером
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# На сервере
|
||||||
|
cd /opt/gitea
|
||||||
|
|
||||||
|
# Просмотр логов
|
||||||
|
docker-compose logs -f gitea
|
||||||
|
|
||||||
|
# Статус контейнеров
|
||||||
|
docker-compose ps
|
||||||
|
|
||||||
|
# Перезапуск
|
||||||
|
docker-compose restart
|
||||||
|
|
||||||
|
# Остановка
|
||||||
|
docker-compose down
|
||||||
|
|
||||||
|
# Запуск
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# Обновление Gitea
|
||||||
|
docker-compose pull
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Устранение проблем
|
||||||
|
|
||||||
|
### Gitea не запускается
|
||||||
|
```bash
|
||||||
|
docker-compose logs gitea
|
||||||
|
docker-compose logs db
|
||||||
|
```
|
||||||
|
|
||||||
|
### Порты заняты
|
||||||
|
```bash
|
||||||
|
# Проверьте что порты свободны
|
||||||
|
netstat -tulpn | grep 3000
|
||||||
|
netstat -tulpn | grep 2222
|
||||||
|
```
|
||||||
|
|
||||||
|
### Забыли пароль админа
|
||||||
|
```bash
|
||||||
|
docker exec -it gitea gitea admin user change-password -u admin -p новый_пароль
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🌐 Следующие шаги (опционально)
|
||||||
|
|
||||||
|
### 1. Настройка домена (вместо IP)
|
||||||
|
Если есть домен `git.umbrix.net`:
|
||||||
|
1. Добавьте A-запись: `git.umbrix.net → 85.208.139.84`
|
||||||
|
2. Установите Nginx + Certbot для HTTPS
|
||||||
|
3. Обновите `GITEA__server__DOMAIN` в docker-compose.yml
|
||||||
|
|
||||||
|
### 2. Автоматизация сборки
|
||||||
|
Настройте Gitea Actions (аналог GitHub Actions) для автоматической сборки при push.
|
||||||
|
|
||||||
|
### 3. Зеркала
|
||||||
|
Разверните такие же контейнеры на других IP для обхода блокировок.
|
||||||
|
|
||||||
|
## ✅ Готово!
|
||||||
|
|
||||||
|
Теперь у вас работает:
|
||||||
|
- ✓ Gitea на http://85.208.139.84:3000
|
||||||
|
- ✓ API обновлений: http://85.208.139.84:3000/api/v1/repos/admin/umbrix/releases
|
||||||
|
- ✓ Umbrix проверяет обновления через Gitea
|
||||||
110
update-server/WINDOWS_BUILD_CHEATSHEET.md
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
# Windows Build Cheat Sheet
|
||||||
|
|
||||||
|
## 🚀 Быстрая сборка (на Windows машине)
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# 1. Клонировать репозиторий
|
||||||
|
git clone --recursive https://update.umbrix.net/vodorod/umbrix.git
|
||||||
|
cd umbrix
|
||||||
|
|
||||||
|
# 2. Скачать и заменить libcore.dll
|
||||||
|
curl -L -o libcore.tar.gz "https://update.umbrix.net/vodorod/umbrix-libcore/releases/download/v1.7.0-umbrix/libcore-windows-amd64-umbrix.tar.gz"
|
||||||
|
tar -xzf libcore.tar.gz
|
||||||
|
Copy-Item libcore.dll -Destination libcore\bin\libcore.dll -Force
|
||||||
|
|
||||||
|
# 3. Установить flutter_distributor (один раз)
|
||||||
|
dart pub global activate flutter_distributor
|
||||||
|
|
||||||
|
# 4. СОБРАТЬ УСТАНОВЩИК
|
||||||
|
dart run flutter_distributor:main package --platform windows --targets exe --skip-clean
|
||||||
|
|
||||||
|
# ✅ Результат: dist\1.7.3+173\umbrix-setup-x64.exe (~60MB)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📦 Что получается?
|
||||||
|
|
||||||
|
**Один .exe файл** который содержит:
|
||||||
|
- umbrix.exe (основное приложение)
|
||||||
|
- Flutter runtime
|
||||||
|
- libcore.dll (45MB VPN ядро)
|
||||||
|
- WebUI
|
||||||
|
- Все зависимости
|
||||||
|
- Установщик Inno Setup
|
||||||
|
|
||||||
|
## 📤 Загрузка в Gitea
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Переименовать для релиза
|
||||||
|
$version = "1.7.3"
|
||||||
|
$file = "dist\$version+173\umbrix-setup-x64.exe"
|
||||||
|
$newName = "umbrix-$version-windows-setup-x64.exe"
|
||||||
|
Copy-Item $file $newName
|
||||||
|
|
||||||
|
# Загрузить
|
||||||
|
$token = "YOUR_GITEA_TOKEN"
|
||||||
|
$releaseId = 1
|
||||||
|
|
||||||
|
curl -X POST "https://update.umbrix.net/api/v1/repos/vodorod/umbrix/releases/$releaseId/assets?name=$newName" `
|
||||||
|
-H "Authorization: token $token" `
|
||||||
|
-H "Content-Type: application/octet-stream" `
|
||||||
|
--data-binary "@$newName"
|
||||||
|
```
|
||||||
|
|
||||||
|
## ✅ Тестирование автообновлений
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# 1. Установить старую версию (например 1.7.0)
|
||||||
|
.\umbrix-1.7.0-windows-setup-x64.exe
|
||||||
|
|
||||||
|
# 2. Запустить приложение
|
||||||
|
# Через 5 секунд появится уведомление об обновлении
|
||||||
|
|
||||||
|
# 3. Нажать "Обновить"
|
||||||
|
# Автоматически скачается, установится, перезапустится
|
||||||
|
|
||||||
|
# 4. Проверить версию
|
||||||
|
# Должна быть 1.7.3
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Требования
|
||||||
|
|
||||||
|
- Windows 10/11
|
||||||
|
- Flutter 3.24.0+
|
||||||
|
- Visual Studio 2022 с C++
|
||||||
|
- Inno Setup 6.x+ (https://jrsoftware.org/isdl.php)
|
||||||
|
|
||||||
|
## 📚 Документация
|
||||||
|
|
||||||
|
- **Полная инструкция:** [WINDOWS_DISTRIBUTOR_BUILD.md](WINDOWS_DISTRIBUTOR_BUILD.md)
|
||||||
|
- **Подпись кода:** [CODE_SIGNING_WINDOWS.md](CODE_SIGNING_WINDOWS.md)
|
||||||
|
- **Ручная сборка:** [WINDOWS_BUILD_INSTRUCTIONS.md](WINDOWS_BUILD_INSTRUCTIONS.md)
|
||||||
|
|
||||||
|
## ⚠️ Частые ошибки
|
||||||
|
|
||||||
|
**"Failed to lookup symbol 'changeHiddifyOptions'"**
|
||||||
|
→ Используйте libcore.dll из umbrix-libcore, НЕ из оригинального Hiddify
|
||||||
|
|
||||||
|
**"Inno Setup not found"**
|
||||||
|
→ Установите Inno Setup и добавьте в PATH
|
||||||
|
|
||||||
|
**"flutter_distributor command not found"**
|
||||||
|
→ `dart pub global activate flutter_distributor`
|
||||||
|
→ Добавьте `C:\Users\YOUR_NAME\AppData\Local\Pub\Cache\bin` в PATH
|
||||||
|
|
||||||
|
## 💡 Сертификат кода
|
||||||
|
|
||||||
|
**Не обязателен для работы!**
|
||||||
|
- Без сертификата: Windows показывает предупреждение, но приложение работает
|
||||||
|
- С сертификатом: Нет предупреждений, "Проверенный издатель"
|
||||||
|
- Цена: $299-799/год (DigiCert, Sectigo, Certum)
|
||||||
|
- Подробности: [CODE_SIGNING_WINDOWS.md](CODE_SIGNING_WINDOWS.md)
|
||||||
|
|
||||||
|
## 🎯 Итого
|
||||||
|
|
||||||
|
**Одна команда → Один .exe файл → Готово к релизу**
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
dart run flutter_distributor package --platform windows --targets exe
|
||||||
|
```
|
||||||
|
|
||||||
|
Всё остальное делается автоматически! 🚀
|
||||||
230
update-server/WINDOWS_BUILD_INSTRUCTIONS.md
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
# Windows Build & Update Instructions
|
||||||
|
|
||||||
|
## ⚡ РЕКОМЕНДУЕТСЯ: flutter_distributor (автоматическая упаковка)
|
||||||
|
|
||||||
|
**Используйте [WINDOWS_DISTRIBUTOR_BUILD.md](WINDOWS_DISTRIBUTOR_BUILD.md)** для автоматической сборки через flutter_distributor.
|
||||||
|
|
||||||
|
Преимущества:
|
||||||
|
- ✅ **Один .exe файл** вместо папки с множеством файлов
|
||||||
|
- ✅ Автоматическая упаковка через Inno Setup
|
||||||
|
- ✅ Та же команда, что для Linux (deb/rpm/appimage)
|
||||||
|
- ✅ Готовый конфиг уже настроен в `windows/packaging/exe/`
|
||||||
|
|
||||||
|
**Команда:**
|
||||||
|
```powershell
|
||||||
|
dart run flutter_distributor:main package --platform windows --targets exe --skip-clean
|
||||||
|
```
|
||||||
|
|
||||||
|
**Результат:** `dist/1.7.3+173/umbrix-setup-x64.exe` (~60MB) - готов к загрузке!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Альтернатива: Ручная сборка через Inno Setup
|
||||||
|
|
||||||
|
Используйте этот метод только если flutter_distributor не работает.
|
||||||
|
|
||||||
|
## Система автообновлений для Windows
|
||||||
|
|
||||||
|
### Требования для Windows EXE сборки
|
||||||
|
|
||||||
|
1. **Inno Setup** - для создания установщика
|
||||||
|
- Скачать: https://jrsoftware.org/isdl.php
|
||||||
|
- Версия: 6.x или новее
|
||||||
|
|
||||||
|
2. **Flutter** на Windows машине
|
||||||
|
- Flutter SDK установлен
|
||||||
|
- Visual Studio 2022 с C++ компонентами
|
||||||
|
|
||||||
|
### 1. Сборка Windows приложения
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Сборка Release версии
|
||||||
|
flutter build windows --release
|
||||||
|
|
||||||
|
# Результат: build/windows/x64/runner/Release/
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Создание Inno Setup скрипта
|
||||||
|
|
||||||
|
Создайте файл `windows/installer.iss`:
|
||||||
|
|
||||||
|
```inno
|
||||||
|
#define MyAppName "Umbrix"
|
||||||
|
#define MyAppVersion "1.7.3"
|
||||||
|
#define MyAppPublisher "Umbrix Team"
|
||||||
|
#define MyAppURL "https://umbrix.net"
|
||||||
|
#define MyAppExeName "umbrix.exe"
|
||||||
|
|
||||||
|
[Setup]
|
||||||
|
AppId={{YOUR-GUID-HERE}}
|
||||||
|
AppName={#MyAppName}
|
||||||
|
AppVersion={#MyAppVersion}
|
||||||
|
AppPublisher={#MyAppPublisher}
|
||||||
|
AppPublisherURL={#MyAppURL}
|
||||||
|
DefaultDirName={autopf}\{#MyAppName}
|
||||||
|
DefaultGroupName={#MyAppName}
|
||||||
|
OutputDir=..\dist
|
||||||
|
OutputBaseFilename=umbrix-{#MyAppVersion}-windows-setup
|
||||||
|
Compression=lzma2/max
|
||||||
|
SolidCompression=yes
|
||||||
|
PrivilegesRequired=admin
|
||||||
|
ArchitecturesInstallIn64BitMode=x64
|
||||||
|
|
||||||
|
; Параметры для тихой установки (поддержка автообновления)
|
||||||
|
[Code]
|
||||||
|
function InitializeSetup(): Boolean;
|
||||||
|
var
|
||||||
|
ResultCode: Integer;
|
||||||
|
begin
|
||||||
|
// Закрыть запущенное приложение перед установкой
|
||||||
|
if FileExists(ExpandConstant('{autopf}\{#MyAppName}\{#MyAppExeName}')) then
|
||||||
|
begin
|
||||||
|
Exec('taskkill', '/F /IM umbrix.exe', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
||||||
|
end;
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
[Files]
|
||||||
|
Source: "..\build\windows\x64\runner\Release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
|
||||||
|
|
||||||
|
[Icons]
|
||||||
|
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
||||||
|
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
||||||
|
|
||||||
|
[Run]
|
||||||
|
Filename: "{app}\{#MyAppExeName}"; Description: "Launch {#MyAppName}"; Flags: nowait postinstall skipifsilent
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Компиляция установщика
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# В папке windows/
|
||||||
|
iscc installer.iss
|
||||||
|
|
||||||
|
# Результат: dist/umbrix-1.7.3-windows-setup.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Загрузка в Gitea
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Загрузка в релиз через API
|
||||||
|
$token = "YOUR_GITEA_TOKEN"
|
||||||
|
$file = "dist/umbrix-1.7.3-windows-setup.exe"
|
||||||
|
|
||||||
|
curl -X POST "https://update.umbrix.net/api/v1/repos/vodorod/umbrix/releases/1/assets?name=umbrix-1.7.3-windows-setup.exe" `
|
||||||
|
-H "Authorization: token $token" `
|
||||||
|
-H "Content-Type: application/octet-stream" `
|
||||||
|
--data-binary "@$file"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Как работает автообновление на Windows
|
||||||
|
|
||||||
|
### 1. Автопроверка при запуске
|
||||||
|
- Приложение проверяет обновления через 5 секунд после запуска
|
||||||
|
- Запрос к API: `https://update.umbrix.net/api/v1/repos/vodorod/umbrix/releases`
|
||||||
|
|
||||||
|
### 2. Обнаружение обновления
|
||||||
|
- Парсит JSON с assets
|
||||||
|
- Ищет файл с расширением `.exe`
|
||||||
|
- Показывает диалог "Доступно обновление"
|
||||||
|
|
||||||
|
### 3. Автоматическая установка
|
||||||
|
При нажатии "Обновить":
|
||||||
|
|
||||||
|
1. **Скачивание** - файл загружается в `%TEMP%\umbrix-1.7.3.exe`
|
||||||
|
2. **Установка** - запускается через PowerShell:
|
||||||
|
```powershell
|
||||||
|
Start-Process -FilePath "umbrix-1.7.3.exe" `
|
||||||
|
-ArgumentList "/VERYSILENT", "/SUPPRESSMSGBOXES", "/NORESTART" `
|
||||||
|
-Verb RunAs -Wait
|
||||||
|
```
|
||||||
|
3. **Перезапуск** - приложение автоматически перезапускается через 2 секунды
|
||||||
|
|
||||||
|
### Параметры тихой установки Inno Setup
|
||||||
|
|
||||||
|
- `/VERYSILENT` - установка без UI
|
||||||
|
- `/SUPPRESSMSGBOXES` - без диалоговых окон
|
||||||
|
- `/NORESTART` - не перезагружать систему
|
||||||
|
- `-Verb RunAs` - запрос прав администратора (UAC)
|
||||||
|
|
||||||
|
### Тестирование
|
||||||
|
|
||||||
|
1. Соберите версию 1.7.0
|
||||||
|
2. Установите: `umbrix-1.7.0-windows-setup.exe`
|
||||||
|
3. Соберите версию 1.7.3, загрузите в Gitea
|
||||||
|
4. Запустите приложение 1.7.0
|
||||||
|
5. Должно появиться уведомление об обновлении
|
||||||
|
6. Нажмите "Обновить" → автоустановка → автоперезапуск
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
**Ошибка: "PowerShell не найден"**
|
||||||
|
- PowerShell должен быть установлен (входит в Windows)
|
||||||
|
- Проверьте: `powershell --version`
|
||||||
|
|
||||||
|
**Ошибка: "Access denied"**
|
||||||
|
- Установщик требует прав администратора
|
||||||
|
- UAC запросит подтверждение
|
||||||
|
|
||||||
|
**Установка не запускается автоматически**
|
||||||
|
- Проверьте антивирус - может блокировать
|
||||||
|
- Запустите вручную скачанный `.exe`
|
||||||
|
|
||||||
|
## Альтернатива: MSI установщик
|
||||||
|
|
||||||
|
Если нужен MSI вместо EXE:
|
||||||
|
|
||||||
|
1. Используйте WiX Toolset: https://wixtoolset.org/
|
||||||
|
2. Создайте `.wxs` файл с описанием установки
|
||||||
|
3. Скомпилируйте: `candle installer.wxs && light installer.wixobj`
|
||||||
|
4. Результат: `umbrix-1.7.3.msi`
|
||||||
|
5. Установка: `msiexec /i umbrix-1.7.3.msi /qn` (silent)
|
||||||
|
|
||||||
|
## Continuous Integration
|
||||||
|
|
||||||
|
Для автоматизации сборки Windows версии на GitHub Actions:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Build Windows
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-windows:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: subosito/flutter-action@v2
|
||||||
|
with:
|
||||||
|
flutter-version: '3.24.0'
|
||||||
|
|
||||||
|
- name: Build Windows
|
||||||
|
run: flutter build windows --release
|
||||||
|
|
||||||
|
- name: Download Inno Setup
|
||||||
|
run: |
|
||||||
|
Invoke-WebRequest -Uri "https://jrsoftware.org/download.php/is.exe" -OutFile "inno-setup.exe"
|
||||||
|
./inno-setup.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART
|
||||||
|
|
||||||
|
- name: Build Installer
|
||||||
|
run: iscc windows/installer.iss
|
||||||
|
|
||||||
|
- name: Upload to Gitea
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||||
|
run: |
|
||||||
|
$file = "dist/umbrix-${{ github.ref_name }}-windows-setup.exe"
|
||||||
|
curl -X POST "https://update.umbrix.net/api/v1/repos/vodorod/umbrix/releases/assets" `
|
||||||
|
-H "Authorization: token $env:GITEA_TOKEN" `
|
||||||
|
--data-binary "@$file"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Заключение
|
||||||
|
|
||||||
|
Теперь система автообновлений работает одинаково на:
|
||||||
|
- ✅ **Linux** - DEB пакеты через `apt install`
|
||||||
|
- ✅ **Windows** - EXE установщики через PowerShell
|
||||||
|
- ✅ **Автопроверка** - при запуске для всех платформ
|
||||||
|
- ✅ **Автоперезагрузка** - после установки для всех платформ
|
||||||
271
update-server/WINDOWS_DISTRIBUTOR_BUILD.md
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
# Сборка Windows установщика через flutter_distributor
|
||||||
|
|
||||||
|
## ✅ РЕШЕНИЕ: Один .exe файл со всеми зависимостями
|
||||||
|
|
||||||
|
Hiddify использует **flutter_distributor** с **target: exe**, который:
|
||||||
|
1. Собирает Flutter приложение
|
||||||
|
2. Упаковывает ВСЕ файлы (exe + dll + data + libcore.dll)
|
||||||
|
3. Создает **Inno Setup** установщик
|
||||||
|
4. Результат: **ОДИН .exe файл** (~50-60MB)
|
||||||
|
|
||||||
|
## Требования
|
||||||
|
|
||||||
|
1. **Windows машина** (или VM)
|
||||||
|
2. **Flutter SDK** 3.24.0+
|
||||||
|
3. **Visual Studio 2022** с C++ компонентами
|
||||||
|
4. **Inno Setup** 6.x+ (скачать: https://jrsoftware.org/isdl.php)
|
||||||
|
|
||||||
|
## Шаг 1: Клонирование репозитория на Windows
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Клонировать с Gitea
|
||||||
|
git clone --recursive https://update.umbrix.net/vodorod/umbrix.git
|
||||||
|
cd umbrix
|
||||||
|
|
||||||
|
# Или обновить submodules если уже клонировано
|
||||||
|
git submodule update --init --recursive
|
||||||
|
```
|
||||||
|
|
||||||
|
## Шаг 2: Замена libcore.dll
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Скачать libcore с Gitea
|
||||||
|
curl -L -o libcore-windows.tar.gz "https://update.umbrix.net/vodorod/umbrix-libcore/releases/download/v1.7.0-umbrix/libcore-windows-amd64-umbrix.tar.gz"
|
||||||
|
|
||||||
|
# Распаковать
|
||||||
|
tar -xzf libcore-windows.tar.gz
|
||||||
|
|
||||||
|
# Заменить в проекте
|
||||||
|
Copy-Item libcore.dll -Destination libcore\bin\libcore.dll -Force
|
||||||
|
Copy-Item HiddifyCli.exe -Destination libcore\bin\HiddifyCli.exe -Force
|
||||||
|
Copy-Item -Path webui -Destination libcore\bin\ -Recurse -Force
|
||||||
|
```
|
||||||
|
|
||||||
|
## Шаг 3: Установка flutter_distributor
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Активировать плагин
|
||||||
|
dart pub global activate flutter_distributor
|
||||||
|
|
||||||
|
# Добавить в PATH (если еще нет)
|
||||||
|
# C:\Users\YOUR_USERNAME\AppData\Local\Pub\Cache\bin
|
||||||
|
```
|
||||||
|
|
||||||
|
## Шаг 4: Сборка установщика
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Собрать Windows .exe установщик
|
||||||
|
dart run flutter_distributor:main package --platform windows --targets exe --skip-clean
|
||||||
|
|
||||||
|
# Процесс:
|
||||||
|
# 1. flutter build windows --release (5-10 минут)
|
||||||
|
# 2. Копирование файлов в temp директорию
|
||||||
|
# 3. Запуск Inno Setup для создания установщика (1-2 минуты)
|
||||||
|
# 4. Результат: dist\1.7.3+173\umbrix-setup-x64.exe (~50-60MB)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Что происходит внутри?
|
||||||
|
|
||||||
|
### 1. Flutter Build
|
||||||
|
```
|
||||||
|
build/windows/x64/runner/Release/
|
||||||
|
├── umbrix.exe (основной исполняемый файл)
|
||||||
|
├── data/ (ресурсы Flutter)
|
||||||
|
│ ├── app.so
|
||||||
|
│ ├── icudtl.dat
|
||||||
|
│ └── flutter_assets/
|
||||||
|
├── flutter_windows.dll (Flutter engine)
|
||||||
|
├── libcore.dll (VPN ядро, 45MB)
|
||||||
|
└── другие .dll
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Inno Setup упаковывает
|
||||||
|
- Все файлы из `build/windows/x64/runner/Release/`
|
||||||
|
- Создает установщик с GUI на русском/английском
|
||||||
|
- Добавляет ярлыки (рабочий стол + меню Пуск)
|
||||||
|
- Регистрирует в "Установка и удаление программ"
|
||||||
|
- Поддерживает тихую установку `/VERYSILENT`
|
||||||
|
|
||||||
|
### 3. Результат
|
||||||
|
```
|
||||||
|
dist/1.7.3+173/umbrix-setup-x64.exe (~50-60MB)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Этот файл содержит ВСЁ:**
|
||||||
|
- umbrix.exe
|
||||||
|
- Flutter runtime
|
||||||
|
- libcore.dll (45MB)
|
||||||
|
- WebUI
|
||||||
|
- Все зависимости
|
||||||
|
|
||||||
|
## Шаг 5: Тестирование
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Запустить установщик
|
||||||
|
.\dist\1.7.3+173\umbrix-setup-x64.exe
|
||||||
|
|
||||||
|
# Или тихая установка (для тестирования автообновлений)
|
||||||
|
.\umbrix-setup-x64.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART
|
||||||
|
|
||||||
|
# Проверить установку
|
||||||
|
dir "C:\Program Files\Umbrix"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Шаг 6: Загрузка в Gitea
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Переименовать для релиза
|
||||||
|
$version = "1.7.3"
|
||||||
|
$file = "dist\$version+173\umbrix-setup-x64.exe"
|
||||||
|
$newName = "umbrix-$version-windows-setup-x64.exe"
|
||||||
|
Copy-Item $file $newName
|
||||||
|
|
||||||
|
# Загрузить через API
|
||||||
|
$token = "YOUR_GITEA_TOKEN"
|
||||||
|
$releaseId = 1 # ID релиза v1.7.3
|
||||||
|
|
||||||
|
curl -X POST "https://update.umbrix.net/api/v1/repos/vodorod/umbrix/releases/$releaseId/assets?name=$newName" `
|
||||||
|
-H "Authorization: token $token" `
|
||||||
|
-H "Content-Type: application/octet-stream" `
|
||||||
|
--data-binary "@$newName"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Автоматизация (GitHub Actions)
|
||||||
|
|
||||||
|
Создайте `.github/workflows/build-windows.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Build Windows
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: ['v*']
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- uses: subosito/flutter-action@v2
|
||||||
|
with:
|
||||||
|
flutter-version: '3.24.0'
|
||||||
|
|
||||||
|
- name: Download libcore
|
||||||
|
run: |
|
||||||
|
curl -L -o libcore.tar.gz "https://update.umbrix.net/vodorod/umbrix-libcore/releases/download/v1.7.0-umbrix/libcore-windows-amd64-umbrix.tar.gz"
|
||||||
|
tar -xzf libcore.tar.gz
|
||||||
|
Copy-Item libcore.dll -Destination libcore\bin\libcore.dll -Force
|
||||||
|
|
||||||
|
- name: Install flutter_distributor
|
||||||
|
run: dart pub global activate flutter_distributor
|
||||||
|
|
||||||
|
- name: Build Windows EXE
|
||||||
|
run: dart run flutter_distributor:main package --platform windows --targets exe --skip-clean
|
||||||
|
|
||||||
|
- name: Upload to Gitea
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||||
|
run: |
|
||||||
|
$file = Get-ChildItem dist\*\umbrix-setup-x64.exe | Select-Object -First 1
|
||||||
|
curl -X POST "https://update.umbrix.net/api/v1/repos/vodorod/umbrix/releases/assets" `
|
||||||
|
-H "Authorization: token $env:GITEA_TOKEN" `
|
||||||
|
--data-binary "@$($file.FullName)"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Конфигурация (уже настроено)
|
||||||
|
|
||||||
|
**windows/packaging/exe/make_config.yaml:**
|
||||||
|
```yaml
|
||||||
|
app_id: 7U904649-52C2-5607-H590-CK880G32B76E
|
||||||
|
publisher: Umbrix Team
|
||||||
|
publisher_url: https://umbrix.net
|
||||||
|
display_name: Umbrix
|
||||||
|
executable_name: umbrix.exe
|
||||||
|
output_base_file_name: umbrix-setup-x64.exe
|
||||||
|
create_desktop_icon: true
|
||||||
|
install_dir_name: "{autopf64}\\Umbrix"
|
||||||
|
setup_icon_file: ..\..\windows\runner\resources\app_icon.ico
|
||||||
|
locales:
|
||||||
|
- en
|
||||||
|
- ru
|
||||||
|
```
|
||||||
|
|
||||||
|
**windows/packaging/exe/inno_setup.sas:**
|
||||||
|
- Шаблон Inno Setup с поддержкой тихой установки
|
||||||
|
- Автоматически закрывает старую версию перед установкой
|
||||||
|
- Создает ярлыки на рабочем столе и в меню Пуск
|
||||||
|
|
||||||
|
## Альтернатива: Ручная сборка через Inno Setup
|
||||||
|
|
||||||
|
Если flutter_distributor не работает:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# 1. Собрать Flutter
|
||||||
|
flutter build windows --release
|
||||||
|
|
||||||
|
# 2. Создать installer.iss (см. WINDOWS_BUILD_INSTRUCTIONS.md)
|
||||||
|
|
||||||
|
# 3. Скомпилировать через Inno Setup GUI
|
||||||
|
# Или через командную строку:
|
||||||
|
"C:\Program Files (x86)\Inno Setup 6\ISCC.exe" installer.iss
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
**Ошибка: "Inno Setup not found"**
|
||||||
|
```powershell
|
||||||
|
# Установить Inno Setup
|
||||||
|
# Добавить в PATH: C:\Program Files (x86)\Inno Setup 6
|
||||||
|
```
|
||||||
|
|
||||||
|
**Ошибка: "flutter_distributor command not found"**
|
||||||
|
```powershell
|
||||||
|
# Переустановить
|
||||||
|
dart pub global activate flutter_distributor
|
||||||
|
|
||||||
|
# Проверить PATH
|
||||||
|
echo $env:PATH | Select-String "Pub\\Cache\\bin"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Ошибка: "Failed to lookup symbol 'changeHiddifyOptions'"**
|
||||||
|
```powershell
|
||||||
|
# Убедитесь, что используете libcore.dll из umbrix-libcore репозитория
|
||||||
|
# НЕ используйте оригинальный Hiddify libcore!
|
||||||
|
```
|
||||||
|
|
||||||
|
**Большой размер файла (~60MB)**
|
||||||
|
- Это нормально! Включает:
|
||||||
|
- Flutter runtime (~10MB)
|
||||||
|
- libcore.dll (45MB)
|
||||||
|
- WebUI (~600KB)
|
||||||
|
- Инсталлятор Inno Setup (~5MB)
|
||||||
|
|
||||||
|
## Сравнение с Linux сборкой
|
||||||
|
|
||||||
|
| Платформа | Команда | Результат | Размер |
|
||||||
|
|-----------|---------|-----------|--------|
|
||||||
|
| **Linux** | `dart run flutter_distributor package --platform linux --targets deb` | umbrix-1.7.3-linux.deb | 29MB |
|
||||||
|
| **Windows** | `dart run flutter_distributor package --platform windows --targets exe` | umbrix-setup-x64.exe | 60MB |
|
||||||
|
|
||||||
|
**Почему Windows больше?**
|
||||||
|
- libcore.dll (45MB) vs libcore.so (45MB) - одинаково
|
||||||
|
- Inno Setup упаковщик добавляет ~5MB
|
||||||
|
- Windows DLL зависимости больше чем Linux .so
|
||||||
|
|
||||||
|
## Итого
|
||||||
|
|
||||||
|
✅ **flutter_distributor решает все проблемы:**
|
||||||
|
- Один .exe файл вместо папки с множеством файлов
|
||||||
|
- Автоматическая упаковка через Inno Setup
|
||||||
|
- Поддержка тихой установки `/VERYSILENT`
|
||||||
|
- Совместимость с системой автообновлений
|
||||||
|
- Та же команда, что и для Linux (deb/rpm/appimage)
|
||||||
|
|
||||||
|
🎯 **На Windows машине выполнить одну команду:**
|
||||||
|
```powershell
|
||||||
|
dart run flutter_distributor:main package --platform windows --targets exe --skip-clean
|
||||||
|
```
|
||||||
|
|
||||||
|
**Результат:** `dist/1.7.3+173/umbrix-setup-x64.exe` - готов к загрузке в Gitea!
|
||||||
37
update-server/api/appcast.xml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle">
|
||||||
|
<channel>
|
||||||
|
<title>Umbrix Updates</title>
|
||||||
|
<description>Umbrix VPN автообновления</description>
|
||||||
|
<link>http://localhost:8000</link>
|
||||||
|
<language>ru</language>
|
||||||
|
|
||||||
|
<!-- ТЕСТОВАЯ ВЕРСИЯ 1.7.3 - АКТИВИРОВАНА -->
|
||||||
|
<item>
|
||||||
|
<title>Umbrix 1.7.3</title>
|
||||||
|
<description>🚀 Новые функции:
|
||||||
|
- Улучшена стабильность
|
||||||
|
- Исправлены ошибки
|
||||||
|
- Single instance работает идеально</description>
|
||||||
|
<pubDate>Sat, 18 Jan 2026 07:00:00 +0000</pubDate>
|
||||||
|
<sparkle:version>1.7.3</sparkle:version>
|
||||||
|
<sparkle:shortVersionString>1.7.3</sparkle:shortVersionString>
|
||||||
|
<sparkle:minimumSystemVersion>1.0.0</sparkle:minimumSystemVersion>
|
||||||
|
|
||||||
|
<enclosure
|
||||||
|
url="http://localhost:8000/downloads/umbrix-1.7.3-linux.deb"
|
||||||
|
sparkle:version="1.7.3"
|
||||||
|
sparkle:os="linux"
|
||||||
|
type="application/x-debian-package"
|
||||||
|
length="30000000" />
|
||||||
|
</item>
|
||||||
|
|
||||||
|
<!-- Текущая версия 1.7.0 -->
|
||||||
|
<item>
|
||||||
|
<title>Umbrix 1.7.0</title>
|
||||||
|
<description>Стабильный релиз</description>
|
||||||
|
<pubDate>Fri, 17 Jan 2026 08:49:07 +0000</pubDate>
|
||||||
|
<sparkle:version>1.7.0</sparkle:version>
|
||||||
|
</item>
|
||||||
|
</channel>
|
||||||
|
</rss>
|
||||||
8
update-server/api/latest
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"version": "1.7.3",
|
||||||
|
"build_number": "173",
|
||||||
|
"is_prerelease": false,
|
||||||
|
"download_url": "http://localhost:8000/downloads/umbrix-1.7.3-linux.deb",
|
||||||
|
"release_notes": "🚀 Новые функции:\n- Улучшена стабильность\n- Исправлены ошибки\n- Single instance работает идеально",
|
||||||
|
"published_at": "2026-01-18T07:00:00Z"
|
||||||
|
}
|
||||||
14
update-server/api/latest.php
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
header('Access-Control-Allow-Origin: *');
|
||||||
|
|
||||||
|
$version = [
|
||||||
|
"version" => "1.7.3",
|
||||||
|
"build_number" => "173",
|
||||||
|
"is_prerelease" => false,
|
||||||
|
"download_url" => "http://localhost:8000/downloads/umbrix-1.7.3-linux.deb",
|
||||||
|
"release_notes" => "🚀 Новые функции:\n- Улучшена стабильность\n- Исправлены ошибки\n- Single instance работает идеально",
|
||||||
|
"published_at" => "2026-01-18T07:00:00Z"
|
||||||
|
];
|
||||||
|
|
||||||
|
echo json_encode($version, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||||
1
update-server/downloads/umbrix-1.7.3-linux.deb
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Тестовый .deb для версии 1.7.3
|
||||||
64
update-server/gitea-docker-compose.yml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
version: "3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
gitea:
|
||||||
|
image: gitea/gitea:latest
|
||||||
|
container_name: gitea
|
||||||
|
environment:
|
||||||
|
- USER_UID=1000
|
||||||
|
- USER_GID=1000
|
||||||
|
# Настройки домена
|
||||||
|
- GITEA__server__DOMAIN=git.umbrix.net
|
||||||
|
- GITEA__server__ROOT_URL=https://git.umbrix.net
|
||||||
|
- GITEA__server__SSH_DOMAIN=git.umbrix.net
|
||||||
|
- GITEA__server__SSH_PORT=2222
|
||||||
|
# Настройки зеркал (можно добавлять через запятую)
|
||||||
|
- GITEA__server__ALLOWED_HOST_LIST=git.umbrix.net,git-mirror1.umbrix.net,git-mirror2.umbrix.net
|
||||||
|
# Отключить регистрацию новых пользователей (для приватного использования)
|
||||||
|
- GITEA__service__DISABLE_REGISTRATION=true
|
||||||
|
- GITEA__service__REQUIRE_SIGNIN_VIEW=false
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- gitea
|
||||||
|
volumes:
|
||||||
|
- ./gitea/data:/data
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
ports:
|
||||||
|
- "3000:3000" # HTTP (Nginx будет проксировать)
|
||||||
|
- "2222:22" # SSH для git push
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:14
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=gitea
|
||||||
|
- POSTGRES_PASSWORD=gitea_secure_password_change_me
|
||||||
|
- POSTGRES_DB=gitea
|
||||||
|
networks:
|
||||||
|
- gitea
|
||||||
|
volumes:
|
||||||
|
- ./gitea/postgres:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
# Nginx для HTTPS + зеркала
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: nginx-gitea
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
- ./nginx/ssl:/etc/nginx/ssl:ro
|
||||||
|
- ./gitea/data/gitea/public:/usr/share/nginx/html/public:ro
|
||||||
|
networks:
|
||||||
|
- gitea
|
||||||
|
depends_on:
|
||||||
|
- gitea
|
||||||
|
|
||||||
|
networks:
|
||||||
|
gitea:
|
||||||
|
external: false
|
||||||
147
update-server/install-gitea.sh
Executable file
@@ -0,0 +1,147 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Цвета для вывода
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo -e "${GREEN}=== Установка Gitea на сервере ===${NC}"
|
||||||
|
|
||||||
|
# Проверка root
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo -e "${RED}Запустите скрипт с sudo${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 1. Обновление системы
|
||||||
|
echo -e "${YELLOW}[1/7] Обновление системы...${NC}"
|
||||||
|
apt update && apt upgrade -y
|
||||||
|
|
||||||
|
# 2. Установка Docker
|
||||||
|
echo -e "${YELLOW}[2/7] Установка Docker...${NC}"
|
||||||
|
if ! command -v docker &> /dev/null; then
|
||||||
|
curl -fsSL https://get.docker.com -o get-docker.sh
|
||||||
|
sh get-docker.sh
|
||||||
|
rm get-docker.sh
|
||||||
|
systemctl enable docker
|
||||||
|
systemctl start docker
|
||||||
|
echo -e "${GREEN}✓ Docker установлен${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}✓ Docker уже установлен${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3. Установка Docker Compose
|
||||||
|
echo -e "${YELLOW}[3/7] Установка Docker Compose...${NC}"
|
||||||
|
if ! command -v docker-compose &> /dev/null; then
|
||||||
|
apt install -y docker-compose
|
||||||
|
echo -e "${GREEN}✓ Docker Compose установлен${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}✓ Docker Compose уже установлен${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4. Создание директорий
|
||||||
|
echo -e "${YELLOW}[4/7] Создание директорий...${NC}"
|
||||||
|
mkdir -p /opt/gitea/{gitea/data,gitea/postgres,nginx/ssl}
|
||||||
|
cd /opt/gitea
|
||||||
|
|
||||||
|
# 5. Создание docker-compose.yml
|
||||||
|
echo -e "${YELLOW}[5/7] Создание конфигурации Docker...${NC}"
|
||||||
|
cat > docker-compose.yml <<'EOF'
|
||||||
|
version: "3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
gitea:
|
||||||
|
image: gitea/gitea:latest
|
||||||
|
container_name: gitea
|
||||||
|
environment:
|
||||||
|
- USER_UID=1000
|
||||||
|
- USER_GID=1000
|
||||||
|
- GITEA__database__DB_TYPE=postgres
|
||||||
|
- GITEA__database__HOST=db:5432
|
||||||
|
- GITEA__database__NAME=gitea
|
||||||
|
- GITEA__database__USER=gitea
|
||||||
|
- GITEA__database__PASSWD=gitea_secure_pass_2026
|
||||||
|
- GITEA__server__DOMAIN=85.208.139.84
|
||||||
|
- GITEA__server__ROOT_URL=http://85.208.139.84:3000
|
||||||
|
- GITEA__server__SSH_DOMAIN=85.208.139.84
|
||||||
|
- GITEA__server__SSH_PORT=2222
|
||||||
|
- GITEA__service__DISABLE_REGISTRATION=true
|
||||||
|
- GITEA__service__REQUIRE_SIGNIN_VIEW=false
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- gitea
|
||||||
|
volumes:
|
||||||
|
- ./gitea/data:/data
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
- "2222:22"
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:14-alpine
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=gitea
|
||||||
|
- POSTGRES_PASSWORD=gitea_secure_pass_2026
|
||||||
|
- POSTGRES_DB=gitea
|
||||||
|
networks:
|
||||||
|
- gitea
|
||||||
|
volumes:
|
||||||
|
- ./gitea/postgres:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
networks:
|
||||||
|
gitea:
|
||||||
|
external: false
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 6. Настройка firewall
|
||||||
|
echo -e "${YELLOW}[6/7] Настройка firewall...${NC}"
|
||||||
|
if command -v ufw &> /dev/null; then
|
||||||
|
ufw allow 3000/tcp
|
||||||
|
ufw allow 2222/tcp
|
||||||
|
echo -e "${GREEN}✓ Firewall настроен${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}⚠ UFW не установлен, убедитесь что порты 3000 и 2222 открыты${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 7. Запуск Gitea
|
||||||
|
echo -e "${YELLOW}[7/7] Запуск Gitea...${NC}"
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# Ожидание запуска
|
||||||
|
echo -e "${YELLOW}Ожидание запуска сервисов...${NC}"
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# Проверка статуса
|
||||||
|
if docker ps | grep -q gitea; then
|
||||||
|
echo -e "${GREEN}"
|
||||||
|
echo "╔════════════════════════════════════════════════════════════╗"
|
||||||
|
echo "║ ✓ Gitea успешно установлен и запущен! ║"
|
||||||
|
echo "╚════════════════════════════════════════════════════════════╝"
|
||||||
|
echo ""
|
||||||
|
echo "🌐 Откройте браузер: http://85.208.139.84:3000"
|
||||||
|
echo ""
|
||||||
|
echo "📝 Первоначальная настройка:"
|
||||||
|
echo " - Database Type: PostgreSQL"
|
||||||
|
echo " - Host: db:5432"
|
||||||
|
echo " - Username: gitea"
|
||||||
|
echo " - Password: gitea_secure_pass_2026"
|
||||||
|
echo " - Database Name: gitea"
|
||||||
|
echo ""
|
||||||
|
echo "👤 Первый зарегистрированный пользователь = админ"
|
||||||
|
echo ""
|
||||||
|
echo "📊 Управление контейнерами:"
|
||||||
|
echo " docker-compose logs -f # Логи"
|
||||||
|
echo " docker-compose ps # Статус"
|
||||||
|
echo " docker-compose restart # Перезапуск"
|
||||||
|
echo " docker-compose down # Остановка"
|
||||||
|
echo "${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Ошибка запуска Gitea. Проверьте логи: docker-compose logs${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
78
update-server/nginx.conf
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
# Nginx конфигурация для Gitea с зеркалами
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
upstream gitea {
|
||||||
|
server gitea:3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Перенаправление HTTP → HTTPS
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name git.umbrix.net git-mirror1.umbrix.net git-mirror2.umbrix.net;
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Основной домен
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name git.umbrix.net;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/ssl/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
|
||||||
|
client_max_body_size 512M;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://gitea;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Зеркало 1
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name git-mirror1.umbrix.net;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/ssl/mirror1-fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/nginx/ssl/mirror1-privkey.pem;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
|
||||||
|
client_max_body_size 512M;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://gitea;
|
||||||
|
proxy_set_header Host git.umbrix.net; # Важно! Gitea думает что основной домен
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Зеркало 2 (аналогично)
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name git-mirror2.umbrix.net;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/ssl/mirror2-fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/nginx/ssl/mirror2-privkey.pem;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
|
||||||
|
client_max_body_size 512M;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://gitea;
|
||||||
|
proxy_set_header Host git.umbrix.net;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -68,8 +68,8 @@ function InitializeSetup(): Boolean;
|
|||||||
var
|
var
|
||||||
ResultCode: Integer;
|
ResultCode: Integer;
|
||||||
begin
|
begin
|
||||||
Exec('taskkill', '/F /IM hiddify.exe', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
|
Exec('taskkill', '/F /IM umbrix.exe', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
|
||||||
Exec('net', 'stop "HiddifyTunnelService"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
|
Exec('net', 'stop "UmbrixTunnelService"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
|
||||||
Exec('sc.exe', 'delete "HiddifyTunnelService"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
|
Exec('sc.exe', 'delete "UmbrixTunnelService"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
|
||||||
Result := True;
|
Result := True;
|
||||||
end;
|
end;
|
||||||
@@ -1,17 +1,13 @@
|
|||||||
app_id: 6L903538-42B1-4596-G479-BJ779F21A65D
|
app_id: 7U904649-52C2-5607-H590-CK880G32B76E
|
||||||
publisher: Hiddify
|
publisher: Umbrix Team
|
||||||
publisher_url: https://github.com/hiddify/hiddify-next
|
publisher_url: https://umbrix.net
|
||||||
display_name: Hiddify
|
display_name: Umbrix
|
||||||
executable_name: Hiddify.exe
|
executable_name: umbrix.exe
|
||||||
output_base_file_name: Hiddify.exe
|
output_base_file_name: umbrix-setup-x64.exe
|
||||||
create_desktop_icon: true
|
create_desktop_icon: true
|
||||||
install_dir_name: "{autopf64}\\Hiddify"
|
install_dir_name: "{autopf64}\\Umbrix"
|
||||||
setup_icon_file: ..\..\windows\runner\resources\app_icon.ico
|
setup_icon_file: ..\..\windows\runner\resources\app_icon.ico
|
||||||
locales:
|
locales:
|
||||||
- ar
|
|
||||||
- en
|
- en
|
||||||
- fa
|
|
||||||
- ru
|
- ru
|
||||||
- pt
|
|
||||||
- tr
|
|
||||||
script_template: inno_setup.sas
|
script_template: inno_setup.sas
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 206 KiB |