Skip to content

aymanbagabas/go-git-daemon

Repository files navigation

Git Daemon

Latest Release Go Docs Go Report Card

This is a Go implementation of the Git Transport protocol and git-daemon binary. It is meant to be used as a Go library to replace git-daemon, but can also be used as a binary to serve repositories using git transport.

Dependencies

The default handler uses the git binary underneath. Specifically, git-upload-pack, git-upload-archive, and git-receive-pack. The git binary is optional if you're using a pure-go implementation, for example go-git, to handle these requests.

Usage

To import this package as a library

go get github.com/aymanbagabas/go-git-daemon

And then import it in your project

import (
    daemon "github.com/aymanbagabas/go-git-daemon"
)

To install the git-daemon binary

go install github.com/aymanbagabas/go-git-daemon/cmd/git-daemon@latest

Binary usage

Usage of git-daemon:
      --access-hook string       run external command to authorize access
      --base-path string         base path for all repositories
      --disable stringArray      disable a service
      --enable stringArray       enable a service
      --export-all               export all repositories
      --host string              the server hostname to advertise (default "localhost")
      --idle-timeout int         timeout (in seconds) between each read/write request
      --init-timeout int         timeout (in seconds) between the moment the connection is established and the client request is received
      --listen string            listen on the given address (default ":9418")
      --log-destination string   log destination (default "stderr")
      --max-connections int      maximum number of simultaneous connections (default 32)
      --max-timeout int          timeout (in seconds) the total time the connection is allowed to be open
      --strict-paths             match paths exactly
      --timeout int              timeout (in seconds) for specific client sub-requests
      --verbose                  enable verbose logging

Examples

To use this as a server

package main

import (
    "log"

    daemon "github.com/aymanbagabas/go-git-daemon"
)

func main() {
    // Enable upload-archive
    daemon.Enable(daemon.UploadArchiveService)

    // Start server on the default port :9418
    if err := daemon.ListenAndServe(":9418"); err != nil {
        log.Fatal(err)
    }
}

Or create a new server instance with custom options and access hook

package main

import (
    "log"

    daemon "github.com/aymanbagabas/go-git-daemon"
)

func accessHook(service Service, path string, host string, canoHost string, ipAdd string, port string, remoteAddr string) error {
    log.Printf("[%s] Requesting access to %s from %s (%s)", service, path, remoteAddr, host)

    // deny any push access except to "public.git"
    if service == daemon.ReceivePackService && path != "/srv/git/public.git" {
        return fmt.Errorf("access denied")
    }

    // deny all push/fetch access to "private.git"
    if path == "/srv/git/private.git" {
        return fmt.Errorf("access denied")
    }

    return nil // allow access
}

func main() {
    logger := log.Default()
    logger.SetPrefix("[git-daemon] ")

    // Create a new server instance
    server := daemon.Server{
        MaxConnections:       0,                                  // unlimited concurrent connections
        Timeout:              3,                                  // 3 seconds timeout
        BasePath:             "/srv/git",                         // base path for all repositories
        ExportAll:            true,                               // export all repositories
        AccessHook:           accessHook,                         // use a custom access hook
        Logger:               logger,                             // use logger
        //Verbose:              true,                             // enable verbose logging
    }

    // Enable all services 💃
    server.Enable(daemon.UploadPackService)
    server.Enable(daemon.UploadArchiveService)
    server.Enable(daemon.ReceivePackService)

    // Start server on the default port (9418)
    if err := server.ListenAndServe("0.0.0.0:9418"); err != nil {
        log.Fatal(err)
    }
}

License

MIT