feat: MyPointVPN landing on mypointvpn.sokolab.xyz and post about Serverus
Landings get per-project themes (params.theme, params.fonts) and optional chat/start/note/engine sections, so they don't look like clones. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6958d0a975
commit
672467a699
6 files changed
+538
-4
No files matched your search
@@ -0,0 +1,83 @@
|
||||
---
|
||||
title: "MyPointVPN: how a VPN bot learned to manage servers"
|
||||
date: 2026-10-13T12:00:00+04:00
|
||||
draft: false
|
||||
tags:
|
||||
- telegram
|
||||
- vpn
|
||||
- server
|
||||
- ansible
|
||||
- docker
|
||||
summary: "It started as a portfolio bot that installs 3x-ui. Along the way I split out Serverus, a package that manages the whole server. Now the bot lives on a server it manages itself"
|
||||
---
|
||||
|
||||
On September 23 I made the first commit to a portfolio project: a Telegram bot that installs and configures the 3x-ui panel by itself, so a person gets their own VPN without any manual fiddling. Three weeks and about 40 commits later, the VPN turned out not to be the most interesting part.
|
||||
|
||||
## How it looks
|
||||
|
||||
You rent a server with Debian 12 or 13 from any hosting provider, get an IP and a root password, and send the bot one line: `ip:password`. The bot moves ssh to a random port with key-only login, turns on a firewall, updates the system and from then on manages the server itself.
|
||||
|
||||
You can take the server back at any time with the "Return" button. The bot removes its access, rolls back ssh and the firewall and sends you a new root password. Your data on the server stays.
|
||||
|
||||
## VPN
|
||||
|
||||
This is what it all started for. The bot installs 3x-ui and sets up:
|
||||
|
||||
- a VLESS + XHTTP + Reality connection on port 443, with the Reality target picked by the bot
|
||||
- an optional camouflage server: clients connect to it, it forwards traffic to the panel, and the panel's address is never exposed
|
||||
- a domain with a Let's Encrypt certificate for the panel and the subscription, and without a domain a short-lived IP certificate that renews automatically
|
||||
- an outbound proxy: your own or Cloudflare WARP
|
||||
- encrypted DNS on the server: DNS-over-TLS, with DNS-over-HTTPS as a fallback if TLS gets blocked
|
||||
|
||||
The bot issues and revokes client keys and hands out subscription links for v2rayN, Hiddify, Happ and v2rayNG. Keys have no limits: no traffic cap, no expiry, no device limit. For every key you can see the traffic and when the client was last online.
|
||||
|
||||
Once a day the bot checks the panel, Xray and the subscription certificate and tells you if something broke or got fixed.
|
||||
|
||||
## Why no Cloudflare
|
||||
|
||||
At first the bot could work through Cloudflare, and I had to drop it. Cloudflare terminates TLS on its side and opens a new connection to the server. Reality lives right inside the client's TLS handshake, and the server has to see it untouched. Reality can't work behind Cloudflare, so I removed the support.
|
||||
|
||||
## Where the real work is
|
||||
|
||||
When I looked at the code, almost all of the bot's work came down to one thing: take a bare Debian, lock it down and then manage it by key. Roughly what I described in [initial Debian server setup](/en/blog/zero-setup-debian-server/), just without a human. 3x-ui is only one of the tasks on top of that.
|
||||
|
||||
So I moved the server setup code into a separate package, `serverus`. It's an ansible-based library with no Django and no Telegram and a clear programmatic API. The Telegram part also became a separate package. The Django app stayed as the glue with the business logic.
|
||||
|
||||
## Second scenario: a docker server
|
||||
|
||||
With that foundation in place, the next scenario comes together quickly. I built a docker server:
|
||||
|
||||
- the bot installs Docker, Caddy and automatic system updates, and Caddy issues certificates for domains
|
||||
- an app is a folder with `docker-compose.yaml`, `.env` and `caddy.conf`, sent to the bot as an archive or file by file
|
||||
- before applying, the bot shows a diff and per-file warnings, and warns you if a domain doesn't point to the server
|
||||
- while applying, it checks the compose file, busy ports and the Caddy config, and if something is wrong it leaves the app untouched
|
||||
- only the changed services are recreated
|
||||
- the "Roll back" button restores the previous version of the files
|
||||
- there are start, stop, restart and logs per service, login to a private docker registry and guest access to volumes for uploading data
|
||||
|
||||
The example in the repo is a self-hosted RustDesk server.
|
||||
|
||||
## One codebase, different bots
|
||||
|
||||
What the bot can do is decided by the interface selected in the admin panel: "MyPoint VPN", "Serverus" or both. It switches on the fly, without a restart. That's how one codebase makes different bots.
|
||||
|
||||
## The bot hosts itself
|
||||
|
||||
My favorite part. Production MyPointVPN is deployed as a Serverus app on a docker server managed by this very bot. To the bot, its own new version is just another app, like RustDesk.
|
||||
|
||||
## Stack
|
||||
|
||||
Python, Django, PostgreSQL, RabbitMQ + dramatiq (background jobs with a supervisor), ansible, a self-hosted Telegram Bot API server, Docker, Caddy, 3x-ui v3.8.5.
|
||||
|
||||
## Try it and talk about it
|
||||
|
||||
The project has its own page: **[mypointvpn.sokolab.xyz](https://mypointvpn.sokolab.xyz/en/)**.
|
||||
|
||||
- [The bot](https://t.me/barbarisiska_bot)
|
||||
- [Code](https://git.sokolab.xyz/s0k0l/mypointvpn), with a wiki: deployment, data migration and how a Serverus app is structured
|
||||
- [Issues in Redmine](https://redmine.sokolab.xyz/projects/mypointvpn)
|
||||
- [Forum for questions and ideas](https://redmine.sokolab.xyz/boards/2/topics/3), with a guest login, no sign-up needed
|
||||
|
||||
## What's next
|
||||
|
||||
Serverus will most likely become a separate project. I'll write about it in a separate post, and it will get its own landing page. To be continued.
|
||||
@@ -0,0 +1,83 @@
|
||||
---
|
||||
title: "MyPointVPN: как бот для VPN научился управлять серверами"
|
||||
date: 2026-10-13T12:00:00+04:00
|
||||
draft: false
|
||||
tags:
|
||||
- telegram
|
||||
- vpn
|
||||
- server
|
||||
- ansible
|
||||
- docker
|
||||
summary: "Начинал с бота для портфолио, который ставит 3x-ui. По дороге выделил пакет Serverus, который управляет сервером целиком. Теперь бот живет на сервере, которым сам же и управляет"
|
||||
---
|
||||
|
||||
23 сентября я сделал первый коммит в проект для портфолио: Телеграм-бот, который сам ставит и настраивает панель 3x-ui, чтобы у человека был свой VPN без ручной возни. Прошло три недели и около 40 коммитов, и VPN оказался не самой интересной частью.
|
||||
|
||||
## Как это выглядит
|
||||
|
||||
Вы арендуете сервер с Debian 12 или 13 у любого хостера, получаете IP и пароль root и присылаете боту одну строку `ip:пароль`. Бот переводит ssh на случайный порт со входом только по ключу, включает фаервол, обновляет систему и дальше управляет сервером сам.
|
||||
|
||||
Сервер можно забрать в любой момент кнопкой «Вернуть». Бот уберет свои доступы, откатит ssh и фаервол и пришлет новый пароль root. Данные на сервере останутся.
|
||||
|
||||
## VPN
|
||||
|
||||
Ради этого все и затевалось. Бот ставит 3x-ui и настраивает:
|
||||
|
||||
- подключение VLESS + XHTTP + Reality на 443 порту, цель для Reality бот подбирает сам
|
||||
- по желанию сервер маскировки: клиенты подключаются к нему, он пересылает трафик на панель, и адрес панели нигде не светится
|
||||
- домен с сертификатом Let's Encrypt для панели и подписки, а без домена короткий сертификат на IP, который продлевается автоматически
|
||||
- прокси на выходе: свой или Cloudflare WARP
|
||||
- шифрованный DNS на сервере: DNS-over-TLS, а если его режут, запасной DNS-over-HTTPS
|
||||
|
||||
Ключи клиентов бот выпускает и отзывает сам и выдает ссылки на подписку для v2rayN, Hiddify, Happ и v2rayNG. Ограничений на ключи нет: ни по трафику, ни по сроку, ни по устройствам. По каждому ключу видно трафик и когда клиент был онлайн.
|
||||
|
||||
Раз в сутки бот проверяет панель, Xray и сертификат подписки и пишет, если что-то сломалось или починилось.
|
||||
|
||||
## Почему без Cloudflare
|
||||
|
||||
Сначала бот умел работать через Cloudflare, и от этого пришлось отказаться. Cloudflare сам завершает TLS у себя и открывает до сервера новое соединение. А Reality живет как раз внутри TLS-рукопожатия клиента, и сервер должен увидеть его как есть. За Cloudflare Reality работать не может, так что поддержку я убрал.
|
||||
|
||||
## Где на самом деле работа
|
||||
|
||||
Когда я посмотрел на код, оказалось, что почти вся работа бота сводится к одному: взять голый Debian, закрыть его и дальше управлять им по ключу. Примерно то, что я описывал в [первичной настройке сервера](/blog/zero-setup-debian-server/), только без человека. 3x-ui лишь одна из задач поверх этого.
|
||||
|
||||
Поэтому код настройки серверов я выделил в отдельный пакет `serverus`. Это библиотека на ansible без Django и без Telegram с понятным программным API. Телеграм-часть тоже стала отдельным пакетом. Django-приложение осталось связующим звеном с бизнес-логикой.
|
||||
|
||||
## Второй сценарий: docker-сервер
|
||||
|
||||
Когда такая основа есть, следующий сценарий собирается быстро. Я сделал docker-сервер:
|
||||
|
||||
- бот ставит Docker, Caddy и автообновления системы, сертификаты для доменов выпускает Caddy
|
||||
- приложение это папка с `docker-compose.yaml`, `.env` и `caddy.conf`, ее можно прислать боту архивом или по файлам
|
||||
- перед применением бот показывает разницу и предупреждения по файлам, а если домен не указывает на сервер, тоже предупредит
|
||||
- при применении бот проверяет compose, занятость портов и конфиг Caddy, и если что-то не так, приложение не трогает
|
||||
- пересоздаются только изменившиеся сервисы
|
||||
- кнопка «откатить» возвращает предыдущую версию файлов
|
||||
- есть старт, стоп, рестарт и логи по сервисам, логин в приватный docker registry и гостевой доступ к volumes, чтобы залить данные
|
||||
|
||||
В примере к проекту лежит свой сервер RustDesk.
|
||||
|
||||
## Один код, разные боты
|
||||
|
||||
Что умеет бот, решает интерфейс, выбранный в админке: «MyPoint VPN», «Serverus» или оба сразу. Переключается на ходу, без перезапуска. Так из одного кода получаются разные боты.
|
||||
|
||||
## Бот держит сам себя
|
||||
|
||||
Моя любимая часть. Прод MyPointVPN развернут как приложение Serverus на docker-сервере, которым управляет этот же бот. Новая версия бота для него такое же приложение, как RustDesk.
|
||||
|
||||
## Стек
|
||||
|
||||
Python, Django, PostgreSQL, RabbitMQ + dramatiq (фоновые задачи с супервизором), ansible, собственный сервер Telegram Bot API, Docker, Caddy, 3x-ui v3.8.5.
|
||||
|
||||
## Попробовать и обсудить
|
||||
|
||||
У проекта есть своя страница: **[mypointvpn.sokolab.xyz](https://mypointvpn.sokolab.xyz/)**.
|
||||
|
||||
- [Бот](https://t.me/barbarisiska_bot)
|
||||
- [Код](https://git.sokolab.xyz/s0k0l/mypointvpn), там же вики: деплой, перенос данных и как устроено приложение для Serverus
|
||||
- [Задачи в Redmine](https://redmine.sokolab.xyz/projects/mypointvpn)
|
||||
- [Форум для вопросов и идей](https://redmine.sokolab.xyz/boards/2/topics/3), там же гостевой вход, регистрироваться не обязательно
|
||||
|
||||
## Что дальше
|
||||
|
||||
Serverus, скорее всего, станет отдельным проектом. Расскажу о нем отдельной записью, и у него будет свой лендинг. Продолжение следует.
|
||||
@@ -0,0 +1,91 @@
|
||||
---
|
||||
title: "MyPoint VPN"
|
||||
tagline: "Your own VPN on your own server in one message"
|
||||
description: "Rent a server, send the Telegram bot its IP and password, and it locks the server down, installs 3x-ui and sets up VLESS + Reality. Client keys and subscriptions come from the bot too."
|
||||
domain: "https://mypointvpn.sokolab.xyz/"
|
||||
badge: "Telegram bot · Debian 12 and 13"
|
||||
theme: mypointvpn
|
||||
fonts: "family=Unbounded:wght@500;700&family=Manrope:wght@400;600;800&family=JetBrains+Mono:wght@400;600"
|
||||
post: "/blog/mypointvpn-serverus"
|
||||
postLabel: "How a VPN bot learned to manage servers"
|
||||
build:
|
||||
list: never
|
||||
sitemap:
|
||||
disable: true
|
||||
|
||||
nav:
|
||||
- { label: "Features", href: "#features" }
|
||||
- { label: "Get started", href: "#start" }
|
||||
- { label: "Serverus", href: "#engine" }
|
||||
- { label: "Community", href: "#community" }
|
||||
|
||||
cta:
|
||||
- { label: "Open the bot", href: "https://t.me/barbarisiska_bot", primary: true }
|
||||
- { label: "Get started", href: "#start" }
|
||||
|
||||
chat:
|
||||
title: "What it looks like in the bot"
|
||||
messages:
|
||||
- { from: "me", text: "`203.0.113.7:root-password`" }
|
||||
- { from: "bot", text: "ssh moved to a random port, key-only login. Firewall on, system updated." }
|
||||
- { from: "bot", text: "3x-ui installed: VLESS + XHTTP + Reality on port 443." }
|
||||
- { from: "me", text: "Issue a key" }
|
||||
- { from: "bot", text: "Done. Here is the subscription link for your client." }
|
||||
|
||||
features:
|
||||
title: "What you get"
|
||||
items:
|
||||
- title: "VLESS + XHTTP + Reality"
|
||||
text: "A connection on port 443. The bot picks the Reality target itself."
|
||||
- title: "Camouflage server"
|
||||
text: "Optional. Clients connect to it, it forwards traffic to the panel, and the panel's address is never exposed."
|
||||
- title: "Certificates"
|
||||
text: "A domain with Let's Encrypt for the panel and the subscription. Without a domain the bot issues a short-lived IP certificate and renews it itself."
|
||||
- title: "Keys without limits"
|
||||
text: "No traffic cap, no expiry, no device limit. Subscriptions for v2rayN, Hiddify, Happ and v2rayNG. For every key you see the traffic and when the client was last online."
|
||||
- title: "Proxy and DNS"
|
||||
text: "Outbound through your own proxy or Cloudflare WARP. DNS on the server is encrypted: DNS-over-TLS, with DNS-over-HTTPS as a fallback if TLS gets blocked."
|
||||
- title: "Health checks"
|
||||
text: "Once a day the bot checks the panel, Xray and the subscription certificate and tells you if something broke or got fixed."
|
||||
|
||||
start:
|
||||
title: "Get started"
|
||||
steps:
|
||||
- title: "Rent a server"
|
||||
text: "Any hosting provider, Debian 12 or 13. All you need is the IP and the root password."
|
||||
- title: "Send the bot `ip:password`"
|
||||
text: "The bot moves ssh to a random port with key-only login, turns on a firewall, updates the system and installs 3x-ui."
|
||||
- title: "Issue a key"
|
||||
text: "Add the subscription link to your client, and the VPN works."
|
||||
|
||||
note:
|
||||
title: "The server stays yours"
|
||||
text: "The \"Return\" button removes the bot's access, rolls back ssh and the firewall and sends you a new root password. Your data on the server stays. And the bot deliberately doesn't work through Cloudflare: Cloudflare terminates TLS itself, and Reality can't work behind it."
|
||||
|
||||
engine:
|
||||
kicker: "Under the hood"
|
||||
title: "Serverus"
|
||||
lead: "Almost all of the bot's work comes down to one thing: take a bare Debian, lock it down and manage it by key. That's the job of `serverus`, an ansible-based package inside the project. The VPN is just one task on top of it, the second one is a docker server."
|
||||
items:
|
||||
- "Docker, Caddy and automatic system updates, with Caddy issuing certificates for domains"
|
||||
- "An app is a folder with `docker-compose.yaml`, `.env` and `caddy.conf`, sent as an archive or file by file"
|
||||
- "A diff and per-file warnings before applying, including when a domain doesn't point to the server"
|
||||
- "Checks of the compose file, ports and Caddy config. On error the app is left untouched, and only changed services are recreated"
|
||||
- "Rollback to the previous version of the files, start, stop, restart and logs per service"
|
||||
- "Login to a private docker registry and guest access to volumes for uploading data"
|
||||
callout:
|
||||
title: "The bot hosts itself"
|
||||
text: "Production MyPoint VPN runs as a Serverus app on a docker server managed by this very bot. What the bot can do is set by the interface in the admin panel: \"MyPoint VPN\", \"Serverus\" or both."
|
||||
|
||||
community:
|
||||
title: "Community"
|
||||
lead: "Questions, ideas and bugs go to Redmine. No sign-up needed: the guest login is in the [forum topic](https://redmine.sokolab.xyz/boards/2/topics/3)."
|
||||
links:
|
||||
- { title: "Bot", text: "Start using it in Telegram.", href: "https://t.me/barbarisiska_bot" }
|
||||
- { title: "Code", text: "Sources and wiki: deployment, data migration, Serverus apps.", href: "https://git.sokolab.xyz/s0k0l/mypointvpn" }
|
||||
- { title: "Issues", text: "Bugs and wishes in Redmine.", href: "https://redmine.sokolab.xyz/projects/mypointvpn" }
|
||||
- { title: "Forum", text: "Questions and ideas, plus the guest login.", href: "https://redmine.sokolab.xyz/boards/2/topics/3" }
|
||||
- { title: "Blog post", text: "How a VPN bot learned to manage servers.", href: "https://sokolab.xyz/en/blog/mypointvpn-serverus/" }
|
||||
|
||||
footer: "Use a VPN within the laws of your country."
|
||||
---
|
||||
@@ -0,0 +1,91 @@
|
||||
---
|
||||
title: "MyPoint VPN"
|
||||
tagline: "Свой VPN на своем сервере за одно сообщение"
|
||||
description: "Арендуйте сервер, пришлите Телеграм-боту IP и пароль, и он сам закроет сервер, поставит 3x-ui и настроит VLESS + Reality. Ключи и подписки для клиентов тоже выдает бот."
|
||||
domain: "https://mypointvpn.sokolab.xyz/"
|
||||
badge: "Телеграм-бот · Debian 12 и 13"
|
||||
theme: mypointvpn
|
||||
fonts: "family=Unbounded:wght@500;700&family=Manrope:wght@400;600;800&family=JetBrains+Mono:wght@400;600"
|
||||
post: "/blog/mypointvpn-serverus"
|
||||
postLabel: "Как бот для VPN научился управлять серверами"
|
||||
build:
|
||||
list: never
|
||||
sitemap:
|
||||
disable: true
|
||||
|
||||
nav:
|
||||
- { label: "Возможности", href: "#features" }
|
||||
- { label: "Как начать", href: "#start" }
|
||||
- { label: "Serverus", href: "#engine" }
|
||||
- { label: "Сообщество", href: "#community" }
|
||||
|
||||
cta:
|
||||
- { label: "Открыть бота", href: "https://t.me/barbarisiska_bot", primary: true }
|
||||
- { label: "Как начать", href: "#start" }
|
||||
|
||||
chat:
|
||||
title: "Так это выглядит в боте"
|
||||
messages:
|
||||
- { from: "me", text: "`203.0.113.7:пароль-root`" }
|
||||
- { from: "bot", text: "ssh перенесен на случайный порт, вход только по ключу. Фаервол включен, система обновлена." }
|
||||
- { from: "bot", text: "3x-ui установлена: VLESS + XHTTP + Reality на 443 порту." }
|
||||
- { from: "me", text: "Выпустить ключ" }
|
||||
- { from: "bot", text: "Готово. Вот ссылка на подписку для клиента." }
|
||||
|
||||
features:
|
||||
title: "Что вы получаете"
|
||||
items:
|
||||
- title: "VLESS + XHTTP + Reality"
|
||||
text: "Подключение на 443 порту. Цель для Reality бот подбирает сам."
|
||||
- title: "Сервер маскировки"
|
||||
text: "По желанию. Клиенты подключаются к нему, он пересылает трафик на панель, и адрес панели нигде не светится."
|
||||
- title: "Сертификаты"
|
||||
text: "Домен с Let's Encrypt для панели и подписки. Без домена бот выпустит короткий сертификат на IP и будет продлевать его сам."
|
||||
- title: "Ключи без ограничений"
|
||||
text: "Ни по трафику, ни по сроку, ни по устройствам. Подписки для v2rayN, Hiddify, Happ и v2rayNG. По каждому ключу видно трафик и когда клиент был онлайн."
|
||||
- title: "Прокси и DNS"
|
||||
text: "На выходе свой прокси или Cloudflare WARP. DNS на сервере шифруется: DNS-over-TLS, а если его режут, запасной DNS-over-HTTPS."
|
||||
- title: "Присмотр"
|
||||
text: "Раз в сутки бот проверяет панель, Xray и сертификат подписки и пишет, если что-то сломалось или починилось."
|
||||
|
||||
start:
|
||||
title: "Как начать"
|
||||
steps:
|
||||
- title: "Арендуйте сервер"
|
||||
text: "Любой хостер, Debian 12 или 13. Нужны только IP и пароль root."
|
||||
- title: "Пришлите боту `ip:пароль`"
|
||||
text: "Бот переведет ssh на случайный порт со входом по ключу, включит фаервол, обновит систему и поставит 3x-ui."
|
||||
- title: "Выпустите ключ"
|
||||
text: "Добавьте ссылку на подписку в клиент, и VPN работает."
|
||||
|
||||
note:
|
||||
title: "Сервер остается вашим"
|
||||
text: "Кнопка «Вернуть» убирает доступы бота, откатывает ssh и фаервол и присылает новый пароль root. Данные на сервере остаются. А через Cloudflare бот не работает специально: Cloudflare сам завершает TLS, и Reality за ним работать не может."
|
||||
|
||||
engine:
|
||||
kicker: "Под капотом"
|
||||
title: "Serverus"
|
||||
lead: "Почти вся работа бота сводится к одному: взять голый Debian, закрыть его и управлять им по ключу. Этим занимается `serverus`, пакет на ansible внутри проекта. VPN лишь одна из задач поверх него, вторая это docker-сервер."
|
||||
items:
|
||||
- "Docker, Caddy и автообновления системы, сертификаты для доменов выпускает Caddy"
|
||||
- "Приложение это папка с `docker-compose.yaml`, `.env` и `caddy.conf`, архивом или по файлам"
|
||||
- "Перед применением разница и предупреждения по файлам, в том числе если домен не указывает на сервер"
|
||||
- "Проверка compose, портов и конфига Caddy. При ошибке приложение не трогается, пересоздаются только изменившиеся сервисы"
|
||||
- "Откат на предыдущую версию файлов, старт, стоп, рестарт и логи по сервисам"
|
||||
- "Логин в приватный docker registry и гостевой доступ к volumes для заливки данных"
|
||||
callout:
|
||||
title: "Бот держит сам себя"
|
||||
text: "Прод MyPoint VPN развернут как приложение Serverus на docker-сервере, которым управляет этот же бот. Что умеет бот, решает интерфейс в админке: «MyPoint VPN», «Serverus» или оба сразу."
|
||||
|
||||
community:
|
||||
title: "Сообщество"
|
||||
lead: "Вопросы, идеи и баги принимаются в Redmine. Регистрироваться не обязательно: гостевой вход описан в [теме на форуме](https://redmine.sokolab.xyz/boards/2/topics/3)."
|
||||
links:
|
||||
- { title: "Бот", text: "Начать пользоваться в Телеграме.", href: "https://t.me/barbarisiska_bot" }
|
||||
- { title: "Код", text: "Исходники и вики: деплой, перенос данных, приложения Serverus.", href: "https://git.sokolab.xyz/s0k0l/mypointvpn" }
|
||||
- { title: "Задачи", text: "Баги и пожелания в Redmine.", href: "https://redmine.sokolab.xyz/projects/mypointvpn" }
|
||||
- { title: "Форум", text: "Вопросы и идеи, там же гостевой вход.", href: "https://redmine.sokolab.xyz/boards/2/topics/3" }
|
||||
- { title: "Запись в блоге", text: "Как бот для VPN научился управлять серверами.", href: "https://sokolab.xyz/blog/mypointvpn-serverus/" }
|
||||
|
||||
footer: "Используйте VPN в рамках законов вашей страны."
|
||||
---
|
||||
Reference in new issue
Block a user