Что такое Wails?
Wails - это легковесный фреймворк, предназначенный для создания кросс-платформенных GUI приложений рабочего стола на golang и стандартных веб технологиях (Svelte, React, Preact, Vue, Lit, Vanilla JS). Ближайшие аналоги это естественно Electron (JS), Tauri (Rust), хочется добавить Qt (С++), но это уже другой уровень. Сразу скажу, что Wails не идеален, имеет множество ограничений и в целом не подойдёт для чего-то крупного, Tauri к примеру более зрелый проект, больше функций, быстрее развивается, больше и живее сообщество, но это уже на rust, а это не наш стэк.
Ключевое отличие Wails и Tauri от Electron, в том, что последний таскает с собой chromium, тогда как Wails и Tauri используют встроенный в систему нативный браузер. В Windows - движок Edge, Webview2 (по сути chromium). В macOS - это движок Safari, WebKit. В Linux - WebKitGTK. Исходя из этого есть ограничения, к примеру поддерживается только Windows 10+, а в Linux вы устанете на этапе сборки и дистрибуции, так как зоопарк дистрибутивов и библиотеки с зависимостями (webkitgtk2) везде называются по разному.
Но у нас не было требований к какой-то огромной функциональности, почти всё базовое есть в текущей версии, не хватает пожалуй поддержки трея, нотификаций и открытия дочерних окон, но для первой версии мы решили, что это не критично. Да и вроде как медленно но верно развивается 3я версия фреймворка где функций станет больше и всё это появится!
И да, мы говорим о Wails v2.
Инициализация проекта
Чтобы вы понимали насколько легко начать, я покажу:
Устанавливаем Wails:
go install github.com/wailsapp/wails/v2/cmd/wails@latest
Устанавливаем node.js:
nvm install --lts
nvm use --lts
Запустите
wails doctor
, он просканирует систему и подскажет что ещё установить:
Пример вывода wails doctor
$ wails doctor
Wails Doctor
# Wails
Version | v2.10.1
Package Manager | zypper
# System
WARNING: failed to read int from file: open /sys/devices/system/cpu/cpu0/online: no such file or directory
┌───────────────────────────────────────────────────────────────────────────────────────┐
| OS | openSUSE Tumbleweed |
| Version | 20250531 |
| ID | opensuse-tumbleweed |
| Go Version | go1.23.8 |
| Platform | linux |
| Architecture | amd64 |
| CPU | 12th Gen Intel(R) Core(TM) i7-1260P |
| GPU 1 | TU117GLM [T550 Laptop GPU] (NVIDIA Corporation) - Driver: nvidia |
| GPU 2 | Alder Lake-P GT2 [Iris Xe Graphics] (Intel Corporation) - Driver: i915 |
| Memory | 47GB |
└───────────────────────────────────────────────────────────────────────────────────────┘
# Dependencies
┌───────────────────────────────────────────────────────────────────┐
| Dependency | Package Name | Status | Version |
| *docker | docker | Installed | 28.2.2_ce-17.1 |
| gcc | gcc-c++ | Installed | 14-3.1 |
| libgtk-3 | gtk3-devel | Installed | 3.24.49+14-1.1 |
| libwebkit | webkit2gtk3-soup2-devel | Available | 2.48.3-1.1 |
| npm | Unknown | Not Found | 10.9.2 |
| pkg-config | pkgconf-pkg-config | Installed | 2.2.0-1.3 |
| |
└───────────────────── * - Optional Dependency ─────────────────────┘
# Diagnosis
Required package(s) installation details:
- libwebkit: sudo zypper in webkit2gtk3-soup2-devel
WARNING Your system has missing dependencies!
Fatal:
Required dependencies missing: npm
Please read this article on how to resolve this: https://wails.io/guides/resolving-missing-packages
♥ If Wails is useful to you or your company, please consider sponsoring the project:
https://github.com/sponsors/leaanthony
Инициализируйте проект:
$ wails init -n desktop -t vue
Wails CLI v2.10.1
# Initialising Project 'desktop'
Project Name | desktop
Project Directory | /tmp/tmp.hX2eO7pGKq/desktop
Template | Vue + Vite
Template Source | https://wails.io
Initialised project 'desktop' in 53ms.
♥ If Wails is useful to you or your company, please consider sponsoring the project:
https://github.com/sponsors/leaanthony
Запустите проект в DEV режиме
wails dev

