Recently I switched my home server to GNU Guix, this is a quick guide
on how I setup cgit. Hope this helps some of you.
Why I use GNU Guix for my server
GNU Guix is my preferred system for every machine I use, recently I even switched my home server (back) to Guix. I use my home server to host this blog as well as my cgit instance, so far I recommend using Guix, as a hobbyist, for the following reasons:
Roll backs- I had tried both Gentoo and Debian before for my server, more than once I had one or more of my self hosted services down because an update broke my setup. My time is limited and those breakages would often occur at busy weeks where I didn’t have the time to fix them. With Guix I can just roll back to a previous working generation if an update or a misconfiguration of mine breaks something.
Reproducibility- Define your setup once, run anywhere. I do not want to manually setup anything.
Simplicity- The entirety of Guix code lives in one repo and is almost entirely written in one language, guile scheme. If you find any issues with a service or a package you can redefine it as you like in your configuration.
Why self-host a git server?
Why would you not self-host your own projects? I find it antithetical to the FOSS ethos, and perhaps even ironic, to rely on proprietary platforms for distributing free software.
Hosting a Git server is straightforward and requires minimal resources.
git-http-backend “/” uri issue and fix
Guix has a separate configuration data type for serving Git
repositories over HTTP. Currently, the regex it uses does not allow
the root "/" to be used a URI for serving (ref archive).
The issue is in the (gnu services version-control) module, specifically in this part:
(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
;; ISSUE here: regex won't allow for "/"
(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 ";")
(list "fastcgi_param GIT_CONFIG_GLOBAL "
(plain-file "gitconfig"
(string-append "[safe]\n\tdirectory = " git-root "/*\n"))
";")
"fastcgi_param PATH_INFO $1;"))))))
Thankfully, we can easily resolve this by redefining
(gnu services version-control).
- My changes (diff) to fix this issue, as well as specify git actions:
diff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scm
index a7f40812a6c..e33e5de21f0 100644
--- a/gnu/services/version-control.scm
+++ b/gnu/services/version-control.scm
@@ -235,7 +235,11 @@ (define* (git-http-nginx-location-configuration #:optional
(($ <git-http-configuration> package git-root export-all?
uri-path fcgiwrap-socket)
(nginx-location-configuration
- (uri (string-append "~ /" (string-trim-both uri-path #\/) "(/.*)"))
+ (uri (string-append "~ "
+ (if (string=? uri-path "/")
+ ""
+ (string-append "/" (string-trim-both uri-path #\/)))
+ "/(info/refs|git-upload-pack|git-receive-pack)"))
(body
(list
(list "fastcgi_pass " fcgiwrap-socket ";")
@@ -254,7 +258,7 @@ (define* (git-http-nginx-location-configuration #:optional
(plain-file "gitconfig"
(string-append "[safe]\n\tdirectory = " git-root "/*\n"))
";")
- "fastcgi_param PATH_INFO $1;"))))))
+ "fastcgi_param PATH_INFO $uri;"))))))
;;;
You can find the full module that I use here in my dotfiles repo.
I’d recommend creating your own module and load it by running the following command:
sudo guix system reocnfigure ~/dotfiles/guix/server-config.scm -L ~/dotfiles/guix
Configuring cgit-service-type
Guix provides a cgit service module (gnu services cgit).
A couple things to note:
- You can provide
cssandfaviconusing an external url. You can find the css styling that I use here.
Example cgit-service-type
(define my/git-repos
(list
(repository-cgit-configuration
(url "repo1")
(name "repo1")
(desc "Example Repo 1")
(path "/srv/git/repo1")
(section "Section 1"))
(repository-cgit-configuration
(url "repo2")
(name "repo2")
(desc "Example Repo 2")
(path "/srv/git/repo2")
(homepage "https://myhomepage")
(section "Section 2"))))
(service cgit-service-type
(cgit-configuration
(package cgit)
(root-desc "Root Desc")
(repository-directory "")
(root-title "Root Title")
(repositories my/git-repos)
(enable-index-owner? #f)
(enable-http-clone? #f)
(clone-prefix '("https://git.thanosapollo.org")) ;; change this to your own url
;; Cache
(cache-root "/var/cache/cgit")
;; 20000 = 5 hours. Feel free to adjust this.
(cache-size 20000)
(cache-static-ttl 20000)
(cache-dynamic-ttl 20000)
(cache-repo-ttl 20000)
(cache-root-ttl 20000)
(cache-scanrc-ttl 20000)
(cache-about-ttl 20000)
(cache-snapshot-ttl 20000)
(case-sensitive-sort? #f)
(css "https://thanosapollo.org/cgit.css") ;; My personal css.
(nginx
(list
(nginx-server-configuration
(server-name '("git.thanosapollo.org"))
(root cgit)
(try-files (list "$uri" "@cgit"))
;; I use cloudflare tunnel, which handles certs for me.
(listen '("80"))
(ssl-certificate #f)
(ssl-certificate-key #f)
;; ;; If you use certbot try the following:
;; (listen '("443 ssl"))
;; (ssl-certificate
;; "/etc/certs/git.my-host.org/fullchain.pem")
;; (ssl-certificate-key
;; "/etc/certs/git.my-host.org/privkey.pem")
(locations
(list
(nginx-location-configuration
(uri "@cgit")
(body '("fastcgi_param SCRIPT_FILENAME $document_root/lib/cgit/cgit.cgi;"
"fastcgi_param PATH_INFO $uri;"
"fastcgi_param QUERY_STRING $args;"
"fastcgi_param HTTP_HOST $server_name;"
"fastcgi_pass 127.0.0.1:9000;")))
(git-http-nginx-location-configuration
(git-http-configuration
(uri-path "/")
(export-all? #t))))))))))
You can find my home server configuration here.