From 73cad447699024a5930da3281f338cf6a5324c61 Mon Sep 17 00:00:00 2001 From: Daniel Arroyo Date: Thu, 9 Jul 2026 12:43:13 -0400 Subject: [PATCH] Bump version to 1.0.18 --- Makefile | 2 +- cmd/server/main.go | 2 +- internal/syncengine/engine.go | 14 ++++++++---- internal/syncengine/rsync_runner.go | 34 ++++++++++++++++++++++------- 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index eb097e1..7665584 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ BINARY=syncserver -VERSION?=1.0.17 +VERSION?=1.0.18 GO?=go LDFLAGS=-s -w -X main.version=$(VERSION) -X main.commit=$(shell git rev-parse --short HEAD 2>/dev/null || echo unknown) BUILD_FLAGS=CGO_ENABLED=0 diff --git a/cmd/server/main.go b/cmd/server/main.go index 94bea9d..ff47302 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -20,7 +20,7 @@ import ( "github.com/syncserver/internal/syncengine" ) -var version = "1.0.17" +var version = "1.0.18" func main() { cfgPath := flag.String("config", "", "Path to config.yaml") diff --git a/internal/syncengine/engine.go b/internal/syncengine/engine.go index 95b6db8..f53e057 100644 --- a/internal/syncengine/engine.go +++ b/internal/syncengine/engine.go @@ -261,11 +261,17 @@ func (e *Engine) Run(ctx context.Context, jobID int64, pairID int64) error { var result *RsyncResult if isRemoteToRemote(srcMachine, dstMachine) { + destPrivKey, err := e.resolveSSHKey(dstMachine) + if err != nil { + slog.Warn("failed to resolve destination SSH key, using server key", "error", err) + destPrivKey = filepath.Join(e.cfg.SSHDir(), "id_ed25519") + } result, err = runner.RunRemote(jobCtx, cfg, RemoteMachine{ - Host: srcMachine.Host, - Port: srcMachine.Port, - SSHUser: srcMachine.SSHUser, - PrivKey: privKey, + Host: srcMachine.Host, + Port: srcMachine.Port, + SSHUser: srcMachine.SSHUser, + PrivKey: privKey, + DestPrivKey: destPrivKey, }, onLine) } else { result, err = runner.Run(jobCtx, cfg, onLine) diff --git a/internal/syncengine/rsync_runner.go b/internal/syncengine/rsync_runner.go index 17f313a..12c9bba 100644 --- a/internal/syncengine/rsync_runner.go +++ b/internal/syncengine/rsync_runner.go @@ -2,6 +2,7 @@ package syncengine import ( "context" + "encoding/base64" "fmt" "io" "os/exec" @@ -180,26 +181,43 @@ func (r *RsyncRunner) buildRemoteArgs(pair *SyncPairConfig) []string { } type RemoteMachine struct { - Host string - Port int - SSHUser string - PrivKey string + Host string + Port int + SSHUser string + PrivKey string + DestPrivKey string } func (r *RsyncRunner) RunRemote(ctx context.Context, pair *SyncPairConfig, remote RemoteMachine, onLine func(stream string, line string)) (*RsyncResult, error) { - args := r.buildRemoteArgs(pair) + args := r.buildArgs(pair) + + var remoteCmd string + if remote.DestPrivKey != "" { + encodedKey := base64.StdEncoding.EncodeToString([]byte(remote.DestPrivKey)) + innerSSH := fmt.Sprintf(`ssh -i /tmp/syncserver-dest-key -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=/dev/null`) + rsyncPart := fmt.Sprintf("rsync %s -e %q %s %s", + strings.Join(args, " "), innerSSH, pair.Source, pair.Dest) + remoteCmd = fmt.Sprintf( + `echo '%s' | base64 -d > /tmp/syncserver-dest-key && chmod 600 /tmp/syncserver-dest-key && %s; STATUS=$?; rm -f /tmp/syncserver-dest-key; exit $STATUS`, + encodedKey, rsyncPart) + } else { + remoteCmd = "rsync " + strings.Join(args, " ") + } sshArgs := []string{ "ssh", "-i", remote.PrivKey, "-o", "StrictHostKeyChecking=accept-new", "-o", "UserKnownHostsFile=" + strings.TrimRight(r.sshDir, "/") + "/known_hosts", - "-tt", "-p", fmt.Sprintf("%d", remote.Port), fmt.Sprintf("%s@%s", remote.SSHUser, remote.Host), - "rsync", } - sshArgs = append(sshArgs, args...) + if remote.DestPrivKey != "" { + sshArgs = append(sshArgs, "bash", "-c", remoteCmd) + } else { + sshArgs = append(sshArgs, "rsync") + sshArgs = append(sshArgs, args...) + } cmd := exec.CommandContext(ctx, "ssh", sshArgs...)