Introduktion till Nginx

Nginx

Om den duger åt Facebook, Instagram, Dropbox, Netflix, WordPress.com och NASA så duger den troligtvis även åt dig. Nginx är webbservern som driver 15% av världens hemsidor (och ökande) och däribland flera av världens mest trafikerade sådana.

I den här artikeln kommer jag att berätta om vad Nginx är, hur den fungerar, hur man installerar den på Debian och till slut hur den konfigureras för att helt ersätta Apache.

Vad är Nginx?

Nginx är — precis som Apache — en Linux-baserad webbserver, men som uttalas “Engine X” och inget annat (jag gick tyvärr runt i nästan en vecka och sade “En-Ginks” innan jag upptäckte detta). Om du är osäker på vilken webbserver du använder så är det troligast Apache, som är vanligast till 65%.

Det som skiljer Nginx från de flesta andra webbservrar är dess prestanda och effektivitet. Tester visar att den kan prestera 46% snabbare och 177% effektivare, men när det kommer till att skicka statiska filer till webbläsare visar tester på hela 65% bättre prestanda.

Nginx kan även fungera som en omvänd proxy-server och belastningsutjämnare som tar emot alla anrop och delar upp dem till en eller flera andra servrar. Detta kommer jag dock inte gå igenom i den här artikeln.

Hur fungerar Nginx?

Icke-blockerande webbserver

Den största anledningen till att Nginx presterar så mycket bättre än Apache och de flesta andra webbservrar är hur det är uppbyggt i grunden. Apache är en så kallad processdriven webbserver (ibland tråddriven beroende på konfiguration), vilket innebär att det skapas en ny process för varje anrop. Processerna är oberoende av varandra och har en egen del av minnet på servern, och på så vis kräver Apache mycket minne för att kunna prestera bra.

Ifall det maximala antalet processer är uppnått, eller om minnet inte räcker till, blockerar Apache nya anrop tills det finns resurser att hantera dem. Apache blockerar även upp när den väntar på resultat från exempelvis ett PHP-skript. Dessa avbrott rör sig oftast bara om millisekunder, men med många bäckar små kan servern bli långsam under hög trafik.

Nginx är dock uppbyggt på ett annorlunda sätt där i princip allting är händelsebaserat. Det finns en eller flera så kallade “workers” som delar på minnet (som därmed kan vara minimalt) och kan ta hand om flera tusen besökare var. Istället för att göra som Apache’s processer och vänta på att någonting ska hända (till exempel på att ett skript ska köras klart) så ber workern istället skriptet att säga till när det finns ett resultat — under tiden tar workern hand om någon annan. Därmed är Nginx icke-blockerande.

Observera att en besökare oftast gör flera anrop i följd; först för HTML-dokumentet, sedan ett anrop för varje bild, stilmall, JavaScript-fil och speciella typsnitt. Det är inte ovanligt att det tillsammans blir 50 anrop per besökare och sida, på vissa webbplatser ännu fler.

Ungefär så här kan det gå till när Apache tar hand om sina besökare:

Hur Apache fungerar
  1. En besökare anländer och gör ett anrop mot servern.
  2. Apache skapar en process för besökaren.
  3. Processen plockar fram det dokument som har blivit anropat.
  4. Dokumentet innehåller PHP-kod som körs. Processen väntar på att koden ska köras klart och skickar sedan resultatet till besökaren, därefter dör processen.
  5. Dokumentet innehåller en bild som måste hämtas. Denna gång finns det ingen ledig plats för en ny process. Anropet får vänta på sin tur, därefter plockas bilden fram och skickas till besökaren.

Här är samma exempel fast med Nginx som webbserver som har blivit konfigurerad att bara använda en worker:

Hur Nginx fungerar
  1. En besökare anländer och gör ett anrop mot servern.
  2. Nginx ger anropet till sin worker.
  3. Workern plockar fram det dokument som har blivit anropat.
  4. Dokumentet innehåller PHP-kod som körs. Under tiden tar workern hand om nästa besökare. När koden är klar skickas resultatet till workern och sedan till besökaren.
  5. Eftersom workern aldrig väntar på något så har den tid med att plocka fram en bild och skicka till besökaren trots att den samtidigt tar hand om flera andra besökare.

Det kan vara mycket information att ta till sig, så titta gärna på illustrationerna ovan och jämför det som pågår. Illustrationerna är väldigt förenklade, om du vill fördjupa dig mer i hur Nginx fungerar rekommenderar jag den här artikeln.

