tavis nörttimaailmassa

EksisONE - artikkeleita ja ohjeita nörttimaailmasta

Varnish, Apache2 ja useampi domain

Siitä miten Varnish asennetaan välimuistittamaan http-liikennettä yhdelle domainille, löytyy ohjeita vaikka kuinka. Kun kysellään SSL-sertifikaatin https:n perään, niin neuvojen määrä romahtaa. Kun aletaan kyselemään tuossa ympäristössä Apachen käytöstä hoitamaan SSL, niin neuvoja löytyy enää pari, täältä yksi. Mielenkiintoinen tilanne, kun puhutaan maailman yleisimmästä ratkaisusta toteuttaa web-serveri. Mutta ei yllättävä, koska neuvoja ja how-to selityksiä kirjoittavat harrastajat ja heidän mielenkiintonta on yleensä hieman marginaalisimmissa asioissa. Sitä vastaan punnittaessa ei ole enää yllätys, että kun laitetaan Googleen samaan hakuun Varnish, Apache2, SSL ja useampi virtual host, niin hakutulokset näyttävät lähes nollaa. Siihen saattaa olla syynsä. Moinen niputtaminen on persaukisten ratkaisu.

Varnishin perusasennus yhdellä default.vcl -tiedostolla ei mahdollista suoraan kovinkaan helposti usemman virtual hostin eli domainin käyttöä. Varnish välimuistittaa sille tulevan liikenteen ja tuuppaa sen eteenpäin. Ei Varnish piittaa esimerkiksi mille domainille mikäkin cookien on tarkoitettu, vaan joko tiputtaa ne suoraan tai ohittaa välimuistin, säännöistä riippuen. Minulla on samalla virtuaaliserverillä tavallinen ja hyvinkin staattinen wordpress, woocommerce-kauppa erilaisilla jäsenkilkkeillä ollen kovinkin dynaaminen toisessa ja moodle-asennus kolmannessa plus tämä saitti neljäntenä. Noilla kaikilla on hyvinkin erilaiset vaatimukset välimuistin suhteen.

Domainit on mahdollista hoitaa ainakin teoriassa käyttämällä pitkää rotlaa if-lausekkeita, jotka osoittavat haluttuun .vcl-tiedostoon:

if (! req.http.Host) {
   error 404 "Need a host header";
}
set req.http.Host = regsub(req.http.Host, "^www\.", "");
set req.http.Host = regsub(req.http.Host, ":80$", "");

if (req.http.Host == "example.com") {
      include "/etc/varnish/example.com.vcl";
   } elsif (req.http.Host == "example2.com") {
      include "/etc/varnish/example2.com.vcl";
..
}

Isot pojat ovat kuitenkin kertoneet, että tuo on huonoa politiikkaa ja liian joustamaton. Älkää kysykö miksi, sillä en minä Varnishin sielunelämästä mitään ymmärrä. Luulen, että se liittyy vahvasti siihen, että if - elseif -rakenne täytyy laittaa aina, kun domainit haluavat erilaisia asioita. Olen edelleenkin vain valistunut loppukäyttäjä, joka on niin yksityishenkilönä kuin yrittäjänäkin aivan liian persaukinen kyetäkseen maksamaan asiantuntijoiden palkkioita. Joten säästän ja teen itse. Matkalla oppii jotain, varsinkin sitten kun systeemi ei toimikaan.

Mutta jos olen ymmärtänyt oikein, niin esitetty tapa perustuu – paitsi selkeyteen – niin Varnishin tapaan käsitellä eri .vcl-tiedostoja. Kun nuo käännetään komennolla systemctl restart varnish, niin se yhdistää Varnishin sisäisen builtin.vcl -tiedoston itse säädettyyn default.vcl – tiedostoon sekä mahdolliset muut .vcl-tiedostot, joiden paikka on kerrottu include -lausekkeella. Builtin.vcl pitää sisällään Varnishin perustoiminnallisuuden, joita sitten säädetään muilla.

Säätö tapahtuu rutiinien suoritusjärjestyksellä:

  1. rutiinit tiedostosta default.vcl
  2. rutiinit tiedostosta <include>.vcl, listan järjestyksessä
  3. rutiinit tiedostosta builtin.vcl

