О чем эта статья?
Эта секция написана уже после статьи, чтобы читатель посмотрел, а надо ли ему что-то отсюда или нет, но это забавное приключение (напоминаю, что статьи в форме (б|в)лога, как всегда.
Что будет ниже:
Поиск open source решения для общения голосом, шаринга экрана, включения видео и чатов в режиме peer-to-peer, без лишних бекендов
Запуск этого решения в открытую в github pages
Заворачивание этого решения на приватный сервер
Простенькое закрытие доступа туды через http basic authentication
Заключение с описанием некоторых замечаний и потенцевальных возможностей
Зачем?
![Типичное проприетарное решение, которое не дает вам пользоваться всеми преимуществами коммуникации Типичное проприетарное решение, которое не дает вам пользоваться всеми преимуществами коммуникации](https://habrastorage.org/getpro/habr/upload_files/c8f/807/933/c8f807933290f422a7b49b99e54de868.png)
В продолжении к первой публикации про старт инди-дев-(б|в)лога, в котором поделился первыми шагами по созданию кроссплатформенного решения, я понял, что мне негде его обсуждать, а значит нужен добротный, как гнедой конь, решение по коммуникации.
Звонки в raidcall, skype, teams, mattermost, google chat, slack, jabber и телеге звучат безумно, особенно, когда нужно быстро подключиться, пошарить экран, а самое главное — не думать о том, что шаришь кому-то телеметрию за проприетарное 3rd-party.
Когда ведешь лекции, особенно бесит, что дискорд блочит screen sharing, когда там юзеров >25, а в гугл мит есть лимит по времени.
Разумеется, читатель имеет право предъявить за проприетарные ОС, браузеры и прочие ПО, либо, что мне просто лень платить, но скорее просто хочется поискать велосипедов, да и поделиться с вами, что накопал и начал юзать.
Как и говорилось ранее, я попытался придумать оправданий для велосипедов, едем-те.
Гуглим какой-нибудь open source
![И находим там всякий хлам, ищем дальше, конкретизируя запросы И находим там всякий хлам, ищем дальше, конкретизируя запросы](https://habrastorage.org/getpro/habr/upload_files/828/504/71e/82850471ee1e90cf063745613bb98d96.png)
Спустя полчаса поисков, находим какое-то более менее звучащее решение
![Читаем ридмик, и видим, что в целом удовлетворяет Читаем ридмик, и видим, что в целом удовлетворяет](https://habrastorage.org/getpro/habr/upload_files/f7c/9eb/d9a/f7c9ebd9a4a1b74e3e354b36d9644e48.png)
![](https://habrastorage.org/getpro/habr/upload_files/a86/684/b49/a86684b493f77fe9ee40cbc7b9a868dd.png)
![](https://habrastorage.org/getpro/habr/upload_files/a07/d7e/167/a07d7e1674ee55bb209635c30a4f593b.png)
Надо пойти посмотреть демку - https://chitchatter.im/
Выглядит более чем достаточно, переходя по кнопкам находим, что есть: mardkown-based чат, видео, аудио, шаринг экрана и файлов
![](https://habrastorage.org/getpro/habr/upload_files/354/c9c/a2f/354c9ca2fd3b1504d4cb3d9532efeade.png)
Тестим и понимаем, что работает вроде как норм, осталось разобраться что под капотом.
![](https://habrastorage.org/getpro/habr/upload_files/9a2/47d/1ad/9a247d1ad9f3ad368fc3e6cc0a5891fb.png)
Находим упоминания rtc, а самое главное trystero
import { joinRoom as trysteroJoinRoom, Room, BaseRoomConfig } from 'trystero'
export const joinRoom: typeof trysteroJoinRoom = (
_config: BaseRoomConfig,
_roomId: string
) => {
const room: Room = {
makeAction: () => [() => Promise.resolve([]), () => {}, () => {}],
ping: () => Promise.resolve(0),
leave: () => {},
getPeers: () => ({}),
addStream: () => [Promise.resolve()],
removeStream: () => {},
addTrack: () => [Promise.resolve()],
removeTrack: () => {},
replaceTrack: () => [Promise.resolve()],
onPeerJoin: () => {},
onPeerLeave: () => {},
onPeerStream: () => {},
onPeerTrack: () => {},
}
return room
}
export const selfId = ''
Копаем про этого зверя и находим репу trystero, а с ним и вебсайт, обещающий сделать любое решение мультиплеером — https://oxism.com/trystero/
![](https://habrastorage.org/getpro/habr/upload_files/b82/b67/38f/b82b6738f06a40e243024b946bd3f5a4.png)
Читаем и понимаем, что это какая-то шляпо про
Trystero can connect peers via ? BitTorrent, ? Nostr, ? MQTT, ? IPFS, and ? Firebase.
Посидел, покурил, не понял, думаю комментаторы лучше объяснят, почему для https://en.wikipedia.org/wiki/Session_Description_Protocol нужен торрент, жду объяснений в комментариях. Учитывая, что все обещают зашифрованный трафик, вроде как звучит норм.
Решение найдено, теперь внедряем
Форк
![](https://habrastorage.org/getpro/habr/upload_files/280/a37/7b5/280a377b588641babe7de08285aef418.png)
Просто делаем форк основного репозитория отседа
И идем его настраивать:
-
Вырубаем ненужные странички (Wikis, Issues, Projects), и идем сразу же конфигурировать все необходимое из секции self-hosted
-
Включаем удаление веток, оставляем только Rebase flow (почему? пишите нормальные коммиты, не храните PRs дольше 1-2 дней, и будет вам счастье)
Судя по README, нужно сделать две вещи:
Поменять homepage в package.json, чтобы приложение резолвило к себе статику
Указать DEPLOY_KEY (как же бесит постоянна вакханалия вокруг обслуживания ключей в очередном github action
Начну со второго, так как сначала надо проверить, что оно запускается само
![](https://habrastorage.org/getpro/habr/upload_files/ec1/ccb/072/ec1ccb072a54a03ad4af6670b3f1d2a5.png)
Локально генерим ключики
ssh-keygen -t rsa -b 4096 -C "$(git config user.email)" -f gh-pages -N ""
Топаем сюды — settings → deploy keys → add new
Пишем в Title: DEPLOY_KEY
Пишем в Key: значение сгнерированного публичного ключа: cat gh-pages.pub
Ставим галочку возле Allow write access
![](https://habrastorage.org/getpro/habr/upload_files/99f/9c7/698/99f9c7698d4f6c559aba39e81e7e63ea.png)
Потом идем в — secrets → actions → new repository secret, и делаем тоже самое, только вставляя приватный ключ: cat gh-pages
![](https://habrastorage.org/getpro/habr/upload_files/714/ce1/216/714ce1216c3e6e47aa2d2b1ee1091622.png)
Судя по action-у, оно будет тригерриться только при пуше в main и в github pages, а значит надо создать main ветку и сделать её главной
![](https://habrastorage.org/getpro/habr/upload_files/82b/9bc/fe3/82b9bcfe3705fd4025fcf1579453a594.png)
Топаем в ветки и создаем main
![](https://habrastorage.org/getpro/habr/upload_files/451/cb5/2a9/451cb52a9cc74e4aa5c882b76e4f2f79.png)
Затем топаем в настройки репозитория и ставим main главной веткой
![](https://habrastorage.org/getpro/habr/upload_files/94b/419/ef3/94b419ef31c1f54dfe8268ebc50906d5.png)
Дальше пытаемся понять почему не запустились actions и находим, что надо было разрешить actions у форкнутой репы
![](https://habrastorage.org/getpro/habr/upload_files/46f/1a3/fc1/46f1a3fc1ff835765308214d11837402.png)
Соглашаемся и триггерим action для деплоя в gh-pages
![](https://habrastorage.org/getpro/habr/upload_files/33d/086/b99/33d086b996aadcb537c0f587f01e1eb2.png)
Примерно полторы минуты, оно прошло
![](https://habrastorage.org/getpro/habr/upload_files/bf2/b54/2bb/bf2b542bbc094becdb1a79e7a7d51019.png)
Справа Code-странице репозитория появляется инфо про github pages
![](https://habrastorage.org/getpro/habr/upload_files/512/939/60e/51293960e18376bc8c1bb1a1d3041bf1.png)
Кликаем туда и находим ссылку на инстанс по клику на иконку возле 1 minute ago
![](https://habrastorage.org/getpro/habr/upload_files/82f/1bf/edb/82f1bfedb4725f10bc66e69060947070.png)
Работать оно работает, вот только статику не отдаёт, но это не важно, так как статика просто не там лежит
Оно ищет под https://the-homeless-god.github.io/assets/index-OD1TD8_t.js
А вот часть github pages оно пропустило в рамках homepage
![](https://habrastorage.org/getpro/habr/upload_files/a17/803/efe/a17803efeb6812ce94afd9b22215d4b5.png)
В любом случае, давайте настроим, чтобы лишний раз убедиться, что всё работает, а вдруг и кому-то достаточно только этого.
Так что 1 раз пушим в мастер редактирование в package.json поля homepage на ссылку на наш github page
![](https://habrastorage.org/getpro/habr/upload_files/740/688/bfd/740688bfdaebe495d159a8d7ed04a89d.png)
Коммитим и ждем как пройдет пайплайн
![](https://habrastorage.org/getpro/habr/upload_files/5a8/cf8/a00/5a8cf8a00dcfb85d514354c48f5251f2.png)
Помогло? Нет.
Идем в vite.config.js и указываем ему base
![](https://habrastorage.org/getpro/habr/upload_files/cb6/0e5/af4/cb60e5af4bbf98fb93e797fe05cd0485.png)
Запустилось, потыкался, ок
![](https://habrastorage.org/getpro/habr/upload_files/d2c/f91/104/d2cf91104624085eb6c7e8dfa6c41ae1.png)
Пойду открою им PR в README хоть, пусть про base напишут
![](https://habrastorage.org/getpro/habr/upload_files/e0b/1b5/e42/e0b1b5e42c1b8e302a6784651c73d94e.png)
А теперь мы хотим это тащить на приватный сервер
А почему? А зачем? Оно же итак работает из-под github pages, но вот что важно — а я не хочу чтобы туда кто-то имел доступ
Берите тачку где хотите, мне нравятся ruvds, digitalocean и из самых бюджетных — это justhost.
Берите бубунту (осуждаю, но для статьи на хабре пойдет).
На этой самой бубунте:
-
Создайте отдельного юзера и папку под нашу статику, ну и права отдайте
adduser ga mkdir -m 755 /var/www/chat chown ga:ga /var/www/chat su -- ga mkdir /home/ga/.ssh/ ssh-keygen -t rsa -b 4096 -C "deployer" -f deployer -N ""
И пишем публичный ключик в
authorized_keys
-
Поставьте nginx и настройте конфиг смотреть на статику
# устанавливаем nginx apt install nginx # говорим firewall чтоб разрешал ваш nginx, ssh и http/https ufw allow ssh ufw enable ufw allow http ufw allow https ufw allow 'Nginx HTTP'
-
И редачим конфиг: vim /etc/nginx/nginx.conf
server { access_log /var/log/nginx/access.log; add_header X-Xss-Protection "1; mode=block" always; add_header X-Frame-Options SAMEORIGIN; add_header X-Content-Type-Options nosniff; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; root /var/www/chat; index index.html; location / { try_files $uri $uri/ /index.html; } }
В настройках репозитория добавляем три новых ключа:
SERVER_HOST
- адрес нашего сервакаSERVER_USERNAME
- имя юзераSERVER_SSH_KEY
- содержимое приватного ключа
![](https://habrastorage.org/getpro/habr/upload_files/5aa/8e2/24e/5aa8e224e25c44013e3dba72ef9dc165.png)
И дописываем deploy-логику
# тут мы собс-на просто смотрим, что сервер жив и радуемся
- name: agent - get server status
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: neofetch && df -H / && free -m
# тут мы ставим на github action ssh ключ, чтобы можно было пользоваться всякими командами а-ля rsync, scp и прочее
- name: agent - install ssh key
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.SERVER_SSH_KEY }}
known_hosts: unnecessary
# тут мы его устанавливаем
- name: agent - install ssh
run: ssh-keyscan -p 22 -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts
# подчищаем за собой директорию на сервере
- name: agent - cleanup static folder
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: rm -rf /var/www/chat/**
# деплоим статику на сервер
- name: agent - deploy static
run: ls -la ./dist && rsync -avz -r -e "ssh -p 22" ./dist/ ${{ secrets.SERVER_USERNAME }}@${{ secrets.SERVER_HOST }}:/var/www/chat/
# смотрим, что статика действительно там
- name: agent - show deployed dir
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: ls -la /var/www/chat/
Коммитим это всё и ждём
![](https://habrastorage.org/getpro/habr/upload_files/96f/a7f/e9b/96fa7fe9b5162e021dae2af81d289afc.png)
Прячем за basic http authentication
Подробнее тут
# Ставим либу
apt install apache2-utils
# Генерим пользователя + пароль
htpasswd -c /etc/apache2/.htpasswd ga
# Смотрим, что всё хорошо
cat /etc/apache2/.htpasswd
Дальше в nginx.conf пишем чтобы доступов не было
auth_basic "Administrator’s Area";
auth_basic_user_file /etc/apache2/.htpasswd;
Получится что-то вроде
![](https://habrastorage.org/getpro/habr/upload_files/bb7/0bb/8c4/bb70bb8c457e003aea758329f651c7c7.png)
Перезапускаем Nginx + дописываем себе генерацию серта откуда-нибудь, будь-то Let’s Encrypt
systemctl nginx restart
И теперь когда вы перейдете по ip своего сервера будет окошко с запросом логина и пароля
![](https://habrastorage.org/getpro/habr/upload_files/0ef/7b7/849/0ef7b7849ac2ee2438e2c569ebdfcdf0.png)
Остаётся только убирать налету информацию про ip адрес в homepage в package.json и удалить содержимое vite.config.ts про base
Получится примерно так:
![](https://habrastorage.org/getpro/habr/upload_files/a1c/92d/5bd/a1c92d5bd6aac8d9bf85a662f988410a.png)
Мы просто удаляем строку с помощью sed
, а для подмены содержимого homepage
поля используем встроенные методы и пересобираем
Заключение
Теперь у вас как и у меня есть свой спрятанный на сервере клиент для коммуникации без проприетарного бугага.
Может быть вы что-то накоммуниздите здесь полезного для себя, а может что-то напишите тут на улучшение.
Допустим вы решили коммерциализировать это решение, но оно по лицензии к вам не подходит?
Вы можете написать адаптер который вклинивается в этот код с вашими дописками хоть из-под другого npm пакета, хоть из-под git submodule.
Из ограничений у этого клиента — 256 участников в вашей комнате
![](https://habrastorage.org/getpro/habr/upload_files/c55/5ff/4d9/c555ff4d91ce782cd310da7b80e1198e.png)
Я бы написал как это всё дело скрыть под VPN, но мне лень писать статью дольше чем сейчас, так как просто сидел в дискорде и хотел показать коллегам другие способы коммуницировать и шарить экран, а поэтому это тянет для другой статьи организации демо-энва только для режима разработчиков.
Среди прочего, упустил немногое про бубунту, просто потому что ну не люблю я её, используйте BSD.
А в остальном — ничего нигде не хранится, всё шифруется, да и всё бесплатно, если не нужно приватить доступ к статике. И можно вести лекции не боясь, что качество просядет и общаться с коллегами используя максимальный стриминг.
Спасибо за внимание, надеюсь следующая статейка выйдет раньше чем разница между этой и предыдущей.
Have a fun!
Комментарии (11)
jarkevithwlad
06.04.2024 23:54интересно какие там ограничения по разрешению / частоте кадров / битрейту ? Ну и было бы ещё удалённое управление цены бы не было, сейчас пользуемся sunshine + moonlight, там вполне себе можно 4к / 120fps / 150 мб/с и даже hdr, единственное звонок в другом ПО + порты должны быть открыты, но и задержки самые минимальные, можно и играть
SabMakc
06.04.2024 23:54Можно затестить: https://chitchatter.im/public/habrahabr
Как понимаю, одна вкладка - одна комната. И пока вкладка открыта хоть у кого-либо - беседа существует.А одинаковые приватные комнаты с уникальным паролем образуют уникальные комнаты )
Правда идет ли трафик между всеми "одинаковыми" комнатами (и потом расшифровывается по паролю) или трафик идет с учетом пароля - вопрос отдельный.
AcckiyGerman
06.04.2024 23:54+2А почему Jitsi не подошла?
Решение обкатанное, ставится за 15 минут, вашим запросам удовлетворяет, не требует возни с гитхабом.SabMakc
06.04.2024 23:54А разве здесь возня с GitHub обязательна?
Да и фишка с "работает через GitHub Pages" лично мне нравится )
the_homeless_god Автор
PR по апдейту доки приняли сразу, и, вот, я в списке контрибьюторов, приятно