Kort sagt kan man beskriva Nginx som en multi-tasker som håller flera bollar i luften samtidigt, medan Apache gärna gör en sak i taget.

Hur man installerar Nginx

Installationen av Nginx är ganska enkel. Detta förutsätter att du kör Debian på din server och kan nå den via SSH — jag använder personligen Putty för detta ändamål, och en textredigerare med SFTP-åtkomst för att ändra i konfigurationsfiler.

Om du har Apache bör du inaktivera det och/eller avinstallera det innan du börjar installationen av Nginx.

1. Ändring av sources.list

Öppna upp filen /etc/apt/sources.list och lägg till följande rader:

deb http://nginx.org/packages/debian/ squeeze nginx
deb-src http://nginx.org/packages/debian/ squeeze nginx

Detta gör så att du kommer ladda hem rätt version av Nginx i det tredje steget.

2. Uppdatera alla paket

Det är en god vana att uppdatera alla paket på din server till den senaste versionen innan du installerar något nytt. Det gör du med dessa två kommandon:

apt-get update
apt-get upgrade

3. Installation

Beroende på vilka moduler du behöver så finns det tre olika paket att välja mellan; nginx-light, nginx-full och nginx-extras. Välj mittenvarianten om du inte har några speciella behov:

apt-get install nginx-full

4. Starta Nginx

Webbservern startar inte automatiskt efter installationen. För att starta Nginx så kör du följande kommando:

service nginx start

Vid behov kan du även stoppa och starta om webbservern med service nginx stop respektive service nginx restart.

5. Titta så att det fungerar

Öppna din favoritwebbläsare och surfa in på din IP-adress. Där bör du få ett varmt välkomnande av din nya webbserver.

PHP då?

Nginx stödjer inte PHP från grunden (vilket Apache inte heller gör för den delen) och måste installeras även det. Det finns olika sätt och paket att installera för att få stöd för PHP, min favorit är PHP-FPM som är snabbt och därför går väldigt bra ihop med Nginx. Observera att detta paket inte finns i Debian Squeeze, därför behöver du ha Debian Wheezy installerat.

apt-get install php5-fpm

Därefter behöver du lägga in en kodsnutt i konfigurationen för din webbplats som skickar PHP-filer till PHP-FPM. Hur du gör detta förklarar jag nedan.

Konfiguration av Nginx

Enligt mig är det bästa med Nginx, bortsett från prestandan, konfigurationen — den är mycket enklare och överskådligare än Apache’s. Och .htaccess-filerna? Glöm dem — inte bara är de onödigt långa och fula, utan de stjäl även prestanda från servern när den tvingas leta efter .htaccess-filer i hela sökvägens mappar för varje anrop.

Här kommer jag bara gå igenom det nödvändigaste i Nginx’s konfiguration, resten finns väl dokumenterat.

Huvudkonfigurationen

Konfigurationen för Nginx ligger i /etc/nginx/nginx.conf. Det enda vi ska titta på är de här raderna i början:

worker_processes 4;
pid /var/run/nginx.pid;

events {
    worker_connections 768;
}

Den första raden, worker_processes, bestämmer hur många workers Nginx ska använda sig av. Man brukar säga att detta värde ska vara lika med antalet kärnor serverns processor har. Om du är osäker kan du lämna det som det är.

Den andra raden anger vart processens ID ska sparas, den raden behöver du inte röra.

Sedan kommer vi till worker_connections som ligger inom events. Det här värdet avgör hur många anrop en worker ska kunna hantera samtidigt. Att öka värdet gör inte Nginx automatiskt snabbare, utan det fungerar som ett skydd så att servern inte ska hantera fler anrop än vad den klarar av. Vi kan enkelt räkna ut hur många anrop Nginx ska klara av samtidigt genom att multiplicera det här värdet med antalet workers — i det här fallet blir det 3072 anrop. Ifall du inte räknar med att ha fler samtida anrop än så behöver du inte öka värdet för worker_connections.

Nginx behöver inte startas om för att konfigurationen ska börjar gälla — man kan istället blixtsnabbt ladda om konfigurationen.

nginx -t
service nginx reload

Det första kommandot kontrollerar din konfiguration så att inget är fel — kör alltid den innan du laddar om konfigurationen med det andra kommandot.

Konfiguration av webbplatser

Nginx hanterar flera sajter på ett väldigt snyggt sätt, och det är denna del som ersätter Apache’s .htaccess-filer.

