W I części zbudowałem mikro-serwis działający lokalnie. Teraz pora przenieś go do internetu.
Serwer WWW - NGINX
Do wyboru jest Apache i NGINX. Rzut monetą wskazał na drugi webserver (ok, tak naprawdę to wybrany z premedytacją).
Instalacja serwera:
sudo apt-get install nginx
Po wpisaniu IP servera (192.166.219.228
) powinien pojawić się komunikat powitalny nginx
Welcome to ngnix!
If you see this page, the ngnix web server is successfully installed and working.
Further configuration is required.
W razie potrzeby można wymusić start/restart/stop serwera ręcznie poniższymi komendami:
sudo systemctl start ngnix
sudo systemctl restart ngnix
sudo systemctl stop ngnix
Status serwer nginx:
systemctl status nginx
Status usługi:
sudo systemctl status nginx
* nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2020-07-11 15:08:47 CEST; 4min 24s ago
Docs: man:nginx(8)
Main PID: 15737 (nginx)
Tasks: 2 (limit: 4657)
Memory: 6.5M
CGroup: /system.slice/nginx.service
|-15737 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
`-15738 nginx: worker process
Firewall
Do konfiguracji firewalla można użyć (wyświetli dostępne domyślnie tryby):
sudo ufw app list
Wybranie któregoś z nich odbywa się poprzez:
sudo ufw allow 'Nginx Full'
sudo ufw allow OpenSSH
Sprawdzenie statusu:
sudo ufw enable
sudo ufw status
Wynik:
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx Full ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Nginx Full (v6) ALLOW Anywhere (v6)
Przygotowanie środowiska
Kod serwisu będzie znajdował się w var/www/
:
cd /var/www
git clone -b <branch> https://github.com/<repo>.git
Utworzenie wirtualnego środowiska na serwerze VPS:
python3 -m venv --copies fast_ve
source fast_ve/bin/activate
pip install --upgrade pip
pip install setuptools
pip install wheel
Instalacja FastApi, Gunicorn, Unicorn
pip install fastapi[all]
pip install gunicorn
pip install unicorn
Dotychczasowy kod aplikacji:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
Tak jak w przypadku instrukcji dla Flask zaczniemy testy od ręcznego uruchomienia (/var/www/fastapi_www/app
):
gunicorn main:app -w 2 -k uvicorn.workers.UvicornWorker -b "0.0.0.0:5000"
Musimy jeszcze odblokować port 5000:
sudo ufw allow 5000
Teraz przejście na remontmaszyn.pl:5000
powinno pokazać naszą stronę.
Konfiguracja systemd
Utworzenie pliku
sudo nano /etc/systemd/system/fastapi.service
o zawartości:
[Unit]
Description=Gunicorn instance daemon to serve FastAPI
#After=network.target
After=multi-user.target
StartLimitBurst=60
StartLimitIntervalSec=60
[Service]
User=lambda
Group=www-data
WorkingDirectory=/var/www/fastapi_www/app
Environment="PATH=/var/www/fastapi_www/fast_ve/bin"
ExecStart=/var/www/fastapi_www/fast_ve/bin/gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker -b unix:fastapi.sock -m 007
Restart=on-failure
RestartSec=60
[Install]
WanterBy=multi-user.target
Jest to odpowiednik ręcznej komendy którą testowałem akapit wcześniej.
Uruchomianie
sudo systemctl start fastapi
Ponieważ strona ma działać na standardowym porcie i być obsługiwana przez NGNIX to potrzebujemy wprowadzić kilka zmian:
Konfiguracja NGINX
Utworzenie pliku konfiguracyjnego
cd /etc/nginx/sites-available/
sudo nano helloworld
Zawartość:
server {
listen 80;
listen [::]:80;
root /home/lambda/py_env/www_env/www/;
index index.html index.htm index.ngnix-debian.html;
server_name 192.166.219.228 remontmaszyn.pl;
location / {
include proxy_params;
proxy_pass http://unix:/home/lambda/py_env/www/app/fastapi.sock;
}
}
Żeby zacząć korzystać z nowych ustawień dla serwera należy stworzyć link konfiguracji ( dowiązanie symboliczne ) w katalogu sites-enabled nginx.
sudo ln -s /etc/nginx/sites-available/helloworld /etc/nginx/sites-enabled/
Z niewiadomego (wiadomego: literówka ) powodu powyższa komenda nie chciała tym razem działać obszedłem to poprzez:
cd /etc/nginx/sites-enabled/
sudo ln -s ../sites-available/helloworld
ls -l
Rezultat:
total 0
lrwxrwxrwx 1 root root 34 Jul 13 14:35 default -> /etc/nginx/sites-available/default
lrwxrwxrwx 1 root root 29 Jul 15 10:35 helloworld -> ../sites-available/helloworld
Po wszystkich zmianach należy przeprowadzić test składni pliku konfiguracyjnego nginx files:
sudo nginx -t
Jeżeli wszystko jest ok, to można przeładować serwer żeby wczytać nowe ustawienia:
sudo systemctl restart nginx
Jeżeli wszystko poszło ok, to po wejściu na stronę główną pojawi się komunikat…. 502 Bad gateway
. Co oznacza że pora wrócić do konfiguracji Gunicorn.
Uvicorn - finałowe zmiany
Ponieważ strona ma działać na standardowym porcie i być obsługiwana przez NGNIX to finalnie plik service wygląda jak poniżej:
[Unit]
Description=Gunicorn instance daemon to serve FastAPI
After=network.target
[Service]
User=lambda
Group=www-data
WorkingDirectory=/var/www/fastapi_www/app
Environment="PATH=/var/www/fastapi_www/fast_ve/bin"
ExecStart=/var/www/fastapi_www/fast_ve/bin/gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker -b unix:fastapi.sock -m 007
[Install]
WanterBy=multi-user.target
Weryfikacja poprawności działania:
sudo systemctl status fastapi
● fastapi.service - Gunicorn instance daemon to serve FastAPI
Loaded: loaded (/etc/systemd/system/fastapi.service; static; vendor preset: enabled)
Active: active (running) since Thu 2021-04-22 12:13:30 CEST; 5s ago
Main PID: 50936 (gunicorn)
Tasks: 5 (limit: 4656)
Memory: 101.8M
CGroup: /system.slice/fastapi.service
├─50936 /var/www/fastapi_www/fast_ve/bin/python3 /var/www/fastapi_www/fast_ve/bin/gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker -b unix:fastapi.sock -m 007
├─50948 /var/www/fastapi_www/fast_ve/bin/python3 /var/www/fastapi_www/fast_ve/bin/gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker -b unix:fastapi.sock -m 007
├─50949 /var/www/fastapi_www/fast_ve/bin/python3 /var/www/fastapi_www/fast_ve/bin/gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker -b unix:fastapi.sock -m 007
├─50950 /var/www/fastapi_www/fast_ve/bin/python3 /var/www/fastapi_www/fast_ve/bin/gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker -b unix:fastapi.sock -m 007
└─50951 /var/www/fastapi_www/fast_ve/bin/python3 /var/www/fastapi_www/fast_ve/bin/gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker -b unix:fastapi.sock -m 007
Bonus Vue.js
Konfiguracja dla przypadku gdzie w pliku index.html
mamy frontend w Vue.js, a API chcemy przenieść na port 5000
server {
listen 80;
# listen 5000;
listen [::]:80;
root /var/www/html;
index index.html index.htm index.ngnix-debian.html;
server_name 192.166.219.228 remontmaszyn.pl;
location / {
try_files $uri /index.html;
# include proxy_params;
# proxy_pass http://unix:/var/www/fastapi_www/app/fastapi.sock;
}
}
server {
listen 5000;
server_name 192.166.219.228 remontmaszyn.pl;
location / {
proxy_pass http://unix:/var/www/fastapi_www/app/fastapi.sock;
}
}
alternatywnie
server {
listen 80 default_server;
listen [::]:80 default_server;
set $path_front /opt/fake-front;
set $path_api /opt/fake-api;
root $path_front;
index index.html;
server_name _;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
location ~ ^/api/(.+\.php)$ {
index index.php;
root $path_api;
try_files /$1 =404;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_NAME $1;
fastcgi_param SCRIPT_FILENAME $path_api/$1;
fastcgi_param PATH_INFO $fastcgi_path_info;
error_log /var/log/nginx/api.error.log;
access_log /var/log/nginx/api.access.log;
}
location ~ ^/api/(.*) {
index index.php;
root $path_api;
try_files $1 =404 /api/index.php?$args;
error_log /var/log/nginx/api.error.log;
access_log /var/log/nginx/api.access.log;
}
location /favicon.ico {
log_not_found off;
access_log off;
}
location /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location / {
index index.html
root $path_front;
try_files $uri $uri/ /index.php?$args;
error_log /var/log/nginx/front.error.log;
access_log /var/log/nginx/front.access.log;
}
location ~ \.php$ {
index index.php
root $path_front;
try_files $uri =404;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
error_log /var/log/nginx/front.error.log;
access_log /var/log/nginx/front.access.log;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
index index.html
root $path_front;
expires max;
log_not_found off;
error_log /var/log/nginx/front.error.log;
access_log /var/log/nginx/front.access.log;
}
}
Ubuntu 20.04 (remontmaszyn + imion)
server {
root /var/www/html;
index index.html index.htm index.ngnix-debian.html;
server_name imion.eu www.imion.eu;
location / {
root /var/www/html;
try_files $uri $uri/ /index.html;
add_header 'Access-Control-Allow-Origin' 'origin-list';
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_headers_hash_max_size 512;
proxy_headers_hash_bucket_size 128;
}
# location /idd {
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header Host $http_host;
# proxy_http_version 1.1;
# proxy_pass http://unix:/var/www/fastapi_www/app/fastapi.sock;
# }
# location /api {
# include proxy_params;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header Host $http_host;
# proxy_http_version 1.1;
# proxy_pass http://192.166.219.228:5000/api;
# }
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/imion.eu/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/imion.eu/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
root /var/www/api;
index api_index.html;
server_name api.imion.eu www.api.imion.eu;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_pass http://unix:/var/www/fastapi_www/app/fastapi.sock;
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_headers_hash_max_size 512;
proxy_headers_hash_bucket_size 128;
}
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/api.imion.eu/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/api.imion.eu/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
root /var/www/manuto;
index index.html index.htm index.ngnix-debian.html;
server_name remontmaszyn.pl www.remontmaszyn.pl;
location / {
root /var/www/manuto;
try_files $uri $uri/ /index.html;
add_header 'Access-Control-Allow-Origin' 'origin-list';
}
listen 80; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/remontmaszyn.pl/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/remontmaszyn.pl/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.imion.eu) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = imion.eu) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name imion.eu www.imion.eu;
return 404; # managed by Certbot
}
server {
if ($host = api.imion.eu) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name api.imion.eu www.api.imion.eu;
return 404; # managed by Certbot
}
Wdrażanie zmian na serwerze
Ponieważ kod serwisu znajduje się w repozytorium to wszelkie zmiany na serwer można wprowadzać pobierając aktualną wersję z gałęzi master
sudo systemctl stop fastapi
git pull
sudo systemctl start fastapi