From 460c0a2db4a04314f64f7016e0a7f829d1f58c28 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sun, 28 Aug 2022 16:26:38 +0200 Subject: [PATCH] first working build --- cmd/main.go | 5 +- cmd/main_fasthttp.go | 154 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 cmd/main_fasthttp.go diff --git a/cmd/main.go b/cmd/main.go index 3560ad4..ed8f864 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "net" + "net/http" "os" "strings" "time" @@ -136,7 +137,7 @@ func Serve(ctx *cli.Context) error { if enableHTTPServer { go func() { log.Info().Msg("Start HTTP server listening on :80") - err := httpServer.ListenAndServe("[::]:80") + err := http.ListenAndServe("[::]:80", httpServer) if err != nil { log.Panic().Err(err).Msg("Couldn't start HTTP fastServer") } @@ -145,7 +146,7 @@ func Serve(ctx *cli.Context) error { // Start the web fastServer log.Info().Msgf("Start listening on %s", listener.Addr()) - err = fastServer.Serve(listener) + http.Serve(listener, fastServer) if err != nil { log.Panic().Err(err).Msg("Couldn't start fastServer") } diff --git a/cmd/main_fasthttp.go b/cmd/main_fasthttp.go new file mode 100644 index 0000000..c15bcb8 --- /dev/null +++ b/cmd/main_fasthttp.go @@ -0,0 +1,154 @@ +//go:build fasthttp + +package cmd + +import ( + "context" + "crypto/tls" + "errors" + "fmt" + "net" + "os" + "strings" + "time" + + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" + "github.com/urfave/cli/v2" + + "codeberg.org/codeberg/pages/server" + "codeberg.org/codeberg/pages/server/cache" + "codeberg.org/codeberg/pages/server/certificates" + "codeberg.org/codeberg/pages/server/database" + "codeberg.org/codeberg/pages/server/gitea" +) + +// AllowedCorsDomains lists the domains for which Cross-Origin Resource Sharing is allowed. +// TODO: make it a flag +var AllowedCorsDomains = []string{ + "fonts.codeberg.org", + "design.codeberg.org", +} + +// BlacklistedPaths specifies forbidden path prefixes for all Codeberg Pages. +// TODO: Make it a flag too +var BlacklistedPaths = []string{ + "/.well-known/acme-challenge/", +} + +// Serve sets up and starts the web server. +func Serve(ctx *cli.Context) error { + // Initalize the logger. + logLevel, err := zerolog.ParseLevel(ctx.String("log-level")) + if err != nil { + return err + } + log.Logger = zerolog.New(zerolog.ConsoleWriter{Out: os.Stderr}).With().Timestamp().Logger().Level(logLevel) + + giteaRoot := strings.TrimSuffix(ctx.String("gitea-root"), "/") + giteaAPIToken := ctx.String("gitea-api-token") + rawDomain := ctx.String("raw-domain") + mainDomainSuffix := ctx.String("pages-domain") + rawInfoPage := ctx.String("raw-info-page") + listeningAddress := fmt.Sprintf("%s:%s", ctx.String("host"), ctx.String("port")) + enableHTTPServer := ctx.Bool("enable-http-server") + + acmeAPI := ctx.String("acme-api-endpoint") + acmeMail := ctx.String("acme-email") + acmeUseRateLimits := ctx.Bool("acme-use-rate-limits") + acmeAcceptTerms := ctx.Bool("acme-accept-terms") + acmeEabKID := ctx.String("acme-eab-kid") + acmeEabHmac := ctx.String("acme-eab-hmac") + dnsProvider := ctx.String("dns-provider") + if (!acmeAcceptTerms || dnsProvider == "") && acmeAPI != "https://acme.mock.directory" { + return errors.New("you must set $ACME_ACCEPT_TERMS and $DNS_PROVIDER, unless $ACME_API is set to https://acme.mock.directory") + } + + allowedCorsDomains := AllowedCorsDomains + if len(rawDomain) != 0 { + allowedCorsDomains = append(allowedCorsDomains, rawDomain) + } + + // Make sure MainDomain has a trailing dot, and GiteaRoot has no trailing slash + if !strings.HasPrefix(mainDomainSuffix, ".") { + mainDomainSuffix = "." + mainDomainSuffix + } + + keyCache := cache.NewKeyValueCache() + challengeCache := cache.NewKeyValueCache() + // canonicalDomainCache stores canonical domains + canonicalDomainCache := cache.NewKeyValueCache() + // dnsLookupCache stores DNS lookups for custom domains + dnsLookupCache := cache.NewKeyValueCache() + // clientResponseCache stores responses from the Gitea server + clientResponseCache := cache.NewKeyValueCache() + + giteaClient, err := gitea.NewClient(giteaRoot, giteaAPIToken, clientResponseCache, ctx.Bool("enable-symlink-support"), ctx.Bool("enable-lfs-support")) + if err != nil { + return fmt.Errorf("could not create new gitea client: %v", err) + } + + // Create handler based on settings + handler := server.Handler(mainDomainSuffix, rawDomain, + giteaClient, + giteaRoot, rawInfoPage, + BlacklistedPaths, allowedCorsDomains, + dnsLookupCache, canonicalDomainCache) + + fastServer := server.SetupServer(handler) + httpServer := server.SetupHTTPACMEChallengeServer(challengeCache) + + // Setup listener and TLS + log.Info().Msgf("Listening on https://%s", listeningAddress) + listener, err := net.Listen("tcp", listeningAddress) + if err != nil { + return fmt.Errorf("couldn't create listener: %v", err) + } + + // TODO: make "key-database.pogreb" set via flag + certDB, err := database.New("key-database.pogreb") + if err != nil { + return fmt.Errorf("could not create database: %v", err) + } + defer certDB.Close() //nolint:errcheck // database has no close ... sync behave like it + + listener = tls.NewListener(listener, certificates.TLSConfig(mainDomainSuffix, + giteaClient, + dnsProvider, + acmeUseRateLimits, + keyCache, challengeCache, dnsLookupCache, canonicalDomainCache, + certDB)) + + acmeConfig, err := certificates.SetupAcmeConfig(acmeAPI, acmeMail, acmeEabHmac, acmeEabKID, acmeAcceptTerms) + if err != nil { + return err + } + + if err := certificates.SetupCertificates(mainDomainSuffix, dnsProvider, acmeConfig, acmeUseRateLimits, enableHTTPServer, challengeCache, certDB); err != nil { + return err + } + + interval := 12 * time.Hour + certMaintainCtx, cancelCertMaintain := context.WithCancel(context.Background()) + defer cancelCertMaintain() + go certificates.MaintainCertDB(certMaintainCtx, interval, mainDomainSuffix, dnsProvider, acmeUseRateLimits, certDB) + + if enableHTTPServer { + go func() { + log.Info().Msg("Start HTTP server listening on :80") + err := httpServer.ListenAndServe("[::]:80") + if err != nil { + log.Panic().Err(err).Msg("Couldn't start HTTP fastServer") + } + }() + } + + // Start the web fastServer + log.Info().Msgf("Start listening on %s", listener.Addr()) + err = fastServer.Serve(listener) + if err != nil { + log.Panic().Err(err).Msg("Couldn't start fastServer") + } + + return nil +}