Budujemy własny serwer do programowania w R i Pythonie, razem z serwerem WWW, PHP oraz bazami danych MySQL i PostgreSQL.
Tym razem więcej administrowana serwerami, a mniej programowania i analizowania danych. Zbudujemy własny serwer do programowania w R i Pythonie, razem z serwerem WWW (aby móc prezentować wynik swoich prac).
Opis środowiska
W niniejszym wpisie przygotujemy serwer zbudowany na linuxie w dystrybucji Ubuntu z działającym na nim (i dostępnym przez przeglądarkę z dowolnego miejsca z internetem) RStudio. Serwer pozwoli nam też na budowanie i publikowanie aplikacji napisanych w Shiny. Przy okazji zainstalujemy Pythona razem z Jupyter Notebook (oraz JupyterLab) do wygodnej pracy. Całości dopełni baza danych PostgreSQL. Aby móc publikować swoje dzieła w formie bloga zainstalujemy PHP oraz bazy MySQL – być może zechcesz zainstalować WordPressa, a on tego wymaga.
Do czego taka maszyna może się przydać? W zależności od wydajności:
- Mały serwer swobodnie może posłużyć do nauki programowania (R, Python, PHP), prowadzenia własnego blogaska (na przykład o programowaniu).
- Duża maszyna (dużo RAMu, dużo procesorów, wszystkiego dużo) to już kwestia wyobraźni. Ja na przykład wyobrażam sobie działający w PHP jakiś serwis udostępniający użytkownikom w czasie (prawie) rzeczywistym informacje zebrane przy pomocy Pythona z wielu miejsc sieci, przetworzone na przykład modelami opartymi o TensorFlow (też w Pythonie) i ubranymi w wykresy (narysowane w R + ggplot) wyeksportowane do statycznych plików, które później są pokazywane w ramach prezentacji treści (przez tego początkowego PHPa).
- Wszystko jedno jaki serwer, ważne żeby był online przez 24h/dobę – wówczas nie musimy zostawiać komputera na noc (albo kilka dni) włączonego żeby się coś przeliczyło. Albo jeśli zbieramy każdego dnia jakieś dane z jakiegoś serwisu (zbierałem tak dane o Veturilo, teraz zbierają się dane o wycieczkach do Grecji) albo mamy jakieś boty (na przykład mój twitterowy rstatspl).
Wszystko jednak musi mieć swój początek. Najpierw
Zakupy
Kupujemy domenę
Skorzystałem z NameSilo bo chciałem dziwaczną domenę, a w dodatku jak najtaniej – być może tylko na potrzeby tego wpisu. Liczę się z tym, że zostanę przy niej przez kilka lat, stąd wybór po cenie odnowienia domeny, nie interesowały mnie domeny za 0 zł. W każdym razie domenę można kupi w dowolnym miejscu (w dowolnym sklepie z domenami rzecz jasna), ważne jest aby mieć dostęp do panelu konfiguracyjnego domeny, a ten w NameSilo umożliwia wiele chociaż jest mało intuicyjny. Na razie tylko kupujemy i niczego nie robimy. Mamy, cieszymy się.
Kupujemy VPSa
Tutaj sprawa jest już trudniejsza. Nie będę zbytnio zanudzał: trzeba znaleźć serwer odpowiedni do swoich potrzeb. Najlepiej z możliwością łatwej rozbudowy. Może być 1 procesor (core), 1 GB RAMu i 10 GB dysku (mniej według mnie nie ma sensu – to co instalujemy w dzisiejszym odcinku zjada jakieś 8 GB dysku, a jest to gołe środowisko pracy), może być i takie f1.16xlarge z Amazona (64 core, 976 GB pamięci i 4x 940 dysku). Może być z Azure czy Google (takie na przykład 96 core, 624 GB pamięci, 8 GPU Tesla V100 i 3x 375 GB dysku) – bagatelka, jakieś 13.5 tys. dolarów miesięcznie w Google Cloud). Może być z OVH, wszystko jedno. Jedyne czego trzymamy się w tym wpisie to publiczne stałe IP, prawa roota i dostęp przez SSH.
Równie dobrze może to być goły Linux (tutaj: Ubuntu) zainstalowany na przykład na komputerze stojącym gdzieś w naszej piwnicy albo nawet jako maszyna wirtualna na laptopie (działająca wtedy, kiedy jest włączona. Rozwiązanie do nauki w sam raz, do pracy już raczej nie bardzo).
Ja skorzystałem z webh, czytając raczej dobre opinie w sieci i widząc atrakcyjną cenę. Jeśli się zdecydujesz na tego dostawcę skorzystaj proszę przy zakupie z podanego linku albo kodu promocyjnego PROMO25475.
Konfigurujemy VPSa
Wyklikujemy więc u naszego dostawcy nasz serwer (jego parametry), płacimy i po kilku minutach maszyna powinna być gotowa. Dostawca napisze nam (w jakiś sposób, to zapewne zależy już od dostawcy) jak się do maszyny dostać (jej IP i hasło do roota).
Logowanie i SSH
W pierwszej kolejności potrzebujemy klienta SSH – dla Windows jest to na przykład PuTTy. Ściągamy, instalujemy, uruchamiamy, konfigurujemy połączenie do naszego serwera.
Tworzymy użytkownika o uprawnieniach roota
Tworzymy użytkownika, w przykładzie będzie to lemur
.
1 |
adduser lemur |
Ubuntu zapyta nas przede wszystkim o hasło do nowego konta i kilka innych informacji.
W następnej kolejności dodajemy nowemu użytkownikowi prawa roota (a tak na prawdę pozwalamy mu korzystać z sudo
czyli uruchamiać komendy z konsoli z prawami roota):
1 |
gpasswd -a lemur sudo |
Teraz możemy się wylogować z konta roota (i już do niego nie wracać) i zalogować się na utworzone konto. To na nim działamy w dalszym ciągu.
Update serwera
Warto na początek sprawdzić czy Ubuntu jest aktualne, a jeśli trzeba – niech się zaktualizuje:
1 2 |
sudo apt-get update sudo apt-get upgrade |
W zależności od dostawcy VPSa może coś się zaktualizować, ale nie musi. W przypadku mojego dostawcy system był aktualny. Warto co jakiś (na przykład raz w miesiącu, można to wrzucić w cron
a) czas powtarzać powyższe komendy.
Ze względów bezpieczeństwa dobrze jest wyłączyć dostęp do serwera przez SSH dla użytkownika root
. Logujemy się więc na nasz serwer (nowo utworzonym kontem) i przechodzimy do konfiguracji SSH:
1 |
sudo nano /etc/ssh/sshd_config |
Może okazać, się że nie mamy zainstalowanego nano
(to edytor tekstu wygodny i dla laików prostszy w obsłudze niż na przykład vi
) – wówczas go instalujemy:
1 |
sudo apt-get install nano |
Po ewentualnej instalacji możemy przejść do edycji. Aby zablokować dostęp dla root
a po SSH odnajdujemy w pliku /etc/ssh/sshd_config
linię
1 |
PermitRootLogin yes |
i zmieniamy na
1 |
PermitRootLogin no |
Zapisujemy plik i restartujemy serwer SSH:
1 |
sudo service ssh restart |
To wszystko. Jeśli zajdzie potrzeba zalogowania się na konto roota poprzez SSH zawsze możemy powtórzyć powyższe kroki i umożliwić logowanie (zmieniając PermitRootLogin
na yes
w pliku /etc/ssh/sshd_config
i restartując SSH).
DNS
Konfiguracja DNS to nadanie naszemu serwerowi konkretnej nazwy (na razie mamy tylko IP) i umożliwienie dotarcia do serwera (w internecie) poprzez nazwę a nie numerek. W panelu domeny wskazujemy adres IP naszego serwera, a firma rejestrująca domeny zapewni nam, że ktoś wpisując nasza.domena
na przykład w przeglądarce trafi na odpowiedni serwer. A co będzie pod tym numerkiem to już nasza sprawa. Ta cześć konfiguracji zależy od konkretnego dostawcy domeny. Robimy to dla każdej subdomeny, wszystkie kierujemy na jeden adres – rozdzieleniem ruchu zajmiemy się po swojej stronie. W dużym uproszczeniu:
- w rekord typu A wpisujemy nasz IP
- w rekordy typu CNAME wpisujemy z jednej strony subdomenę, a z drugiej – domenę (czyli np. rstudio i nasza.domena)
- w rekordy typy MX rzeczy związane z pocztą, ale można też (NameSilo to umożliwia) przekierować pocztę na poziomie DNSów, bez budowania serwera pocztowego
Wydelegowanie domeny na adres IP może trochę potrwać, więc nie przejmuj się jeśli kolejne kroki nie będą działać od razu. W NameSilo było to… kilkanaście minut (kiedyś to i dwa dni się czekało).
Możemy zmienić też nazwę hosta, czyli to pod jaką nazwą system widzi sam siebie. Wystarczy edycja pliku
1 |
sudo nano /etc/hostname |
Wpisana tam nazwa serwera nie powinna zawierać kropki – najlepiej niech będą to same literki i ewentualnie cyferki. Aby zmiany odniosły skutek resetujemy usługę hostname:
1 |
sudo /etc/init.d/hostname.sh start |
Serwer WWW – konfiguracja
Zaczynamy od zainstalowania serwera WWW – w tym przypadku będzie to Nginx.
1 |
sudo apt-get install nginx |
Po chwili wpisanie w przeglądarce http://nasza.domena (o ile DNSy już kierują na nasz serwer – jeśli nie podaj numer IP) powinno wyświetlić coś na kształt:
Sam serwer jeszcze będziemy konfigurować, więc na razie przechodzimy dalej i instalujemy serwer MySQL, który będzie potrzebny na przykład WordPressowi. Sprawa znowu jest prosta:
1 |
sudo apt-get install mysql-server |
To trochę większa rzecz, potrwa więc dłużej. Po drodze zostaniemy poproszeni na przykład o hasło roota dla bazy danych. Zapisz je sobie, bo zapomnisz i będzie problem. Ogólnie wszystkie hasła sobie zapisuj i niech każde będzie inne, mocno skomplikowane (z 15 znaków, duże i małe litery, cyfry i znaki specjalne).
Ostatni krok to PHP, w którym napisana jest duża cześć stron. Nginx nie posiada wewnętrznego procesora PHP trzeba więc zainstalować php-fpm
. Przy okazji zainstalujemy dodatkowy pakiet dla PHP do komunikacji z MySQL oraz kilka innych przydatnych bibliotek.
1 |
sudo apt-get install php-fpm php-mysql php-curl php-gd php-mbstring php-mcrypt php-xml php-xmlrpc |
Instalacja była prosta, z konfiguracją trochę więcej pracy. Przede wszystkim musimy skonfigurować PHP. W pliku /etc/php/7.0/fpm/php.ini
potrzebujemy ustawić parametr cgi.fix_pathinfo
na 0, co z poziomu konsoli robimy:
1 |
sudo nano /etc/php/7.0/fpm/php.ini |
i znajdujemy odpowiednią linię w edytorze (będzie zakomentować średnikiem i z wartością ustawioną na 1), a później zapisujemy plik. Po poprawce resetujemy serwer PHP:
1 |
sudo systemctl restart php7.0-fpm |
Teraz jeszcze musimy serwerowi WWW (nasz Nginx) powiedzieć co ma robić z plikami *.php. Najważniejsza cześć pliku /etc/nginx/sites-available/default
(po usunięciu komentarzy) wygląda tak:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name _; location / { try_files $uri $uri/ =404; } } |
Na szczęście wszystko czego potrzebujemy jest wpisane w konfiguracji i wystarczy zdjąć komentarze. Docelowo interesujące nas fragmenty powinny wyglądać tak:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html; index index.php< index.html index.htm; server_name _; location / { try_files $uri $uri/ =404; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.0-fpm.sock; } location ~ /\.ht { deny all; } } |
Restartujemy serwer Nginx (nie ostatni raz):
1 |
sudo systemctl reload nginx |
i PHP działa! Jak to sprawdzić? Stworzymy prosty plik info.php
, który umieścimy w folderze serwera www, czyli /var/www/html
(to wynika z konfiguracji wyżej)
1 2 3 |
<?php phpinfo(); ?> |
Możemy wejść na http://nasza.domena/info.php i powinniśmy dostać informacje o PHP:
To co widać na stronie (wynik PHPowego phpinfo()
) lepiej ukryć przed niepowołanymi osobami, zatem skasujmy ten plik:
1 |
sudo rm /var/www/html/info.php |
R, RStudio i Shiny
Czas na najbardziej oczekiwany kawałek – przygotowanie środowiska do programowania w R razem z Shiny.
Instalujemy R
Postępujemy zgodnie z instrukcją na CRANie:
- generujemy klucz szyfrujący
1 2 |
sudo apt-key adv –keyserver keyserver.ubuntu.com –recv-keys E084DAB9 gpg -a --export E084DAB9 | sudo apt-key add - |
- dodajemy repozytorium dla apt-get
1 |
sudo add-apt-repository 'deb https://cloud.r-project.org/bin/linux/ubuntu xenial/' |
jeśli dostaniemy informację, że to polecenie nie jest znane trzeba doinstalować mały pakiecik:
1 |
sudo apt-get install software-properties-common |
i powtórzyć
1 |
sudo add-apt-repository 'deb https://cloud.r-project.org/bin/linux/ubuntu xenial/' |
A dalej już tylko pozostaje instalacja R – identyczna jak właściwie każdego programu na Ubuntu:
1 2 3 |
sudo apt-get update sudo apt-get install r-base sudo apt-get install r-base-dev |
Teraz w konsoli możemy po prostu wpisać nasze ukochane R
i…
Gotowe!
Instalujemy RStudio
RStudio nie znajdziemy w repozytoriach Ubuntu, musimy więc pobrać pakiet instalacyjny ze strony RStudio:
1 2 3 4 |
sudo apt-get install gdebi-core wget https://download2.rstudio.org/rstudio-server-1.1.453-amd64.deb sudo gdebi rstudio-server-1.1.453-amd64.deb rm rstudio-server-1.1.453-amd64.deb |
Po tych czterech linijkach możemy w przeglądarce wpisać http://nasza.domena:8787 i cieszyć się świeżym RStudio na własnym serwerze. Fragment rstudio-server-1.1.453-amd64.deb
to odpowiednia wersja, która może się z czasem zmieniać – warto sprawdzi na stronie RStudio.com co tam jest aktualnie. To samo odnosi się do Shiny. Możemy również użyć wersji beta dziennych – linki znajdziecie na odpowiedniej stronie.
Instalacja przydatnych pakietów
Na początek warto zainstalować wszystkie przydatne pakiety. Kilka z tych, które instaluję zazwyczaj:
- stringi
- stringr
- tidyverse
- readr
- readxl
- XML
- jsonlite
- tidytext
- forecast
- caret
- e1071
- odbc
- xts
- zoo
Czyli odpalamy z konsoli R (wpisując po prostu R
), a potem to co już doskonale znamy:
1 |
install.packages(c("stringi", "stringr", "tidyverse", "readr", "readxl", "XML", "jsonlite", "tidytext", "forecast", "caret", "e1071", "odbc", "xts", "zoo")) |
Idziemy na piwo. Ale zanim to zrobimy trzeba zainstalować kilka bibliotek systemowych, gdyż instalacja kilku pakietów się nie uda. Instalujemy zatem:
1 |
sudo apt-get install libxml2-dev libssl-dev unixodbc-dev libcurl4-openssl-dev libudunits2-dev |
Warto też zainstalować Javę:
1 2 |
sudo apt-get install default-jre sudo apt-get install default-jdk |
I dopiero teraz instalujemy co potrzebne z poziomu R:
1 |
install.packages(c("stringi", "stringr", "tidyverse", "readr", "readxl", "XML", "jsonlite", "tidytext", "forecast", "caret", "e1071", "odbc", "xts", "zoo")) |
Instalujemy Shiny
W pierwszej kolejności musimy zainstalować pakiet shiny
w R na prawach roota, zatem:
1 |
sudo R -e "install.packages(c('shiny', 'rmarkdown', 'devtools', 'RJDBC'), repos='http://cran.rstudio.com/')" |
w drugiej kolejności – zainstalować sam serwer, znowu ściągając instalkę:
1 2 3 4 |
sudo apt-get install gdebi-core wget https://download3.rstudio.org/ubuntu-14.04/x86_64/shiny-server-1.5.7.907-amd64.deb sudo gdebi shiny-server-1.5.7.907-amd64.deb rm shiny-server-1.5.7.907-amd64.deb |
Po instalacji wchodzimy na http://nasza.domena:3838 i sprawdzamy czy wszystko działa. Jeśli nie działa – patrzymy w logi z folderu /var/log/shiny-server/
i zastanawiamy się co zrobić. Najczęściej przyczyną problemów są uprawnienia do folderów lub brak bibliotek. Serwer Shiny działa na użytkowniku shiny
, ale możemy to zmienić w jego konfiguracji, w pliku /etc/shiny-server/shiny-server.conf
1 |
sudo nano /etc/shiny-server/shiny-server.conf |
i zmieniamy
1 |
run_as shiny; |
na naszego użytkownika:
1 |
run_as lemur; |
gdzie lemur
to nasz użytkownik. Ja używam sam swojego serwera, więc mogę sobie na to pozwolić. Ale jeśli mamy wielu użytkowników R, każdy z własnym kontem to musimy się na jakieś zdecydować. Albo zainstalować odpowiednie pakiety R-a dla użytkownika shiny
. To jest niestety upierdliwe w systemach linuxowych.
Po zmianach w konfiguracji serwera trzeba go zrestartować, aby załapał nowe ustawienia:
1 |
sudo systemctl restart shiny-server |
Konfiguracja serwera Shiny
Gdzie będą trzymane aplikacje? Standardowo w folderze /srv/shiny-server/
co wynika z wpisu w pliku /etc/shiny-server/shiny-server.conf
. Jeśli potrzebujemy – możemy to zmienić. Możemy zmienić również port na którym działa serwer. Pamiętać jednak należy, żeby później odpowiednio dostosować konfigurację subdomen w Nginxie (o tym za chwilę). Ja u siebie zostawiłem bez zmian.
Ale nie samym R żyje człowiek, przyda się też
Python i Jupyter
Instalujemy Pythona
a może jest zainstalowany? Ubuntu 16.04 na dzień dobry przychodzi z Pythonem 2.7 oraz Pythonem 3.5 (w odpowiednich podwersjach):
1 |
python3 -V |
Jeśli chcemy Pythona 3.6 to wykonujemy trzy kolejne linie:
1 2 3 |
sudo add-apt-repository ppa:jonathonf/python-3.6 sudo apt-get update sudo apt-get install python3.6 |
W tym momencie mamy w systemie trzy wersje Pythona:
- python – uruchomi nam wersję 2.7,
- python3 – wersję 3.5,
- a python3.6 – 3.6
Jeśli chcemy móc wybierać z której wersji (3.5 czy 3.6) korzystać będzie polecenie python3
wykonujemy dwa polecenia:
1 2 |
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.5 1 sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 2 |
Teraz możemy się przełączać między wersjami z użyciem
1 |
sudo update-alternatives --config python3 |
Ja wybrałem jako domyślną wersję 3.5, więc po
1 |
python3 -V |
widzę Python 3.5.2
. Uwaga – na wybranej wersji zainstalowany zostanie za kilka chwil Jupyter, więc wybierz mądrze :)
Instalujemy pip dla Pythona 3:
1 |
sudo apt-get install python3-pip |
Kilka bibliotek systemowych może być koniecznych, zatem zainstalujmy je już teraz (podobnie jak w przypadku instalowania pakietów do R):
1 |
sudo apt-get install build-essential libssl-dev libffi-dev python-dev |
Biblioteki Pythona
Warto na początek zainstalować kilka podstawowych:
- numpy
- pandas
- nltk
- matplotlib
- SciPy
- Seaborn
- SciKit-Learn
- Statsmodels
- TensorFlow
- Keras
Pytanie tylko czy od razu, dla własnego użytkownika czy też tworzyć środowiska wirtualne Pythona? To już pozostawiam Wam do decyzji. Tutaj jedziemy po bandzie, bez żadnych środowisk wirtualnych i wszystkie kolejne biblioteki instalujemy przez
1 |
sudo -H pip3 install nazwa_biblioteki |
Instalujemy Jupyter
Jupyter to taka zubożona wersja RStudio. Lepsze to niż Python z konsoli – widać przynajmniej krok po kroku co się dzieje w kodzie. Poza tym wszyscy z niego korzystają ;)
1 2 |
sudo apt-get install ipython ipython-notebook sudo -H pip3 install jupyter |
Pierwszy krok przygotowania do normalnego funkcjonowania to zbudowanie domyślnego pliku konfiguracyjnego:
1 |
jupyter notebook --generate-config |
Teraz wygenerujemy hasło dostępu do Jupytera:
1 |
jupyter notebook password |
Uruchamiamy Jupytera
1 |
jupyter notebook |
Wystarczy w tym momencie przejść na stronę http://nasza.domena:8888, zalogować się utworzonym hasłem i możemy działać w Pythonie!
Zamknijmy go jednak i zainstalujemy JupyterLab. Zamknąć można z konsoli (Ctrl-C) lub z przeglądarki (guzik Quit).
instalujemy JupyterLab
1 |
sudo -H pip3 install jupyterlab |
Po instalacji uruchamiamy JupyterLab:
1 |
jupyter lab |
Teraz po wejściu na http://nasza.domena:8888 powinien uruchomić się JupyterLab, a po wejściu na http://nasza.domena:8888/tree – Jupyter. Możemy ponownie zamknąć Jupytera i uruchomić go w tle:
1 |
jupyter lab & |
Zwróć uwagę na &
na końcu linii.
To jednak wymaga uruchamiania Jupytera ręcznie, po każdym restarcie serwera. Możemy to zmienić dopisując do pliku /etc/rc.local
następującą linijkę (odpowiednio zmieniając ścieżki plików):
1 |
su <username> -c "jupyter notebook --config=/location/of/your/config/file/.jupyter/jupyter_notebook_config.py --no-browser --notebook-dir=/location/of/yournotebooks" & |
Ważne: to musi być dopisane przed linijką z exit 0
. Dodanie tej linii spowoduje, że http://jupyter.nasza.domena otworzy Jupytera – aby korzystać z JupyterLab uruchamiamy http://jupyter.nasza.domena/lab. W miejsce wpisujemy oczywiście naszego użytkownika.
Subdomeny – konfiguracja
- nasza.domena oraz www.nasza.domena – strona WWW na standardowym porcie 80
- rstudio.nasza.domena – RStudio, na porcie 8787
- shiny.nasza.domena – serwer Shiny, na porcie 3838
- jupyter.nasza.domena – Jupyter Notebook, na porcie 8888
Całość opiera się na konfiguracji Nginxa. Dobrym dla nas jest to, że wszystkie usługi działają na oddzielnych portach – będzie bardzo łatwo przekierować je na subdomeny.
W folderze /etc/nginx/sites-enabled
tworzymy sobie pliki dla każdej subdomeny. Różnić będą się w trzech miejscach:
- linii czwartej podajemy subdomenę
- w liniach 7 i 8 odpowiedni port
Przykład dla RStudio (plik /etc/nginx/sites-enabled/rstudio.conf
):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
server { listen 80; server_name rstudio.nasza.domena; location / { proxy_pass http://localhost:8787; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $http_host; proxy_http_version 1.1; proxy_redirect off; proxy_buffering off; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 86400; } } |
Co to robi? Nasłuchuje portu 80 na adresie rstudio.nasza.domena i przekierowuje ruch na port 8787 (czyli RStudio).
Dla Shiny (plik shiny.conf
):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
server { listen 80; server_name shiny.nasza.domena; location / { proxy_pass http://localhost:3838; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $http_host; proxy_http_version 1.1; proxy_redirect off; proxy_buffering off; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 86400; } } |
Dla Jupytera jest nieco inaczej:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
server { listen 80; server_name jupyter.nasza.domena; location / { proxy_pass http://localhost:8888; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $http_host; proxy_http_version 1.1; proxy_redirect off; proxy_buffering off; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 86400; } location ~ /api/kernels/ { proxy_pass http://localhost:8888; proxy_set_header Host $host; # websocket support proxy_http_version 1.1; proxy_set_header Upgrade "websocket"; proxy_set_header Connection "Upgrade"; proxy_read_timeout 86400; } location ~ /terminals/ { proxy_pass http://localhost:8888; proxy_set_header Host $host; # websocket support proxy_http_version 1.1; proxy_set_header Upgrade "websocket"; proxy_set_header Connection "Upgrade"; proxy_read_timeout 86400; } } |
Po przygotowaniu wszystkich plików konfiguracyjnych restartujemy serwer Nginx:
1 |
sudo systemctl reload nginx |
Teraz wpisując w przeglądarce http://rstudio.nasza.domena powinniśmy trafić do RStudio, zaś http://shiny.nasza.domena – do głównego folderu z aplikacjami Shiny. Nadal zadziała http://nasza.domena:8787 dla RStudio (serwer obsłuży to bez przekierowania). Dla Jupytera mamy http://jupyter.nasza.domena, dla JupyterLab http://jupyter.nasza.domena/lab.
Kolejne aplikacje umieszczamy w folderach /srv/shiny-server/
, np. /srv/shiny-server/nasza_apka
i poprzez http://shiny.nasza.domena/nasza_apka trafimy tam gdzie trzeba, uruchamiając aplikację. Jeśli nie posprzątaliśmy folderu /srv/shiny-server/
to http://shiny.nasza.domena/sample-apps/hello/ uruchomi przykładową.
Dodatki
GitHub
Przyda nam się git
chociażby po to, aby na GitHubie trzymać swoje pliki źródłowe.
1 |
sudo apt-get install git |
git
a musimy też skonfigurować:
1 2 |
git config --global user.name "user_name" git config --global user.email "email_id" |
W “user_name” i “email_id” wprowadzamy dane swojego konta na GitHubie.
PostgerSQL
Mamy zainstalowaną bazę MySQL, ale możemy z różnych powodów chcieć korzystać z PostgreSQL.
Instalacja jest prosta i analogiczna do wszystkich wcześniejszych:
1 |
sudo apt-get install postgresql postgresql-contrib |
PostgreSQL działa w oparciu o role, a po instalacji istnieje tylko rola postgres
. Warto stworzyć nową – uruchamiamy psql
dla istniejącej roli:
1 |
sudo -u postgres psql |
A następnie tworzymy bazę danych, użytkownika (razem z hasłem) i nadajemy mu uprawnienia do stworzonej bazy:
1 2 3 |
CREATE DATABASE nazwa_bazy_danych; CREATE USER nazwa_użytkownika WITH ENCRYPTED PASSWORD 'hasło_użytkownika'; GRANT ALL PRIVILEGES ON DATABASE nazwa_bazy_danych TO nazwa_użytkownika; |
Teraz (działając na naszym standardowym loginie) możemy uruchomi psql
łącząc się z nową bazą (na razie pustą):
1 |
psql -d nazwa_bazy_danych |
Po połączeniu się z bazą, już z poziomu pqsl
możemy utworzyć sobie stosowne tabele, od dla przykładu (z jakiegoś tutoriala):
1 2 3 4 5 6 7 |
CREATE TABLE playground ( equip_id serial PRIMARY KEY, type varchar (50) NOT NULL, color varchar (25) NOT NULL, location varchar(25) check (location in ('north', 'south', 'west', 'east', 'northeast', 'southeast', 'southwest', 'northwest')), install_date date ); |
Czy tabela powstała? Będąc nadal w psql
sprawdzamy to wpisując \d
co powinno dać wynik typu:
1 2 3 4 5 6 7 8 9 |
baza=# \d List of relations Schema | Name | Type | Owner --------+-------------------------+----------+------- public | playground | table | lemur public | playground_equip_id_seq | sequence | lemur (2 rows) baza=# |
Wpisując \q
możemy wyjść z PostgreSQL. Wcześniej możemy usunąć testową tabelę:
1 |
DROP TABLE playground; |
Oczywiście na bazę danych możemy mieć inny serwer niż na resztę – oszczędzamy wówczas miejsce na aplikacje. Podobnie z plikami statycznymi. Ale to już robi się małą farma ;)
Serwer FTP
Po co nam serwer FTP? Chociażby po to, aby w prosty sposób przekazywać pliki na serwer (lub z niego je pobierać). Konfiguracja jest szybka i dość prosta. Najpierw oczywiście instalacja:
1 |
sudo apt install vsftpd |
Serwer już działa. Warto jeszcze ograniczyć dostęp dla użytkowników tylko do ich domowych folderów oraz pozwolić im na zapis plików, zatem zdejmujemy komentarz z linii:
1 2 |
chroot_local_user=YES write_enable=YES |
oraz dodać
1 2 |
allow_writeable_chroot=YES hide_file=NO |
w pliku /etc/vsftpd.conf
. Po zmianach oczywiście restart serwera:
1 |
sudo systemctl restart vsftpd.service |
Ograniczenie dostępu do folderów to zwiększenie bezpieczeństwa (na przykład żeby nikt nie skasował przez przypadek produkcyjnych plików z serwera www albo Shiny). Zawsze można pliki przerzucić do folderu w domku użytkownika, a następnie – już z konsoli – podmienić pliki.
Serwer działa w trybie passive
– to może być istotne w konfiguracji klienta FTP.
rgdal
Jeśli chcemy wykorzystywać mapy i pliki SHP to przyda nam się biblioteka rgdal
(w R). Ta zaś łatwo się nie zainstaluje bo najnowsza wersja wymaga gdal w wersji >= 1.11.4, a domyślnie w repozytoriach mamy wersję niższą. Podobnie jak wcześniej – trzeba zainstalować coś w systemie zanim zainstalujemy pakiet w R:
1 2 3 4 5 |
sudo add-apt-repository -y ppa:ubuntugis/ppa sudo apt-get updatae sudo apt-get upgrade sudo apt install libgdal1-dev libproj-dev gdal-bin python-gdal python3-gdal sudo apt-get install libgdal-dev libgdal20 |
Teraz już rdgal uda się zainstalować – skorzystaliśmy z innego repozytorium, gdzie jest nowsza wersja biblioteki systemowej gdal
. Przy okazji instalując co trzeba dla Pythona.
LaTeX/Pandoc
Jeśli chcesz generować raporty w plikach PDF korzystając z rmarkdown to potrzebujesz LaTeXa i pandoc. Do renderowania plików LaTeXa polecam xetex
1 2 |
sudo apt-get install pandoc sudo apt-get install texlive-xetex |
W konfiguracji RStudio trzeba wybrać “Typeset LaTeX info PDF using: XaLaTeX”. Powinno zadziałać.
Teraz taki hint – rozwiązanie problemu, z którym walczyłem pół dnia próbując renderowac raporty skryptami odpalanymi cyklicznie z cron
a. W przypadku renderingu plików do LaTeXa/PDFa uruchamianych z konsoli (np. przez Rscript
) odpowiednio musimy ustawić zmienną środowiskową RSTUDIO_PANDOC (domyślnie ma wartośc /usr/lib/rstudio-server/bin/pandoc
). Zatem na początku skryptu R uruchamianego z konsoli wpisujemy:
1 |
Sys.setenv(RSTUDIO_PANDOC = "/usr/lib/rstudio-server/bin/pandoc") |
i sprawa załatwiona – rmarkdown::render()
działa jak należy.
WordPress
Przygotowane środowisko gotowe jest na przyjęcie na przykład WordPressa (na którym można postawić stronę www). Proces instalacji świetnie opisuje post w serwisie Hostovia.pl – całość jest prosta i sprowadza się do kilku (może dziesięciu) kroków.
Hugo
Zamiast pisać blogaska w WordPressie możemy zechcieć skorzystać np. z Hugo, czyli silnika do generowania stron statycznych, których całą treść można trzymać w plikach Markdown i renderować całe serwisy. To bardzo popularne w środowisku użytkowników R. Szczegóły instalacji znajdziecie na stronie GoHugo.io.
Koniec
Na koniec tego wszystkiego możemy zresetować serwer, zobaczyć czy ruszy i czy wszystkie nasze usługi działają poprawnie. Aby zresetować maszynę wpisujemy w konsoli:
1 |
sudo shutdown -r 0 |
Jeśli nie – szukamy w sieci dlaczego nie działa i co trzeba poprawić ;). Co warto sprawdzić?
- czy RStudio uruchamia się w przeglądarce?
- czy można zainstalować nowe pakiety z poziomu RStudio?
- czy pliki RMarkdown renderują się do HTMLa i PDFa?
- czy Jupyter i JupyterLab otwierają się w przeglądarce?
- czy kernele w obu Jupyterach działają (czy działa Python)?
- w jakiej wersji jest Python w Jupyterach? Do tego wystarczy wpisać w nowym notatniku Jupytera/JupyterLaba:
1 2 |
import sys print(sys.version) |
- czy FTP działa – czy można się do niego dostać, ściągnąć i zapisać pliki?
- czy można połączyć się z bazami danych – MySQL i PostgreSQL? Najlepiej też z poziomu R i Pythona
- jeśli instalowaliśmy WordPressa – czy działa sama strona oraz panel administracyjny?
- czy działa Git? Też z poziomu RStudio (bo to wygodne)?
- czy działa PHP i odpowiednie biblioteki (jak działa WordPress to raczej tak)
U mnie działa, chociaż było trochę klikania i szukania. Ale uzupełniałem też niniejszy wpis, więc powinien być kompletny.
Mam nadzieję, że zebranie wszystkiego w jednym miejscu ułatwi Wam przygotowanie środowiska. Jeśli jednak napotkacie na jakieś problemy – szukajcie sami. Nie jestem administratorem serwerów i w sumie nie zamierzam nim być. Uważam jednak, że data scientist powinien potrafić zrobić kilka rzeczy w systemie Linuxowym, coś w konsoli bazy danych czy też proste rzeczy związane z konfiguracją serwera WWW (domeny, przekierowania). Do nauki tego typu rzeczy własny serwer (lub komputer w piwnicy jak wspomniałem na początku) jest najlepszym rozwiązaniem.
Przy pisaniu tego postu posiłkowałem się cennymi źródłami wiedzy, przede wszystkim serią Konfigurujemy VPS z Notatnika Marcina Kasperskiego.
Dobra robota!
Dobry wpis! Zastanawiam się czy 1vCPU (plan mini) na początek zabawy z danymi wystarczy. Na chwilę obecną przerabiam podstawowe zagadnienia uczenia maszynowego w pythonie, póki co GPU nie używam. Masz może jakieś info o wydajności na webh?
The Real Person!
The Real Person!
Nie badałem wydajności. Na pewno na początek zabawy z danymi 1 CPU daje radę. Jeśli coś pójdzie znośnie na laptopie i3 z 4 GB RAM to pójdzie też na takim serwerze.
Bardzo ciekawy wpis, natomiast jest to droga dla prawdziwych twardzieli czyli budowanie środowiska z ustawień od zera. A masz może wiedzę gdzie można skorzystać z gotowej chmurowej platformy do tworzenia / deployment’u typu Heroku ale bardziej w Europie/ PL ?
The Real Person!
The Real Person!
Spróbuj AWS z obrazem RStudioAMI
Tak jeszcze pomyślałem, do pythona i dodatków można dołączyć skrypt jaki proponuje Vladimir. Wtedy to już bedzie kosmos.
Dzięki za wpis. Czy przy konfiguracji subdomen trzeba je dodawać u dostarczyciela domeny?
The Real Person!
The Real Person!
Tak, w DNS domeny dodaje się wpisy CNAME kierujące na podstawowy serwer.
Dziękuję, lata temu dodawałem subdomeny, a ta opcja na OVH jest nieźle schowana.
Pingback: Google Analytics w R | Łukasz Prokulski
Spoko blog!
Co do uruchamiania demow polecam uzyc tego https://webinsider.pl/linux-autostart/
co do ftp, to ja bym go calkiem wylaczyl/skasowal i dane wysylal na serwer scp a pobieral przez www, zamiast putty polecam MobaXterm
dodatkowo polecam zainstalwac fail2ban tak na wszelki wypadek lepiej miec, niz nie miec
ps. i czy nie zastanawiales sie na opakowaniem tego calego srodowiska w technologie docker?
pozdro i czekam na kolejne wisy :)
Dockera „macam” dopiero na lokalnych maszynach, więc to potrwa. Ale może zakończyć się serią wpisów na ten temat (no, może jednym dużym – dobra seria jest tutaj).
OK, dziki za link nie znalem