Структура проекта будет выглядеть примерно так:
$ tree -L 2 .
.
├── app.go
├── build
│ ├── appicon.png
│ ├── bin
│ ├── darwin
│ ├── README.md
│ └── windows
├── frontend
│ ├── dist
│ ├── index.html
│ ├── node_modules
│ ├── package.json
│ ├── package.json.md5
│ ├── package-lock.json
│ ├── README.md
│ ├── src
│ ├── vite.config.js
│ └── wailsjs
├── go.mod
├── go.sum
├── main.go
├── README.md
└── wails.json
В корне у вас есть файл wails.json, в нём информация о проекте, многое придётся переопределить для дистрибуции, имена и прочее. В каталоге frontend - как ни странно UI часть приложения. В каталоге build OS специфичные файлы нужные для последующей сборки артефактов и дистрибуции, тут же иконка и так далее. Я не хочу расписывать всё подробно, так как всё это есть в документации и issues на GH.
Архитектура и разработка
После запуска wails dev
, у вас откроется окно приложения, с заданными параметрами из main.go, а интерфейс вы разрабатываете в каталоге frontend. Но кажется нужно немного пояснить, у вас не будет привычного REST API, вместо этого будет RPC взаимодействие между фронтендом (JavaScript/TypeScript) и бэкендом (Go). Это позволяет фронтенду вызывать методы, которые реализованы на Go, так, будто они локальные JavaScript-функции.

Более подробно про то, как это работает можно почитать тут. Так что если сразу уложить это в голове, то всё становится просто.
Tuna Desktop
Перейдём к нашему приложению. Основной наш продукт - это реверс прокси туннели из интернета в локальную сеть, т.е. аналог Ngrok. И да у нас есть консольный клиент - tuna, и так как мы сами активно пользуемся своим продуктом, в какой-то момент мы подумали - Было бы классно сделать десктопное приложение!

🤷♂️ Зачем?
При локальной разработке часто бывает так, что есть какой-то туннель с статичным адресом, который должен быть доступен всегда. Например, когда мы тестируем наши платежи в ЮКасса, у нас есть тестовый магазин для каждого разработчика, где прописан статический адрес HTTP уведомления. Открывать каждый раз отдельный терминал и писать tuna http -l ru -s test-yookassa-1 8080
становится утомительно, я каждый раз забываю сделать это заранее и приходится создавать несколько счетов или ждать когда платёжная система отправит повторное уведомление.
Также мы знаем, что порой открыть доступ к локальному ресурсу нужно не только разработчикам или системным администраторам, а командная строка не самый дружелюбный интерфейс.
Сложив несколько факторов мы решили сделать GUI приложение с максимально простым интерфейсом, чтобы пользоваться было комфортно даже бухгалтерке.
🎯 Ключевые возможности
Исходя из требований - приложение должно быть супер простым, а также ограничение самого фреймворка, сейчас на момент первого релиза, приложение имеет минимум возможностей:
При этом даже этот функционал сильно ограничен относительно консольной версии. В будущем мы всё таки планируем расширить функционал, к примеру добавить файловый сервер и базовую авторизацию.
🧑💻 Поддерживаемые платформы
У нас примерно равное количество клиентов на всех OS, поэтому вопрос о кроссплатформенности не стоял, это было обязательное требование. Так, что сегодня вы можете установить наше десктопное приложение на любой современной ОС.

