summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-08-02 18:50:47 +0300
committerPaul Buetow <paul@buetow.org>2026-08-02 18:50:47 +0300
commit4aebd8dda1306a2e7634b53a84182f8590aae459 (patch)
tree530c48f789d025b0c9fe2561233058612d518bdb
parent76e151fc9141ef3ccbafc22c62985a30afb54b02 (diff)
Optimize VPN mirror sync and release v0.19.2v0.19.2
Amp-Thread-ID: https://ampcode.com/threads/T-019fc31d-668a-769a-8dc8-554ecbd6a274 Co-authored-by: Amp <amp@ampcode.com>
-rw-r--r--cmd/snonux/sync.go18
-rw-r--r--internal/version/version.go2
2 files changed, 13 insertions, 7 deletions
diff --git a/cmd/snonux/sync.go b/cmd/snonux/sync.go
index e6311f4..af05533 100644
--- a/cmd/snonux/sync.go
+++ b/cmd/snonux/sync.go
@@ -17,7 +17,10 @@ import (
// SNONUX_SYNC_USER overrides the SSH username for rsync (default: current login name).
const envSyncUser = "SNONUX_SYNC_USER"
-const wireGuardJumpHost = "rex@fishfinger.buetow.org:2"
+const (
+ wireGuardJumpHost = "rex@fishfinger.buetow.org:2"
+ sshControlPath = "~/.ssh/snonux-%C"
+)
// defaultSyncTargets are the built-in mirror hosts used when no configuration overrides them.
var defaultSyncTargets = []string{
@@ -77,7 +80,9 @@ func syncOutput(ctx context.Context, cfg *config.Config) error {
syncTargets := make([]string, 0, len(cfg.SyncTargets))
for _, host := range cfg.SyncTargets {
+ log.Printf("checking sync target %q", host)
target, ok := reachableSyncTarget(host, hostPingable, func(fallback string) bool {
+ log.Printf("sync target %q not pingable; checking WireGuard fallback %q via %q", host, fallback, wireGuardJumpHost)
return hostReachableViaWireGuard(fallback, sshUser)
})
if !ok {
@@ -108,11 +113,11 @@ func syncOutput(ctx context.Context, cfg *config.Config) error {
// the remote webserver runs as its own unprivileged user (e.g. bozohttpd's
// _httpd), not as the SSH login user, so published files must be
// world-readable regardless of local perms.
- ssh := "ssh -p 22 -o BatchMode=yes -o ConnectTimeout=15"
+ ssh := "ssh -p 22 -o BatchMode=yes -o ConnectTimeout=15 -o ControlMaster=auto -o ControlPersist=30 -o ControlPath=" + sshControlPath
if wireGuardFallbackHost(host) {
ssh += " -o HostKeyAlias=" + wireGuardHostKeyAlias(host) + " -J " + wireGuardJumpHost
}
- cmd := exec.CommandContext(ctx, "rsync", "-az", "--chmod=D755,F644", "-e", ssh, src, dest)
+ cmd := exec.CommandContext(ctx, "rsync", "-az", "--checksum", "--info=progress2", "--chmod=D755,F644", "-e", ssh, src, dest)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
@@ -166,6 +171,7 @@ func hostReachableViaWireGuard(host, sshUser string) bool {
defer cancel()
cmd := exec.CommandContext(ctx,
"ssh", "-p", "22", "-o", "BatchMode=yes", "-o", "ConnectTimeout=5",
+ "-o", "ControlMaster=auto", "-o", "ControlPersist=30", "-o", "ControlPath="+sshControlPath,
"-o", "HostKeyAlias="+wireGuardHostKeyAlias(host),
"-J", wireGuardJumpHost, sshUser+"@"+host, "true",
)
@@ -175,10 +181,10 @@ func hostReachableViaWireGuard(host, sshUser string) bool {
}
func hostPingable(host string) bool {
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
- // Linux iputils-ping: -c 1 one packet, -W 3 wait up to 3s for reply.
- cmd := exec.CommandContext(ctx, "ping", "-c", "1", "-W", "3", host)
+ // Linux iputils-ping: -c 1 one packet, -W 1 wait up to 1s for reply.
+ cmd := exec.CommandContext(ctx, "ping", "-c", "1", "-W", "1", host)
cmd.Stdout = nil
cmd.Stderr = nil
return cmd.Run() == nil
diff --git a/internal/version/version.go b/internal/version/version.go
index 12bd890..d200a7a 100644
--- a/internal/version/version.go
+++ b/internal/version/version.go
@@ -2,4 +2,4 @@
package version
// Version is the application version (semantic versioning).
-const Version = "0.19.1"
+const Version = "0.19.2"