Tuohon voidaan vaikuttaa laittamalla return(…) kutsu, joka ei päästä suoritusta lisättyyn .vcl-tiedostoon. Joten Varnishin builtin.vcl -tiedostoon rakennettuun perustoimintaan voidaan vaikuttaa. Kun default.vcl pitää osiossa vcl_recv sisällään kutsun return(...), niin suoritus pysyy pelkästään default.vcl – tiedoston määräämissä asioissa. Eli edellinen suoritusjärjestys onkin pelkästään

  1. rutiinit tiedostosta default.vcl

En minä tuota osaa hyödyntää. Mutta nyt tiedän sen, että kun virtual hostit on rakennettu Varnishille, niin lopullisessa default.vcl -tiedostossa ei saa missään nimessä olla kutsua return(...) osassa vcl_recv. Jos on, niin virtual hostien cache lakkaa toimimasta, internet menee rikki ja maailma tuntemassamme muodossa on vaarassa.

Oma kokemus

Yritin hyödyntää Varnishia kuuden eri domainin kanssa. Rakentamiseen meni tunti .vcl -tiedostoilla, jotka eivät cachenneet mitään. Tein hitaasti, mutta näppärämpi säätää moisen systeemin toimintaan vartissa. Jokaisen domainin toimivaan .vcl-tiedostoon voikin mennä enemmän aikaa, jos niissä on domain-kohtaisia säätöjä.

Minulla meni kolme iltaa ja hyvin pitkiä öitä, ennenkuin sain ainakin päällisin puolin toimivan systeemin. Toki ajasta iso osa upposi googlettamiseen, koska en ymmärtänyt sitä ainoaa ohjetta, jonka netin syövereistä löysin. Kokeilun ja erehdyksen kautta sain jonkin paketin aikaiseksi.

Lisäksi törmäsin kokeilujeni myötä tunteeseen, että eri domainien paketointi omien -vcl-tiedostojensa kautta ei ole ihan niin läpihuuto kuin ne harvat aihetta käsitelleet verkkolähteet antoivat ymmärtää. Ehkä tässä ollaan sen juurisyyn paikkeilla miksi ratkaisuja löytyy niin nihkeästi: se ei vain ole fiksu tapa.

Lähtötilanne

Esittelen mitä itse tein ahkeran googleamisen jälkeen, niin joku voi halutessaan kokeilla jotain vastaavaa.

Ympäristö on

  • DigitalOceanin droplet, 4G/80G
  • Ubuntu 18.04
  • Apache2
  • Varnish 4.x
  • Hitch
  • 6 virtual hostia (2x wordpress+woocommerce; 3x wordpress, 1 moodle)

Käytän esimerkeissä aitoja tietoja, joten jos kopypeistaat, niin muista muuttaa ne itsellesi sopiviksi.

Varnish on asennettu, samaten. Kaikki toimii, mutta yhden Varnishin asennuksen takaa. Tehdään seuraavat:

  1. teen vaaditut .vcl-tiedostot
  2. käynnistän Varnishin
  3. sammutan tulipalot

Kaikki esimerkit ovat oletuksella, että käytetään root-tunnusta. Jos itse et sitä tee, niin muista sudo tai su sopivissa paikoissa.

Virtual hostit Varnishiin

Ensimmäiseksi tehdään virtual hosteille oma hakemisto Varnishin hakemistoon.

mkdir /etc/varnish/sites-enabled
  • Tehdään jokaiselle virtual hostille oma .vcl-tiedosto. Nimeän omani domainien mukaan esimerkiksi katiska.info.vcl ja eksis.one.vcl.
  • Lisäksi tehdään yksi yhteinen yhteisille asioille, kuten vaikka sallimaan Google Analyticsin cookiet. Sen nimi on all-common.vcl.
  • Tarvitaan vielä yksi, jossa kerrotaan kaikkien vhostien .vcl-tiedoston paikka: all-vhost.vcl.

Teen hyvin perusmuotoiset .vcl-tiedostot. Ihan siksi, että systeemin täytyy ensin pyöriä ja vasta sitten tehdään säädöt. Löydät käyttämäni .vcl-tiedostot GitHubista.

