From 3b97a1779f3b65d582b8edc8c154b6414314b946 Mon Sep 17 00:00:00 2001 From: Marius Bakke Date: Sun, 26 Aug 2018 23:33:48 +0200 Subject: services: Add Varnish service. * gnu/services/web.scm (): New record type. (%varnish-accounts, %varnish-service-type): New variables. (varnish-shepherd-service): New procedure. * gnu/tests/web.scm (%varnish-vcl, %varnish-os): New variables. (%test-varnish): New test. * doc/guix.texi (Web Services): Document it. --- doc/guix.texi | 80 +++++++++++++++++++++++++++++++++++++++++++ gnu/services/web.scm | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++- gnu/tests/web.scm | 41 ++++++++++++++++++++++ 3 files changed, 216 insertions(+), 1 deletion(-) diff --git a/doc/guix.texi b/doc/guix.texi index 76ec718b07..6b4b06f46d 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -16888,6 +16888,86 @@ body of a named location block cannot contain location blocks. @end table @end deftp +@subsubheading Varnish Cache +@cindex Varnish +Varnish is a fast cache server that sits in between web applications +and end users. It proxies requests from clients and caches the +accessed URLs such that multiple requests for the same resource only +creates one request to the back-end. + +@defvr {Scheme Variable} varnish-service-type +Service type for the Varnish daemon. +@end defvr + +@deftp {Data Type} varnish-configuration +Data type representing the @code{varnish} service configuration. +This type has the following parameters: + +@table @asis +@item @code{package} (default: @code{varnish}) +The Varnish package to use. + +@item @code{name} (default: @code{"default"}) +A name for this Varnish instance. Varnish will create a directory in +@file{/var/varnish/} with this name and keep temporary files there. If +the name starts with a forward slash, it is interpreted as an absolute +directory name. + +Pass the @code{-n} argument to other Varnish programs to connect to the +named instance, e.g. @command{varnishncsa -n default}. + +@item @code{backend} (default: @code{"localhost:8080"}) +The backend to use. This option has no effect if @code{vcl} is set. + +@item @code{vcl} (default: #f) +The @dfn{VCL} (Varnish Configuration Language) program to run. If this +is @code{#f}, Varnish will proxy @code{backend} using the default +configuration. Otherwise this must be a file-like object with valid +VCL syntax. + +@c Varnish does not support HTTPS, so keep this URL to avoid confusion. +For example, to mirror @url{http://www.gnu.org,www.gnu.org} with VCL you +can do something along these lines: + +@example +(define %gnu-mirror + (plain-file + "gnu.vcl" + "vcl 4.1; +backend gnu @{ .host = "www.gnu.org"; @}")) + +(operating-system + ... + (services (cons (service varnish-service-type + (varnish-configuration + (listen '(":80")) + (vcl %gnu-mirror))) + %base-services))) +@end example + +The configuration of an already running Varnish instance can be inspected +and changed using the @command{varnishadm} program. + +Consult the @url{https://varnish-cache.org/docs/,Varnish User Guide} and +@url{https://book.varnish-software.com/4.0/,Varnish Book} for +comprehensive documentation on Varnish and its configuration language. + +@item @code{listen} (default: @code{'("localhost:80")}) +List of addresses Varnish will listen on. + +@item @code{storage} (default: @code{'("malloc,128m")}) +List of storage backends that will be available in VCL. + +@item @code{parameters} (default: @code{'()}) +List of run-time parameters in the form @code{'(("parameter" . "value"))}. + +@item @code{extra-options} (default: @code{'()}) +Additional arguments to pass to the @command{varnishd} process. + +@end table +@end deftp + +@subsubheading FastCGI @cindex fastcgi @cindex fcgiwrap FastCGI is an interface between the front-end and the back-end of a web diff --git a/gnu/services/web.scm b/gnu/services/web.scm index 1c38e7d8d3..1edb1f4d34 100644 --- a/gnu/services/web.scm +++ b/gnu/services/web.scm @@ -8,6 +8,7 @@ ;;; Copyright © 2017, 2018 Clément Lassieur ;;; Copyright © 2018 Pierre-Antoine Rouby ;;; Copyright © 2017 Christopher Baines +;;; Copyright © 2018 Marius Bakke ;;; ;;; This file is part of GNU Guix. ;;; @@ -190,7 +191,21 @@ tailon-configuration-config-file tailon-configuration-package - tailon-service-type)) + tailon-service-type + + + varnish-configuration + varnish-configuration? + varnish-configuration-package + varnish-configuration-name + varnish-configuration-backend + varnish-configuration-vcl + varnish-configuration-listen + varnish-configuration-storage + varnish-configuration-parameters + varnish-configuration-extra-options + + varnish-service-type)) ;;; Commentary: ;;; @@ -1162,3 +1177,82 @@ files.") (files (append (tailon-configuration-file-files old-config-file) files)))))))) (default-value (tailon-configuration)))) + + +;;; +;;; Varnish +;;; + +(define-record-type* + varnish-configuration make-varnish-configuration + varnish-configuration? + (package varnish-configuration-package ; + (default varnish)) + (name varnish-configuration-name ;string + (default "default")) + (backend varnish-configuration-backend ;string + (default "localhost:8080")) + (vcl varnish-configuration-vcl ;#f | + (default #f)) + (listen varnish-configuration-listen ;list of strings + (default '("localhost:80"))) + (storage varnish-configuration-storage ;list of strings + (default '("malloc,128m"))) + (parameters varnish-configuration-parameters ;list of string pairs + (default '())) + (extra-options varnish-configuration-extra-options ;list of strings + (default '()))) + +(define %varnish-accounts + (list (user-group + (name "varnish") + (system? #t)) + (user-account + (name "varnish") + (group "varnish") + (system? #t) + (comment "Varnish Cache User") + (home-directory "/var/varnish") + (shell (file-append shadow "/sbin/nologin"))))) + +(define varnish-shepherd-service + (match-lambda + (($ package name backend vcl listen storage + parameters extra-options) + (list (shepherd-service + (provision (list (symbol-append 'varnish- (string->symbol name)))) + (documentation (string-append "The Varnish Web Accelerator" + " (" name ")")) + (requirement '(networking)) + (start #~(make-forkexec-constructor + (list #$(file-append package "/sbin/varnishd") + "-n" #$name + #$@(if vcl + #~("-f" #$vcl) + #~("-b" #$backend)) + #$@(append-map (lambda (a) (list "-a" a)) listen) + #$@(append-map (lambda (s) (list "-s" s)) storage) + #$@(append-map (lambda (p) + (list "-p" (format #f "~a=~a" + (car p) (cdr p)))) + parameters) + #$@extra-options) + ;; Varnish will drop privileges to the "varnish" user when + ;; it exists. Not passing #:user here allows the service + ;; to bind to ports < 1024. + #:pid-file (if (string-prefix? "/" #$name) + (string-append #$name "/_.pid") + (string-append "/var/varnish/" #$name "/_.pid")))) + (stop #~(make-kill-destructor))))))) + +(define varnish-service-type + (service-type + (name 'varnish) + (description "Run the Varnish cache server.") + (extensions + (list (service-extension account-service-type + (const %varnish-accounts)) + (service-extension shepherd-root-service-type + varnish-shepherd-service))) + (default-value + (varnish-configuration)))) diff --git a/gnu/tests/web.scm b/gnu/tests/web.scm index 45fcb668fb..bcc919137b 100644 --- a/gnu/tests/web.scm +++ b/gnu/tests/web.scm @@ -32,6 +32,7 @@ #:use-module (guix store) #:export (%test-httpd %test-nginx + %test-varnish %test-php-fpm %test-hpcguix-web %test-tailon)) @@ -167,6 +168,46 @@ HTTP-PORT." (value (run-webserver-test name %nginx-os #:log-file "/var/log/nginx/access.log")))) + +;;; +;;; Varnish +;;; + +(define %varnish-vcl + (mixed-text-file + "varnish-test.vcl" + "vcl 4.0; +backend dummy { .host = \"127.1.1.1\"; } +sub vcl_recv { return(synth(200, \"OK\")); } +sub vcl_synth { + synthetic(\"" %index.html-contents "\"); + set resp.http.Content-Type = \"text/plain\"; + return(deliver); +}")) + +(define %varnish-os + (simple-operating-system + (dhcp-client-service) + ;; Pretend to be a web server that serves %index.html-contents. + (service varnish-service-type + (varnish-configuration + (name "/tmp/server") + ;; Use a small VSL buffer to fit in the test VM. + (parameters '(("vsl_space" . "4M"))) + (vcl %varnish-vcl))) + ;; Proxy the "server" using the builtin configuration. + (service varnish-service-type + (varnish-configuration + (parameters '(("vsl_space" . "4M"))) + (backend "localhost:80") + (listen '(":8080")))))) + +(define %test-varnish + (system-test + (name "varnish") + (description "Test the Varnish Cache server.") + (value (run-webserver-test "varnish-default" %varnish-os)))) + ;;; ;;; PHP-FPM -- cgit v1.2.3