diff --git a/Dockerfile b/Dockerfile index 42e73de..f67d43c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,8 @@ FROM alpine:3.21@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c # Create non-root user and set up permissions in a single layer -RUN adduser -k /dev/null -u 10001 -D gorge \ +RUN apk add --no-cache curl \ + && adduser -k /dev/null -u 10001 -D gorge \ && chgrp 0 /home/gorge \ && chmod -R g+rwX /home/gorge diff --git a/cmd/serve.go b/cmd/serve.go index 9ec4192..4d79ef9 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -61,7 +61,7 @@ You can also enable the caching functionality to speed things up.`, Run: func(_ *cobra.Command, _ []string) { var err error - log.Setup(config.Dev) + log.Setup(config.Dev, config.Debug) config.ModulesDir, err = utils.ExpandTilde(config.ModulesDir) if err != nil { @@ -401,6 +401,7 @@ func init() { serveCmd.Flags().StringVar(&config.CORSOrigins, "cors", "*", "allowed cors origins separated by comma") serveCmd.Flags().StringVar(&config.FallbackProxyUrl, "fallback-proxy", "", "optional comma separated list of fallback upstream proxy urls") serveCmd.Flags().BoolVar(&config.Dev, "dev", false, "enables dev mode") + serveCmd.Flags().BoolVar(&config.Debug, "debug", false, "enables debug mode") serveCmd.Flags().BoolVar(&config.DropPrivileges, "drop-privileges", false, "drops privileges to the given user/group") serveCmd.Flags().BoolVar(&config.UI, "ui", false, "enables the web ui") serveCmd.Flags().StringVar(&config.CachePrefixes, "cache-prefixes", "/v3/files", "url prefixes to cache") diff --git a/go.sum b/go.sum index e029226..0cb820d 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +1,8 @@ -github.com/a-h/templ v0.2.793 h1:Io+/ocnfGWYO4VHdR0zBbf39PQlnzVCVVD+wEEs6/qY= -github.com/a-h/templ v0.2.793/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w= -github.com/a-h/templ v0.3.819 h1:KDJ5jTFN15FyJnmSmo2gNirIqt7hfvBD2VXVDTySckM= -github.com/a-h/templ v0.3.819/go.mod h1:iDJKJktpttVKdWoTkRNNLcllRI+BlpopJc+8au3gOUo= github.com/a-h/templ v0.3.833 h1:L/KOk/0VvVTBegtE0fp2RJQiBm7/52Zxv5fqlEHiQUU= github.com/a-h/templ v0.3.833/go.mod h1:cAu4AiZhtJfBjMY0HASlyzvkrtjnHWPeEsyGK2YYmfk= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/dadav/stampede v0.0.0-20241228165756-61568b6ca93b h1:t22u27sjssQ2146msFpZXX47oRgtiHDdudc4zCwwyPU= -github.com/dadav/stampede v0.0.0-20241228165756-61568b6ca93b/go.mod h1:O/5HgfMaQjv+J8LZCVmaKdE1cD7JsUhwnCuK5BnU0XI= -github.com/dadav/stampede v0.0.0-20241228171116-ae01e8a04d08 h1:TUK02XGb2f5GgZ5PTNFWgRr+gGSEiwhijvR/pVwSz98= -github.com/dadav/stampede v0.0.0-20241228171116-ae01e8a04d08/go.mod h1:O/5HgfMaQjv+J8LZCVmaKdE1cD7JsUhwnCuK5BnU0XI= github.com/dadav/stampede v0.0.0-20241228173147-dd16def44490 h1:uSaqpXtJE+DofLTUebe7+3bxm5YVrVL8rqIDV+fpRh4= github.com/dadav/stampede v0.0.0-20241228173147-dd16def44490/go.mod h1:O/5HgfMaQjv+J8LZCVmaKdE1cD7JsUhwnCuK5BnU0XI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -24,8 +15,6 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/go-chi/chi/v5 v5.2.0 h1:Aj1EtB0qR2Rdo2dG4O94RIU35w2lvQSj6BRA4+qwFL0= -github.com/go-chi/chi/v5 v5.2.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8= github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= @@ -88,12 +77,8 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= diff --git a/internal/config/config.go b/internal/config/config.go index ad9cec0..2fe2e71 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -7,6 +7,7 @@ var ( Port int Bind string Dev bool + Debug bool DropPrivileges bool UI bool ModulesDir string diff --git a/internal/log/zap.go b/internal/log/zap.go index 8901f87..8c77494 100644 --- a/internal/log/zap.go +++ b/internal/log/zap.go @@ -7,14 +7,19 @@ import ( var Log *zap.SugaredLogger -func Setup(dev bool) { +func Setup(dev bool, debug bool) { var logger *zap.Logger + if dev { config := zap.NewDevelopmentConfig() config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder logger, _ = config.Build() } else { - logger, _ = zap.NewProduction() + cfg := zap.NewProductionConfig() + if debug { + cfg.Level = zap.NewAtomicLevelAt(zap.DebugLevel) + } + logger, _ = cfg.Build() } defer logger.Sync() Log = logger.Sugar() diff --git a/internal/v3/backend/filesystem.go b/internal/v3/backend/filesystem.go index d71bb04..2e7888e 100644 --- a/internal/v3/backend/filesystem.go +++ b/internal/v3/backend/filesystem.go @@ -91,8 +91,8 @@ func ReleaseToAbbreviatedRelease(release *gen.Release) *gen.ReleaseAbbreviated { } func (s *FilesystemBackend) GetAllReleases() ([]*gen.Release, error) { - s.muReleases.Lock() - defer s.muReleases.Unlock() + s.muReleases.RLock() + defer s.muReleases.RUnlock() result := []*gen.Release{} for _, v := range s.Releases { @@ -153,12 +153,7 @@ func ModuleFromRelease(release *gen.Release) *gen.Module { } } -func (s *FilesystemBackend) AddRelease(releaseData []byte) (*gen.Release, error) { - s.muModules.Lock() - s.muReleases.Lock() - defer s.muModules.Unlock() - defer s.muReleases.Unlock() - +func (s *FilesystemBackend) addReleaseWithLock(releaseData []byte) (*gen.Release, error) { metadata, readme, err := ReadReleaseMetadataFromBytes(releaseData) if err != nil { return nil, err @@ -248,11 +243,21 @@ func (s *FilesystemBackend) AddRelease(releaseData []byte) (*gen.Release, error) } return release, nil + } -func (s *FilesystemBackend) GetAllModules() ([]*gen.Module, error) { +func (s *FilesystemBackend) AddRelease(releaseData []byte) (*gen.Release, error) { s.muModules.Lock() + s.muReleases.Lock() defer s.muModules.Unlock() + defer s.muReleases.Unlock() + + return s.addReleaseWithLock(releaseData) +} + +func (s *FilesystemBackend) GetAllModules() ([]*gen.Module, error) { + s.muModules.RLock() + defer s.muModules.RUnlock() result := []*gen.Module{} @@ -264,8 +269,8 @@ func (s *FilesystemBackend) GetAllModules() ([]*gen.Module, error) { } func (s *FilesystemBackend) GetModuleBySlug(slug string) (*gen.Module, error) { - s.muModules.Lock() - defer s.muModules.Unlock() + s.muModules.RLock() + defer s.muModules.RUnlock() if module, ok := s.Modules[slug]; !ok { return nil, errors.New("module not found") } else { @@ -274,8 +279,8 @@ func (s *FilesystemBackend) GetModuleBySlug(slug string) (*gen.Module, error) { } func (s *FilesystemBackend) GetReleaseBySlug(slug string) (*gen.Release, error) { - s.muReleases.Lock() - defer s.muReleases.Unlock() + s.muReleases.RLock() + defer s.muReleases.RUnlock() for _, moduleReleases := range s.Releases { for _, release := range moduleReleases { if release.Slug == slug { @@ -348,13 +353,13 @@ func (s *FilesystemBackend) DeleteReleaseBySlug(slug string) error { } func (s *FilesystemBackend) LoadModules() error { - // Initialize maps if they haven't been created yet - if s.Modules == nil { - s.Modules = make(map[string]*gen.Module) - } - if s.Releases == nil { - s.Releases = make(map[string][]*gen.Release) - } + s.muModules.Lock() + s.muReleases.Lock() + defer s.muModules.Unlock() + defer s.muReleases.Unlock() + + s.Modules = make(map[string]*gen.Module) + s.Releases = make(map[string][]*gen.Release) // Walk through all files in the modules directory recursively err := filepath.Walk(s.ModulesDir, func(path string, info os.FileInfo, err error) error { @@ -376,7 +381,7 @@ func (s *FilesystemBackend) LoadModules() error { // Process the release archive and add it to the backend // This will update both s.Modules and s.Releases maps - _, err = s.AddRelease(releaseBytes) + _, err = s.addReleaseWithLock(releaseBytes) return err }) if err != nil {