diff mbox

gnu: services: Add git-service.

Message ID 20161120105529.30792-1-iyzsong@member.fsf.org
State New
Headers show

Commit Message

=?utf-8?B?5a6L5paH5q2m?= Nov. 20, 2016, 10:55 a.m. UTC
From: ng0 <ng0@we.make.ritual.n0.is>

* gnu/services/version-control.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
* doc/guix.texi (Misellaneous Services)(Version Control): New section.

Co-authored-by: 宋文武 <iyzsong@member.fsf.org>
---
 doc/guix.texi                    |  61 +++++++++++++++++
 gnu/local.mk                     |   1 +
 gnu/services/version-control.scm | 141 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 203 insertions(+)
 create mode 100644 gnu/services/version-control.scm

Comments

Mathieu Lirzin Nov. 20, 2016, 11:28 a.m. UTC | #1
Hello,

宋文武 <iyzsong@member.fsf.org> writes:

> From: ng0 <ng0@we.make.ritual.n0.is>
>
> * gnu/services/version-control.scm: New file.
> * gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
> * doc/guix.texi (Misellaneous Services)(Version Control): New section.

but I find this notation confusing, since "Version Control" belongs to
"Miscellaneous Services".  @node identifiers are unique, so it is
reasonable to refers to them with '()', and use '<>' for their parts as
suggested by GCS:

  https://www.gnu.org/prep/standards/html_node/Indicating-the-Part-Changed.html#Indicating-the-Part-Changed

Thanks.
Mathieu Lirzin Nov. 20, 2016, 11:32 a.m. UTC | #2
Mathieu Lirzin <mthl@gnu.org> writes:

> 宋文武 <iyzsong@member.fsf.org> writes:
>
>> From: ng0 <ng0@we.make.ritual.n0.is>
>>
>> * gnu/services/version-control.scm: New file.
>> * gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
>> * doc/guix.texi (Misellaneous Services)(Version Control): New section.
>
> but I find this notation confusing, since "Version Control" belongs to
  ^^^
Please ignore this "but" that shouldn't be here.
=?utf-8?B?5a6L5paH5q2m?= Nov. 20, 2016, 12:05 p.m. UTC | #3
Mathieu Lirzin <mthl@gnu.org> writes:

> Mathieu Lirzin <mthl@gnu.org> writes:
>
>> 宋文武 <iyzsong@member.fsf.org> writes:
>>
>>> From: ng0 <ng0@we.make.ritual.n0.is>
>>>
>>> * gnu/services/version-control.scm: New file.
>>> * gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
>>> * doc/guix.texi (Misellaneous Services)(Version Control): New section.
>>
>> but I find this notation confusing, since "Version Control" belongs to
>   ^^^
> Please ignore this "but" that shouldn't be here.

Thanks!  I'll change it to '[Version Control]'.
non such Nov. 20, 2016, 12:28 p.m. UTC | #4
宋文武 <iyzsong@member.fsf.org> writes:

> From: ng0 <ng0@we.make.ritual.n0.is>
>
> * gnu/services/version-control.scm: New file.
> * gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
> * doc/guix.texi (Misellaneous Services)(Version Control): New section.
>
> Co-authored-by: 宋文武 <iyzsong@member.fsf.org>

Thanks! As reply to the mssage you've sent before this one: I'm
okay with the changes. My intention with the services I'm working
on is to learn and improve my knowledge on how service for Guix
are written and work.

