Опубликовал сервис.
Разделил доступы.

Настроил два обратных SSH-туннеля между домашним Debian и VPS. Один обслуживает HTTP-запросы, другой — выпуск версий. Соединения устанавливает сам Debian.

Пробросы на VPS доступны только через 127.0.0.1.

Опубликовал приложение
с домашнего сервера.

Задача — дать приложению внешний вход и сохранить понятный маршрут до домашнего Debian. Для этого VPS принимает подключения, а Debian сам создаёт исходящие SSH-соединения с обратными пробросами.

Разделил HTTP и доставку версий на две службы. Это позволяет проверять каждый путь отдельно: доступность веб-приложения через 8080 и подключение для выпуска через 2222. Оба порта на VPS привязаны к loopback.

Внешний вход для домашнего приложения.

TaskFlow работает на домашнем сервере. Публичной точкой входа стал VPS: он принимает HTTP и SSH, а Debian устанавливает к нему исходящие соединения. Приложение публикуется через эти туннели.

HTTP доходит до маршрутизатора приложения.

Nginx на VPS принимает запрос на :80 и передаёт его в 127.0.0.1:8080. Обратный туннель доставляет запрос на Debian :80. Контейнер taskflow-router выбирает интерфейс или API активного окружения.

SSH-доступ выделен в отдельный маршрут.

Для выпуска GitHub Actions использует VPS :22 и ProxyCommand к 127.0.0.1:2222. Этот проброс ведёт на Debian :22. Nginx в доставке команд выпуска не участвует.

Соединения поддерживает systemd.

Туннели описаны в taskflow-tunnel.service и taskflow-web-tunnel.service. Настроены контроль соединения, проверка ключа хоста и автоматический перезапуск. HTTP-туннель зависит от основного SSH-сервиса.

Пробросы ограничены локальным адресом VPS.

Порты 8080 и 2222 привязаны к 127.0.0.1. Они не являются публичными слушателями. При этом отказ VPS или домашнего соединения влияет на доступность приложения.

WireGuard wg0 используется для удалённого доступа; tun0 — для удалённого рабочего стола. Старый wg-vps не входит в действующий маршрут приложения и CI/CD.