Joten ensimmäiseksi

cd /etc/varnish/sites-enabled[/bash]

Kaikille sama .vcl

nano eksis.one.vcl

Haluan tällä hetkellä vasta kaikki Varnishin taakse ja teen sitten myöhemmin paremmalla ajalla aidot säädöt.

sub vcl_recv {
   if (req.http.host == "a.example.com" || req.http.host == "www.a.example.com") {
     return(pass);
   }
}

On aivan makuasia tekeekö tuon erikseen kaikille domaineille, vai kopioiko yksitellen. Pääasia ei ole helpoin ratkaisu, vaan missä luottaa eniten tekemisiinsä. Tai sitten voi kopioida ensimmäisen yhdellä komentorivillä.

cat eksis.one.vcl | tee {eksis.fi,example.com,example2.com}.vcl >/dev/null
  • cat kopioi tiedoston eksis.one.vcl sisällön
  • tee tuuppaa ne tiedostoihin, jotka se nimeää aaltosulkeiden sisällä oleviin ja laittaa perään .vcl
  • >dev/null estää sisältöjen näkymisen ruudulla.

Sitten otetaan jokainen .vcl erikseen auki ja muutetaan a.example.com juuri sille domainille oikeaksi, eli esimerkiksi tiedostossa eksis.one.vcl se täytyy olla eksis.one. Sama juttu www-alkuisen kanssa: www.a.example.com muutetaan www.eksis.one

En tiedä onko aivan ehdottoman tärkeää sallia erikseen myös www, mutta ei se siinä mitään haittaakaan. Hieman toisella merkinnällä olisi saanut sen hoidettu ajatuksella *eksis.one mutta jätin sen harkitusti tekemättä. Nyt saan alidomainit hoidettua erillisinä sivustoina tarvitsematta muistaa muokata tuota, jos joskus innostun moiseen.

Yhteiset vcl-tiedostot

Koska nyt on virtual hostit tehtynä ja jokaisella domainilla on oma .vcl-tiedosto, niin palataan hakemistoissa yksi ylöspäin takaisin Varnishin omaan hakemistoon /etc/varnish ja tehdään puuttuvat kaksi .vcl-tiedostoa.

cd ..

all-common.vcl

Tehdään kaikille yhteinen .vcl-tiedosto. Vien sinne Googlen Analytics-cookiet, koska ne ainakin on mentävä kaikkiin. Aidosti niitä on kylläkin enemmän, mutta hion tuonkin myöhemmin kuntoon. Aidosti tämän voisi tässä vaiheessa jättää vaikka tyhjäksi, koska return(pass); estää muutenkin cacheamisen.

nano all-common.vcl
sub vcl_recv {
     set req.http.Cookie = regsuball(req.http.Cookie, "_ga=[^;]+(; )?", "");
     set req.http.Cookie = regsuball(req.http.Cookie, "_gat=[^;]+(; )?", "");
}

all-vhost.vcl

Nyt kerätään kaikki virtual hostien vcl-tiedostot samaan pakettiin, jotta voidaan default.vcl -tiedostossa kertoa Varnishille missä ne ovat.

nano all-vhost.vcl
include "sites-enabled/eksis.one.vcl";
include "sites-enabled/eksis.fi.vcl";
include "sites-enabled/katiska.pro.vcl";
jne

default.vcl

Viimeiseksi täytyy koota kaikki varsinaiseen default.vcl tiedostoon. Ja taas, teen siitä nyt hyvin simppelin, joka ei tee muuta kuin on..

nano default.vcl
## Jakke Lehtonen
## by several sources
## Varnish default.vcl for multiple virtual hosts
## Just very simple and plain, mostly for testing
#
# Lets's start caching

#

# Marker to tell the VCL compiler that this VCL has been adapted to the 4.0 format.
vcl 4.1;

backend default { 
     .host = "127.0.0.1"; # IP or Hostname of backend
     .port = "8080";      # Apache or whatever is listening
}


sub vcl_recv {

     # Your lifeline: Turn OFF cache
     # For caching keep this commented
     # return(pass);

}

..kaikki muu vcl-alkuinen
# at the very bottom:
include "all-vhost.vcl";
include "all-common.vcl";

Mitä sitten?

