Как я докатился до жизни такой?
Всех приветствую. Это мой сайт. Сам я FavorPTG и так меня кто-то может знать в интернете. Вообще, это не первая моя статья на ndlink.ru, но только сейчас я решил полноценно представиться, так как это уже полноценная статья – то, ради чего всё это создавалось.
А рассказать я хотел о том, что, зачем и почему я делал на пути к независимости в части некоторых интернет-сервисов.
Скажу сразу: моей давней мечтой было запустить свою почту. Помимо очевидного плюса, что ваш адрес может быть admin@... (даже не думайте спорить – это неоспоримый плюс, как и RGB-подсветка на ПК 😂😂), это ещё и независимость и возможность более тонкой настройки. Это то, что было важно для меня. Но есть и минусы, о которых я знал с самого начала: вам нужен домен. И если вы где-то регистрируетесь на эту почту, то домен этот должны стать вашим просто на веки! Причина: боты, которые массово скупают просроченные домены, тоже запускают там почту и всё – теперь они могут попытаться восстановить пароль от вашего аккаунта. А вы – нет, домен-то больше не ваш. И это реально большая проблема. Особенно по части ценообразования региональных DNS-провайдеров. Напомню, что цена домена из зон типа .ru часто резко возрастает на второй-третий год продления. Вы купили новый домен (обычно минимум на год) за 300 рублей. А за второй год получаете счёт на 1300. Продлили его ещё на год – цена вырастет снова. И снова. И снова. Не так резко (тут я сильно утрирую) но цена будет расти.
Резюмирую: хотите свою почту – готовьтесь с каждым годом отдавать за домен либо круглую сумму за международный домен, либо всё большое и больше. И обязательно имейте подушку безопасности, чтобы быстро восстановить доступ к аккаунтам, где использовалась ваша почта, если она вдруг станет не вашей.
Зато с остальными сервисами сильно проще! Лично для меня важно было настроить синхронизацию паролей. У меня большое количество устройств и раньше перенос паролей был сущим адом. Основная их часть была на телефоне. То есть для части аккаунтов схема была следующая: взять телефон, подключиться по kde connect к ПК (если этого не произошло автоматически), зайти в менеджер паролей, найти нужный, скопировать его, передать буфер обмена на ПК, вставить пароль в нужное поле. Не то чтобы это сложно, но удобством точно не пахнет. Вот тут и спасает синхронизация. Я не решался доверять пароли сторонним сервисам (и вам не советую), а вот у себя на сервере – другое дело.
Что ещё вам может понадобиться? Кто знает... Мне вот нужен был сервис для синхронизации заметок Obsidian. Я пользовался WebDAV к mail ru drive, а ещё чуть ранее – к Yandex disk. Удобно и работает даже при белых списках (новая норма в РФ...), но Яндекс меня подставил довольно жёстко: в какой-то момент просто стал выдавать ошибку синхронизации с требованием заплатить, чтобы дальше пользоваться. Скорее всего я упёрся в какой-то внутренний лимит на месяц, но об этом нигде не сказано, да и заметок у меня на пару мегабайт. Эх контора...
Но давайте к практике.
Как поднимать сервисы?
Первый вопрос, которым вы можете задаться: как поднимать кучу сервисов на одном VPS? Ответ простой: через docker. Именно так у меня работает большая часть всего. Исключение – этот сайт. Он написан на golang, зависимостей не требует, компилируется в один файл.
Кратко расскажу о docker. Если не планируете создавать что-то своё, то вам нужен docker-compose. Он предельно прост: создаёте файл docker-compose.yaml, заполняете его, а затем выполняете docker compose up -d. И всё. Если сервис настроен верно, то он запустится и будет работать. Если нет – можете проверить это командой docker logs *container_name*. Либо изначально запускать docker-compose без флага -d – в таком случае весь лог будет идти в открытую консоль.
Ниже пример файла docker-compose.yaml для сервиса WebDAV-хранилища файлов:
services:
webdav:
image: ionelmc/webdav:latest
container_name: webdav
restart: unless-stopped
ports:
- "127.0.0.1:8081:8080"
environment:
- WEBDAV_USERNAME=admin
- WEBDAV_PASSWORD=PASSWORD
volumes:
- ./data:/var/webdav
Поясню, что тут происходит:
- Мы создаём новый сервис webdav и названием контейнера тоже webdav (можно и по разному – это ни на что не влияет).
- Используем официальный образ
ionelmc/webdav:latest(рекомендую указывать конкретную версию, а не latest, если вам нужна стабильность, однако контейнер не обновляется автоматически, так что если оно работает – оно работать и будет) - Связываем порт
8081на вашем VPS с портом8080в контейнере. Именно на порту 8080 работает webdav. - Связываем локальную директорию
./data(будет создана рядом с файлом docker-compose) с директорией/var/webdavв контейнере. - В блоке environment задаются переменные окружения для контейнера. Они будут отличаться для каждого образа контейнера, так что изучайте документацию. В данном случае это настройки логина и пароля для доступа к хранилищу.
- Ну и через
restart: unless-stoppedмы указываем, что при любом сбое контейнер должен быть перезапущен.
Ничего сложного. Если у вас всё же возникают сложности с самостоятельным описанием контейнера, то знайте, что большинство образов сопровождается примером файла docker-compose.yaml – google вам в помощь. Само собой, я многого не уточнил и у docker много своих особенностей, которые вы можете/должны знать/использовать, но в этой статье я и не имею цели обучить вас работе с docker.
Как создать защищённое соединение?
После запуска вашего сервиса, он будет доступен в браузере по адресу http://*IP вашего сервера:8081. Это уже круто! Но http не безопасен и все данные передаются в открытом виде. Сейчас крайне небольшое количество публичных сервисов используют http. В основном, это те, кто не собирают от пользователей никаких данных, не имеют баз данных и прочего – просто статические страницы, сайты-визитки и подобное.
Нам это не подходит, так что давайте защитим наш сервис от утечек данных! Самый простой способ это сделать – reverse-proxy. Это программа, которая подхватывает запрос, оборачивает его в https и уже в таком виде отправляет пользователю. Безопасно и не сложно.
Однако, перед тем, как настраивать защищённое соединение, нам необходим домен. Только на домен можно получить полноценный SSL-сертификат. Можно использовать и самоподписный на IP, но на него браузер будет ругаться и могут быть проблемы с работой API (если вдруг они у вас есть). В данной статье я не буду рассматривать то, как получить доменное имя. Будем считать, что оно у вас уже есть.
Теперь необходимо получить SSL-сертификаты. Это можно сделать на сайте let's encrypt, либо через программу certbot прямо на сервере.
Воспользуемся вторым вариантом. Если у вас ещё не установлен nginx – установите его, он нам понадобится. А также всё необходимое. Сделать это можно следующей командой на Ubuntu/Debian (для других ОС смотрите команды сами):
sudo apt update && sudo apt install -y nginx certbot python3-certbot-nginx
Nginx должен запуститься в фоне автоматически. Можете проверить это следующей командой:
sudo systemctl status nginx
Если всё в порядке, выполните следующую команду, указав своё доменное имя:
sudo certbot certonly --nginx -d webdav.example.com
Если вы только что изменили параметры домена (например, добавили A запись и хотите использовать её), то certbot может выдать ошибку. В таком случае подождите пару минут – DNS-записи обновятся и команда выполнится без проблем. В результате вы получите путь к созданным файлам сертификатов. Они нам скоро понадобятся.
Далее я буду использовать nginx. Для описания нового сервиса, создайте любой понятный всм файл по пути /etc/nginx/sites-available/*name_of_file* с подобным содержимым:
server {
listen 80;
server_name webdav.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name webdav.example.com;
ssl_certificate /etc/letsencrypt/live/webdav.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/webdav.example.com/privkey.pem;
# Максимальный размер загружаемого файла
client_max_body_size 100M;
location / {
proxy_pass http://127.0.0.1:8081;
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;
}
}
Что тут происходит:
- В первом блоке
serverмы задаём правило, при котором любой запрос http к нашему WebDAV будет перенаправлен на https. - Во втором блоке мы задаём правила для https: имя сервера, на который придёт запрос, пути к ssl-сертификатам, максимальный размер тела запроса (в основном, не обязательно), а также настройки перенаправления полученного запроса на локальный http.
- Собственно, блок
location / {...}отвечает за то, какой адрес мы певерс-проксируем. proxy_pass http://127.0.0.1:8081заставляет nginx перенаправлять все запросы сhttps://webdav.example.com/на локальныйhttp://127.0.0.1:8081/.proxy_set_header Host $hostзаставляет nginx передать внутреннему сервису имя хоста, на которое пришёл запрос. В данном случае этоwebdav.example.com. Без этой строки внутренний сервис будет считать, что запрос пришёл на127.0.0.1.proxy_set_header X-Real-IP $remote_addrзаставляет nginx передать внутреннему сервису реальный IP-адрес пользователя. Без неё сервис будет считать, что запрос пришёл от самого nginx, а не от пользователя.proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_forпередаёт внутреннему сервису полную цепочку IP-адресов, которые прошёл запрос. Это нужно в случае, например, использования прокси (от cloudflare или подобрые).proxy_set_header X-Forwarded-Proto $schemeпередаёт внутреннему сервису протокол, по которому реально пришёл запрос. Без него сервис будет считать его http, так как именно так его присылает nginx. Это довольно шаблонная конструкция и её можно дополнительно адаптировать для других сервисов.
Теперь нужно сделать сервис активным, заставить nginx прочитать новую конфигурацию и перезапустить его:
sudo ln -s /etc/nginx/sites-available/webdav /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Готово! Теперь попробуйте зайти на страницу, вписав http://webdav.example.com и увидите, что окажетесь на https://webdav.example.com. Само собой, замените домен на свой.
Более сложные сервисы
Самым сложным, что я настраивал, была почта. Это многоуровневая процедура, связывающая воедино настройку DNS-записей, сервера, а в моём случае ещё и web-клиента.
Думаю, в основном за этим вы сюда и пришли)) Приступим!
Первое, что мы сделаем – это настроим DNS-записи на сервере:
Aзапись: mail.example.com -> IP_VPSMXзапись: example.com -> значение: mail.example.com (приоритет 10)TXTзапись:v=spf1 mx a ip4:IPVPS ~allTXTзапись: _dmarc.example.com -> значение:v=DMARC1; p=none; rua=mailto:postmaster@example.com
Готово. Остальное не трогаем.
Теперь нужно настроить сам сервер: добавить PTR-запись (Reverse DNS) для вашего IP-адреса на значение mail.example.com. Тут я мало, что могу советовать, так как у разных провайдеров это делается по разному. Чаще всего нужно писать в тех-поддержку и они всё сделают.
Этот этап можно отложить и, наконец, приступить к настройке ПО. Я использовал проект docker-mailserver. На его примере показывать и буду.
Для начала, создадим на сервере новую директорию и скачаем туда всё необходимое:
mkdir -p ~/mailserver && cd ~/mailserver
# Официальный установочный скрипт управления (setup.sh)
curl -sSL https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master/setup.sh -o setup.sh
chmod +x setup.sh
# Пример файла docker-compose.yml
curl -sSL https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master/compose.yaml -o docker-compose.yml
# Переменные окружения для сервера
curl -sSL https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master/mailserver.env -o mailserver.env
Обратите внимание, что переменные окружения вынесены в отдельный файл. Связано это с тем, что их довольно много. Поэтому в docker-compose.yaml нужно поменять только имя хоста на своё (поле OVERRIDE_HOSTNAME=mail.example.com) и добавить:
volumes:
- /etc/letsencrypt/:/etc/letsencrypt/:ro
Сразу сгенерируем сертификаты для сервера. Для этого воспользуемся уже знакомым вам certbot:
sudo certbot certonly --nginx -d mail.example.com
Далее переходим в файл mailserver.env. Файл хорошо документирован, так что можете изучить его и включить/отключить то, что Вам нужно. Из интересного:
# Отключаем тяжелый антивирус
ENABLE_CLAMAV=0
# Включаем легкий и умный антиспам
ENABLE_RSPAMD=1
# Защита от подбора паролей
ENABLE_FAIL2BAN=1
# SSL-сертификаты
SSL_TYPE=manual
SSL_CERT_PATH=/etc/letsencrypt/live/mail.example.com/fullchain.pem
SSL_KEY_PATH=/etc/letsencrypt/live/mail.example.com/privkey.pem
Теперь запустим docker:
sudo docker compose up -d
Когда он запустится, можем создать нашего первого пользователя, а также алиас на системного пользователя, который будет получать отчёты:
./setup.sh email add admin@example.com
./setup.sh alias add postmaster@example.com admin@example.com
Команда создаст пользователя admin и попросит ввести пароль для него. Не отказываем ей в этом удовольствии.
Теперь сгенерируем цифровую подпись для наших писем:
./setup.sh config dkim
Команда создаст файл, который мы должны прочитать:
cat docker-data/dms/config/opendkim/keys/example.com/mail.txt
Там будет что-то вроде этого:
mail._domainkey IN TXT ( "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQ..." )
Осталось создать ещё одну DNS-запись типа TXT, хост mail._domainkey.example.com, а в качестве значения вставьте содержимое mail.txt (то, что в скобках, но без кавычек).
После всего этого можно попробовать отправить наше первое письмо. Сделать это можно прямо из консоли:
docker exec -it mailserver swaks --to my_best_real_email@gmail.com \
--from admin@example.com \
--server localhost:587 \
--auth LOGIN \
--auth-user admin@example.com \
--auth-password "ПАРОЛЬ_ОТ_ADMIN" \
--header "Subject: Test mail from VPS" \
--body "Привет! Это первое тестовое письмо."
Зайдите на свою почту и порадуйтесь тому, что увидите письмо со своего собственного домена и скорее всего со сбитой кодировкой из за специфики консоли 😂😂! Не переживайте – всё в норме!
Следующий шаг – открыть почтовый клиент и добавить туда Вашу новую почту точно так же, как вы это делали с mail.ru или подобными.
Готово! Я вас поздравляю с ещё одним шагом к независимости от корпораций! Думаю, это не последняя моя статья по настройке сервера – будет ещё про создание блога, про хранилище паролей vaultwarden, возможно ещё о чём-то.
На этом у меня всё. Найти меня можно:
В matrix: @favorptg:tchncs.de
В telegram: @FavorPTG
В X.com: @MetthewRog52189
Всем мира и удачи!