fix(config): use abs paths

Ayman Bagabas created

Change summary

cmd/soft/hook.go                |  4 +-
cmd/soft/migrate_config.go      |  2 
server/backend/sqlite/sqlite.go |  2 
server/cmd/hook.go              |  3 -
server/config/config.go         | 50 +++++++++++++++++++++++++++++++---
server/jobs.go                  |  2 
server/server.go                |  5 +--
server/ssh/ssh.go               |  2 
8 files changed, 54 insertions(+), 16 deletions(-)

Detailed changes

cmd/soft/hook.go 🔗

@@ -176,7 +176,7 @@ func commonInit() (c *gossh.Client, s *gossh.Session, err error) {
 
 func newClient(cfg *config.Config) (*gossh.Client, error) {
 	// Only accept the server's host key.
-	pk, err := keygen.New(filepath.Join(cfg.DataPath, cfg.SSH.KeyPath), nil, keygen.Ed25519)
+	pk, err := keygen.New(cfg.SSH.KeyPath, nil, keygen.Ed25519)
 	if err != nil {
 		return nil, err
 	}
@@ -184,7 +184,7 @@ func newClient(cfg *config.Config) (*gossh.Client, error) {
 	if err != nil {
 		return nil, err
 	}
-	ik, err := keygen.New(filepath.Join(cfg.DataPath, cfg.SSH.InternalKeyPath), nil, keygen.Ed25519)
+	ik, err := keygen.New(cfg.SSH.InternalKeyPath, nil, keygen.Ed25519)
 	if err != nil {
 		return nil, err
 	}

cmd/soft/migrate_config.go 🔗

@@ -57,7 +57,7 @@ var (
 					log.Errorf("failed to copy ssh key: %s", err)
 				}
 
-				cfg.SSH.KeyPath = filepath.Join("ssh", filepath.Base(keyPath))
+				cfg.SSH.KeyPath = filepath.Join(cfg.DataPath, "ssh", filepath.Base(keyPath))
 			}
 
 			// Read config

server/backend/sqlite/sqlite.go 🔗

@@ -187,7 +187,7 @@ func (d *SqliteBackend) ImportRepository(name string, remote string, opts backen
 				fmt.Sprintf(`GIT_SSH_COMMAND=ssh -o UserKnownHostsFile="%s" -o StrictHostKeyChecking=no -i "%s"`,
 					filepath.Join(d.cfg.DataPath, "ssh", "known_hosts"),
 					// FIXME: upstream keygen appends _ed25519 to the key path.
-					filepath.Join(d.cfg.DataPath, d.cfg.SSH.ClientKeyPath)+"_ed25519",
+					d.cfg.SSH.ClientKeyPath+"_ed25519",
 				),
 			},
 		},

server/cmd/hook.go 🔗

@@ -3,7 +3,6 @@ package cmd
 import (
 	"bufio"
 	"fmt"
-	"path/filepath"
 	"strings"
 
 	"github.com/charmbracelet/keygen"
@@ -119,7 +118,7 @@ func hookCommand() *cobra.Command {
 func checkIfInternal(cmd *cobra.Command, _ []string) error {
 	cfg, s := fromContext(cmd)
 	pk := s.PublicKey()
-	kp, err := keygen.New(filepath.Join(cfg.DataPath, cfg.SSH.InternalKeyPath), nil, keygen.Ed25519)
+	kp, err := keygen.New(cfg.SSH.InternalKeyPath, nil, keygen.Ed25519)
 	if err != nil {
 		logger.Errorf("failed to read internal key: %v", err)
 		return err

server/config/config.go 🔗

@@ -3,6 +3,7 @@ package config
 import (
 	"os"
 	"path/filepath"
+	"strings"
 
 	"github.com/caarlos0/env/v7"
 	"github.com/charmbracelet/log"
@@ -115,6 +116,10 @@ func ParseConfig(path string) (*Config, error) {
 		return nil, err
 	}
 
+	if err := cfg.init(); err != nil {
+		return nil, err
+	}
+
 	return cfg, nil
 }
 
@@ -131,11 +136,6 @@ func DefaultConfig() *Config {
 		dataPath = "data"
 	}
 
-	dp, _ := filepath.Abs(dataPath)
-	if dp != "" {
-		dataPath = dp
-	}
-
 	cfg := &Config{
 		Name:     "Soft Serve",
 		DataPath: dataPath,
@@ -181,6 +181,10 @@ func DefaultConfig() *Config {
 		log.Fatal(err)
 	}
 
+	if err := cfg.init(); err != nil {
+		log.Fatal(err)
+	}
+
 	return cfg
 }
 
@@ -189,3 +193,39 @@ func (c *Config) WithBackend(backend backend.Backend) *Config {
 	c.Backend = backend
 	return c
 }
+
+func (c *Config) init() error {
+	// Use absolute paths
+	if !filepath.IsAbs(c.DataPath) {
+		dp, err := filepath.Abs(c.DataPath)
+		if err != nil {
+			return err
+		}
+		c.DataPath = dp
+	}
+
+	c.SSH.PublicURL = strings.TrimSuffix(c.SSH.PublicURL, "/")
+	c.HTTP.PublicURL = strings.TrimSuffix(c.HTTP.PublicURL, "/")
+
+	if c.SSH.KeyPath != "" && !filepath.IsAbs(c.SSH.KeyPath) {
+		c.SSH.KeyPath = filepath.Join(c.DataPath, c.SSH.KeyPath)
+	}
+
+	if c.SSH.ClientKeyPath != "" && !filepath.IsAbs(c.SSH.ClientKeyPath) {
+		c.SSH.ClientKeyPath = filepath.Join(c.DataPath, c.SSH.ClientKeyPath)
+	}
+
+	if c.SSH.InternalKeyPath != "" && !filepath.IsAbs(c.SSH.InternalKeyPath) {
+		c.SSH.InternalKeyPath = filepath.Join(c.DataPath, c.SSH.InternalKeyPath)
+	}
+
+	if c.HTTP.TLSKeyPath != "" && !filepath.IsAbs(c.HTTP.TLSKeyPath) {
+		c.HTTP.TLSKeyPath = filepath.Join(c.DataPath, c.HTTP.TLSKeyPath)
+	}
+
+	if c.HTTP.TLSCertPath != "" && !filepath.IsAbs(c.HTTP.TLSCertPath) {
+		c.HTTP.TLSCertPath = filepath.Join(c.DataPath, c.HTTP.TLSCertPath)
+	}
+
+	return nil
+}

server/jobs.go 🔗

@@ -39,7 +39,7 @@ func mirrorJob(cfg *config.Config) func() {
 					fmt.Sprintf(`GIT_SSH_COMMAND=ssh -o UserKnownHostsFile="%s" -o StrictHostKeyChecking=no -i "%s"`,
 						filepath.Join(cfg.DataPath, "ssh", "known_hosts"),
 						// FIXME: upstream keygen appends _ed25519 to the key path.
-						filepath.Join(cfg.DataPath, cfg.SSH.ClientKeyPath)+"_ed25519",
+						cfg.SSH.ClientKeyPath+"_ed25519",
 					),
 				)
 				if _, err := cmd.RunInDir(r.Path); err != nil {

server/server.go 🔗

@@ -4,7 +4,6 @@ import (
 	"context"
 	"errors"
 	"net/http"
-	"path/filepath"
 
 	"github.com/charmbracelet/keygen"
 	"github.com/charmbracelet/log"
@@ -54,7 +53,7 @@ func NewServer(ctx context.Context, cfg *config.Config) (*Server, error) {
 
 		// Create internal key.
 		ikp, err := keygen.NewWithWrite(
-			filepath.Join(cfg.DataPath, cfg.SSH.InternalKeyPath),
+			cfg.SSH.InternalKeyPath,
 			nil,
 			keygen.Ed25519,
 		)
@@ -65,7 +64,7 @@ func NewServer(ctx context.Context, cfg *config.Config) (*Server, error) {
 
 		// Create client key.
 		ckp, err := keygen.NewWithWrite(
-			filepath.Join(cfg.DataPath, cfg.SSH.ClientKeyPath),
+			cfg.SSH.ClientKeyPath,
 			nil,
 			keygen.Ed25519,
 		)

server/ssh/ssh.go 🔗

@@ -103,7 +103,7 @@ func NewSSHServer(cfg *config.Config, hooks hooks.Hooks) (*SSHServer, error) {
 		ssh.PublicKeyAuth(s.PublicKeyHandler),
 		ssh.KeyboardInteractiveAuth(s.KeyboardInteractiveHandler),
 		wish.WithAddress(cfg.SSH.ListenAddr),
-		wish.WithHostKeyPath(filepath.Join(cfg.DataPath, cfg.SSH.KeyPath)),
+		wish.WithHostKeyPath(cfg.SSH.KeyPath),
 		wish.WithMiddleware(mw...),
 	)
 	if err != nil {