Sitten käynnistetään Varnish komennolla systemctl restart varnish ja jännitetään toimiiko kaikki. Vilkaistaan systemctl status varnish ja jos vihreä lamppu palaa, niin ainakin Varnish on pystyssä.

Kun lähdetään säätämään domainien omia .vcl-tiedostoja, niin muutama perussääntö on pidettävä mielessä:

  • ei return(...) kutsuja default.vcl:n vcl_recv osiossa
  • .vcl-tiedostot koskevat vain vcl_recv osiota, ei muita
  • virtual hostien .vcl säätää ainoastaan juuri sen virtual hostin tarpeita; mitä laitetaan cacheen, mitä päästetään läpi. Siellä saa olla return(...) kutsuja tarpeen mukaan
  • all-common.vcl sisältää vain ja ainoastaan kaikille yhteisiä yleisiä suodatuksia ja säätöjä (miksi ne eivät vain löydy default.vcl -tiedostosta, niin en tiedä) eikä sielläkään saisi olla return(...) kutsua.

Lyhyesti sanottuna tuo tarkoittaa vcl_recv sisällön suhteen:

  1. default.vcl: vain headereitten siivoamista
  2. all-common.vcl: yleiset ja yhtäläiset evästeet ja jotain muuta suodatusta
  3. virtual hostien vcl: käytännössä koko vcl_recv siltä osin kuin mitä juuri se sivusto tarvitsee

Huomioitua

Tuolla systeemillä WordPressin graafinen muokkain ei toimi. jos laittaa tämän


# Fix WordPress visual editor issues, must be the first one to work
if (req.url ~ "/wp-(login|admin|comments-post.php|cron)" || req.url ~ "preview=true" || req.url ~ "xmlrpc.php") {
return (pass);
}

virtual hostien .vcl-tiedostoon, niin se ei toimi. Sen on pakko olla default.vcl tiedoston vcl_recv osion alussa – ja sitähän ei saanut tehdä, koska cache ei toimi ja maailma tuhoutuu. Laitoin silti. Kun kokeilin, niin sivut menivät aivan nätisti välimuistiin. Valinnanvaraa ei kuitenkaan ole, koska WYSIWYG muokkain on pakko olla, jos meinaa kirjoittaa.

En oikein täysin ymmärrä tämän virityksen ideaa. Se on varmasti hyödyllinen, jos kytkee yhteen erityyppisiä palveluja. Jossain on web-sivut, jossain java-palvelin ja jossain joku muu hilavitkutin. Mutta kun samassa dropletissa pyörii useampi sivusto, jotka ovat kaikki Worodress-asennuksia ja yksi Moodle, joka ei mene välimuistiin vaikka yrittäisi, niin ei tämä paljoakaan hyödyllisiä asioita palvele.

Nyt täytyy muistaa, että jos Varnish saa sivun https://www.katiska.info/joku ja sitten https://www.eksis.one/muu niin ei se piittaa. Varnish käsittelee niitä ”vain” verkkosivuina  ja lätkii niitä toisiinsa sotkematta välimuistiin. Yhdessä tekstissä sanottiin, että pitämällä virtual hostit erikseen, niin jos vaikka yhdellä sivustolla ei ole kommentointia, niin silloin sinne saadaan tehokkaampi välimuisti, koska komenntoinnin eväste saadaan hukattua, eikä se estä Varnishia tekemästä töitään. Mutta eihän tuo pidä paikkaansa. Jos sivustolla on kommentointi estetty, niin moista evästettä ei tule muutenkaan.

Olen tunnin seurannut Varnishin välimuistin rakentumista. Toki tätä kirjoitettaessa on yö ja liikennettä vähän, mutta ehkä juurikin tuosta visuaalisen editorin fiksauksesta johtuen välimuistissa on noin 10 %, kun normaalisti ollaan 70 – 80 %. Tai sitten liikkeellä on vain yksittäisiä surffareita, eikä kukaan eksy toista kertaa jo välimuistissa olevaan.

Summa summarum – en hypi riemusta kiljuen. Olen uhrannut tähän kokeiluun melkoisesti tunteja ja hyöty on… nippu hankalammin ylläpidettäviä vcl-tiedostoja.