Настраиваем outline websockets + nginx на своем сервере
У бабушки перестал правильно работать Outline, и я перенастроил ей соединение через новый рекомендуемый способ - websockets + outline.
Сейчас расскажу, как я сделал.
Тут большой пререквизит в том, чтобы поднять полноценный https-сайт. Поэтому сначала займемся созданием сайта.
Начнем с установки nginx: apt install nginx-light
Домен
Раз мы делаем сайт, значит у него должен быть домен. Я завел для этого проекта поддомен line.codepoetry.ru
- просто сделал днс-записи вида
;; ANSWER SECTION:
line.codepoetry.ru. 3485 IN A 65.20.113.21
line.codepoetry.ru. 3600 IN AAAA 2a01:4a7:c112:834e::1
которые указывают на мой сервер, где я все настраиваю.
Если у вас нет своего домена, то вы можете или заиспользовать домен сервера, который дает ваш хостинг-провайдер (обычно это что-то вроде myserver.hosting.company.com). Или, теоретически, еще можно вообще домен не использовать, а только айпи-адрес, но за такой вариант не ручаюсь, не проверял.
После настройки домена и установки nginx первая контрольная точка. Проверяем, что наш новенький сайт открывается: http://line.codepoetry.ru/

Уже неплохо. Значит, домен работает и nginx тоже работает.
Nginx site config
Давайте сделаем для нашего сайта персональный конфиг:
nano /etc/nginx/conf.d/line.codepoetry.ru.conf
server {
listen 80;
listen [::]:80;
server_name line.codepoetry.ru;
root /var/www/html;
index index.html index.nginx-debian.html;
location / {
try_files $uri $uri/ =404;
}
}
И рестарт nginx: nginx -s reload
Тут очень важный параметр - webroot.
Чтобы выпускать сертификат на следующем шаге, нужно перепроверить, что файлы, которые вы в вебрут положите, доступны снаружи.
В конфиге я указал дефолтную папку /var/www/html
, поэтому если положить любой файл echo some > /var/www/html/some.txt
, то он должен открыться по адресу http://line.codepoetry.ru/some.txt
Проверяем:

Отлично! Ставим галочку и идем дальше.
Certbot
Дальше устанавливаем сертбот по инструкции - https://certbot.eff.org/instructions?ws=other&os=pip
Интересно, что способ установки не apt и даже не snap, а просто нужно создать venv, туда поставить питонячий пакет certbot. Вот примерный слепок команд, хотя полная версия по ссылке выше:
sudo apt update
sudo apt install python3 python3-dev python3-venv libaugeas-dev gcc
sudo python3 -m venv /opt/certbot/
sudo /opt/certbot/bin/pip install --upgrade pip
sudo /opt/certbot/bin/pip install certbot
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot
which certbot
Если сертбот запускается, то переходим к выпуску SSL сертификата.
Сертификат
Чтобы наш новый модный сайт line.codepoetry.ru мог работать по https, ему требуется сертификат. Выпустим его с помощью сертбота.
certbot certonly --webroot
Там из основного - домен, контактный емейл и вебрут (тот самый /var/www/html)
.
Если сертификат выписался, то поздравляю. Осталось только добавить его автообновление в крон в соответствии с шагом 9 из инструкции по ссылке выше. На момент написания этой статьи это была команда
echo "0 0,12 * * * root /opt/certbot/bin/python -c 'import random; import time; time.sleep(random.random() * 3600)' && sudo certbot renew -q" | sudo tee -a /etc/crontab > /dev/null
Back to nginx again
Теперь пришло время отредактировать конфиг и прописать туда созданные сертификаты.
nano /etc/nginx/conf.d/line.codepoetry.ru.conf
Добавляем ssl и пути к файлам:
server {
listen 80;
listen [::]:80;
listen 443 ssl;
listen [::]:443 ssl;
server_name line.codepoetry.ru;
ssl_certificate /etc/letsencrypt/live/line.codepoetry.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/line.codepoetry.ru/privkey.pem;
root /var/www/html;
index index.html index.nginx-debian.html;
location / {
try_files $uri $uri/ =404;
}
}
И еще раз релоад:
nginx -s reload
Проверяем: https://line.codepoetry.ru/some.txt

