\input texinfo @documentencoding UTF-8 @settitle godlighty @copying Copyright @copyright{} 2021 @email{stargrave@@stargrave.org, Sergey Matveev} @end copying @node Top @top godlighty @command{godlighty} is highly-customizable HTTP, HTTP/2, HTTPS server written on pure Go. Why yet another web-server? Because all others suck even for my simple ordinary needs: they use hateful OpenSSL, lacks documentation, has complex configuration format, lack some features, hard to extend with. @itemize @item Rather minimalistic pure-Go web-server with few number of dependencies, producing single statically linked executable. Maximal reuse of native libraries capabilities. @item Modern, reliable, secure and fast TLS 1.3 implementation with ChaCha20-Poly1305, session resumption and SNI. @item If built with @url{http://www.gostls13.cypherpunks.ru/, gostls13}, then @url{http://www.gost.cypherpunks.ru/, GOST} TLS 1.3 cryptography will be fully supported, with ability to use GOST-based X.509 certificates if client announces its knowledge of GOST algorithms (with the fallback to ordinary ECDSA ones). @item HTTP/1.1, @url{https://en.wikipedia.org/wiki/HTTP%2F2, HTTP/2} (only when negotiated during ALPN) and keepalives support. Graceful shutdowns. @item @code{gzip} and @url{https://facebook.github.io/zstd/, Zstandard} compression on-the-fly. @item @code{Range}, @code{ETag} (based on file/directory's @code{ctime}), @code{Last-Modified} and corresponding precondition handlers are fully used. @item Auto-generated directory listings and read-only @url{https://en.wikipedia.org/wiki/WebDAV, WebDAV} support. @item Per-domain HTTP basic authorization and TLS client authentication. @item If corresponding @file{.meta4} files are found, then @code{Link} header is generated automatically to that @url{http://www.metalinker.org/, Metalink}. @item Very friendly to @url{http://cr.yp.to/daemontools.html, daemontools}. Can drop (UID, GID, groups) privileges. @end itemize Basically all configuration is done directly inside source code. You have to recompile it every time configuration changes. Is it a problem? I doubt, because Go is very fast. But it produces huge statically linked executables, you say! Use @command{bsdiff}/@command{bspatch}! Send @code{SIGINFO} (@code{SIGUSR1} on Linux) signal to get current daemon's configuration. Initially @command{godlighty} has basic static files handlers (with compression, HTTP preconditions are enabled of course). In the example below there are nearly all default functions. @verbatim Hosts["example.com"] = &godlighty.HostCfg{ Root: "/www/example.com", TLS: &godlighty.TLSCfg{ Cert: "/path/to/example.com.pem", Key: "/path/to/example.com.key.pem", CACert: "/path/to/ca.pem", }, DirList: true, WebDAV: true, MIMEs: map[string]string{ ".special": "text/x-special-type", }, } @end verbatim If your keys and certificates are in single file and you use common CA certificate, then it is trivial to DRY: @verbatim var ( Etc = "/whatever" CACert = path.Join(Etc, "ca.pem") ) func newTLSCfg(host string) *godlighty.TLSCfg { return &godlighty.TLSCfg{ Cert: path.Join(Etc, host+".pem"), Key: path.Join(Etc, host+".pem"), CACert: CACert, } } @end verbatim But there are hooks that can do anything more. For example if you want to run CGI script or make a redirection: @verbatim HostCfg{ ..., Hooks: []godlighty.Hook{ func(w http.ResponseWriter, r *http.Request) bool { if r.URL.Path == "/" { http.Redirect(w, r, "//here.we.go/", http.StatusMovedPermanently) return true } return false }, func(w http.ResponseWriter, r *http.Request) bool { cgi.Handler{ Path: "/usr/local/libexec/git-core/git-http-backend", Dir: "/var/empty", Env: []string{ "GIT_PROJECT_ROOT=" + root, "GIT_HTTP_EXPORT_ALL=", }, }.ServeHTTP(w, r) return true }, }, @end verbatim You can separate your configuration files and add them through @code{init()} call: @verbatim $ ls rc blog.stargrave.org.go ca.cypherpunks.ru.go cgi.go cryptoanarchy.ru.go git.go go.go if.mirror.cypherpunks.ru.go lists.cypherpunks.ru.go mime.go static.go tls.go [...] $ cat rc/static package rc import "path" func addStaticCfg(host, root string) { if !path.IsAbs(root) { root = path.Join(WWW, root) } godlighty.Hosts[host] = &godlighty.HostCfg{ Root: root, TLS: newTLSCfg(host), } } func addStaticListedDir(host, root string) { addStaticCfg(host, root) godlighty.Hosts[host].DirList = true godlighty.Hosts[host].WebDAV = true } func init() { [...] addStaticCfg("paster.stargrave.org", "/storage/paster/pastes") addStaticCfg("www.godlighty.stargrave.org", "godlighty.stargrave.org") addStaticCfg("www.nncpgo.org", "nncpgo.org") addStaticListedDir("www.mds.cypherpunks.ru", "/storage/audiobook/mds") [...] } @end verbatim It is created exclusively to drive my own websites, but if you are interested, then @code{git clone git://git.stargrave.org/godlighty.git} it. @bye