gnu: Add Git HTTP(S) service support.

* doc/guix.texi (Version Control Services): Add documentation on the HTTP
backend for git.
* gnu/services/version-control.scm (<git-http-configuration>): New data type.
(git-http-nginx-location-configuration): New helper function.
This commit is contained in:
Andy Wingo 2017-04-27 15:02:19 +02:00
parent 80d872ae83
commit cb9f33e2a7
No known key found for this signature in database
GPG key ID: DDC0F5358812F8F2
2 changed files with 132 additions and 2 deletions

View file

@ -14645,7 +14645,11 @@ Defaults to @samp{#f}.
@subsubsection Version Control Services
The @code{(gnu services version-control)} module provides a service to
allow remote access to local Git repositories.
allow remote access to local Git repositories. There are two options:
the @code{git-daemon-service}, which provides access to repositories via
the @code{git://} unsecured TCP-based protocol, or extending the
@code{nginx} web server to proxy some requests to
@code{git-http-backend}.
@deffn {Scheme Procedure} git-daemon-service [#:config (git-daemon-configuration)]
@ -14702,6 +14706,80 @@ Extra options will be passed to @code{git daemon}, please run
@end table
@end deftp
The @code{git://} protocol lacks authentication. When you pull from a
repository fetched via @code{git://}, you don't know that the data you
receive was modified in transit or not. It's better to use an
authenticated transport, such as @code{https}. Although Git allows you
to serve repositories using unsophisticated file-based web servers,
there is a faster protocol implemented by the @code{git-http-backend}
program. This program is the back-end of a proper Git web service. It
is designed to sit behind a FastCGI proxy. @xref{Web Services}, for more
on running the necessary @code{fcgiwrap} daemon.
Guix has a separate configuration data type for serving Git repositories
over HTTP.
@deftp {Data Type} git-http-configuration
Data type representing the configuration for @code{git-http-service}.
@table @asis
@item @code{package} (default: @var{git})
Package object of the Git distributed version control system.
@item @code{git-root} (default: @file{/srv/git})
Directory containing the Git repositories to expose to the world.
@item @code{export-all?} (default: @var{#f})
Whether to expose access for all Git repositories in @var{git-root},
even if they do not have the @file{git-daemon-export-ok} file.
@item @code{uri-path} (default: @file{/git/})
Path prefix for Git access. With the default @code{/git/} prefix, this
will map @code{http://@var{server}/git/@var{repo}.git} to
@code{/srv/git/@var{repo}.git}. Requests whose URI paths do not begin
with this prefix are not passed on to this Git instance.
@item @code{fcgiwrap-socket} (default: @code{127.0.0.1:9000})
The socket on which the @code{fcgiwrap} daemon is listening. @xref{Web
Services}.
@end table
@end deftp
There is no @code{git-http-service-type}, currently; instead you can
create an @code{nginx-location-configuration} from a
@code{git-http-configuration} and then add that location to a web
server.
@deffn {Scheme Procedure} git-http-nginx-location-configuration @
[config=(git-http-configuration)] Compute an
@code{nginx-location-configuration} the corresponds with the given Git
http configuration. An example nginx service definition to serve the
default @file{/srv/git} over HTTPS might be:
@example
(service nginx-service-type
(nginx-configuration
(server-blocks
(list
(nginx-server-configuration
(http-port #f)
(server-name "git.my-host.org")
(ssl-certificate
"/etc/letsencrypt/live/git.my-host.org/fullchain.pem")
(ssl-certificate-key
"/etc/letsencrypt/live/git.my-host.org/privkey.pem")
(locations
(list
(git-http-nginx-location-configuration
(git-http-configuration (uri-path "/"))))))))))
@end example
This example assumes that you are using Let's Encrypt to get your TLS
certificate. @xref{Certificate Services}. The default @code{certbot}
service will redirect all HTTP traffic on @code{git.my-host.org} to
HTTPS. You will also need to add an @code{fcgiwrap} proxy to your
system services. @xref{Web Services}.
@end deffn
@node Miscellaneous Services
@subsubsection Miscellaneous Services

View file

@ -21,6 +21,7 @@ (define-module (gnu services version-control)
#:use-module (gnu services)
#:use-module (gnu services base)
#:use-module (gnu services shepherd)
#:use-module (gnu services web)
#:use-module (gnu system shadow)
#:use-module (gnu packages version-control)
#:use-module (gnu packages admin)
@ -32,7 +33,11 @@ (define-module (gnu services version-control)
#:export (git-daemon-service
git-daemon-service-type
git-daemon-configuration
git-daemon-configuration?))
git-daemon-configuration?
git-http-configuration
git-http-configuration?
git-http-nginx-location-configuration))
;;; Commentary:
;;;
@ -139,3 +144,50 @@ (define* (git-daemon-service #:key (config (git-daemon-configuration)))
@code{<git-daemon-configuration>} object, by default it allows read-only
access to exported repositories under @file{/srv/git}."
(service git-daemon-service-type config))
;;;
;;; HTTP access. Add the result of calling
;;; git-http-nginx-location-configuration to an nginx-server-configuration's
;;; "locations" field.
;;;
(define-record-type* <git-http-configuration>
git-http-configuration
make-git-http-configuration
git-http-configuration?
(package git-http-configuration-package ;package
(default git))
(git-root git-http-configuration-git-root ;string
(default "/srv/git"))
(export-all? git-http-configuration-export-all? ;boolean
(default #f))
(uri-path git-http-configuration-uri-path ;string
(default "/git/"))
(fcgiwrap-socket git-http-configuration-fcgiwrap-socket ;string
(default "127.0.0.1:9000")))
(define* (git-http-nginx-location-configuration #:optional
(config
(git-http-configuration)))
(match config
(($ <git-http-configuration> package git-root export-all?
uri-path fcgiwrap-socket)
(nginx-location-configuration
(uri (string-append "~ /" (string-trim-both uri-path #\/) "(/.*)"))
(body
(list
(list "fastcgi_pass " fcgiwrap-socket ";")
(list "fastcgi_param SCRIPT_FILENAME "
package "/libexec/git-core/git-http-backend"
";")
"fastcgi_param QUERY_STRING $query_string;"
"fastcgi_param REQUEST_METHOD $request_method;"
"fastcgi_param CONTENT_TYPE $content_type;"
"fastcgi_param CONTENT_LENGTH $content_length;"
(if export-all?
"fastcgi_param GIT_HTTP_EXPORT_ALL \"\";"
"")
(list "fastcgi_param GIT_PROJECT_ROOT " git-root ";")
"fastcgi_param PATH_INFO $1;"))))))