🤔 Так почему мы всё таки выбрали Wails?
Действительно, если есть пробелы в функционале, то почему мы просто не взяли Tauri или проверенный годами Electron или QT?
Главный аргумент - Wails это наш стэк! 🐘💪
Проект уже полностью написан на Go, есть полноценный консольный клиент и мы можем на основе единой кодовой базы использовать один и тот же конструктор. Именно поэтому мы смогли всё сделать так быстро ну и как нам кажется качественно. В случае Electron - пришлось бы тянуть клиент tuna cli и запускать туннели с помощью exec, следить, что они не упали, синхронизировать всё это. С Tauri скорее всего пришлось бы заново написать логику клиента на Rust, а с QT на C++, ну такое 😁.
Ну и Tuna Desktop - это не Slack или Spotify, мы преследовали другие цели.
Когда мы начали разрабатывать приложение, мы хотели не просто завернуть наш личный кабинет в обёртку WebView. Мы отказались от этого самого простого и часто используемого пути, по которому идут многие десктопные приложения.
Нам хотелось создать новый пользовательский опыт — особенно для тех, кому неудобно работать с консолью. Есть пользователи, которым просто неприятно взаимодействовать с терминалом, кому-то не нравится формат CLI, а кто-то просто предпочитает привычный интерфейс с кнопками и понятной навигацией. Мы хотели, чтобы у этих людей был выбор — пользоваться десктопным, нативным на вид приложением.
Конечно, по сути мы использовали те же самые компоненты, которые уже были реализованы в личном кабинете и клиенте: тот же UI, та же GOшная кодовая база. Но мы подошли к дизайну по-другому, чтобы это действительно ощущалось как самостоятельное приложение, а не просто оболочка вокруг веба.
В результате за буквально один-два дня мы собрали рабочий прототип. Это было быстро и просто, потому что мы использовали уже готовые элементы — нам не пришлось тратить время на долгие исследования или продумывать всё с нуля. Мы сразу сделали то, что можно было бы уже распространять.
Сложности при сборке и дистрибуции
Если вы вдруг подумали, что всё так просто и радужно, то - НЕТ!
Выше я упомянул, что приложение было готово за 1-2 дня, так вот на сборку и настройку дистрибуции ушло около 3-х недель 🤯.
Во первых так как есть глубокие интеграции с OS - это зависимость от CGO, а так как проект кросс-платформенный - добро пожаловать в мир кросс-компиляции c CGO в golang. Но я сэкономлю вам неделю исследований и скажу так - вы не сможете собрать проект из Linux для macOS 🤷♂️. Вот тут я описал проблематику, если коротко, то в macOS SDK есть заглушки которые не позволят вам собрать GUI приложение не на Mac. Всё сломается на этапе линковки и не важно что у вас там zig или osxcross, ограничение именно SDK. Поэтому для сборки под macOS вам нужен Mac! Мы поставили gitlab-runner на наш macmini и теперь собираем на нём, но были варианты и с всякими хостингами, так что не тупиковая ситуация.
Кстати у нас есть проект для сборки golang образа с всем нужным тулкитом для кросс-компиляции под разные OS и архитектуры, пользуйтесь.
Во вторых, сборка под Linux...
Ну начнём с того, что есть разные версии библиотек webkit2gtk-4.0 и webkit2gtk-4.1. И например в Ubuntu 24.04 есть уже только последняя и собирать надо с флагом -tags webkit2_41
, а в RHEL 9 (и все клоны) есть только webkit2gtk-4.0, в SUSE, Fedora и ArchLinux есть обе версии. И получается уже на этапе сборки у вас будет 2 артефакта. Но было бы слишком просто если бы этим всё ограничилось. Собрать весь нужный тулкит с нужным окружением и версиями для компиляции под linux arm64 + webkit2gtk-4.1 оказалось дольше и сложнее, чем арендовать linux arm64 сервер и запустить там gitlab-runner, так что мы пошли по простому пути и для Linux arm64 тоже собираем нативно, как и под macOS 🙃.
Далее я думал, что смогу собрать AppImage, но там тоже возникли сложности, потратив несколько дней я понял, что проще собрать классические deb/rpm пакеты и указать зависимости. Опять же, чтобы вы не страдали, я поработал за вас и составил вот такую табличку:
Таблица зависимостей для Wails / WebKitGTK-приложения
Зависимости для сборки под разные дистрибутивы:
Дистрибутив | GTK3 | WebKit2GTK | ABI | Пример установки |
---|---|---|---|---|
Debian 12 / Ubuntu 22.04 (и старше) | libgtk-3-0 | libwebkit2gtk-4.1-0 | 4.1 |
|
Debian 11 / Ubuntu 20.04 (и младше) | libgtk-3-0 | libwebkit2gtk-4.0-37 | 4.0 |
|
openSUSE Leap / Tumbleweed | libgtk-3-0 | libwebkit2gtk-4_1-0 | 4.1 |
|
RHEL / CentOS / AlmaLinux / Rocky (до 9) | gtk3 | webkit2gtk3 | 4.0 |
|
Fedora 40+ | gtk3 | webkit2gtk4.1 | 4.1 |
|
Arch Linux / Manjaro | gtk3 | webkit2gtk-4.1 | 4.1 |
|
Примечания:
В openSUSE Leap доступны обе версии WebKitGTK (4.0 и 4.1), но мы берём
libwebkit2gtk-4_1-0
В Fedora до версии 39 включительно был только webkit2gtk4.0, начиная с Fedora 40 появился webkit2gtk4.1.
В RHEL/Alma/Rocky/CentOS (8 и 9) webkit2gtk3 — это 4.0 ABI, 4.1 пока нет.
В Arch есть оба пакета (
webkit2gtk
иwebkit2gtk-4.1
), но для нового ABI используем второй.
Получается с флагом -tags webkit2_40
собираем только для RHEL, остальные уже имеют современную версию и для них -tags webkit2_41.
Эта таблица максимально отражает современное состояние репозиториев и пакетов (на май 2025 года).
Как итог теперь у нас есть 3 разных rpm пакета 1 deb и 1 pacman, все под amd64 и arm64.
Удивительно, но меньше всего проблем оказалось при сборке для Windows, но мы пока не стали собирать для arm64, так как в репозиториях debian нет готового тулкита Mingw-w64 для этой архитектуры, а я устал ещё на этапе с Linux 😄. К слову в Wails есть поддержка NSIS инсталлятора из коробки, так что и тут всё решено и вашему приложению не обязательно быть portable.
Публикация в Store
Мы находимся здесь 😉
Для Linux все обновления автоматические через репозиторий, не зря мы всё таки решили собирать стандартные пакеты. А вот для macOS мы пока пакуем DMG и распространяем через сайт, в Windows таже ситуация но с EXE установщиком. И получается ни там ни там, нет нормальной системы доставки. Поэтому сейчас мы на этапе публикации приложения в официальные магазины Apple App Store и Microsoft Windows Store. Так, что если вам интересен этот опыт, то напишите об этом в комментариях и позже я постараюсь подготовить статью об этом опыте.
Итоги
Мы однозначно довольны выбором Wails, конечно, если бы изначально были реализованы такие вещи, как трей, уведомления и дочерние окна, это был бы почти идеальный проект — слишком хороший, чтобы быть доступным просто так и бесплатно. Но мы потратили не так много ресурсов, а наши пользователи остались довольны.
Если вы хотите начать делать своё GUI приложение подойдите к выбору основательно, не забывайте про правило 20/80 и не бойтесь чем то жертвовать. Лучше НЕ идеальное приложение сегодня, чем идеальное никогда.
На этом у меня всё, спасибо что дочитали до конца 🙂
Если вы мечтали о десктопной версии аналога Ngrok, то - используйте Tuna Desktop.
Тут я хочу напомнить, что Tuna - это платформа для разработчиков и их команд, нацеленная на ускорение разработки, упрощение командного взаимодействия и безопасность.
Контакты
Если возникли вопросы, можете задать их нам по почте info@tuna.am, тут в коментариях или нашем чате в telegram.