Het opzetten van nginx op os-x

Introductie
Nu we bezig zijn met het opzetten van een nieuwe server, vond ik het een mooi moment een oud flask/sqlalchemy weer wat nieuw leven in te blazen. Dit projectje is volgens de git-logs een jaar geleden tot stilstand gekomen, vlak voordat ik een eerste versie in productie wilde zetten. Ik had toen geen zin (want tijd maak je wel als je zin hebt) om uit te zoeken hoe dat exact moest en daarna is het in de dagelijkse drukte ondergesneeuwd.  Maar die nieuwe server was een mooie aanleiding om een maandagavond op te offeren om er eens goed voor te gaan zitten.

Flask en nginx
Flask levert een ingebouwde server mee, maar die is niet geschikt voor productiedoeleinden. Je kunt met mod_wsgi apache wel configureren om flask te serven, maar gebruikelijk is het om hiervoor de server ngnix te gebruiken. Ik had al bedacht dat als ik de applicatie via ngnix op poort 8080 (of zo) zou kunnen laten draaien, dat het dan relatief eenvoudig zou moeten zijn om dat via apache weer door te sluizen (maar dat is voor later zorg).

Voordat ik deze architectuur op de productieserver ging opzetten, wilde ik eerst eens alle noodzakelijke stappen op mijn eigen mac uitproberen en documenteren (en deze blog schrijven). Ik had al geruime tijd geleden een vrij goede tutorial gevonden, maar die is wel bedoeld voor Ubuntu en ook op details wat achterhaald. Dus ben ik zelf maar aan de slag gegaan, met die tutorial als basis.

Vreemd genoeg kon ik geen package manager voor OS-X vinden die ngnix kon downloaden. Zowel pip3 als easy_install als brew gaven aan dat ze geen distributie hiervoor konden vinden. Dus toen maar gewoon de tarball gedownload en zelf de boel installeren. De eerste configuratie ging echter mis, omdat ik iets vergeten was:

./configure --sbin-path=/usr/local/nginx/nginx  --conf-path=/usr/local/nginx/nginx.conf   --pid-path=/usr/local/nginx/nginx.pid   --with-http_ssl_module

./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using --with-pcre=<path> option.

Ook best logisch, want zoals de meeste webservers maakt ook nginx uitgebreid gebruik van reguliere expressies voor rewrite en dergelijke. Het is mogelijk om nginx te installeren zonder pcre, maar het is beter om ze wel mee te nemen. Dus eerst dat maar installeren, waarbij het wel van belang is dat je onthoudt wat je als prefix meegeeft, want die heb je later weer nodig bij de configuratie van nginx zelf:

$ cd pcre-8.41
$ ./configure --prefix=/usr/local
$ sudo make install

Nu kunnen we nginx goed configureren:

$ ./configure  --sbin-path=/usr/local/nginx/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/usr/local/nginx/nginx.pid --with-http_ssl_module --with-pcre=../pcre-8.41
$ make
$ sudo make install

Als je de boel dan wilt opstarten, kun je een foutmelding verwachten: nginx luistert standaard naar poort 80, maar ik heb (zoals de meeste mensen) ook apache al draaien die ook naar die poort luistert:

$ sudo /usr/local/nginx/nginx
nginx: [emerg] bind() to 0.0.0.0:80 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (48: Address already in use)
nginx: [emerg] still could not bind()

Eenvoudig de configuratie aanpassen, waarbij je de poort naar 8080 zet; dan werkt het.

nginx en uWSGI
In principe kan nginx alleen maar statische bestanden serven. Om python uit te kunnen laten voeren en het resultaat daarvan te serven heb je uWSGI nodig. Vreemd genoeg kon ik die wel gewoon met pip3 installeren:

$ pip3 install uwsgi
Collecting uwsgi
Downloading uwsgi-2.0.15.tar.gz (795kB)
100% |████████████████████████████████| 798kB 712kB/s
Installing collected packages: uwsgi
Running setup.py install for uwsgi ... done
Successfully installed  uwsgi-2.0.15
$

Voor deze test had ik een eenvoudige flask applicatie geschreven in de directory /Sites/flask/. Om nginx en uWSGI aan elkaar te knopen, veranderde ik eerst opnieuw het config-bestand van de eerste om hem naar de juiste directory te verwijzen:

server {
  listen       8080;
  server_name  localhost;
  charset utf-8;

  location / { try_files $uri @the_application; }
  location @the_application {
    include uwsgi_params;
    uwsgi_pass unix:/Sites/flask/demoapp_uwsgi.sock;
  }

Nu krijgen we een foutmelding; dat verwachtte ik ook, want dat .sock bestaat nog niet, omdat we uWSGI nog niet geconfigureerd:

De configuratie van uWSGI doen we via een .ini-bestand in de directory waar nginx naar kijkt, dus /Sites/flask/. Hier kopieerde ik voornamelijk de code in die in de tutorial staan, met wat voor zichzelf sprekende aanpassingen. Nu kunnen we de boel opstarten met

sudo uwsgi --ini demoapp_uwsgi.ini

Twee verschillende versies
In principe zou dit moeten werken, maar er gebeurde niks. Pas toen ik de error-logs keek, zag ik dat er bij het opstarten van uWSGI een foutmelding kwam:

ModuleNotFoundError: No module named 'encodings'

Het blijkt dat de python-versie die gelinkt is aan uWSGI dezelfde moet zijn als de versie die op het os draait. Stom genoeg draai ik nog standaard 2.7 (hoewel ik alles allang in 3.6 doe). Het makkelijkste is om even een virtuele omgeving op te zetten met de juiste python-versie en dan van daaruit uWSGI op te starten. Het enige is dat ik dan alle dependencies daar weer in moet installeren, maar dat is voorlopig alleen Flask dus dat valt wel mee.

$ source venv/bin/activate
(venv) argentina-minor:flask bart$ sudo uwsgi --ini demoapp_uwsgi.ini
Password:
[uWSGI] getting INI configuration from demoapp_uwsgi.ini

Nu hebben we eindelijk het gewenste resultaat (let op het poortnummer):

De volgende stap
De volgende stap is dit alles als achtergrondproces te laten draaien, maar dat is een volgend projectje. Ik ga eerst proberen deze zelfde stappen op de productieserver uit te voeren.

Comments (2)

  1. Jos

    Goed zo Bart! Nu de stappen in script en dan ben je al aardig op weg naar een positie binen het NSE team 😉

Leave a comment

Your email address will not be published. Required fields are marked *