Varnish ei osaa hoitaa SSL-sertifikaatteja, eikä tule koskaan osaamaankaan reverse proxynä. Välimuistittaja tarvitsee jonkun eteensä muuntamaan nettiliikenteen tavalliseksi http-pyynnöksi ja jälkeensä jonkun antamaan sen sisällön, jota välimuistitetaan. Käytännössä tuo tarkoittaa useimmin webpalvelinta Varnishin molemmilla puolilla, joko samana ohjelmana tai erillisinä. On kolmaskin ratkaisu terminoimaan SSL ja se on käyttää ns. tyhmää proxyä, joka ei muuta tee kuin varmistaa pyydetyn https-liikenteen vaatiman SSL-sertifikaatin ja siirtää siitä eteenpäin tavallista http:tä. Olen kokeillut tuohon pariakin ratkaisua ja nyt sivustofarmin SSL-tarpeet hoitaa Nginx. Mielestäni jopa melkoisen mallikkaasti.
Kun otin Varnishin aikoinaan käyttöön, niin ensimmäisenä kokeilin ratkaisua, jossa Apache2:een rakennetaan oma virtual host ottamaan vastaan portista 443 tuleva https ja vastaava virtual host, mutta Varnishin takana, kuunteli sitten http-asiaa. Varnish hoiti maailman suuntaan http:n portin 80. Se toimi sinänsä hyvin ja kun oivalsin miten homma hoidetaan useammalla virtual hostilla, niin olin kohtuullisen tyytyväinen. Ainakin jonkun aikaa.
Taustaa
Apache2 > Varnish > Apache2 pino oli hivenen raskas. Toki olisin voinut ostaa dropletiin, joka on DigitalOceanin nimi virtuaalipalvelimelle, lisää prosessoreita ja RAM:ia, mutta olin sitä mieltä, että 4 CPU:ta 8 gigalla pitäisi riittää isompaan kuin yhdelle suomalaisittain vilkkaalle blogahtavalle koirasivustolle, muutamalla lähes kuolleelle wordpress-asennukselle, parille hitaasti myyvälle verkkokauppalle ja vähäkäyttöiselle Moodlelle. Älä ymmärrä väärin, eivät sivustot olleet lähelläkään kaatua resurssien vähyyden takia, mutta kuorma oli liian kova.
Kun yhtälöön lisättiin halu saada hyödynnettyä HTTP/2, niin keulilla oleva Apache2 saisi lähteä. Periaatteessa HTTP/2 on mahdollista toteuttaa Apachella ottamalla mod_http2
käyttöön, mutta se ei onnistu pakasta revittynä. Ongelmaksi tulee sellaiset kuin ALPN ja TLS (ihan sama asia kuin SSL, ovat muuttamassa nimeä), joka vahvistaa salauksen käyttöä. HTTP/2 ei moista vaadi, mutta selainvalmistajat vaativat.
Pariskunta ALPN/TLS on rakennettavissa, mutta se vaatii PHP-FPM:n ottamista käyttöön sekä yhden työkalun muuttamista käsin. Yhtään en tajua mistä on kyse, mutta Apachen ja PHP:n mukana oletuksena oleva kummajainen mpm_prefork
kieltäytyy HTTP/2:sta ja tipauttaa yhteyden tuttuun HTTP/1.1:een taustalla sen kummallisemmin asiasta huutaen. Kyllä se ilmoittaa, mutta ilmoitusta täytyy tajuta vilkaista Apachen error.log
tiedostosta.
Tein kaiken ohjeiden mukaan ja kaadoin jokaisen saittini. Lisäksi serveri sekosi päästään. Yritin palauttaa alkutilanteen, mutta sekään ei onnistunut. Minulla oli periaatteessa PHP-FPM poistettu, mutta silti jokainen virtual host vaati merkinnän sen käytöstä. Olin palauttanut sen takaisin paikalleen ja käyttöön mpm_prefork
kummajaisen, jota systeemi ei osannut kuitenkaan käyttää. Googlen mukaan osa on saanut Apachen toimimaan myös HTTP/2:den kanssa, jopa Varnishin edessä. Minä en onnistunut. Googlen hakutulosten mukaan en ollut ainoa.
Tein sen minkä jokainen arvonsa tunteva web/system manager tekisi: tuore virtuaaliserveri käyttöön ja saitit sinne – se ei muuten onnistu ihan vartissa. Nyt otin käyttöön aikoinaan hylkäämäni stackin: Hitch > Varnish > Apache2.
Oli jo kokeillut Hitchiä terminoimassa SSL:n ja hoitamassa HTTP/2:den kuntoon. Se on kevyt, tehokas ja tekee toimiessaan juuri sen minkä pitääkin. Taatusti aivan erinomainen valinta, mutta ei minulle. Jostain syystä Hitch kämmäili Lets Encryptin sertifikaattien kanssa ja jos sen hoitamilla domaineilla yhden sertifikaatti ei ollut sitä mitä Hitch halusi, niin se kaatoi itsensä kokonaan vieden mukanaan aivan kaikki sivustot. Virheilmoitukset olivat Windows-tasoa, eli täysin hyödyttömiä. Piti aina erikseen selvittää mistä Hitch oli ottanut nokkiinsa, ja se vei aikaa. Ilman Monitin tekemää valvontaa minulla olisi saattanut olla sivustot saavuttamattomissa luoja tietää kuinka kauan – kävijät eivät nimittäin kaatuneesta sivustosta ilmoittele, eivät edes tutut.
Olisin saattanut pystyä elämään tuon kanssa, mutta Hitch ei tullut toimeen Moodlen kanssa jostain todella oudosta syystä. Hitch on niin sanottu tyhmä proxi. Se ei tee sen enempää kuin hoitaa SSL:n, ei muuta headereita tai mitään muutakaan, vaan siirtää https:n jälkeen kaiken sellaisenaan Varnishille. Silti Moodle ei päästänyt kirjautumaan ja oireet olivat kuin cookiet eivät olisi kulkeneet. Sama systeemi samoilla Varnishin asetuksilla toimi kuitenkin Apachen ollessa keulilla ja tarjotessa HTTP/1.1:stä. Lisäksi Varnish oli asetettu antamaan Moodlelle return(pipe)
, joka tarkoittaa cachen läpijuoksua ilman, että yhtään mitään muutettaisiin. Yleensä neuvotaan käyttämään return(pass)
, mutta se jättää vain cacheamatta ja silti siivoaa cookiet, muokkaa headereita jne – joten jos sinulla on joskus Varnishin kanssa tarve läpäistä cache totaalisesti, niin tuo kannattaa pitää mielessä.
Minulla alkoi olla vaihtoehdot vähissä. Toki olisin voinut kokeilla Poundia ja paria muuta Hitchiä vastaavaa tai sen edeltäjää, mutta aloin olla kurkkuani myötä säätöjä, korjauksia ja valvottuja öitä. Otin siis käyttöön toisen mainstream webserverin: Nginx.
Lähtöasetelma
Päätin pitää backendinä Apachen. Toki se on hivenen raskaampi kuin Nginx, ainakin niin väitetään, mutta tunsin se jotenkin ja minulla oli jo olemassa sillä toimiva setup. En halunnut korjata ja muuttaa jotain, joka ei muutosta tarvinnut. Eräs totesi minulle, että Apache2 kannattaa heivata, koska Nginx on parempi tarjoamaan isoja staattisia tiedostoja. Anteeksi vain, mutta minulla on sisältösivustoja, ei tiedostonjakopalvelua. Lisäksi CDN hoitaa tiedostot Amazonin S3:n kautta ja Varnish tekee kaikkensa, että kukaan ei ylipäätään menisi Apachelle.
Oli toinenkin rajoite miksi Nginx ei ollut valinta taustalle. Minulla on muutama asiakkaan sivusto serverillä, enkä jaksa/halua tehdä virtual conf – tasolla erillisistä pyynnöistä muutoksia. He saavat siis käyttää .htaccess
säätöjä, vaikka ne olenkin omilla sivuistoillani estänyt. Nginx ei tajua .htaccess
tiedostoista mitään ja siksi niihin pääsy pitäisi varmuuden vuoksi erikseen jopa estää per virtual host – ylipäätään aika monet asiat on Ngixinssä tehtävä aina sivustokohtaisesti, eikä niitä saa tehtyä serverin tasolla globaalisti kaikkia koskeviksi.
Minulla siis
- Nginx kuuntelee portteja 80 ja 443, ja kääntää http-pyynnöt https:ksi
- Nginx vastaanottaa HTTP/2-liikenteen ja hoitaa SSL-sertfikaatit
- Varnish kuuntelee Nginxiä portissa 8080 (nuo sisäiset portithan saa laittaa melkein miksi tahansa, kunhan käyttää vapaita) ja hoitaa välimuistit
- Apache2 kuuntelee Varnishia portissa 81 ja tarjoaa niiden websivujen sisällön, joita ei saada cachesta
Usein tehdään niin, että Varnish kuuntelee porttia 80 ja sitten ohjaa http-pyynnöt takaisin edessä olevalle webserverille tai mikä 443 porttia kuunteleekaan, jonka jälkeen sama pyyntö palaa takaisin Varnishille http-pyyntönä. Turhaa mutkittelua vain siitä ilosta, että saadaan pitää Varnish auki maailmalle ja silti pakotettua asiakas https-protokollalle.
Nginx pystyy myös toimimaan reverse proxynä, joten siltä osin Varnish olisi turha. Mutta Varnish on tehokkaampi kuin Nginx koskaan, sekä ainakin minusta myös helpompi. Lisäksi jos jokin osa-alue kiukuttelee, niin se ei potkaise pallia muiden alta. Jos haluaa todella urakalla laittaa kaikki munat samaan koriin, niin antaa Nginxin hoitaa aivan kaiken – ja kun Nginx hajoaa, niin hajoaa aivan kaikki.
PHP-FPM
PHP-FPM on php:n laajennus, jota webserverit käyttävät. Siitä on hyötyä, kun kävijöitä tulee paljon. PHP-FPM osaa tehostaa toimintaansa kovemmassa kuormituksessa. Tavallisilla saiteilla, kun puhutaan maksimissaan tuhannesta kävijästä päivässä, PHP-FPM ei anna mitään varsinaista tehokasta aitoa etua, mutta sitä tarvitaan yhteen työhön: se auttaa HTTP/2 käytössä.
PHP-FPM on helppo asentaa:
apt install php-fpm
Tuo asentaa saman version PHP-FPM:n kuin mikä php:n versio on; tätä kirjoitettaessa minulla on php 7.3, joten PHP-FPM löytyy nimellä php7.3-fpm
ja sen hakemisto on /etc/php/7.3/fpm
. Hakemisto on oleellinen siksi, että siellä piilee php.ini
ja se on seuraavaksi muokkauksessa – kaikki muutokset, jotka olet aikoinaan tehty php:lle tiedostoon php.ini
, eivät enää vaikuta nettipuolella, koska PHP-FPM ottaa ylivallan. Ne on tehtävä uudestaan. Ylipäätään oletusasetukset ovat mallia mikroskooppinen serveri, jossa ei käy kuin ylläpito joskus ja harvoin. Esimerkit ovat minulle sopivia, joten muokkaa itsellesi tarkoituksenmukaisemmiksi tai lähde liikkeelle ehdotetuista.
nano /etc/php/7.3/fpm/php.ini
max_execution_time = 300
max_input_time = 190
max_input_vars = 10000
post_max_size = 128M
upload_max_filesize = 64M
memory_limit = 512M
Tarvitaan vielä kaksi muutosta lisää.
Avaa PHP-FPM:n oma asetustiedosto:
nano /etc/php/7.3/fpm/php-fpm.conf
Lisää sinne tämä tai etsi vastaavat, aseta arvot ja poista kommentointi:
emergency_restart_threshold 10 emergency_restart_interval 1m process_control_timeout 10s
Tuo tarkoittaa, että jos 10 lapsiprosessia on saavuttamattomissa minuutin, niin PHP-FPM käynnistää itsensä, mutta antaa järjissään oleville 10 sekuntia aikaa hoitaa hommansa loppuun.
nano /etc/php/7.3/fpm/pool.d/www.conf
Muuta nämä (minulla on 4 CPU/8 GB RAM):
pm.max_children
= kaava on (koko muisti – muu käyttö) / keskimääräisen prosessin koko (minulla 32; laita sama, jos ei ole muuta ajatusta)pm.start_servers
= CPU:t x 4 (minulla 16)pm.min_spare_servers
= CPU:t x 2 (minulla 8)pm.max_spare_servers
= sama kuinstart_servers
(minulla 16)pm.process_idle_timeout
= 10s (oletus)pm.max_requests
= 500 (oletus)
Käynnistä PHP-FPM uudestaan:
systemctl restart php7.3-fpm
Sallitaan PHP-FPM mm. rebootissa:
systemctl enable php7.3-fpm
Käynnistetään PHP-FPM:
systemctl start php7.3-fpm
PHP:ssä muutokset otetaan käyttöön käynnistämällä Apache2 uudestaan, mutta nyt joudutaan käynnistämään PHP-FPM uudestaan aina kun on tehty muutoksia:
systemctl restart php7.3-fpm
- Kun sinulla on hieman joutoaikaa, niin tutustu paremmin PHP-FPM:n säätämiseen. Nyt tarjotut oletuarvot eivät välttämättä ole pitkän päälle paras mahdollinen vaihtoehto.
Nginx: asentaminen
Nginx asentuu tyypilliseen tapaan:
apt install nginx
Tehdään heti alkuun muutama muutos oletusarvoihin, joka helpottaa useamman serverin hallintaa muistitasolla ja muutenkin. Avataan nginx.conf
:
nano /etc/nginx/nginx.conf
- Alussa, ennen lohkoa
events
on kohta:worker_processes auto;
Se asettaa arvon samaksi kuin montako prosessorin ydintä sinulla on käytössä. Itselläni se on sama kuin 4. Useimmat ohjeet käskevät vaihtaa arvoksi ytimien määrän, mutta ohjeet koskevat vanhoja versioita, joissa oletusarvo oli 1. Nykyinenauto
hoitaa arvon kohdalleen eikä sitä tarvitse muuttaa. Jos olet utelias, niin saat ytimien määrän selville komennolla:
nproc --all
- Muuta
events
lohkon alussa olevanworker_connections 768;
arvoksi1024
arvot määräävät kuinka monta yhteyttä Nginx hyväksyy sekunnissa. Kun yksi vierailija käyttää yleensä aina kaksi yhteyttä (se mitä kysymykseen ja vastaukseen tarvitaan, niin oletusarvo tarkoittaakin 384 kyselyä sekunnissa (joka on hieman eri asia kuin kävijöiden määrä). Tuo riittää suurimmalle osalle, joilla on harvoin noin paljon yhtä aikaisia vierailijoita. Mutta jos raja saavutetaan, niin kyselyt jätetään jonoon ja hoidetaan vasta kun jono menee eteenpäin. Se voi aiheuttaa pullonkaulan ja hidastaa.Yhteyksien määrä on
workerprocesses x connections
eli minulla nyt 4 x 1024 = 4096, joka siis periaatteessa on lähellä samaa kuim 2048 samanaikaista kävijää sekunnissa (se riittää aika pitkälle…). Osassa vinkkejä kehoitetaan tuplaamaanconnections
esimerkiksi arvoon 2048 jos tuntuu siltä, että ahdistaa. Vinkki on pätevä, jos sattuu omaamaan isoja tehokkaita prosessoreita. Suurimmalla osalla VPS-asiakkaita budjettihinnalla näin ei ole ja arvon nostaminen yli sen, mihin prosessorit kykenevät, on yksiselitteisesti tyhmää.Saat selvitettyä maksimiarvon tällä komennolla:
ulimit -n
- Laita
http
lohkoonserver_tokens off;
tai poista sen kommentointi.
Se estää kyselijöitä saamasta selville serverisi version; pieni varmuustoimenpide siis aukkojen ja haavoittuvuuksien metsästäjiä vastaan. - Etsi tämä rivi ja poista kommentointi eli risuaidan # merkki:
# server_names_hash_bucket_size 64;
Palomuuri
Nginx tarvitsee pääsyn ulkomaailmaan. Käytetään siihen palomuuria ja tarkkaan ottaen iptablesin liittymää ufw.
Jos sinulla on ollut jo Apache2 käytössä, niin periaatteessa portit 80 ja 443 ovat jo auki. Luultavasti ne on silloin aukaistu nimellä Apache Full
. Jostain syystä, joka saattoi olla mitenkään liittymättä tuohon, niin minulla Nginx ei tykännyt ollenkaan tuosta asetuksesta. Jouduin ottamaan sen pois päältä ja kytkemään tilalle Nginx Full
.
Näet käytettävät sovellukset näin:
ufw app list
Palomuurin nykytilanne selviää tästä:
ufw status numbered
- vipu
numbered
ei ole pakollinen, mutta helpottaa, jos jotain täytyy sammuttaa
Jos sinulla näkyy, että Apache on asennettu tavalla tai toisella, niin saat sen otettua pois päältä:
ufw delete <numero>
Nginx sallitaan näin:
ufw allow "Nginx Full"
Voit tarkistaa ketkä kuuntelevat portteja, vaihda tilalle haluamasi portti:
netstat -tlnp | grep 443
Voit käyttää tätäkin:
fuser -v 443/tcp
Jos porttia kuuntelee väärä ohjelma, tai sinne yrittää joku muukin, niin helpoin tapa on katkaista kaikilta yhteys:
fuser -k 443/tcp
Sen jälkeen voit käynnistää esimerkiksi Nginxin. Jos samaa porttia oli kuunnellut Apache, niin varmista, että olet määritellyt /etc/apache2/ports.conf
tiedostossa Apachelle pääsyn vain haluttuun porttiin.
Lets Encrypt
Tarvitset SSL-sertifikaatin ja siihen kannattaa käyttää Let’s Encryptiä. Toki voit ostaa maksullisenkin SSL-sertfikaatin, mutta ei se mitään aitoa lisäarvoa turvallisuuteen tuo.
Asennetaan ensin Let’s Enrypt:
apt install letsencrypt
Jos käytät sertifikaatin hankkimiseen --nginx
vipua, niin asennetaan sekin:
apt install python-certbot-nginx
Ongelma on siinä, että jos teet Nginxissä virtual hostin server-blokin portille 443 ilman sertifikaattia, niin Nginx kaatuu. Tarkoittaa sitä, että jokainen uusi domain on tehtävä ensin virtual hostin määrittelyllä, joka juttelee vain portin 80 kautta ja ilman Varnishia. Sen jälkeen muokkaat virtual hostin uudestaan Varnishin ymmärtämäksi. Apachessa pääsee helpommalla ja itse koen tämän jopa ärsyttäväksi.
Jos joutuu asettamaan usein uusia virtual hosteja, niin kannattanee kehittää jokin kiertotie – mikä sellainen olisi, niin ei hajuakaan (kommentoinnissa saa vinkata). Ja jos olet kuten minä, että uusia domaineja ei olla ostamassa ihan joka viikko, niin ehtii unohtamaan kaikki koukerot, että saa virtual hostin toimimaan.
Joudut siis tekemään yhden väliaikaisen virtual hostin Nginxiin. Se kannattaa nimetä lopullisella nimellä ja kun SSL-sertifikaatti on vihdoin haettu Let’s Encryptiltä, niin sitten muokkaa konffin lopulliseksi.
Tehdään virtual hostille hakemisto ja <domain> tarkoittaa tietysti sitä miten hakemiston nimeät:
mkdir -p /var/www/<domain>/public_html
Minulla epäonnistui pariin kertaan sertifikaatin haku tyhjälle hakemistolle, joten laitetaan sinne index.html tiedosto:
touch /var/www/<domain>/public_html/index.html
Jos haluat sinne jotain tekstiä varmistaaksesi, että oikea sivusto löytyy, niin avaa se ja lisää vaikka ’terve’ tai sivuston nimi, mutta pakko ei ole:
nano /etc/nginx/sites-available/<domain>/index.html
Tehdään virtual host:
server { listen 80; server_name <domain> www.<domain>; root /var/www/<domain>/public_html; index index.html; }
Tarkista, että ei ole kirjoitusvirheitä:
nginx -t
Otetaan virtual host käyttöön:
ln -s /etc/nginx/sites-available/<domain> /etc/nginx/sites-enabled/
Ladataan Nginx uudestaan:
systemctl reload nginx
Varmista, että sivuston nimipalvelinmuutokset ovat voimassa:
curl -vL <domain>
Kun nimipalvelimet ovat päivittyneet, niin haetaan sertifikaatti:
certbot certonly --webroot --preferred-challenges http -d <domain> -d www.<domain>
Sinulta kysytään webrootia (Input the webroot for ..), Anna siihen sivuston hakemisto:
/var/www/<domain>/public_html
Sinulta kysytään www-alkuisen webrootia, joten vastaa 2
eli sama.
Voit toki asentaa SSL-sertifikaatin suoraankin, jolloin Lets Encrypt kirjoittaa tarvittavat tiedot conf-tiedostoon. Mutta jos olet koskaan aikaisemmin hakenut sertifikaatin jollekin domainille, niin siitähän saa kopioitua suoraan tarvittavat rivit, kunhan muistaa muuttaa domainin.
Tämä toimii joskus paremmin kuin certbot certonly
, enkä tiedä miksi.
certbot --nginx -d <domain> -d www.<domain>
Ensimmäisellä kerralla siltä nimenomaiselta virtuaalipalvelimelta sertifikaattia hakiessasi joudut hyväksymään ehdot, antamaan sähköpostiosoitteesi ja halutessasi pääset liittymään EFF:n postituslistalle.
Jos sait virheilmoituksen, että certbot sai
error 404
, niin luultavasti nimipalvelimet eivät ole päivittyneeterror 403
, niin sinulla ei ole sivuston hakemistossa tiedostoa, jota Nginx/certbot suostuu lukemaan, kuten index.htmlerror 500/503
, niin yrität saada sertifikaatitonta domainia menemään Varnishin kautta Apachelle, jossa ei ole domainille omaa virtual hostia
Kummassakin tapauksessa palaa takaisin ja korjaa Nginxin virtual host aiemmin olevan esimerkin mukaiseksi.
Joudut muokkaamaan virtual hostin lopulliseen muotoonsa ja silloin lisään porttia 443 kuuntelevaan server-blokkiin Let’s Encryptin tekemät SSL-sertifikaatin tiedot:
ssl_certificate /etc/letsencrypt/live/example.tld/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.tld/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
Voit hakea sertifikaatin myös komennolla certbot --nginx -d <domain> -d www.<domain>
ja saat sen. Ongelmaksi nousee sertifikaatin uusiminen. Se ei onnistu kuin portin 80 kautta, ja jos/kun 80 käännetään porttiin 443, niin certbot ei saa sertifikaattia uusittua. Silloin vaihtoehdoiksi jää portin 80 kuuntelu Varnishin puolella tai jokainen uusimiskerta käsin poistaa Nginxissä uudelleenohjauksen porttiin 443 ja palauttaa se kun sertifikaatti on uusittu. Molemmat ovat hyvin kaukana näppärän ketterästä ratkaisusta, joten käytetään vipua --webroot
, jolloin porttiongelmaa ei ole.
Virtual host
Virtual hostit tehdään hakemistoon /etc/nginx/sites-available/
ja aktiiviset näkyvät myös hakemistossa /etc/nginx/sites-enabled/
aivan kuten Apachessakin. Periaatteessa Nginx käyttää samanlaista rakennetta kuin Apache2, mutta syntaksi on kuitenkin aika ajoin niin erilainen, että asioita ei voi siirtää noiden kahden välillä kopypeistaamalla.
On niissä muitakin eroja. Kuten että Nginx ei vaadi erillistä asettamista kuunnellakseen jotain porttia, kuten tehdään Apachessa tiedostossa /etc/apache2/ports.conf
. Jos Nginxissä portti on mainittu listen
-komennolla jossain virtual hostissa, niin sitä kuunnellaan. Jos ei ole, niin sitä ei kuunnella. Vastaavia eroja on muitakin.
Jos tarvitset jotain säätöjä, niin googleta. Mutta jos tarve on saada Nginx Varnishin eteen hoitamaan SSL-terminointi portissa 443 ja lisäksi myös HTTP/2 hoidettua, niin käytä tätä esimerkkiä:
- tarvitset
map
komennon, jos sinulla on 301 uudelleenohjauksia; jos ei ole, niin kommentoi - tarvitset
hash_map_bucket_size
suuremmalle asetukselle, jos sinulla on paljon uudelleenohajuksia malliin satoja; oletus on 64. - vaihda
<ip-address>
virtuaalipalvelimesi IP-osoitteeksi, mutta toimii ilmankin example.tld
on domainisi
Esimerkki tekee kaksi uudelleenohjausta:
- kääntää kaikki http-pyynnöt muotoon https (http://www.example.tld > https://www.example.tld
- kääntää kaikki ilman www-alkua olevat www:lle (http://example.com / https://example.tld > https://www.example.tld
Virtual host otetaan käyttöön tekemällä sen conf-tiedostosta symbolinen linkki hakemistosta sites-available
hakemistoon sites-enabled
. Apache2 tekee aivan samoin, mutta siihen on olemassa oma komentonsa a2ensite
ja a2dissite
. Nginxillä se tehdään linuxin komennoilla. Minusta Apachen tapa on helpompi omaksua ja muistaa, mutta minulta ei kysytä.
Kun haluat ottaa virtual hostin käyttöön:
ln -s /etc/nginx/sites-available/example.tld /etc/nginx/sites-enabled/
- example.tld on tekemäsi tiedoston nimi; sen ei tarvitse olla domainin mukaan, mutta selvyyden takia useimmat niin nimeävät
Kun haluat ottaa virtual hostin pois linjoilta, niin poistat symbolisen linkin:
unlink /etc/nginx/sites-enabled/example.tld
Nginx asettaa asennuksessa oletushostin, aivan samoin kuin Apache2 tekee 000-default.conf
kanssa. Se kannattaa ottaa pois päältä (tai sitten teet suoraan siihen ja jätät sen päälle, jos sinulla on vain yksi domain):
unlink /etc/nginx/sites-enabled/default
Aina kun teet muutoksia, niin tarkista että edes syntaksi on oikein (ja tämä kannattaa opetella ulkoa ja käyttää aina muokkauksissa):
nginx -t
Normaalisti nyt ladattaisiin Nginx uudestaan, mutta ensiasennuksessa saa vielä odottaa.
HTTP/2
HTTP/2 käyttöönotto ei vaadi sen kummempia. Ei mitään modulien asentamista, jota Apache2 vaatii. Riittää, että sivustolla on SSL käytössä ja HTTP/2 merkitään virtual hostin server
-blokkiin listen-riville:
Listen 443 ssl http2;
Perään reload:
systemctl reload nginx
Ja se oli siinä. Voit testata HTTP/2 ja ALPN toimivuuden täällä.
Tässä on kuitenkin koukku. Nginx pystyy käyttämään vain yhtä HTTP-versiota samassa IP-osoitteessa ja portissa. Tuo tarkoittaa sitä, että jos asennat yhteenkin virtual hostiin porttiin 443 HTTP/2:den, niin HTTP/2 on käytössä aivan kaikissa sen IP-osoitteen virtual hosteissa portissa 443. Kääntäen, jos poistat HTTP/2:den käytöstä, niin se täytyy poistaa aivan kaikista, jotta se todellakin olisi poissa käytöstä.
Toki tuo helpottaa elämää siinä suhteessa, että riittää kun ottaa HTTP/2:den yhdessä virtual hostissa. Ei tarvitse editoida kaikkien muidenkin conf-tiedostoja. Mutta jos olet tilanteessa, että yksikin sivusto tarvitsisi jostain syystä vain HTTP/1.1 käyttöönsä ja muissa saisi olla HTTP/2, niin se ei onnistu. Se on joko kaikki tai ei kukaan. Tuon pystyy kiertämään purkkavirityksella laittamalla sen HTTP/1.1-sivuston kuuntelemaan jotain muuta porttia, kuten vaikka porttia 444 – mutta tuo on purkkaa.
Redirect 301 ja map
Sivuston ”tavalliset” uudelleenohjaukset, eli muuttuneet jutut, urlit jne, kannattaa tehdä heti ketjun alussa Nginxissä. Useinhan tavallisessa pinossa, jossa
- Apache2/Nginx/Hitch/joku kuuntelee porttia 443
- Varnish kuuntelee porttia 80
uudelleenohjaukset tehdään backendissä. Tuossa on pienen pieni teho-ongelma, koska silloin frontend kiertää per osoite:
- kysyy ensin Varnishilta, löytyykö cachesta
- kun ei löydy, niin ohjataan backendille
- backend tekee uudelleenohjauksen ja lähettää takaisin Varnishille
- Varnish antaa joko cachestä tai lähettää backendiin
Oikaistaan hieman mutkia ja tehdään uudelleenohjaus heti alussa, jolloin Varnish tekee vain yhden kerran työt ja backend saa vain kaksi ilmoitusta: ei löydy cachesta tai error 404.
Nginx saadaan laittamaan muistiin redirectit, kun käytetään asetusta map. Siinä tehdään yksinkertainen teksitiedosto, jossa jokaisella rivillä on ensin se url, joka uudelleenohjataan, ja toisena se url, johon uudelleenohjaus menee.
Esimerkiksi näin:
~/tätä/ei/ole/?$ /tänne/halutaan/
Regex auttaa elämää, jos osaa regexiä. Minä en osaa, mutta osaan kopypeistata. Ja kun olen Nginxin kanssa epävarma miten urlit tehdään, niin testaan toimiiko.
Jos/kun on tehnyt uudelleenohjauksia Apachella, niin kolme asiaa on eri tavalla:
- Apache aloittaa
^
-merkillä, Nginx aloittaa~/
tai~*/
- ~ tarkoittaa, että kirjainkoko merkitsee
- ~* tarkoittaa. että kirjainkoko ei merkitse
- Nginx lopettaa aina puolipisteeseen ;
- Apache merkitsee ohjauksen, Nginxillä se kerrotaan erikseen kyselyssä (Apache esim. [R=301,L], kun Nginx return 301)
Jos sinulla on Apachella lista uudelleenohjauksia, niin saat ne muokattua kuntoon kohtuullisen vähälle vaivalle käyttämällä esimerkiksi Notepad++ ohjelman korvaa-toimintaa
RewriteRule ^
korvataan~/
[R=301,L]
(huomaa välilyönti alussa) korvataan;
- [G]
ja/tai- [R=410,L]
korvataan /; – tuo tekee uudelleenohjauksen sivuston juureen, joka on kylläkin väärin, koska 410 on teknisesti 404. Koska halusin aikoinaan todellisenn uudelleenohjauksen error 410 Gone tapauksissa, joka ei onnistu Nginxillä, niin siirsin uudelleenohjauksen backedin Apachelle ja annoin Varnishin tehdä 410-redirectit.
Saatat saada ilmoituksen nginx -t
komennolla, että sääntö ei kelpaa. Se johtuu siitä, että ohjattava osoite on silloin kahteen kertaan. Apache hyväksyy tuplat ja triplat käyttäen ensimmäistä osumaa, mutta Nginx on nirsompi: vain yksi kelpaa.
Nginxin tarkistus ja käynnistys
Kun olet valmis Nginxin kanssa, niin sallitaan sen käynnistys rebootissa:
systemctl enable nginx
Tarkista, että kaikki on kirjoitettu oikein (sanoinko jo, että tämä kannattaa opetella ulkoa ja kokeilla aina kun tekee muutoksia):
nginx -t
Jos virheitä ei ollut, niin ensimmäisellä kerralla käynnistetään:
systemctl start nginx
Jatkossa vain lataat uudestaan, kun olet tehnyt muutoksia virtual hosteihin:
systemctl reload nginx
Mutta jos olet muuttanut itse Nginxin asetuksia ja toimintaa, niin käynnistä uudelleen:
systemctl restart nginx
Varnish
Varnish asennetaan jo rutiinisti:
apt install varnish
Varnishin asettaminen vaatii tiedoston default.vcl
muokkaamista ja sen saaminen kohdalleen voikin vaatia enemmän töitä ja ahkeraa Googlen käyttöä. Mutta jos sinulla on WordPress/Woocommerce sivusto ja toivottavasti vielä useampi domain, niin käy täältä katsomassa mallia.
Jos sinulla on vain yksi domain, niin yksinkertaistetusti kopioi tiedostoista all-common.vcl
ja sopivan domainin .vcl
-tiedostosta kaikki kohdat oikeisiin sub_
kohtiin tiedostoon default.vcl
.
Koska Varnish ei juttele maailmalle, vaan Nginx siirtää proxynä kaiken Varnishille, niin Varnish ei saa jutella portille 80, vaan jollekin muulle vapaana olevalle localhostissa. Itse käytän porttia 8080. Portti on oltava sama kuin mikä Nginxin virtua hostissa asetettiin kohdassa proxy_pass
.
Avataan Varnishin kovan ytimen asetukset:
systemctl edit --full varnish
Lisää sinne tämä:
ExecStart=/usr/sbin/varnishd -P /var/run/varnish.pid -j unix,user=vcache -F -a :8080 -T localhost:6082 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,512m
- kommentoi risuaidalla # vastaava jo olemassaoleva rivi
- vaihda portti 8080, jos käytät jotain muuta
- portti 6082 ei viittaa backnendiin, minulla Apache2, vaan Varnishin omaan liikenteeseen mm.
varnishadm
käyttöön. - 512m on se muistimäärä, joka Varnishille annetaan. 512 megaa riittää normaaliliikenteiselle sivustolle, mutta jos lämmität cachen eli laitat
wget
ohjelman hakemaan muistiin valmiiksi kaikki sivut, niin tuollainen 2000 postauksen WordPress täyttää sen heti. Itse käytän 5G eli viittä gigaa.
Kerrotaan muutos järjestelmälle:
systemctl daemon-reload
Osassa ohjeita käsketään muokata tiedostoa /lib/systemd/system/varnish.service
(myös täällä) eikä minulle ole koskaan oikein selvinnyt, että koska käytetään kumpaa. Niissä on nimittäin samat tiedot, mutta niiden muokkaaminen ei muuta myös toista. Sen tiedän, että jos muokkaan tiedostoa varnish.service
, niin seuraavalla uudelleenkäynnistyksellä käytössä onkin systemctl --edit varnish
komennolla muokattu.
Tuosta tietenkin selviää pitämällä molemmat samanlaisina, mutta asiaa voi testata muuttamalla portti localhost:6082
toiseen vaikka portiksi 6081 (se on portti, jossa Varnish juttelee itsensä kanssa, kun käytetään varnishadm
komentoa) ja kun kysyt systemctl status varnish
niin näet kerrotun portin mukaan kumpaa käytetään. Mutta ilmeisesti systemctl --edit varnish
muokkaa oikeaa silloin kun Varnishia käytetään enable
komennon jälkeen, demonina tai jotain. Tai sitten ei.
Otetaan Varnish käyttöön:
systemctl enable varnish
Ensimmäisellä kerralla käynnistetään:
systemctl start varnish
Kun teet muutoksia vcl-tiedostoihin. niin uudelleenlataa – silloin cache säästyy:
systemctl reload varnish
Jos muutat Varnishin asetuksia, tai haluat tyhjentää välimuistin, niin käynnistä uudelleen:
systemctl restart varnish
Mutta kuten webservereilläkin, niin aina ennen uudelleenkäynnistystä tai -latausta kannattaa varmistaa, että ei ole tullut kirjoitusvirheitä tai puutu puolipisteitä. Jos käynnistät/uudelleenlataat Varnishin kirotusvirheillä, niin se kaatuu,
varnishd -C -f /etc/varnish/default.vcl
- ei tuollaista ulkoa muista, joten siitä kannattaa tehdä alias
Apache2
Saat arvata yhden kerran miten Apache2 asennetaan…
apt install apache2
Apache2 on asennuksessa se, joka pitää sisällään kaikki verkkosivut – sitä kutsutaan myös backendiksi. Koska Apache2 juttelee vain ja ainoastaan Varnishin kanssa, niin sille sallitaan se portti, joka oli asetettu Varnishin default.vcl
tiedoston alussa kohdassa backend default { .port =
joka minulla on 81.
nano /etc/apache2/ports.conf
Tee siitä tällainen:
#Listen 80 Listen 127.0.0.1:81 <IfModule ssl_module> # Listen 443 </IfModule> <IfModule mod_gnutls.c> # Listen 443 </IfModule>
- kommentoi Listen 443 molemmissa kohdissa
- kommentoi Listen 80
- laita tilalle 127.0.0.1:81 eli Apache käyttää localhostin porttia 81
Virtual host
Koska sivusto majailee Apachessa, niin sille tarvitaan eräällä tavalla sisäinen virtual host. Se mikä tehtiin Nginxiin on se, joka näkyy maailmalle. Se mikä tehdään Apacheen, näkyy Varnishille. Koska Nginx on Varnishille proxy, niin se vain välittää pyydetyn domainin ja urlin Varnishille, joka kyselee moisen olemassaolosta Apachelta (jos ei löydä sitä välimuistista). Normaalitilanteessa siis Apache ja tietokantapalvelin vain pyörittelevät peukaloitaan ja pääsevät töihin vain harvoin.
Virtual host tehdään kuten porttiin 80 eli http-liikenteelle yleensä neuvotaan – sisäinen liikenne Varnishin ja Apachen välillä on aina http-liikennettä, ei koskaan SSL-salattua; sen ei tarvitse olla, koska pysytään serverin sisällä; joka toki kannattaa muistaa, jos backend sijaitseekin jossain muualla. Varnishin ja backendin välisen liikenteen saa SSL-salatuksi vain käyttämällä maksullista ja erittäin kallista Varnish Plus ratkaisua, mutta aidostihan tuo ei ole turvallisuusuhka ns. tavallisilla verkkosivuilla ja verkkokaupoilla.
Virtual hostin kohdalla on muistettava kaksi asiaa, loppu on tavanomaista Apachen virtual hostin säätöä:
- alussa on oltava
<VirtualHost 127.0.0.1:81>
(portti on se mikä asetettiin) - VirtualHost osassa on oltava
SetEnvIf X-Forwarded-Proto https HTTP=on
Lisäksi jos otit käyttöön PHP-FPM:n, niin sinulla on oltava tämä, että php ylipäätään toimisi (muista oikea versio):
<FilesMatch \.php$> SetHandler "proxy:unix:/var/run/php/php7.3-fpm.sock|fcgi://localhost/" </FilesMatch>
Täältä löydät sivuston Katiska.info käytössä olevan virtual host tiedoston. Mukana on logien muuttaminen Varnishin vaatimaan muotoon, joka siirtää asiakkaan IP-osoitteen oikeaan paikkaan, sekä redirectit, joita vaativat WordPress (kategoria näkyy urlissa), WP Rocket (sivuvälimuisti) ja EWWW (kuvien optimointi). Voit käyttää sitä itsellesi sopivilta osin mallina.
Lopuksi
Nyt meillä on asennus, jossa
- Nginx kuuntelee portteja 80 ja 443, sekä kääntää kaiken liikenteen porttiin 443 www-alkuisella urlilla
- Varnish hoitaa välimuistin
- Sivustot ovat Apachen hallussa
Jos unohdetaan Varnishin default.vcl
, jonka säätäminen saattaa olla aloittelijalle välillä hermoja raastavaa, niin itselläni suurimmat ongelmakohdat olivat virtual hostien hakemistoihin /var/www/<domain>/public_html
jääneet .htaccess
ja .user.ini
tiedostot, jotka estivät Nginxin ja sotkivat PHP-FPM:n toiminnan; minulla oli noiden takia yksi domain, joka antoi pelkästään error 500/503
Ylipäätään .htaccess kannattaisi ottaa pois käytöstä ja user.ini
tiedostoa käytetään vain silloin kun ehdottomasti tiedetään mitä tehdään.
Domainin kanssa riidellessäni opin pari asiaa. Ensimmäinen on varmasti kokeneemmille selviö ja se on, että curl on paljon näppärämpi kuin latailla sivua selaimessa ja samalla pohtia, että tuleeko tulos sivustolta vai selaimen välimuistista – nimittäin Chrome ainakin laittaa mielellään omaan cacheensa jopa virhesivutkin. Toinen oli, että kirjoitusvirheille tulee sokeaksi – etsin muutaman päivän syytä siihen, miksi sain sivuston näkyviin localhostissa, mutta en muualta maailmasta – minulla oli Nginxin virtuaalikonfiin jäänyt proxyn portiksi 8080, kun se piti olla 80.
Kun haluat tietää headerit:
curl -I <url>
Jos sertfikaatit kiusaavat, niin tämä saattaa auttaa ymmärtämään mitä tapahtuu:
curl -vL <domain>
- Jos kokeilet sitä, niin mielenkiintoinen osa löytyy ennen sivusisältöä
Nyt kun järjestelmä on pystyssä, niin toiminta on vakaampaa kuin muiden viritysten kanssa. Ja käytössä huoleton. Sekä nopea.