I mappen /etc/nginx/sites-available lägger man konfigurationsfiler för olika sajter. I mitt fall kan jag ha en fil där som heter webbmekanikern.se.conf med följande innehåll:

server {

    # Definiera domännamn
    server_name www.webbmekanikern.se;

    # Definiera loggar
    access_log off;
    error_log /var/log/webbmekanikern.se.error.log crit;

    # Definiera root-katalog
    root /var/www/webbmekanikern.se;

    # Prioritera index-filer i följande ordning
    index index.php index.html index.htm;

    # Skicka PHP-filer till PHP-FPM
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_index  index.php;
        fastcgi_pass   unix:/var/run/php5-fpm.sock;
        include        fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        fastcgi_param  SCRIPT_NAME      $fastcgi_script_name;
    }

}

Som du ser är det väldigt överskådligt och ganska enkelt att förstå. Först definierar jag mitt domännamn “www.webbmekanikern.se” som gör att just denna konfiguration endast gäller för denna domän. Därefter stänger jag av åtkomst-loggen (som annars loggar en textsträng för varje anrop) och berättar var loggen för felmeddelanden ska ligga.

Hela webbplatsens innehåll kommer ligga i /var/www/webbmekanikern.se, så det sätter jag som root-katalog. När någon går in på webbplatsen (eller går in i en mapp) så ska index.php laddas i första hand, om inte den finns så laddas index.html eller index.htm.

Sedan kommer den kod som skickar alla PHP-filer till PHP-FPM. Kodsnutten location ~ \.php$ gör en matchning av ett reguljärt uttryck, i det här fallet \.php$ som betyder allt som slutar på “.php”. Med andra ord kommer alla filer som slutar på .php att skickas till PHP-FPM.

Nu är det dags att hoppa till server-rooten (cd /) och aktivera konfigurationen med följande kommando (en rad):

ln -s /etc/nginx/sites-available/webbmekanikern.se.conf /etc/nginx/sites-enabled/webbmekanikern.se.conf

Detta kommer att skapa en symbolisk länk i mappen /etc/nginx/sites-enabled, vilket aktiverar konfigurationen. Om du någon gång i framtiden vill inaktivera konfigurationen så går du bara till mappen och plockar bort länken — själva filen kommer ligga kvar i /etc/nginx/sites-available.

Ladda om konfigurationen och du har en fungerande webbplats (förutsatt att du har lagt några filer i /var/www/webbmekanikern.se).

Observera att denna konfiguration inte kommer gälla för besökare som har skrivit “webbmekanikern.se” i webbläsaren (alltså utan “www”). Detta är en miss som många webbutvecklare gör som dock är väldigt enkel att lösa. Jag ska i samma veva även lösa problemet med att vissa stavar webb med ett B istället för två, vilket egentligen är en olämplig stavning, men för att inte förvirra besökare har jag även köpt domänen “webmekanikern.se” och pekat den mot samma server.

Lägg nedanstående kod högst upp i filen och ladda sedan om konfigurationen med nginx -t följt av service nginx reload. Observera att server-blocket är ett eget block och ska inte förväxlas med det tidigare server-blocket i den här artikeln.

server {

    # Skicka besökare till rätt domän
    server_name webbmekanikern.se webmekanikern.se www.webmekanikern.se;
    return 301 http://www.webbmekanikern.se$request_uri;

}

Mycket snyggt. Jämför det med hur det skulle ha sett ut i Apache’s .htaccess-fil:

RewriteEngine On

RewriteCond %{HTTP_HOST} ^webbmekanikern\.se$ [OR]
RewriteCond %{HTTP_HOST} ^webmekanikern\.se$ [OR]
RewriteCond %{HTTP_HOST} ^www\.webmekanikern\.se$
RewriteRule ^(.*)$ http://www.webbmekanikern.se/$1 [R=301,L]

Inte alls lika snyggt enligt min mening, men det fungerar.

Slutord

Sedan jag gick över till Nginx kommer jag att välja det framför Apache så ofta jag kan. Jag rekommenderar det även till mina kunder som har egna servrar. Webbhotell använder sig dock oftast av Apache, och så kommer det troligtvis vara ett tag till.

Vad tycker du om Nginx?

Ivar Johansson

Skriven av