Иконочка залилась надежным серым замочком. А значит, работает! Если вы дошли до этого шага, поздравляю! Значительная часть конфигурации сделана.
Если что-то в nginx не получается, то ищите причину ошибки в логе: /var/log/nginx/error.log
Дальше можно переключиться на поднятие Outline сервера.
Outline server
Ребята непонятно написали про это у себя в анонсе, но чтобы пользоваться этим методом, не получится использовать их обычный докер и outline manager. Придется самому запустить сервер.
Я сделал так. Пошел на гитхаб в разделе Releases нашел последнюю линуксовую версию, скачал и запустил бинарь
mkdir outline-ss-server
cd outline-ss-server
wget https://github.com/Jigsaw-Code/outline-ss-server/releases/download/v1.9.2/outline-ss-server_1.9.2_linux_x86_64.tar.gz
tar -xf outline-ss-server_1.9.2_linux_x86_64.tar.gz
./outline-ss-server --help
Если работает, то создадим конфиг командой nano config.yaml
вот такого содержимого:
web:
servers:
- id: server1
listen:
- "127.0.0.1:17543"
services:
- listeners:
- type: websocket-stream
web_server: server1
path: "/qk1vrmm1zj9y1qd4xn/tcp"
- type: websocket-packet
web_server: server1
path: "/qk1vrmm1zj9y1qd4xn/udp"
keys:
- id: '1'
cipher: chacha20-ietf-poly1305
secret: just-generate-any-random-string-of-length-20
Тут из важного - нужно сгенерировать любой путь рандомной строкой и никому его не показывать. А также сгенерировать секрет ключа.
Дальше запускаем сервер командой ./outline-ss-server --config config.yaml --replay_history 10000
А чтобы он работал так вечно и не погас, можно было бы запустить его через systemd, но я выбрал вариант проще - я просто запустил его внутри tmux
Снова к Nginx
Возвращаемся к nginx и дописываем конфиг, чтобы прокинуть два пути в ss server. Надо добавить апстрим и два локейшна:
upstream outline {
server localhost:17543;
}
server {
listen 80;
listen [::]:80;
listen 443 ssl;
listen [::]:443 ssl;
server_name line.codepoetry.ru;
ssl_certificate /etc/letsencrypt/live/line.codepoetry.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/line.codepoetry.ru/privkey.pem;
root /var/www/html;
index index.html index.nginx-debian.html;
location / {
try_files $uri $uri/ =404;
}
location /qk1vrmm1zj9y1qd4xn/tcp {
proxy_pass http://outline;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /qk1vrmm1zj9y1qd4xn/udp {
proxy_pass http://outline;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Не забудьте сделать релоад: systemctl reload nginx
Проверить, что работает можно такой командой: curl https://line.codepoetry.ru/path/tcp
- если выдает Bad Request, значит соединение есть.
Осталось только лишь настроить клиент.
Outline Client Configuration
Но и тут нас ждет работа руками. Если вы раньше работали только с ключами вида ss://xxxx
, то вас может удивить, что аутлайн клиент поддерживает и более сложный конфиг - в формате yaml. И он нам понадобится.
Создадим такой конфиг для подключения к нашему серверу:
transport:
$type: tcpudp
tcp:
$type: shadowsocks
endpoint:
$type: websocket
url: wss://line.codepoetry.ru/qk1vrmm1zj9y1qd4xn/tcp
cipher: chacha20-ietf-poly1305
secret: just-generate-any-random-string-of-length-20
udp:
$type: shadowsocks
endpoint:
$type: websocket
url: wss://line.codepoetry.ru/qk1vrmm1zj9y1qd4xn/udp
cipher: chacha20-ietf-poly1305
secret: just-generate-any-random-string-of-length-20
И осталось дело за малым - этот конфиг нужно дать клиенту. Для меня удобный способ - это просто положить его в файл на том же самом сервере, сгенерировав рандомное имя файла. Для примера я использую имя example.txt:
nano /var/www/html/example.txt
Проверим, что файл открывается: https://line.codepoetry.ru/example.txt
И если да, то просто меняем https на ssconf и вот он наш ключ:
ssconf://line.codepoetry.ru/example.txt
Именно этот "ключ" можно добавлять на бабушкином компьютере и проверять соединение.
Работает!