> ---
>  doc/guix.texi                    |  61 +++++++++++++++++
>  gnu/local.mk                     |   1 +
>  gnu/services/version-control.scm | 141 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 203 insertions(+)
>  create mode 100644 gnu/services/version-control.scm
>
> diff --git a/doc/guix.texi b/doc/guix.texi
> index 7352ea9..9353a4c 100644
> --- a/doc/guix.texi
> +++ b/doc/guix.texi
> @@ -11673,6 +11673,67 @@ A @code{<dicod-database>} object serving the GNU Collaborative International
>  Dictonary of English using the @code{gcide} package.
>  @end defvr
>  
> +@subsubsection Version Control
> +
> +The @code{(gnu services version-control)} module provides the following services:
> +
> +@subsubheading Git daemon service
> +
> +@deffn {Scheme Procedure} git-daemon-service [#:config (git-daemon-configuration)]
> +
> +Return a service that runs @command{git daemon}, a simple TCP server to
> +expose repositiories over the Git protocol for annoymous access.
> +
> +The optional @var{config} argument should be a
> +@code{<git-daemon-configuration>} object, by default it allows read-only
> +access to exported@footnote{By creating the magic file
> +"git-daemon-export-ok" in the repository directory.} repositories under
> +@file{/srv/git}.
> +
> +@end deffn
> +
> +@deftp {Data Type} git-daemon-configuration
> +Data type representing the configuration of git-demon.

Typo, it should be "git-daemon".

> +
> +@table @asis
> +@item @code{package} (default: @var{git})
> +Package object of the Git distributed version control system.
> +
> +@item @code{export-all?} (default: @var{#f})
> +Whether to allow access for all Git repositories, even if they do not
> +have the @file{git-daemon-export-ok} file.
> +
> +@item @code{base-path} (default: @file{/srv/git})

Why /srv ? Will the other services (mail, web, etc) use /srv
aswell or do they use /var ? I used /var/git because of /var/www
and iirc this is also in the upstream documentation.

> +Whether to remap all the path requests as relative to the given path.
> +If you run git daemon with @var{(base-path "/srv/git")} on example.com,
> +then if you later try to pull @code{git://example.com/hello.git}, git
> +daemon will interpret the path as @code{/srv/git/hello.git}.
> +
> +@item @code{user-path} (default: @var{#f})
> +Whether to allow @code{~user} notation to be used in requests.  When
> +specified with empty string, requests to @code{git://host/~alice/foo} is
> +taken as a request to access @code{foo} repository in the home directory
> +of user @code{alice}.  If @var{(user-path "path")} is specified, the
> +same request is taken as a request to access @code{path/foo} repository
> +in the home directory of user @code{alice}.
> +
> +@item @code{listen} (default: @var{'()})
> +Whether to listen on specific IP addresses or hostnames, defaults to
> +all.
> +
> +@item @code{port} (default: @var{#f})
> +Whether to listen on an alternative port, which defaults to 9418.
> +
> +@item @code{whitelist} (default: @var{'()})
> +If not empty, only allow access to this list of directories.
> +
> +@item @code{extra-options} (default: @var{'()})
> +Extra options will be passed to @code{git daemon}, please run
> +@command{man git-daemon} for more information.

Ah, nice. So you basically ended up with what I wanted in the
first revision of the git-service.
Documentation looks good to me except this one question about
location, and the one typo.

> +
> +@end table
> +@end deftp
> +
>  @node Setuid Programs
>  @subsection Setuid Programs
>  
> diff --git a/gnu/local.mk b/gnu/local.mk
> index 7112451..8769671 100644
> --- a/gnu/local.mk
> +++ b/gnu/local.mk
> @@ -415,6 +415,7 @@ GNU_SYSTEM_MODULES =				\
>    %D%/services/sddm.scm				\
>    %D%/services/spice.scm				\
>    %D%/services/ssh.scm				\
> +  %D%/services/version-control.scm              \
>    %D%/services/web.scm				\
>    %D%/services/xorg.scm				\
>  						\
> diff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scm
> new file mode 100644
> index 0000000..65bdefb
> --- /dev/null
> +++ b/gnu/services/version-control.scm
> @@ -0,0 +1,141 @@
> +;;; GNU Guix --- Functional package management for GNU
> +;;; Copyright © 2016 ng0 <ng0@we.make.ritual.n0.is>
> +;;; Copyright © 2016 Sou Bunnbu <iyzsong@member.fsf.org>
> +;;;
> +;;; This file is part of GNU Guix.
> +;;;
> +;;; GNU Guix is free software; you can redistribute it and/or modify it
> +;;; under the terms of the GNU General Public License as published by
> +;;; the Free Software Foundation; either version 3 of the License, or (at
> +;;; your option) any later version.
> +;;;
> +;;; GNU Guix is distributed in the hope that it will be useful, but
> +;;; WITHOUT ANY WARRANTY; without even the implied warranty of
> +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +;;; GNU General Public License for more details.
> +;;;
> +;;; You should have received a copy of the GNU General Public License
> +;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
> +
> +(define-module (gnu services version-control)
> +  #:use-module (gnu services)
> +  #:use-module (gnu services base)
> +  #:use-module (gnu services shepherd)
> +  #:use-module (gnu system shadow)
> +  #:use-module (gnu packages version-control)
> +  #:use-module (gnu packages admin)
> +  #:use-module (guix records)
> +  #:use-module (guix gexp)
> +  #:use-module (srfi srfi-1)
> +  #:use-module (srfi srfi-26)
> +  #:use-module (ice-9 match)
> +  #:export (git-daemon-service
> +            git-daemon-service-type
> +            git-daemon-configuration
> +            git-daemon-configuration?))
> +
> +;;; Commentary:
> +;;;
> +;;; Version Control related services.
> +;;;
> +;;; Code:
> +
> +
> +;;;
> +;;; Git daemon.
> +;;;
> +
> +(define-record-type* <git-daemon-configuration>
> +  git-daemon-configuration
> +  make-git-daemon-configuration
> +  git-daemon-configuration?
> +  (package          git-daemon-configuration-package        ;package
> +                    (default git))
> +  (export-all?      git-daemon-configuration-export-all     ;boolean
> +                    (default #f))
> +  (base-path        git-daemon-configuration-base-path      ;string | #f
> +                    (default "/srv/git"))
> +  (user-path        git-daemon-configuration-user-path      ;string | #f
> +                    (default #f))
> +  (listen           git-daemon-configuration-listen         ;list of string
> +                    (default '()))
> +  (port             git-daemon-configuration-port           ;number | #f
> +                    (default #f))
> +  (whitelist        git-daemon-configuration-whitelist      ;list of string
> +                    (default '()))
> +  (extra-options    git-daemon-configuration-extra-options  ;list of string
> +                    (default '())))
> +
> +(define git-daemon-shepherd-service
> +  (match-lambda
> +    (($ <git-daemon-configuration>
> +        package export-all? base-path user-path
> +        listen port whitelist extra-options)
> +     (let* ((git     (file-append package "/bin/git"))
> +            (command `(,git
> +                       "daemon" "--syslog" "--reuseaddr"
> +                       ,@(if export-all?
> +                             '("--export-all")
> +                             '())
> +                       ,@(if base-path
> +                             `(,(string-append "--base-path=" base-path))
> +                             '())
> +                       ,@(if user-path
> +                             `(,(string-append "--user-path=" user-path))
> +                             '())
> +                       ,@(map (cut string-append "--listen=" <>) listen)
> +                       ,@(if port
> +                             `(,(string-append
> +                                 "--port=" (number->string port)))
> +                             '())
> +                       ,@extra-options
> +                       ,@whitelist)))
> +       (list (shepherd-service
> +              (documentation "Git daemon server")
> +              (requirement '(networking))
> +              (provision '(git-daemon))
> +              (start #~(make-forkexec-constructor '#$command
> +                                                  #:user "git-daemon"
> +                                                  #:group "git-daemon"))
> +              (stop #~(make-kill-destructor))))))))
> +
> +(define %git-daemon-accounts
> +  ;; User account and group for git-daemon.
> +  (list (user-group
> +         (name "git-daemon")
> +         (system? #t))
> +        (user-account
> +         (name "git-daemon")
> +         (system? #t)
> +         (group "git-daemon")
> +         (comment "Git daemon user")
> +         (home-directory "/var/empty")
> +         (shell (file-append shadow "/sbin/nologin")))))

Why? I think it should have a home (/var/git (or whereever else))
and use the git-shell so that the ssh functionality is enabled,
which can be used for minimal servers, so you don't actually need
to add the git account.
It's also expected that the name is "git" for this reason and not
"git-daemon".
iirc this affects more software than just git-daemon, every scm
which does not ship its own git daemon uses "git-daemon" by git
upstream. It's reasonable not to break with expectations (and
keep the name short) and give it the name "git", group-name could
be anything though.

> +
> +(define (git-daemon-activation config)
> +  "Return the activation gexp for git-daemon using CONFIG."
> +  (let ((base-path (git-daemon-configuration-base-path config)))
> +    #~(begin
> +        (use-modules (guix build utils))
> +        ;; Create the 'base-path' directory when it's not '#f'.
> +        (and=> #$base-path mkdir-p))))
> +
> +(define git-daemon-service-type
> +  (service-type
> +   (name 'git-daemon)
> +   (extensions
> +    (list (service-extension shepherd-root-service-type
> +                             git-daemon-shepherd-service)
> +          (service-extension account-service-type
> +                             (const %git-daemon-accounts))
> +          (service-extension activation-service-type
> +                             git-daemon-activation)))))
> +
> +(define* (git-daemon-service #:key (config (git-daemon-configuration)))
> +  "Return a service that runs @command{git daemon}, a simple TCP server to
> +expose repositories over the Git protocol for annoymous access.
> +
> +The optional @var{config} argument should be a
> +@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))

Simple, easy to understand. Thanks for fixing my initial work up.
=?utf-8?B?5a6L5paH5q2m?= Nov. 20, 2016, 12:59 p.m. UTC | #5
ng0 <ng0@we.make.ritual.n0.is> writes:

>> [...]
>> +
>> +@deftp {Data Type} git-daemon-configuration
>> +Data type representing the configuration of git-demon.
>
> Typo, it should be "git-daemon".
>

OK.
>> +
>> +@table @asis
>> +@item @code{package} (default: @var{git})
>> +Package object of the Git distributed version control system.
>> +
>> +@item @code{export-all?} (default: @var{#f})
>> +Whether to allow access for all Git repositories, even if they do not
>> +have the @file{git-daemon-export-ok} file.
>> +
>> +@item @code{base-path} (default: @file{/srv/git})
>
> Why /srv ? Will the other services (mail, web, etc) use /srv
> aswell or do they use /var ? I used /var/git because of /var/www
> and iirc this is also in the upstream documentation.
>

it's for serving files to public, our nginx-service use '/srv/http' too.

> [...]
>
> Ah, nice. So you basically ended up with what I wanted in the
> first revision of the git-service.
> Documentation looks good to me except this one question about
> location, and the one typo.

Cool, thanks for your work and feedback!

>> [...]
>> +(define %git-daemon-accounts
>> +  ;; User account and group for git-daemon.
>> +  (list (user-group
>> +         (name "git-daemon")
>> +         (system? #t))
>> +        (user-account
>> +         (name "git-daemon")
>> +         (system? #t)
>> +         (group "git-daemon")
>> +         (comment "Git daemon user")
>> +         (home-directory "/var/empty")
>> +         (shell (file-append shadow "/sbin/nologin")))))
>
> Why? I think it should have a home (/var/git (or whereever else))
> and use the git-shell so that the ssh functionality is enabled,
> which can be used for minimal servers, so you don't actually need
> to add the git account.
> It's also expected that the name is "git" for this reason and not
> "git-daemon".
> iirc this affects more software than just git-daemon, every scm
> which does not ship its own git daemon uses "git-daemon" by git
> upstream. It's reasonable not to break with expectations (and
> keep the name short) and give it the name "git", group-name could
> be anything though.
>

Um, the git-daemon really has nothing to do with git-shell and ssh
access.  If I have ssh service running, I can access all the
repositories the login user can access without git-daemon.  If I want
annoymous ssh access, I can add a 'git' user using 'git-shell', which
rely the exist ssh service, so I leave it..  hope it make sense.


Thanks!
non such Nov. 20, 2016, 1:29 p.m. UTC | #6
iyzsong@member.fsf.org (宋文武) writes:

> ng0 <ng0@we.make.ritual.n0.is> writes:
>
>>> [...]
>>> +
>>> +@deftp {Data Type} git-daemon-configuration
>>> +Data type representing the configuration of git-demon.
>>
>> Typo, it should be "git-daemon".
>>
>
> OK.
>>> +
>>> +@table @asis
>>> +@item @code{package} (default: @var{git})
>>> +Package object of the Git distributed version control system.
>>> +
>>> +@item @code{export-all?} (default: @var{#f})
>>> +Whether to allow access for all Git repositories, even if they do not
>>> +have the @file{git-daemon-export-ok} file.
>>> +
>>> +@item @code{base-path} (default: @file{/srv/git})
>>
>> Why /srv ? Will the other services (mail, web, etc) use /srv
>> aswell or do they use /var ? I used /var/git because of /var/www
>> and iirc this is also in the upstream documentation.
>>
>
> it's for serving files to public, our nginx-service use '/srv/http' too.

That's okay for me then.

>> [...]
>>
>> Ah, nice. So you basically ended up with what I wanted in the
>> first revision of the git-service.
>> Documentation looks good to me except this one question about
>> location, and the one typo.
>
> Cool, thanks for your work and feedback!
>
>>> [...]
>>> +(define %git-daemon-accounts
>>> +  ;; User account and group for git-daemon.
>>> +  (list (user-group
>>> +         (name "git-daemon")
>>> +         (system? #t))
>>> +        (user-account
>>> +         (name "git-daemon")
>>> +         (system? #t)
>>> +         (group "git-daemon")
>>> +         (comment "Git daemon user")
>>> +         (home-directory "/var/empty")
>>> +         (shell (file-append shadow "/sbin/nologin")))))
>>
>> Why? I think it should have a home (/var/git (or whereever else))
>> and use the git-shell so that the ssh functionality is enabled,
>> which can be used for minimal servers, so you don't actually need
>> to add the git account.
>> It's also expected that the name is "git" for this reason and not
>> "git-daemon".
>> iirc this affects more software than just git-daemon, every scm
>> which does not ship its own git daemon uses "git-daemon" by git
>> upstream. It's reasonable not to break with expectations (and
>> keep the name short) and give it the name "git", group-name could
>> be anything though.
>>
>
> Um, the git-daemon really has nothing to do with git-shell and ssh
> access.  If I have ssh service running, I can access all the
> repositories the login user can access without git-daemon.  If I want
> annoymous ssh access, I can add a 'git' user using 'git-shell', which
> rely the exist ssh service, so I leave it..  hope it make sense.
>
>
> Thanks!
>

Okay, I can understand this. If there should be the need to
change this, we can always apply it later.

Looks good to me, just the one typo which can be fixed before
applying. I will build a vm with this later to verify that it
works, but in theory it should just work.
non such Nov. 20, 2016, 6:40 p.m. UTC | #7
ng0 <ng0@we.make.ritual.n0.is> writes:

> Looks good to me, just the one typo which can be fixed before
> applying. I will build a vm with this later to verify that it
> works, but in theory it should just work.

I have problems testing this. Any system configuration I tried so
far silently fails, does not get build, nothing happens not even
an error message.
Even after make clean and bootstraping again etc.
./pre-inst-env guix system vm ~/configgit.scm
For vm-image it is the same.

Do you have a configuration I could test to use it with?
diff mbox

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index 7352ea9..9353a4c 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -11673,6 +11673,67 @@  A @code{<dicod-database>} object serving the GNU Collaborative International
 Dictonary of English using the @code{gcide} package.
 @end defvr
 
+@subsubsection Version Control
+
+The @code{(gnu services version-control)} module provides the following services:
+
+@subsubheading Git daemon service
+
+@deffn {Scheme Procedure} git-daemon-service [#:config (git-daemon-configuration)]
+
+Return a service that runs @command{git daemon}, a simple TCP server to
+expose repositiories over the Git protocol for annoymous access.
+
+The optional @var{config} argument should be a
+@code{<git-daemon-configuration>} object, by default it allows read-only
+access to exported@footnote{By creating the magic file
+"git-daemon-export-ok" in the repository directory.} repositories under
+@file{/srv/git}.
+
+@end deffn
+
+@deftp {Data Type} git-daemon-configuration
+Data type representing the configuration of git-demon.
+
+@table @asis
+@item @code{package} (default: @var{git})
+Package object of the Git distributed version control system.
+
+@item @code{export-all?} (default: @var{#f})
+Whether to allow access for all Git repositories, even if they do not
+have the @file{git-daemon-export-ok} file.
+
+@item @code{base-path} (default: @file{/srv/git})
+Whether to remap all the path requests as relative to the given path.
+If you run git daemon with @var{(base-path "/srv/git")} on example.com,
+then if you later try to pull @code{git://example.com/hello.git}, git
+daemon will interpret the path as @code{/srv/git/hello.git}.
+
+@item @code{user-path} (default: @var{#f})
+Whether to allow @code{~user} notation to be used in requests.  When
+specified with empty string, requests to @code{git://host/~alice/foo} is
+taken as a request to access @code{foo} repository in the home directory
+of user @code{alice}.  If @var{(user-path "path")} is specified, the
+same request is taken as a request to access @code{path/foo} repository
+in the home directory of user @code{alice}.
+
+@item @code{listen} (default: @var{'()})
+Whether to listen on specific IP addresses or hostnames, defaults to
+all.
+
+@item @code{port} (default: @var{#f})
+Whether to listen on an alternative port, which defaults to 9418.
+
+@item @code{whitelist} (default: @var{'()})
+If not empty, only allow access to this list of directories.
+
+@item @code{extra-options} (default: @var{'()})
+Extra options will be passed to @code{git daemon}, please run
+@command{man git-daemon} for more information.
+
+@end table
+@end deftp
+
 @node Setuid Programs
 @subsection Setuid Programs
 
diff --git a/gnu/local.mk b/gnu/local.mk
index 7112451..8769671 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -415,6 +415,7 @@  GNU_SYSTEM_MODULES =				\
   %D%/services/sddm.scm				\
   %D%/services/spice.scm				\
   %D%/services/ssh.scm				\
+  %D%/services/version-control.scm              \
   %D%/services/web.scm				\
   %D%/services/xorg.scm				\
 						\
diff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scm
new file mode 100644
index 0000000..65bdefb
--- /dev/null
+++ b/gnu/services/version-control.scm
@@ -0,0 +1,141 @@ 
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2016 ng0 <ng0@we.make.ritual.n0.is>
+;;; Copyright © 2016 Sou Bunnbu <iyzsong@member.fsf.org>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu services version-control)
+  #:use-module (gnu services)
+  #:use-module (gnu services base)
+  #:use-module (gnu services shepherd)
+  #:use-module (gnu system shadow)
+  #:use-module (gnu packages version-control)
+  #:use-module (gnu packages admin)
+  #:use-module (guix records)
+  #:use-module (guix gexp)
+  #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-26)
+  #:use-module (ice-9 match)
+  #:export (git-daemon-service
+            git-daemon-service-type
+            git-daemon-configuration
+            git-daemon-configuration?))
+
+;;; Commentary:
+;;;
+;;; Version Control related services.
+;;;
+;;; Code:
+
+
+;;;
+;;; Git daemon.
+;;;
+
+(define-record-type* <git-daemon-configuration>
+  git-daemon-configuration
+  make-git-daemon-configuration
+  git-daemon-configuration?
+  (package          git-daemon-configuration-package        ;package
+                    (default git))
+  (export-all?      git-daemon-configuration-export-all     ;boolean
+                    (default #f))
+  (base-path        git-daemon-configuration-base-path      ;string | #f
+                    (default "/srv/git"))
+  (user-path        git-daemon-configuration-user-path      ;string | #f
+                    (default #f))
+  (listen           git-daemon-configuration-listen         ;list of string
+                    (default '()))
+  (port             git-daemon-configuration-port           ;number | #f
+                    (default #f))
+  (whitelist        git-daemon-configuration-whitelist      ;list of string
+                    (default '()))
+  (extra-options    git-daemon-configuration-extra-options  ;list of string
+                    (default '())))
+
+(define git-daemon-shepherd-service
+  (match-lambda
+    (($ <git-daemon-configuration>
+        package export-all? base-path user-path
+        listen port whitelist extra-options)
+     (let* ((git     (file-append package "/bin/git"))
+            (command `(,git
+                       "daemon" "--syslog" "--reuseaddr"
+                       ,@(if export-all?
+                             '("--export-all")
+                             '())
+                       ,@(if base-path
+                             `(,(string-append "--base-path=" base-path))
+                             '())
+                       ,@(if user-path
+                             `(,(string-append "--user-path=" user-path))
+                             '())
+                       ,@(map (cut string-append "--listen=" <>) listen)
+                       ,@(if port
+                             `(,(string-append
+                                 "--port=" (number->string port)))
+                             '())
+                       ,@extra-options
+                       ,@whitelist)))
+       (list (shepherd-service
+              (documentation "Git daemon server")
+              (requirement '(networking))
+              (provision '(git-daemon))
+              (start #~(make-forkexec-constructor '#$command
+                                                  #:user "git-daemon"
+                                                  #:group "git-daemon"))
+              (stop #~(make-kill-destructor))))))))
+
+(define %git-daemon-accounts
+  ;; User account and group for git-daemon.
+  (list (user-group
+         (name "git-daemon")
+         (system? #t))
+        (user-account
+         (name "git-daemon")
+         (system? #t)
+         (group "git-daemon")
+         (comment "Git daemon user")
+         (home-directory "/var/empty")
+         (shell (file-append shadow "/sbin/nologin")))))
+
+(define (git-daemon-activation config)
+  "Return the activation gexp for git-daemon using CONFIG."
+  (let ((base-path (git-daemon-configuration-base-path config)))
+    #~(begin
+        (use-modules (guix build utils))
+        ;; Create the 'base-path' directory when it's not '#f'.
+        (and=> #$base-path mkdir-p))))
+
+(define git-daemon-service-type
+  (service-type
+   (name 'git-daemon)
+   (extensions
+    (list (service-extension shepherd-root-service-type
+                             git-daemon-shepherd-service)
+          (service-extension account-service-type
+                             (const %git-daemon-accounts))
+          (service-extension activation-service-type
+                             git-daemon-activation)))))
+
+(define* (git-daemon-service #:key (config (git-daemon-configuration)))
+  "Return a service that runs @command{git daemon}, a simple TCP server to
+expose repositories over the Git protocol for annoymous access.
+
+The optional @var{config} argument should be a
+@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))