diff --git a/#README.org# b/#README.org# new file mode 100644 index 0000000..ec5fbf1 --- /dev/null +++ b/#README.org# @@ -0,0 +1,594 @@ +#+TITLE: Install server from scratch (Rocky Linux) +#+SUBTITLE: Quick reference card +#+AUTHOR: Norets Alexey +#+EMAIL: (concat "asnorets" at-sign "gmail.com") +#+DESCRIPTION: Rocky Linux from scratch +#+KEYWORDS: Rocky linux, gunicorn + nginx + flask +#+LANGUAGE: ru +#+OPTIONS: H:4 num:nil toc:2 p:t + +* Установка сервера с нуля (gunicorn + nginx + flask) и настройка WireGuard + +Данная инструкция предназначена для перенастройки сервера с сайтом и VPN. + +** Создание и первоначальная настройка сервера + +Создаем сервер. Заходим через SSH -> выходим -> копируем ключи на сервер: +#+begin_src shell +ssh @ +exit +ssh-copy-id @ +#+end_src + +Теперь можем заходить по ключу (~/.ssh). + +На сервере настраиваем SSH (запрет авторизации по паролю, запрет root по ssh): +#+begin_src shell +sudo vi /etc/ssh/sshd_config +#+end_src + +Добавляем или изменяем строки: +#+begin_src conf +PermitRootLogin no +PasswordAuthentication no +#+end_src + +Перезапускаем ssh: +#+begin_src shell +sudo systemctl restart sshd +#+end_src + +** Установка необходимых пакетов + +Обновляем систему: +#+begin_src shell +sudo dnf update +sudo dnf upgrade --refresh +#+end_src + +Включаем CRB репозиторий: +#+begin_src shell +sudo dnf config-manager --set-enabled crb +sudo dnf install epel-release +#+end_src + +Ставим необходимые пакеты: +#+begin_src shell +sudo dnf install zsh vim htop nginx git wget vim python3-pip python3-devel gcc emacs-nox -y +sudo pip3 install virtualenv +#+end_src + +Устанавливаем [[https://github.com/robbyrussell/oh-my-zsh][oh-my-zsh]]: +#+begin_src shell +sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" +#+end_src + +Добавляем в ~~/.zshrc~: +#+begin_src conf +# History +# хранить историю в указанном файле +export HISTFILE=~/.zsh_history +# максимальное число команд, хранимых в сеансе +export HISTSIZE=1000 +export SAVEHIST=$HISTSIZE +# включить историю команд +setopt APPEND_HISTORY +# убрать повторяющиеся команды, пустые строки и пр. +setopt HIST_IGNORE_ALL_DUPS +setopt HIST_IGNORE_SPACE +setopt HIST_REDUCE_BLANKS + +# alias ls='exa' +#+end_src + +** Начинаем работу с проектом. + +Создаем пользователя ~klintorg-www~: +#+begin_src shell +sudo mkdir /home/klintorg-www +sudo groupadd klintorg-www +sudo adduser -G nginx -g klintorg-www -d /home/klintorg-www klintorg-www --system --shell=/bin/false +#+end_src + +~Временно~ выдаем права на папку ~klintorg-www~ и переходим в нее: +#+begin_src shell +sudo chmod -R 777 /home/klintorg-www +cd /home/klintorg-www +#+end_src + +Клонируем проект: +#+begin_src shell +git clone https://github.com/Noretsa/klintorg.git +#+end_src + +git запросит логин и пароль. Пароль необходимо создать, github -> settings -> Developer settings -> Personal access token -> Fine grained tokens. Дальше надо дать права токену, ну разберешься... + +Переходим в папку проекта: +#+begin_src shell +cd klintorg +#+end_src + +Создаем файл ~wsgi.py~: +#+begin_src shell +vim wsgi.py +#+end_src + +В нем делаем так: +#+begin_src python +from __init__ import app + +if __name__ == "__main__": + app.run() +#+end_src + +Создаем папку окружения и ставим зависимости проекта: +#+begin_src shell +virtualenv .klintorg +source .klintorg/bin/activate +pip install -r requirements.txt +pip install gunicorn +deactivate +#+end_src + +Разрешаем в firewall порт 5000 и 8000 для тестов: +#+begin_src shell +sudo firewall-cmd --add-port=5000/tcp +sudo firewall-cmd --add-port=8000/tcp +#+end_src + +Чтобы посмотреть лист открытых портов: +#+begin_src shell +sudo firewall-cmd --list-all +#+end_src + + + +** Тестим проект + +Можем протестировать проект: +#+begin_src shell +python __init__.py +#+end_src + +С локального компьютера открываем браузер на странице http://:5000. + +Если все работает - начинаем тестировать gunicorn: +#+begin_src shell +gunicorn --bind 0.0.0.0:8000 wsgi:app +#+end_src + +С локального компьютера открываем браузер на странице http://:8000. + +Если все работет гасим gunicorn (ctrl+c) и деактивируем окружение python: +#+begin_src shell +deactivate +#+end_src + +Теперь для ~klintorg-www~ назначаем права: +#+begin_src shell +sudo chown -R klintorg-www:nginx /home/klintorg-www +sudo chmod -R 755 /home/klintorg-www +#+end_src + +Отключаем ~SELinux~: +#+begin_src shell +sudo vim /etc/selinux/config +#+end_src + +#+begin_src conf +SELINUX=disabled #enforcing +#+end_src + +Перезагружаемся: +#+begin_src shell +sudo reboot now +#+end_src + + +** Настраиваем Flask Application + +Мы протестировали что наш ~gunicorn~ работает с нашим приложением Flask. Теперь необходимо сделать так, чтобы он загружался при старте системы. Чтобы этого добиться, мы создадим ~systemd service~ и ~socket file~. + +~Gunicorn socket~ будет создаваться при загрузке системы и прослушивать соединения. Когда придет коннект, ~systemd~ автоматически запустит ~Gunicorn~ процесс для поддержания соединения. + +Начнем с создания ~systemd socket~ файла: +#+begin_src shell +sudo vim /etc/systemd/system/klintorg.socket +#+end_src + +Внутри создаем следующие секции: +#+begin_src conf +[Unit] +Description=klintorg socket + +[Socket] +ListenStream=/run/klintorg.sock + +[Install] +WantedBy=sockets.target +#+end_src + +Далее создаем ~systemd service~ файл. Имя этого файла должно совпадать с именем ~socket~ файла: +#+begin_src shell +sudo vim /etc/systemd/system/klintorg.service +#+end_src + +В этом файле будет так: +#+begin_src conf +[Unit] +Description=klintorg daemon +Requires=klintorg.socket +After=network.target + +[Service] +User=nginx +Group=nginx +WorkingDirectory=/home/klintorg-www/klintorg +ExecStart=/home/klintorg-www/klintorg/.klintorg/bin/gunicorn \ + --access-logfile - \ + --workers 3 \ + --bind unix:/run/klintorg.sock -m 007\ + wsgi:app + +[Install] +WantedBy=multi-user.target +#+end_src + +Перезапускаем демоны: +#+begin_src shell +sudo systemctl daemon-reload +#+end_src + +Теперь запускаем ~Gunicorn socket~, когда он запустится, он стартанет наш ~gunicorn service~: +#+begin_src shell +sudo systemctl start klintorg.socket +sudo systemctl enable klintorg.socket +#+end_src + +** Настраиваем NGINX + +Создаем файл конфигурации: +#+begin_src shell +sudo vim /etc/nginx/conf.d/klintorg.conf +#+end_src + +В файл добавляем следующие строки: +#+begin_src conf +server { + listen 80; + server_name server_domain_or_IP; + + location / { + proxy_set_header Host $http_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; + proxy_pass http://unix:/run/klintorg.sock; + } +} +#+end_src + +Теперь разрешаем Nginx доступ к соккету gunicorn: +#+begin_src shell +sudo semanage permissive -a httpd_t +#+end_src + +Так же разрешаем Nginx доступ к папке проекта (???????): +#+begin_src shell +sudo chgrp -R nginx /usr/share/nginx/html/klintorg-www/klintorg/ +#+end_src + +Проверяем синтаксис: +#+begin_src shell +sudo nginx -t +#+end_src + +Запускаем и добавляем в автостарт nginx: +#+begin_src shell +sudo systemctl start nginx +sudo systemctl enable nginx +#+end_src + +Открываем 80 и 443 порты на firewall: +#+begin_src shell +sudo firewall-cmd --add-port=80/tcp --permanent +sudo firewall-cmd --add-port=443/tcp --permanent +sudo firewall-cmd --reload +#+end_src + +** Настраиваем сертификат Let's Encrypt + +Ставим ~certbot~: +#+begin_src shell +sudo dnf install certbot python3-certbot-nginx +#+end_src + +Ставим ~snapd~ для автопродления сертификата: +#+begin_src shell +sudo dnf install snapd +sudo systemctl enable --now snapd.socket +sudo ln -s /var/lib/snapd/snap /snap +exit +#+end_src +Необходимо перезайти в систему! + + +Запускаем: +#+begin_src shell +sudo certbot --nginx +#+end_src + +Проверяем обновляется ли: +#+begin_src shell +sudo certbot renew --dry-run +#+end_src + +Проверяем что встало автообновление: +#+begin_src shell +sudo systemctl list-timers -all +#+end_src + +** Wireguard +# https://www.digitalocean.com/community/tutorials/how-to-set-up-wireguard-on-rocky-linux-8 + +# Это более полезна оказалась: https://unix.stackexchange.com/questions/713798/rocky-linux-9-wireguard-masquerade-traffic-to-internet-not-working + +Начальная установка: +#+begin_src shell +sudo dnf install elrepo-release epel-release +sudo dnf install wireguard-tools +#+end_src + +Генерируем ключи: +#+begin_src shell +wg genkey | sudo tee /etc/wireguard/private.key +sudo chmod go= /etc/wireguard/private.key +sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key +#+end_src + +Создаем файл конфигурации: +#+begin_src shell +sudo vim /etc/wireguard/wg0.conf +#+end_src + +#+begin_src conf +[Interface] +Address = 10.8.0.1/24 +# SaveConfig = true +ListenPort = 51820 +PrivateKey = MOJMpDrnsE5upIw9iqFQgkQnbsCAdQI17tL5mGuGRW8= + +PostUp = firewall-cmd --zone=public --add-masquerade; firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -i wg0 -o ens3 -j ACCEPT; firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -o ens3 -j MASQUERADE; firewall-cmd --add-port=51820/udp + +PostDown = firewall-cmd --zone=public --remove-masquerade; firewall-cmd --direct --remove-rule ipv4 filter FORWARD 0 -i wg0 -o ens3 -j ACCEPT; firewall-cmd --direct --remove-rule ipv4 nat POSTROUTING 0 -o ens3 -j MASQUERADE; firewall-cmd --remove-port=51820/udp + +[Peer] +PublicKey = 6I+0r4jXDsPQJqHEsrNHNu44ZMS/tDivDFL7/rVRxV8= +AllowedIPs = 10.8.0.2/32 +#+end_src + +#+begin_src shell +sudo vim /etc/sysctl.conf +#+end_src +#+begin_src conf +net.ipv4.ip_forward=1 +#+end_src +#+begin_src shell +sudo sysctl -p +#+end_src + + +# https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-using-firewalld-on-rocky-linux-9 +Настраиваем Firewall (сначала делаем без этого, выше ссылка на инструкцию): +#+begin_src shell +firewall-cmd --permanent --direct --passthrough ipv4 -t nat -A POSTROUTING -s 10.8.0.0/24 -o enp0s3 -j MASQUERADE # это в первую очередь и проверяем, потом уже остальные +sudo firewall-cmd --zone=public --add-port=51830/udp --permanent +sudo firewall-cmd --zone=internal --add-interface=wg0 --permanent +sudo firewall-cmd --zone=public --add-rich-rule='rule family=ipv4 source address=10.8.0.0/24 masquerade' --permanent +# sudo firewall-cmd --zone=public --add-rich-rule='rule family=ipv6 source address=fd0d:86fa:c3bc::/64 masquerade' --permanent +sudo firewall-cmd --reload +#+end_src + +Включаем ~Wireguard~: +#+begin_src shell +sudo systemctl enable wg-quick@wg0.service +sudo systemctl start wg-quick@wg0.service +#+end_src + +*** Настройка клиента + +Создаем папку в домашней директории: +#+begin_src shell +mkdir wg_norets +#+end_src + +Создаем клиентскую пару ключей: +#+begin_src shell +wg genkey | tee /home/norets/wg_norets/norets_privatekey | wg pubkey | tee /home/norets/wg_norets/norets_publickey +#+end_src + +Добавляем в конфиг WG: +#+begin_src shell +sudo vim /etc/wireguard/wg0.conf +#+end_src +#+begin_src conf +[Peer] +PublicKey = l3tzC968A9at/1AvLaxRX9BmUj9kfGFql3Y0HEk35So= # +AllowedIPs = 10.8.0.2/32 +#+end_src + +Перезапускаем сервис wireguard: +#+begin_src shell +sudo systemctl restart wg-quick@wg0 +sudo systemctl status wg-quick@wg0 +#+end_src + +На клиенте создаем файл: +#+begin_src conf +[Interface] +PrivateKey = 2JgSg050VqNNgd+9rEt/NkhmuGTdzJNnzhNsDvIvSH8= # +Address = 10.8.0.2/32 +DNS = 8.8.8.8 + +[Peer] +PublicKey = cW4mpBGG3CBcW01I2HTSXpyxzId72Lh/EAF5Q7iS3RQ= # +Endpoint = 88.210.3.57:51830 +AllowedIPs = 0.0.0.0/0 +PersistentKeepalive = 20 +#+end_src + + +** OpenVPN +*** Server + +Просто приложу команды: +#+begin_src shell +sudo -i +dnf install openvpn +dnf install easy-rsa +mkdir /etc/easy-rsa +cp -air /usr/share/easy-rsa/3.0.8/* /etc/easy-rsa/ # last ver. 3.0.8 +cd /etc/easy-rsa/ +./easyrsa init-pki +./easyrsa build-ca +./easyrsa gen-dh +./easyrsa build-server-full server nopass +openvpn --genkey secret /etc/easy-rsa/pki/ta.key +./easyrsa gen-crl +cp -rp /etc/easy-rsa/pki/{ca.crt,dh.pem,ta.key,crl.pem,issued,private} /etc/openvpn/server/ +#+end_src + +*** Clients +#+begin_src shell +./easyrsa build-client-full gentoo nopass # 1 client +./easyrsa build-client-full johndoe nopass # 2 client +mkdir /etc/openvpn/client/{gentoo,johndoe} +cp -rp /etc/easy-rsa/pki/{ca.crt,issued/gentoo.crt,private/gentoo.key} /etc/openvpn/client/gentoo +cp -rp /etc/easy-rsa/pki/{ca.crt,issued/johndoe.crt,private/johndoe.key} /etc/openvpn/client/johndoe/ +cp /usr/share/doc/openvpn/sample/sample-config-files/server.conf /etc/openvpn/server/ +emacs /etc/openvpn/server/server.conf +#+end_src + +Конфиг сервера: +#+begin_src conf +port 1194 +proto udp4 +dev tun +ca ca.crt +cert issued/server.crt +key private/server.key # This file should be kept secret +dh dh.pem +topology subnet +server 10.8.0.0 255.255.255.0 +ifconfig-pool-persist ipp.txt +push "redirect-gateway def1 bypass-dhcp" +push "dhcp-option DNS 208.67.222.222" +push "dhcp-option DNS 192.168.10.3" +client-to-client +keepalive 10 120 +tls-auth ta.key 0 # This file is secret +cipher AES-256-CBC +comp-lzo +user nobody +group nobody +persist-key +persist-tun +status /var/log/openvpn/openvpn-status.log +log-append /var/log/openvpn/openvpn.log +verb 3 +explicit-exit-notify 1 +auth SHA512 +#+end_src + +#+begin_src shell +mkdir /var/log/openvpn/ +echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf +sysctl --system +firewall-cmd --add-port=1194/udp --permanent +firewall-cmd --add-masquerade --permanent +ip route get 8.8.8.8 # Чтобы посмотреть имя сетевого интерфейса ~ens3~ +firewall-cmd --permanent --direct --passthrough ipv4 -t nat -A POSTROUTING -s 10.8.0.0/24 -o ens3 -j MASQUERADE +firewall-cmd --reload +systemctl enable --now openvpn-server@server +tail /var/log/openvpn/openvpn.log +#+end_src + +Конфиг клиентов ~(client_file.ovpn)~: +#+begin_src conf +client +tls-client +pull +dev tun +proto udp4 +remote 192.168.60.19 1194 +resolv-retry infinite +nobind +#user nobody +#group nogroup +persist-key +persist-tun +key-direction 1 +remote-cert-tls server +auth-nocache +comp-lzo +verb 3 +auth SHA512 +tls-auth ta.key 1 +ca ca.crt +cert gentoo.crt +key gentoo.key +#+end_src + +Работать будет только в том случае, если все сертификаты лежат рядом с файлом .ovpn. Иначе надо сертификаты писать в файл, вот так: +#+begin_src conf +client +tls-client +pull +dev tun +proto udp4 +remote 192.168.60.19 1194 +resolv-retry infinite +nobind +#user nobody +#group nogroup +persist-key +persist-tun +key-direction 1 +remote-cert-tls server +auth-nocache +comp-lzo +verb 3 +auth SHA512 + +-----BEGIN OpenVPN Static key V1----- +feb1af5407baa247d4e772c76aed6c75 +... +-----END OpenVPN Static key V1----- + + +-----BEGIN CERTIFICATE----- +MIIDTjCCAjagAwIBAgIUX0VQrHTgLDabUUIOAf7tD9cGp4YwDQYJKoZIhvcNAQEL +... +WA9BBk2shVWfR849Lmkep+GPyqHpU47dZAz37ARB2Gfu3w== +-----END CERTIFICATE----- + + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: +... +/7FvJaeLqmUHnvSs5eBlRZSgtOL19SCFkG0HXdnw3LtBaoHQXxgzOkDPW1+5 +-----END CERTIFICATE----- + + +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC+DI7kg6MsRoCs +... +6WdLcNtWKAcU294xJEZoOA8/ +-----END PRIVATE KEY----- + +#+end_src + +Если работаем с OpenWRT - добавляем опцию (перед ) route-noexec. +После этого добавляем файл в OVPNClient и радуемся) diff --git a/requirements.txt b/requirements.txt index 95fdc55..b042b9b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ click==7.1.2 Flask==1.1.2 Flask-SQLAlchemy==2.5.1 -greenlet==1.1.2 +greenlet>=1.1.2 itsdangerous==1.1.0 Jinja2==2.11.3 MarkupSafe==1.1.1