Ivar började med webbutveckling för tio år sedan och har sedan dess utvecklat breda kunskaper inom framför allt webbprestanda, sökmotorer och användarupplevelse. Idag driver han eget företag där han skapar webbplatser som är snabba, säkra och enkla att hantera.

  1. Kenth Hagström

    28 december, 2013

    Hej,
    Din guide var väldigt nyttig, har lyckats installera nginx. Det fungerar och det är faktiskt märkbart snabbare.

    MySQL fungerade direkt utan krusiduller direkt efter installationen, inget behövde konfigureras. Underbart!

    APC cache blev också installerat, dock efter en del strul med ”segmentation fault” när jag startade om php5-fpm, det visade sig att APC försökte skriva till en tmp-katalog som det inte hade rättigheter till. Snabb fix när man väl uppmärksammade vad som var fel.

    Men jag har inte lyckats få igång ersättningen för mod_rewrite… return 301 http://mindoman.se$request_uri;

    Många andra artiklar där ute säger att det är det första man stör sig på när man nyligen gått över till nginx, samt att htaccess är verkningslös. Har spottat ut en hel drös med svordomar om det en bra stund nu… service nginx reload har exekverats alldeles för många gånger.

    Min hemsida är en WordPress multisite med ”domain mapping” aktiverad, kanske det som krånglar till det hela. Fel-meddelandet jag får när jag går in på en sida annat än index-sidan just nu är: ”This webpage has a redirect loop”

    Så här ser mitt server-block ut för min primära domän, vilken jag vill få att fungera först: http://pastebin.com/BPWdQnsJ

    Så tills vidare så har Apache2 fått hoppa in igen, så allt funkar som det ska fram tills nästa försök. Har inte gett upp hoppet riktigt än. Skriver en rad till efter nästa försök, börjar bli lite för trött nu.

  2. Ivar Johansson

    28 december, 2013

    Hej Kenth!

    Kul att guiden har hjälpt dig! Mindre roligt att du har stött på bekymmer, ska försöka hjälpa dig så gott det går.

    Som du säger så har du en omdirigerings-slinga där du skickar vidare kenthhagstrom.se till sig själv (rad 3-4 i din konfiguration), vilket inte är så bra. I ditt fall behöver du två olika server-block:

    server {
        # Skicka vidare alla subdomäner till huvuddomänen
        server_name *.kenthhagstrom.se;
        return 301 http://kenthhagstrom.se$request_uri;
    }
    
    server {
        server_name kenthhagstrom.se;
        
        # Resten av konfigurationen
        
    }

    Observera att listen 80; inte är nödvändigt att skriva eftersom det redan är satt som standard.

    Berätta hur det går!

  3. Kenth Hagström

    30 december, 2013

    Tyvärr blev jag inte hjälpt av ditt svar då det av någon anledning inte fungerar. Har sökt på Google som en tok, nu har jag äntligen hittat en variant av konfiguration som faktiskt fungerar, så här ser det ut:

    server {
    	listen 80;
    	server_name kenthhagstrom.se *.kenthhagstrom.se;
    
    	index index.php;
    	root /www/kenthhagstrom.se/public;
    
    	# Logging
    	access_log  off;
    
    	location / {
    		try_files $uri $uri/ /index.php?$args;
    	}
    
    	location ~ \.php$ {
    		try_files $uri =404;
    		include fastcgi_params;
    		fastcgi_pass unix:/var/run/php5-fpm.sock;
    	}
    }
    

    Så nu är det bara att se till att lära sig lite mer så man kan finjustera allt så man får till det som man vill ha det! :)

  4. Ivar Johansson

    30 december, 2013

    Nu gör du ju ingen omdirigering (som jag trodde var det du ville ha), men om det fungerar så som du vill ha det så är det ju toppen! :-)

  5. Kenth Hagström

    30 december, 2013

    Ja, nu ska man bara lära sig alla andra små tricks också. Antar att det behöver finjusteras och säkras upp lite. Har ju ingen riktig koll än, men det ska det bli ändring på! :)

  6. Daniel Matsson

    5 januari, 2014

    Tack så mycket för artikeln! Enkel och tydlig, skoj att läsa. Jag har också börjat nyttja nginx på senaste tiden. Främst för att konfigurationen är så simpel att komma igång med, och att du bygger på det du behöver istället för att börja med allting. Kan vara enkelheten som spelar ett spratt, men känns som man på detta sätt får lite mer kontroll om vad som faktiskt händer.

    /Daniel

  7. Anton Carlsson

    28 februari, 2014

    Tack för en bra artikel! Hjälpte mig massor i min första server installation :-)

  8. Daniel O

    1 september, 2015

    Strålande artikel! MYCKET bra hjälp!

Mejla mig: