From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH] (home-)syncthing-service: added support for config serialization Resent-From: Zacchaeus Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Fri, 31 Jan 2025 04:18:03 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 75959@debbugs.gnu.org X-Debbugs-Original-To: guix-patches@gnu.org Received: via spool by submit@debbugs.gnu.org id=B.17382970587045 (code B ref -1); Fri, 31 Jan 2025 04:18:03 +0000 Received: (at submit) by debbugs.gnu.org; 31 Jan 2025 04:17:38 +0000 Received: from localhost ([127.0.0.1]:48851 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tdiTH-0001pQ-Vs for submit@debbugs.gnu.org; Thu, 30 Jan 2025 23:17:38 -0500 Received: from lists.gnu.org ([2001:470:142::17]:54118) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tdccl-0007O5-Vc for submit@debbugs.gnu.org; Thu, 30 Jan 2025 17:03:02 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tdccc-0006O8-CK for guix-patches@gnu.org; Thu, 30 Jan 2025 17:02:50 -0500 Received: from [47.204.136.169] (helo=hun.zacchae.us) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tdccY-0003xA-Id for guix-patches@gnu.org; Thu, 30 Jan 2025 17:02:50 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Transfer-Encoding:Content-Type: MIME-Version:Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=R5kdJCRRt3O/oAWwGScGfxmSrZTOLpVp23UzckEGeco=; i=zacchae.us; b=+TEHxkxlELoD FMDhHTEZhtLqqYixJBK42lS0KbPCaDoUOexuiSXTnxl181x9QpS5hqo0M+Zug63TLYzFCrHWDQ==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Transfer-Encoding:Content-Type:MIME-Version: Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=R5kdJCRRt3O/oAWwGScGfxmSrZTOLpVp23UzckEGeco=; i=zacchae.us; b=UbnHx/F1vj9z lOmioXoACwf0AhMrId+nBe5d542p+0nAO+G3i3zWdUrHT4g5NLPoYS3GEufGVQwp4Ay2ggz6RQ6O7 vOY3VoGr5mFJU3QRgut7WuGZYTkhH9/So6kn1oYBj5FbvbGYvmQHRe8vX1FPE85H+Q2LAxD8zgtjV ozRFE/QdY8h7dbZuVFpttZcKYPCBtHqrebd+CKfAzQfjcIVz3Ie7hQrVy664ftsAxdrB8iZvgfhnQ GCadIVV+eZrW6jtcleCeJS7YZPhvTWRY7V+gZbj0SmN1VFQQZAF4eeHTZfeUivBRazNeG8N9lHc5t kVKs260Q2bfDMr02NhUChg==; Received: from localhost.home ([127.0.0.1]:43730 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1tdccV-000000000Iw-2hrB; Thu, 30 Jan 2025 17:02:44 -0500 From: Zacchaeus Date: Thu, 30 Jan 2025 13:59:12 -0800 Message-ID: <20250130215954.9394-1-eikcaz@zacchae.us> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Host-Lookup-Failed: Reverse DNS lookup failed for 47.204.136.169 (failed) Received-SPF: pass client-ip=47.204.136.169; envelope-from=eikcaz@zacchae.us; helo=hun.zacchae.us X-Spam_score_int: -7 X-Spam_score: -0.8 X-Spam_bar: / X-Spam_report: (-0.8 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_FILL_THIS_FORM_SHORT=0.01, URIBL_SBL_A=0.1 autolearn=no autolearn_force=no X-Spam_action: no action X-Spam-Score: 1.7 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From 48c227546ea15aadbd5f5832d8cd30887f65ace9 Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH] (home-)syncthing-service: added suppor [...] Content analysis details: (1.7 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.1 URIBL_SBL_A Contains URL's A record listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 0.6 URIBL_SBL Contains an URL's NS IP listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2001:470:142:0:0:0:0:17 listed in] [list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record 0.9 SPF_FAIL SPF: sender does not match SPF record (fail) [SPF failed: Please see http://www.openspf.org/Why?s=mfrom; id=eikcaz%40zacchae.us; ip=2001%3A470%3A142%3A%3A17; r=debbugs.gnu.org] 0.0 T_FILL_THIS_FORM_SHORT Fill in a short form with personal information X-Mailman-Approved-At: Thu, 30 Jan 2025 23:17:30 -0500 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 0.7 (/) >From 48c227546ea15aadbd5f5832d8cd30887f65ace9 Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH] (home-)syncthing-service: added support for config serialization Change-Id: I87eeba1ee1fdada8f29c2ee881fbc6bc4113dde9 --- doc/guix.texi | 281 ++++++++++++++++++- gnu/home/services/syncthing.scm | 17 +- gnu/services/syncthing.scm | 459 +++++++++++++++++++++++++++++++- 3 files changed, 752 insertions(+), 5 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index b1b6d98e74..966fe852a4 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -136,6 +136,7 @@ Copyright @copyright{} 2024 Troy Figiel@* Copyright @copyright{} 2024 Sharlatan Hellseher@* Copyright @copyright{} 2024 45mg@* Copyright @copyright{} 2025 S=C3=B6ren Tempel@* +Copyright @copyright{} 2025 Zacchaeus@* =20 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -22669,8 +22670,284 @@ This assumes that the specified group exists. Common configuration and data directory. The default configuration directory is @file{$HOME} of the specified Syncthing @code{user}. =20 -@end table -@end deftp +@item @code{syncthing-config-file} (default: @var{#f}) +Either a file-like object that resolves to a syncthing configuraton xml +file, or a syncthing-config-file record (see below). + +@end table +@end deftp + +In the below, only details specific to Guix, or related to how your +device will ``ping'' others, are presented. Otherwise, you should +consult @uref{https://docs.syncthing.net/users/config.html, Syncthing +config documentation}. Camelcase is preserved below only as to be +consistent with its appearance in Syncthing code/documentation. If you +would like to migrate to Guix-powerd Syncthing configuration, the +generated config adds newlines/whitespace to the produced config such +that your old config can be diff'ed with the new one. + +@deftp {Data Type} syncthing-config-file +Data type representing the configuration file read by the syncthing +daemon. + +@table @asis +@item @code{folders} (default: @var{(list (syncthing-folder (id "default")= (label "Default Folder") (path "~/Sync")))} +The default here is the same as Syncthing's default. The value should +be a list of @code{syncthing-folder}s. + +@item @code{devices} (default: @var{'()} +This should be a list of @code{syncthing-device}s, or strings correspondin= g to +the device ids. A device entry corresponding to the current device is +silently ignored by Syncthing. + +@item @code{gui-enabled} (default: @var{"true"}) +By default, any user on the computer can access the GUI and make changes +to Syncthing. If you leave this enabled, you should probably set +gui-user and gui-password (see belowe). + +@item @code{gui-tls} (default: @var{"false"}) +@item @code{gui-debugging} (default: @var{"false"}) +@item @code{gui-sendBasicAuthPrompt} (default: @var{"false"}) +@item @code{gui-address} (default: @var{"127.0.0.1:8384"}) +@item @code{gui-user} (default: @var{#f}) +@item @code{gui-password} (default: @var{#f}) +@item @code{gui-apikey} (default: @var{"Vuky3VHVseQEoSk9YgxhSkNTnjQmqYK9"}) +@item @code{gui-theme} (default: @var{"default"}) +@item @code{ldap-enabled} (default: @var{#f}) +@item @code{ldap-address} (default: @var{""}) +@item @code{ldap-bindDN} (default: @var{""}) +@item @code{ldap-transport} (default: @var{""}) +@item @code{ldap-insecureSkipVerify} (default: @var{""}) +@item @code{ldap-searchBaseDN} (default: @var{""}) +@item @code{ldap-searchFilter} (default: @var{""}) +@item @code{listenAddress} (default: @var{"default"}) +@item @code{globalAnnounceServer} (default: @var{"default"}) +@item @code{globalAnnounceEnabled} (default: @var{"true"}) +Global discovery servers can be used to help connect devices at unknown +IP addresses by storing the last known IP address. + +@item @code{localAnnounceEnabled} (default: @var{"true"}) +This makes devices find eachother very easily on the same LAN. Often, +this will allow you to just plug an ethernet between two devices, or +connect one device to the other's hotspot and start syncing. + +@item @code{localAnnouncePort} (default: @var{"21027"}) +@item @code{localAnnounceMCAddr} (default: @var{"[ff12::8384]:21027"}) +@item @code{maxSendKbps} (default: @var{"0"}) +@item @code{maxRecvKbps} (default: @var{"0"}) +@item @code{reconnectionIntervalS} (default: @var{"60"}) +@item @code{relaysEnabled} (default: @var{"true"}) +This option allows your Syncthing instance to coordinate with a global +network of relays to enable syncing between devices when all other +methods fail. + +@item @code{relayReconnectIntervalM} (default: @var{"10"}) +@item @code{startBrowser} (default: @var{"true"}) +@item @code{natEnabled} (default: @var{"true"}) +@item @code{natLeaseMinutes} (default: @var{"60"}) +@item @code{natRenewalMinutes} (default: @var{"30"}) +@item @code{natTimeoutSeconds} (default: @var{"10"}) +@item @code{urAccepted} (default: @var{"0"}) +ur* options control usage reporting. Set to -1 to disable, or positive +to enable. The default (0) has reporting disabled, but you will be +asked to decide in the GUI. + +@item @code{urSeen} (default: @var{"0"}) +@item @code{urUniqueID} (default: @var{""}) +@item @code{urURL} (default: @var{"https://data.syncthing.net/newdata"}) +@item @code{urPostInsecurely} (default: @var{"false"}) +@item @code{urInitialDelayS} (default: @var{"1800"}) +@item @code{autoUpgradeIntervalH} (default: @var{"12"}) +@item @code{upgradeToPreReleases} (default: @var{"false"}) +@item @code{keepTemporariesH} (default: @var{"24"}) +@item @code{cacheIgnoredFiles} (default: @var{"false"}) +@item @code{progressUpdateIntervalS} (default: @var{"5"}) +@item @code{limitBandwidthInLan} (default: @var{"false"}) +@item @code{minHomeDiskFree-unit} (default: @var{"%"}) +@item @code{minHomeDiskFree} (default: @var{"1"}) +@item @code{releasesURL} (default: @var{"https://upgrades.syncthing.net/me= ta.json"}) +@item @code{overwriteRemoteDeviceNamesOnConnect} (default: @var{"false"}) +@item @code{tempIndexMinBlocks} (default: @var{"10"}) +@item @code{unackedNotificationID} (default: @var{"authenticationUserAndPa= ssword"}) +@item @code{trafficClass} (default: @var{"0"}) +@item @code{setLowPriority} (default: @var{"true"}) +@item @code{maxFolderConcurrency} (default: @var{"0"}) +@item @code{crashReportingURL} (default: @var{"https://crash.syncthing.net= /newcrash"}) +@item @code{crashReportingEnabled} (default: @var{"true"}) +@item @code{stunKeepaliveStartS} (default: @var{"180"}) +@item @code{stunKeepaliveMinS} (default: @var{"20"}) +@item @code{stunServer} (default: @var{"default"}) +@item @code{databaseTuning} (default: @var{"auto"}) +@item @code{maxConcurrentIncomingRequestKiB} (default: @var{"0"}) +@item @code{announceLANAddresses} (default: @var{"true"}) +@item @code{sendFullIndexOnUpgrade} (default: @var{"false"}) +@item @code{connectionLimitEnough} (default: @var{"0"}) +@item @code{connectionLimitMax} (default: @var{"0"}) +@item @code{insecureAllowOldTLSVersions} (default: @var{"false"}) +@item @code{connectionPriorityTcpLan} (default: @var{"10"}) +@item @code{connectionPriorityQuicLan} (default: @var{"20"}) +@item @code{connectionPriorityTcpWan} (default: @var{"30"}) +@item @code{connectionPriorityQuicWan} (default: @var{"40"}) +@item @code{connectionPriorityRelay} (default: @var{"50"}) +@item @code{connectionPriorityUpgradeThreshold} (default: @var{"0"}) +@item @code{default-folder} (default: @var{(syncthing-folder (label ""))}) +@item @code{default-device} (default: @var{(syncthing-device (id ""))}) +@item @code{default-ignores} (default: @var{"")}) +The default-* above do not affect folders and devices added by the Guix +interface. They will, however, affect folders and devices that are +added through the GUI, or by an ``introducer''. +@end table +@end deftp + +@deftp {Data Type} syncthing-device +Data type representing a device to sync with. + +@table @asis +@item @code{id} +A long hash tied to the keys generated by Syncthing on the first launch. +You can obtain this from the Syncthing GUI or by inpsecting an existing +Syncthing configuration file. + +@item @code{name} (default: @var{""}) +Human readable device name for viewing in the GUI or in scheme. + +@item @code{compression} (default: @var{"metadata"}) +@item @code{introducer} (default: @var{"false"}) +@item @code{skipIntroductionRemovals} (default: @var{"false"}) +@item @code{introducedBy} (default: @var{""}) +@item @code{addresses} (default: @var{'("dynamic")}) +List of addresses at which to search for this device. The special value +``dynamic'' will have syncthing use several means to find the device. + +@item @code{paused} (default: @var{"false"}) +@item @code{autoAcceptFolders} (default: @var{"false"}) +@item @code{maxSendKbps} (default: @var{"0"}) +@item @code{maxRecvKbps} (default: @var{"0"}) +@item @code{maxRequestKiB} (default: @var{"0"}) +@item @code{untrusted} (default: @var{"false"}) +@item @code{remoteGUIPort} (default: @var{"0"}) +@item @code{numConnections} (default: @var{"0")}) + +@end table +@end deftp + +@deftp {Data Type} syncthing-folder +Data type representing a folder to be synced. + +@table @asis +@item @code{id} (default: @var{#f}) +This id cannot match the id of any other folder on this device. If left +unspecified, it will default to the label (see below). + +@item @code{label} +Human readable label for the folder. + +@item @code{path} +The path at which to store this folder. + +@item @code{type} (default: @var{"sendreceive"}) +@item @code{rescanIntervalS} (default: @var{"3600"}) +@item @code{fsWatcherEnabled} (default: @var{"true"}) +@item @code{fsWatcherDelayS} (default: @var{"10"}) +@item @code{ignorePerms} (default: @var{"false"}) +@item @code{autoNormalize} (default: @var{"true"}) +@item @code{devices} (default: @var{'()}) +Devices should be a list of other Syncthing devices. If the current +device is included, it is silently ignored by syncthing (which makes for +lazier scheme code). Each device can be listed as a string representing +the device id, a @code{syncthing-device} object, or a +@code{syncthing-folder-device} object. + +@item @code{filesystemType} (default: @var{"basic"}) +@item @code{minDiskFree-unit} (default: @var{"%"}) +@item @code{minDiskFree} (default: @var{"1"}) +@item @code{versioning-type} (default: @var{#f}) +@item @code{versioning-fsPath} (default: @var{""}) +@item @code{versioning-fsType} (default: @var{"basic"}) +@item @code{versioning-cleanupIntervalS} (default: @var{"3600"}) +@item @code{versioning-cleanoutDays} (default: @var{#f}) +@item @code{versioning-keep} (default: @var{#f}) +@item @code{versioning-maxAge} (default: @var{#f}) +@item @code{versioning-command} (default: @var{#f}) +@item @code{copiers} (default: @var{"0"}) +@item @code{pullerMaxPendingKiB} (default: @var{"0"}) +@item @code{hashers} (default: @var{"0"}) +@item @code{order} (default: @var{"random"}) +@item @code{ignoreDelete} (default: @var{"false"}) +@item @code{scanProgressIntervalS} (default: @var{"0"}) +@item @code{pullerPauseS} (default: @var{"0"}) +@item @code{maxConflicts} (default: @var{"10"}) +@item @code{disableSparseFiles} (default: @var{"false"}) +@item @code{disableTempIndexes} (default: @var{"false"}) +@item @code{paused} (default: @var{"false"}) +@item @code{weakHashThresholdPct} (default: @var{"25"}) +@item @code{markerName} (default: @var{".stfolder"}) +@item @code{copyOwnershipFromParent} (default: @var{"false"}) +@item @code{modTimeWindowS} (default: @var{"0"}) +@item @code{maxConcurrentWrites} (default: @var{"2"}) +@item @code{disableFsync} (default: @var{"false"}) +@item @code{blockPullOrder} (default: @var{"standard"}) +@item @code{copyRangeMethod} (default: @var{"standard"}) +@item @code{caseSensitiveFS} (default: @var{"false"}) +@item @code{junctionsAsDirs} (default: @var{"false"}) +@item @code{syncOwnership} (default: @var{"false"}) +@item @code{sendOwnership} (default: @var{"false"}) +@item @code{syncXattrs} (default: @var{"false"}) +@item @code{sendXattrs} (default: @var{"false"}) +@item @code{xattrFilter-maxSingleEntrySize} (default: @var{"1024"}) +@item @code{xattrFilter-maxTotalSize} (default: @var{"4096")}) +@end table +@end deftp + +@deftp {Data Type} syncthing-folder-device +There is some configuration which is specific to the relationship +between a specific folder and a specific device. If you are fine +leaving these as their default, then you can simply specify a +syncthing-device instead of a syncthing-folder-device. + +@table @asis +@item @code{id} (default: @var{""}) +id can be provided as a string of the id, or a @code{syncthing-device}. + +@item @code{introducedBy} (default: @var{""}) +@item @code{encryptionPassword} (default: @var{""}) +if encryptionPassword is non-empty, then it will be used as a password +to encrypt file chunks as they are synced to that device. For more info +on syncing to devices you don't totally trust, see +@uref{https://docs.syncthing.net/users/untrusted.html, Syncthing Documenta= tion Untrusted}. +Note that file transfers are always end-to-end encrypted, regardless of +this setting. + +@end table +@end deftp + +Here is a more complex example configuration for illustrative purposes: +@lisp +(service syncthing-service-type + (let ((laptop (syncthing-device (id "VHOD2D6-...-7XRMDEN"))) + (desktop (syncthing-device (id "64SAZ37-...-FZJ5GUA") + (addresses '("mydomain.com")))) + (bob-desktop "KYIMEGO-...-FT77EAO")) + (syncthing-configuration + (user "alice") + (syncthing-config-file + (folders (list (syncthing-folder + (label "some-files") + (path "~/data") + (devices (list desktop laptop))) + (syncthing-folder + (label "critical-files") + (path "~/secrets") + (devices + (list desktop + laptop + (syncthing-folder-device + (id bob-desktop) + (encryptionPassword "mypassword")))))= )) + ;; any device used above should be in this list + (devices (list laptop desktop bob-desktop)))) +@end lisp + =20 Furthermore, @code{(gnu services ssh)} provides the following services. @cindex SSH diff --git a/gnu/home/services/syncthing.scm b/gnu/home/services/syncthing.= scm index 8d66a167ce..dd6c752ee4 100644 --- a/gnu/home/services/syncthing.scm +++ b/gnu/home/services/syncthing.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2023 Ludovic Court=C3=A8s +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -24,9 +25,23 @@ (define-module (gnu home services syncthing) #:use-module (gnu home services shepherd) #:export (home-syncthing-service-type) #:re-export (syncthing-configuration - syncthing-configuration?)) + syncthing-configuration? + syncthing-config-file + syncthing-config-file? + syncthing-device + syncthing-device? + syncthing-folder + syncthing-folder? + syncthing-folder-device + syncthing-folder-device?)) =20 (define home-syncthing-service-type (service-type (inherit (system->home-service-type syncthing-service-type)) + ;; system->home-service-type does not convert special-files-service-typ= e to + ;; home-files-service-type, so redefine extensios + (extensions (list (service-extension home-files-service-type + syncthing-files-service) + (service-extension home-shepherd-service-type + syncthing-shepherd-service))) (default-value (for-home (syncthing-configuration))))) diff --git a/gnu/services/syncthing.scm b/gnu/services/syncthing.scm index a7a9c6aadd..4f0d4c1082 100644 --- a/gnu/services/syncthing.scm +++ b/gnu/services/syncthing.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2021 Oleg Pykhalov ;;; Copyright =C2=A9 2023 Justin Veilleux +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -25,9 +26,20 @@ (define-module (gnu services syncthing) #:use-module (guix records) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (sxml simple) #:export (syncthing-configuration syncthing-configuration? - syncthing-service-type)) + syncthing-device + syncthing-device? + syncthing-config-file + syncthing-config-file? + syncthing-folder-device + syncthing-folder-device? + syncthing-folder + syncthing-folder? + syncthing-service-type + syncthing-shepherd-service + syncthing-files-service)) =20 ;;; Commentary: ;;; @@ -35,6 +47,431 @@ (define-module (gnu services syncthing) ;;; ;;; Code: =20 +(define-record-type* + syncthing-device make-syncthing-device + syncthing-device? + (id syncthing-device-id) + (name syncthing-device-name (default "")) + (compression syncthing-device-compression (default "metadata")) + (introducer syncthing-device-introducer (default "false")) + (skipIntroductionRemovals syncthing-device-skipIntroductionRemovals (def= ault "false")) + (introducedBy syncthing-device-introducedBy (default "")) + (addresses syncthing-device-addresses (default '("dynamic"))) + (paused syncthing-device-paused (default "false")) + (autoAcceptFolders syncthing-device-autoAcceptFolders (default "false")) + (maxSendKbps syncthing-device-maxSendKbps (default "0")) + (maxRecvKbps syncthing-device-maxRecvKbps (default "0")) + (maxRequestKiB syncthing-device-maxRequestKiB (default "0")) + (untrusted syncthing-device-untrusted (default "false")) + (remoteGUIPort syncthing-device-remoteGUIPort (default "0")) + (numConnections syncthing-device-numConnections (default "0"))) + +(define syncthing-device->sxml + (match-record-lambda + (id name compression introducer skipIntroductionRemovals introducedB= y addresses paused autoAcceptFolders maxSendKbps maxRecvKbps maxRequestKiB = untrusted remoteGUIPort numConnections) + `(device (@ (id ,id) + (name ,name) + (compression ,compression) + (introducer ,introducer) + (skipIntroductionRemovals ,skipIntroductionRemovals) + (introducedBy ,introducedBy)) + ,@(map (lambda (address) `(address ,address)) addresses) + (paused ,paused) + (autoAcceptFolders ,autoAcceptFolders) + (maxSendKbps ,maxSendKbps) + (maxRecvKbps ,maxRecvKbps) + (maxRequestKiB ,maxRequestKiB) + (untrusted ,untrusted) + (remoteGUIPort ,remoteGUIPort) + (numConnections ,numConnections)))) + +(define (id-or-device->id id-or-device) + (if (syncthing-device? id-or-device) + (syncthing-device-id id-or-device) + id-or-device)) + +(define-record-type* + syncthing-folder-device make-syncthing-folder-device + syncthing-folder-device? + (id syncthing-folder-device-id + (sanitize id-or-device->id)) + (introducedBy syncthing-folder-device-introducedBy (default "") + (sanitize id-or-device->id)) + (encryptionPassword syncthing-folder-device-encryptionPassword (default = ""))) + +(define syncthing-folder-device->sxml + (match-record-lambda + (id introducedBy encryptionPassword) + `(device (@ (id ,id) + (introducedBy ,introducedBy)) + (encryptionPassword ,encryptionPassword)))) + +(define-record-type* + syncthing-folder make-syncthing-folder + syncthing-folder? + (id syncthing-folder-id (default #f)) + (label syncthing-folder-label) + (path syncthing-folder-path) + (type syncthing-folder-type (default "sendreceive")) + (rescanIntervalS syncthing-folder-rescanIntervalS (default "3600")) + (fsWatcherEnabled syncthing-folder-fsWatcherEnabled (default "true")) + (fsWatcherDelayS syncthing-folder-fsWatcherDelayS (default "10")) + (ignorePerms syncthing-folder-ignorePerms (default "false")) + (autoNormalize syncthing-folder-autoNormalize (default "true")) + (devices syncthing-folder-devices (default '()) + (sanitize (lambda (folder-device-list) + (map (lambda (device) + (if (syncthing-folder-device? device) + device + (syncthing-folder-device (id device)))) + folder-device-list)))) + (filesystemType syncthing-folder-filesystemType (default "basic")) + (minDiskFree-unit syncthing-folder-minDiskFree-unit (default "%")) + (minDiskFree syncthing-folder-minDiskFree (default "1")) + (versioning-type syncthing-folder-versioning-type (default #f)) + (versioning-fsPath syncthing-folder-versioning-fsPath (default "")) + (versioning-fsType syncthing-folder-versioning-fsType (default "basic")) + (versioning-cleanupIntervalS syncthing-folder-versioning-cleanupInterval= S (default "3600")) + (versioning-cleanoutDays syncthing-folder-versioning-cleanoutDays (defau= lt #f)) + (versioning-keep syncthing-folder-versioning-keep (default #f)) + (versioning-maxAge syncthing-folder-versioning-maxAge (default #f)) + (versioning-command syncthing-folder-versioning-command (default #f)) + (copiers syncthing-folder-copiers (default "0")) + (pullerMaxPendingKiB syncthing-folder-pullerMaxPendingKiB (default "0")) + (hashers syncthing-folder-hashers (default "0")) + (order syncthing-folder-order (default "random")) + (ignoreDelete syncthing-folder-ignoreDelete (default "false")) + (scanProgressIntervalS syncthing-folder-scanProgressIntervalS (default "= 0")) + (pullerPauseS syncthing-folder-pullerPauseS (default "0")) + (maxConflicts syncthing-folder-maxConflicts (default "10")) + (disableSparseFiles syncthing-folder-disableSparseFiles (default "false"= )) + (disableTempIndexes syncthing-folder-disableTempIndexes (default "false"= )) + (paused syncthing-folder-paused (default "false")) + (weakHashThresholdPct syncthing-folder-weakHashThresholdPct (default "25= ")) + (markerName syncthing-folder-markerName (default ".stfolder")) + (copyOwnershipFromParent syncthing-folder-copyOwnershipFromParent (defau= lt "false")) + (modTimeWindowS syncthing-folder-modTimeWindowS (default "0")) + (maxConcurrentWrites syncthing-folder-maxConcurrentWrites (default "2")) + (disableFsync syncthing-folder-disableFsync (default "false")) + (blockPullOrder syncthing-folder-blockPullOrder (default "standard")) + (copyRangeMethod syncthing-folder-copyRangeMethod (default "standard")) + (caseSensitiveFS syncthing-folder-caseSensitiveFS (default "false")) + (junctionsAsDirs syncthing-folder-junctionsAsDirs (default "false")) + (syncOwnership syncthing-folder-syncOwnership (default "false")) + (sendOwnership syncthing-folder-sendOwnership (default "false")) + (syncXattrs syncthing-folder-syncXattrs (default "false")) + (sendXattrs syncthing-folder-sendXattrs (default "false")) + (xattrFilter-maxSingleEntrySize syncthing-folder-xattrFilter-maxSingleEn= trySize (default "1024")) + (xattrFilter-maxTotalSize syncthing-folder-xattrFilter-maxTotalSize (def= ault "4096"))) + +;; Some parameters, when empty, are fully omitted from the config file. I= t is +;; unknown if this causes a functional difference, but stick to the normal +;; program's behavior to be safe. +(define (maybe-param symbol value) + (if value `((param (@ (key ,(symbol->string symbol)) (val ,value)) "")) = '())) + +(define syncthing-folder->sxml + (match-record-lambda + (id + label path type rescanIntervalS fsWatcherEnabled fsWatcherDelayS + ignorePerms autoNormalize devices filesystemType minDiskFree-unit + minDiskFree versioning-type versioning-fsPath versioning-fsType + versioning-cleanupIntervalS versioning-cleanoutDays versioning-keep + versioning-maxAge versioning-command copiers pullerMaxPendingKiB + hashers order ignoreDelete scanProgressIntervalS pullerPauseS + maxConflicts disableSparseFiles disableTempIndexes paused + weakHashThresholdPct markerName copyOwnershipFromParent modTimeWind= owS + maxConcurrentWrites disableFsync blockPullOrder copyRangeMethod + caseSensitiveFS junctionsAsDirs syncOwnership sendOwnership syncXat= trs + sendXattrs xattrFilter-maxSingleEntrySize xattrFilter-maxTotalSize) + `(folder (@ (id ,(if id id label)) + (label ,label) + (path ,path) + (type ,type) + (rescanIntervalS ,rescanIntervalS) + (fsWatcherEnabled ,fsWatcherEnabled) + (fsWatcherDelayS ,fsWatcherDelayS) + (ignorePerms ,ignorePerms) + (autoNormalize ,autoNormalize)) + (filesystemType ,filesystemType) + ,@(map syncthing-folder-device->sxml + devices) + (minDiskFree (@ (unit ,minDiskFree-unit)) + ,minDiskFree) + (versioning ,@(if versioning-type + `((@ (type ,versioning-type))) + '()) + ,@(maybe-param 'cleanoutDays versioning-cleanoutD= ays) + ,@(maybe-param 'keep versioning-keep) + ,@(maybe-param 'maxAge versioning-maxAge) + ,@(maybe-param 'command versioning-command) + (cleanupIntervalS ,versioning-cleanupIntervalS) + (fsPath ,versioning-fsPath) + (fsType ,versioning-fsType)) + (copiers ,copiers) + (pullerMaxPendingKiB ,pullerMaxPendingKiB) + (hashers ,hashers) + (order ,order) + (ignoreDelete ,ignoreDelete) + (scanProgressIntervalS ,scanProgressIntervalS) + (pullerPauseS ,pullerPauseS) + (maxConflicts ,maxConflicts) + (disableSparseFiles ,disableSparseFiles) + (disableTempIndexes ,disableTempIndexes) + (paused ,paused) + (weakHashThresholdPct ,weakHashThresholdPct) + (markerName ,markerName) + (copyOwnershipFromParent ,copyOwnershipFromParent) + (modTimeWindowS ,modTimeWindowS) + (maxConcurrentWrites ,maxConcurrentWrites) + (disableFsync ,disableFsync) + (blockPullOrder ,blockPullOrder) + (copyRangeMethod ,copyRangeMethod) + (caseSensitiveFS ,caseSensitiveFS) + (junctionsAsDirs ,junctionsAsDirs) + (syncOwnership ,syncOwnership) + (sendOwnership ,sendOwnership) + (syncXattrs ,syncXattrs) + (sendXattrs ,sendXattrs) + (xattrFilter (maxSingleEntrySize ,xattrFilter-maxSingleEntryS= ize) + (maxTotalSize ,xattrFilter-maxTotalSize))))) + +(define-record-type* + syncthing-config-file make-syncthing-config-file + syncthing-config-file? + (folders syncthing-config-folders + ; this matches syncthing's default + (default (list (syncthing-folder (id "default") + (label "Default Folder") + (path "~/Sync"))))) + (devices syncthing-config-devices + (default '())) + (gui-enabled syncthing-config-gui-enabled (default "true")) + (gui-tls syncthing-config-gui-tls (default "false")) + (gui-debugging syncthing-config-gui-debugging (default "false")) + (gui-sendBasicAuthPrompt syncthing-config-gui-sendBasicAuthPrompt (defau= lt "false")) + (gui-address syncthing-config-gui-address (default "127.0.0.1:8384")) + (gui-user syncthing-config-gui-user (default #f)) + (gui-password syncthing-config-gui-password (default #f)) + (gui-apikey syncthing-config-gui-apikey (default "Vuky3VHVseQEoSk9YgxhSk= NTnjQmqYK9")) + (gui-theme syncthing-config-gui-theme (default "default")) + (ldap-enabled syncthing-config-ldap-enabled (default #f)) + (ldap-address syncthing-config-ldap-address (default "")) + (ldap-bindDN syncthing-config-ldap-bindDN (default "")) + (ldap-transport syncthing-config-ldap-transport (default "")) + (ldap-insecureSkipVerify syncthing-config-ldap-insecureSkipVerify (defau= lt "")) + (ldap-searchBaseDN syncthing-config-ldap-searchBaseDN (default "")) + (ldap-searchFilter syncthing-config-ldap-searchFilter (default "")) + (listenAddress syncthing-config-listenAddress (default "default")) + (globalAnnounceServer syncthing-config-globalAnnounceServer (default "de= fault")) + (globalAnnounceEnabled syncthing-config-globalAnnounceEnabled (default "= true")) + (localAnnounceEnabled syncthing-config-localAnnounceEnabled (default "tr= ue")) + (localAnnouncePort syncthing-config-localAnnouncePort (default "21027")) + (localAnnounceMCAddr syncthing-config-localAnnounceMCAddr (default "[ff1= 2::8384]:21027")) + (maxSendKbps syncthing-config-maxSendKbps (default "0")) + (maxRecvKbps syncthing-config-maxRecvKbps (default "0")) + (reconnectionIntervalS syncthing-config-reconnectionIntervalS (default "= 60")) + (relaysEnabled syncthing-config-relaysEnabled (default "true")) + (relayReconnectIntervalM syncthing-config-relayReconnectIntervalM (defau= lt "10")) + (startBrowser syncthing-config-startBrowser (default "true")) + (natEnabled syncthing-config-natEnabled (default "true")) + (natLeaseMinutes syncthing-config-natLeaseMinutes (default "60")) + (natRenewalMinutes syncthing-config-natRenewalMinutes (default "30")) + (natTimeoutSeconds syncthing-config-natTimeoutSeconds (default "10")) + (urAccepted syncthing-config-urAccepted (default "0")) + (urSeen syncthing-config-urSeen (default "0")) + (urUniqueID syncthing-config-urUniqueID (default "")) + (urURL syncthing-config-urURL (default "https://data.syncthing.net/newda= ta")) + (urPostInsecurely syncthing-config-urPostInsecurely (default "false")) + (urInitialDelayS syncthing-config-urInitialDelayS (default "1800")) + (autoUpgradeIntervalH syncthing-config-autoUpgradeIntervalH (default "12= ")) + (upgradeToPreReleases syncthing-config-upgradeToPreReleases (default "fa= lse")) + (keepTemporariesH syncthing-config-keepTemporariesH (default "24")) + (cacheIgnoredFiles syncthing-config-cacheIgnoredFiles (default "false")) + (progressUpdateIntervalS syncthing-config-progressUpdateIntervalS (defau= lt "5")) + (limitBandwidthInLan syncthing-config-limitBandwidthInLan (default "fals= e")) + (minHomeDiskFree-unit syncthing-config-minHomeDiskFree-unit (default "%"= )) + (minHomeDiskFree syncthing-config-minHomeDiskFree (default "1")) + (releasesURL syncthing-config-releasesURL (default "https://upgrades.syn= cthing.net/meta.json")) + (overwriteRemoteDeviceNamesOnConnect syncthing-config-overwriteRemoteDev= iceNamesOnConnect (default "false")) + (tempIndexMinBlocks syncthing-config-tempIndexMinBlocks (default "10")) + (unackedNotificationID syncthing-config-unackedNotificationID (default "= authenticationUserAndPassword")) + (trafficClass syncthing-config-trafficClass (default "0")) + (setLowPriority syncthing-config-setLowPriority (default "true")) + (maxFolderConcurrency syncthing-config-maxFolderConcurrency (default "0"= )) + (crashReportingURL syncthing-config-crashReportingURL (default "https://= crash.syncthing.net/newcrash")) + (crashReportingEnabled syncthing-config-crashReportingEnabled (default "= true")) + (stunKeepaliveStartS syncthing-config-stunKeepaliveStartS (default "180"= )) + (stunKeepaliveMinS syncthing-config-stunKeepaliveMinS (default "20")) + (stunServer syncthing-config-stunServer (default "default")) + (databaseTuning syncthing-config-databaseTuning (default "auto")) + (maxConcurrentIncomingRequestKiB syncthing-config-maxConcurrentIncomingR= equestKiB (default "0")) + (announceLANAddresses syncthing-config-announceLANAddresses (default "tr= ue")) + (sendFullIndexOnUpgrade syncthing-config-sendFullIndexOnUpgrade (default= "false")) + (connectionLimitEnough syncthing-config-connectionLimitEnough (default "= 0")) + (connectionLimitMax syncthing-config-connectionLimitMax (default "0")) + (insecureAllowOldTLSVersions syncthing-config-insecureAllowOldTLSVersion= s (default "false")) + (connectionPriorityTcpLan syncthing-config-connectionPriorityTcpLan (def= ault "10")) + (connectionPriorityQuicLan syncthing-config-connectionPriorityQuicLan (d= efault "20")) + (connectionPriorityTcpWan syncthing-config-connectionPriorityTcpWan (def= ault "30")) + (connectionPriorityQuicWan syncthing-config-connectionPriorityQuicWan (d= efault "40")) + (connectionPriorityRelay syncthing-config-connectionPriorityRelay (defau= lt "50")) + (connectionPriorityUpgradeThreshold syncthing-config-connectionPriorityU= pgradeThreshold (default "0")) + (default-folder syncthing-config-defaultFolder + (default (syncthing-folder (label "") (path "~")))) + (default-device syncthing-config-defaultDevice + (default (syncthing-device (id "")))) + (default-ignores syncthing-config-defaultIgnores (default ""))) + +(define syncthing-config-file->sxml + (match-record-lambda + (folders + devices gui-enabled gui-tls gui-debugging gui-sendBasicAuthPrompt + gui-address gui-user gui-password gui-apikey gui-theme ldap-enabled + ldap-address ldap-bindDN ldap-transport ldap-insecureSkipVerify + ldap-searchBaseDN ldap-searchFilter listenAddress globalAnnounceSer= ver + globalAnnounceEnabled localAnnounceEnabled localAnnouncePort + localAnnounceMCAddr maxSendKbps maxRecvKbps reconnectionIntervalS + relaysEnabled relayReconnectIntervalM startBrowser natEnabled + natLeaseMinutes natRenewalMinutes natTimeoutSeconds urAccepted + urSeen urUniqueID urURL urPostInsecurely urInitialDelayS + autoUpgradeIntervalH upgradeToPreReleases keepTemporariesH + cacheIgnoredFiles progressUpdateIntervalS limitBandwidthInLan + minHomeDiskFree-unit minHomeDiskFree releasesURL + overwriteRemoteDeviceNamesOnConnect tempIndexMinBlocks + unackedNotificationID trafficClass setLowPriority maxFolderConcurre= ncy + crashReportingURL crashReportingEnabled stunKeepaliveStartS + stunKeepaliveMinS stunServer databaseTuning + maxConcurrentIncomingRequestKiB announceLANAddresses + sendFullIndexOnUpgrade connectionLimitEnough connectionLimitMax + insecureAllowOldTLSVersions connectionPriorityTcpLan + connectionPriorityQuicLan connectionPriorityTcpWan + connectionPriorityQuicWan connectionPriorityRelay + connectionPriorityUpgradeThreshold default-folder default-device + default-ignores) + `(configuration (@ (version "37")) + ,@(map syncthing-folder->sxml + folders) + ,@(map syncthing-device->sxml + devices) + (gui (@ (enabled ,gui-enabled) + (tls ,gui-tls) + (debugging ,gui-debugging) + (sendBasicAuthPrompt ,gui-sendBasicAuthPrompt)) + (address ,gui-address) + ,@(if gui-user `((user ,gui-user)) '()) + ,@(if gui-password `((password ,gui-password)) '(= )) + (apikey ,gui-apikey) + (theme ,gui-theme)) + (ldap ,(if ldap-enabled + `((address ,ldap-address) + (bindDN ,ldap-bindDN) + ,@(if ldap-transport + `((transport ,ldap-transport)) + '()) + ,@(if ldap-insecureSkipVerify + `((insecureSkipVerify ,ldap-insecur= eSkipVerify)) + '()) + ,@(if ldap-searchBaseDN + `((searchBaseDN ,ldap-searchBaseDN)) + '()) + ,@(if ldap-searchFilter + `((searchFilter ,ldap-searchFilter)) + '())) + "")) + (options (listenAddress ,listenAddress) + (globalAnnounceServer ,globalAnnounceServer) + (globalAnnounceEnabled ,globalAnnounceEnabled) + (localAnnounceEnabled ,localAnnounceEnabled) + (localAnnouncePort ,localAnnouncePort) + (localAnnounceMCAddr ,localAnnounceMCAddr) + (maxSendKbps ,maxSendKbps) + (maxRecvKbps ,maxRecvKbps) + (reconnectionIntervalS ,reconnectionIntervalS) + (relaysEnabled ,relaysEnabled) + (relayReconnectIntervalM ,relayReconnectInter= valM) + (startBrowser ,startBrowser) + (natEnabled ,natEnabled) + (natLeaseMinutes ,natLeaseMinutes) + (natRenewalMinutes ,natRenewalMinutes) + (natTimeoutSeconds ,natTimeoutSeconds) + (urAccepted ,urAccepted) + (urSeen ,urSeen) + (urUniqueID ,urUniqueID) + (urURL ,urURL) + (urPostInsecurely ,urPostInsecurely) + (urInitialDelayS ,urInitialDelayS) + (autoUpgradeIntervalH ,autoUpgradeIntervalH) + (upgradeToPreReleases ,upgradeToPreReleases) + (keepTemporariesH ,keepTemporariesH) + (cacheIgnoredFiles ,cacheIgnoredFiles) + (progressUpdateIntervalS ,progressUpdateInter= valS) + (limitBandwidthInLan ,limitBandwidthInLan) + (minHomeDiskFree (@ (unit ,minHomeDiskFree-un= it)) + ,minHomeDiskFree) + (releasesURL ,releasesURL) + (overwriteRemoteDeviceNamesOnConnect ,overwri= teRemoteDeviceNamesOnConnect) + (tempIndexMinBlocks ,tempIndexMinBlocks) + (unackedNotificationID ,unackedNotificationID) + (trafficClass ,trafficClass) + (setLowPriority ,setLowPriority) + (maxFolderConcurrency ,maxFolderConcurrency) + (crashReportingURL ,crashReportingURL) + (crashReportingEnabled ,crashReportingEnabled) + (stunKeepaliveStartS ,stunKeepaliveStartS) + (stunKeepaliveMinS ,stunKeepaliveMinS) + (stunServer ,stunServer) + (databaseTuning ,databaseTuning) + (maxConcurrentIncomingRequestKiB ,maxConcurre= ntIncomingRequestKiB) + (announceLANAddresses ,announceLANAddresses) + (sendFullIndexOnUpgrade ,sendFullIndexOnUpgra= de) + (connectionLimitEnough ,connectionLimitEnough) + (connectionLimitMax ,connectionLimitMax) + (insecureAllowOldTLSVersions ,insecureAllowOl= dTLSVersions) + (connectionPriorityTcpLan ,connectionPriority= TcpLan) + (connectionPriorityQuicLan ,connectionPriorit= yQuicLan) + (connectionPriorityTcpWan ,connectionPriority= TcpWan) + (connectionPriorityQuicWan ,connectionPriorit= yQuicWan) + (connectionPriorityRelay ,connectionPriorityR= elay) + (connectionPriorityUpgradeThreshold ,connecti= onPriorityUpgradeThreshold)) + (defaults + ,(syncthing-folder->sxml default-folder) + ,(syncthing-device->sxml default-device) + (ignores ,default-ignores))))) + +;; It is useful to be able to view the xml output by Guix, and to be able = to +;; diff it with a users previous config, especially when migrating one's +;; config to Guix. This function adds whitespace that matches the whitesp= ace +;; of config files managed by syncthing for easy diffing +(define (indent-sxml sxml indent-increment current-indent) + (match sxml + (((tag ('@ properties ...) (subtags ..1) ..1) sibling-tags ...) + `(,current-indent (,tag (@ ,@properties) "\n" + ,@(indent-sxml subtags indent-increment + (string-append indent-incremen= t current-indent)) + ,current-indent) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag ('@ properties ...) primitive ...) sibling-tags ...) + `(,current-indent (,tag (@ ,@properties) ,@primitive) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag (subtags ..1) ..1) sibling-tags ...) + `(,current-indent (,tag "\n" + ,@(indent-sxml subtags indent-increment + (string-append indent-incremen= t current-indent)) + ,current-indent) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag primitive ...) sibling-tags ...) + `(,current-indent (,tag ,@primitive) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (() '()))) + +(define (serialize-syncthing-config-file config) + (with-output-to-string + (lambda () + (sxml->xml (cons '*TOP* (indent-sxml (list (syncthing-config-file->s= xml config)) + " " + "")))))) + (define-record-type* syncthing-configuration make-syncthing-configuration syncthing-configuration? @@ -50,6 +487,8 @@ (define-record-type* (default "users")) (home syncthing-configuration-home ;string (default #f)) + (syncthing-config-file syncthing-configuration-syncthing-config-file + (default #f)) ; syncthing-config-file or = file-like (home-service? syncthing-configuration-home-service? (default for-home?) (innate))) =20 @@ -93,10 +532,26 @@ (define syncthing-shepherd-service (respawn? #f) (stop #~(make-kill-destructor)))))) =20 + +(define syncthing-files-service + (match-record-lambda (syncthing-config-file us= er home home-service?) + (if syncthing-config-file + `((,(if home-service? + ".config/syncthing/config.xml" + (string-join (or home (passwd:dir (getpw user))) + "/.config/syncthing/config.xml")) + ,(if (file-like? syncthing-config-file) + syncthing-config-file + (plain-file "syncthin-config.xml" (serialize-syncthing-con= fig-file + syncthing-config-file))= ))) + '()))) + (define syncthing-service-type (service-type (name 'syncthing) (extensions (list (service-extension shepherd-root-service= -type - syncthing-shepherd-se= rvice))) + syncthing-shepherd-se= rvice) + (service-extension special-files-service= -type + syncthing-files-servi= ce))) (description "Run @uref{https://github.com/syncthing/syncthing, Syncth= ing} decentralized continuous file system synchronization."))) --=20 2.45.2 From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH] (home-)syncthing-service: added support for config serialization References: <20250130215954.9394-1-eikcaz@zacchae.us> In-Reply-To: <20250130215954.9394-1-eikcaz@zacchae.us> Resent-From: Zacchaeus Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sat, 01 Feb 2025 08:59:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 75959@debbugs.gnu.org Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.173840033918139 (code B ref 75959); Sat, 01 Feb 2025 08:59:02 +0000 Received: (at 75959) by debbugs.gnu.org; 1 Feb 2025 08:58:59 +0000 Received: from localhost ([127.0.0.1]:56232 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1te9L8-0004iT-MD for submit@debbugs.gnu.org; Sat, 01 Feb 2025 03:58:59 -0500 Received: from [47.204.136.169] (port=52960 helo=hun.zacchae.us) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1te9L6-0004iD-O4 for 75959@debbugs.gnu.org; Sat, 01 Feb 2025 03:58:57 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Type:MIME-Version:Message-ID:Date: Subject:To:From:Sender:Reply-To:Cc:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=0ZSYgPCZIg40wM3od4xf4ZW3dE/+RIQJH4MGOJOe6yE=; i=zacchae.us; b=JbxATJ083WmX QiIH48KnVtx1+VV5gvrCEzNuWMMUFiQ7ocE5IU+Nnca2GtL3tXPjiW6tIRo6QLY5eVtNfMleAw==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Type:MIME-Version:Message-ID:Date:Subject:To:From: Sender:Reply-To:Cc:Content-Transfer-Encoding:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=0ZSYgPCZIg40wM3od4xf4ZW3dE/+RIQJH4MGOJOe6yE=; i=zacchae.us; b=VBMr4/TpADRT 90WcHr9oV8mu9b7leI+wj87Jorbd/6HPKES3o6ryWMtCQc4kcOkxupqzgiSaPLDVKFjo5ntebdXro FkF2QWFZvKJsK3mm62P3PyLsCD2TxrYxlSO6xWbFWWCxBEA9QB1xpJFl+UhNYpzxuGeJCbWl0yNMg orXE1v/NjCOCLi0+W2x/D/fe+n3q4i3rCFPIWdpqAYTAdMOhzLjTS9r42UM72RxhK5jihSUNf+G6y qxOe3yoJ6LsulKhA+P3/FBq5wDGTA6SP2YY7szOh0N3NNwZ1wYmVNBxmxUtZp9gN1GnnOJ5LvAwUh WqOuW+4zc3Q2DrPsDi/NVA==; Received: from localhost.home ([127.0.0.1]:37806 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1te9Ky-000000005Mo-1jXp for 75959@debbugs.gnu.org; Sat, 01 Feb 2025 03:58:48 -0500 From: Zacchaeus Date: Sat, 01 Feb 2025 03:58:48 -0500 Message-ID: <87bjvmjb1z.fsf@zacchae.us> MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: 1.3 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Hi Guix! In order to test my implementation, I compared two pairs of configs: - the default config generated by syncthing with the default config generated by (syncthing-configuration (syncthing-config-file (syncthing-config-file))). Content analysis details: (1.3 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in sa-accredit.habeas.com] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in bl.score.senderscore.com] 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 0.3 (/) Hi Guix! In order to test my implementation, I compared two pairs of configs: - the default config generated by syncthing with the default config generated by (syncthing-configuration (syncthing-config-file (syncthing-config-file))). - my syncthing-gui-generated config with the config generated by a syncthing-config-file reflecting my (rather complex) setup. There are a few differences: - The core differences hinge around the fact that the current device ID is not known in advance. Of course, if you have already run syncthing and know your device ID, you can specify that in your config. - The default ~/Sync folder normally includes the current device. The documentaiton makes it clear that this is OK (and also I have tested this). - The config does not include the current device. The documentation says "One or more device elements must be present in the file", but it seems to work fine dispite this. - The default folder template normally includes the current device. Also fine. - There are also three miscelaneous differences: - The default device template normally omits the "name" field. I suppose I could have added code to fix this, but I know it doesn't break anything so I opted for slightly simpler code. - The API key doesn't match. Of course it doesn't. - The ~/Sync folder is normally specified by /home//Sync, but since I know ~/Sync works, I found that better than trying to compute ~/ in scheme. In summary, there are differences, but those differences have been accounted for and don't introduce bugs. There were a few undocumented behaviors around the absense or presense of a value. In such cases, I implemented whatever behavior was observed in a config file maintained by the Syncthing GUI. I considered submitting this as two patches, one for the home service and one for the system service, but patching just the system service broke the home service. Is that a valid reason to make it one patch? If not, I can split up the patches and resubmit. Addressing the elephant in the room, as I mentioned in the documentation, I used camelCase only to match syncthing documentation. For instance, the ldap searchFilter setting is configured by (syncthing-config-file (ldap-searchFilter "...")). As nauseous as it made me to write something like that, I think translating names to snake-case adds too much confusion/complexity no matter where you add it. It is useful when refencencing Syncthing documentation to know exactly what keyword too look for. Though I believe exceptions exist to every rule, and that this is maybe the only ecxeption to the no camelcase rule, please do tell me if there is a better way and I will resubmit the patch. eikcaz- From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH] services: syncthing: Added support for config file serialization. References: <20250130215954.9394-1-eikcaz@zacchae.us> In-Reply-To: <20250130215954.9394-1-eikcaz@zacchae.us> Resent-From: Zacchaeus Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sat, 01 Feb 2025 09:38:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 75959@debbugs.gnu.org Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.173840263816516 (code B ref 75959); Sat, 01 Feb 2025 09:38:02 +0000 Received: (at 75959) by debbugs.gnu.org; 1 Feb 2025 09:37:18 +0000 Received: from localhost ([127.0.0.1]:56390 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1te9wC-0004II-0m for submit@debbugs.gnu.org; Sat, 01 Feb 2025 04:37:18 -0500 Received: from [47.204.136.169] (port=59540 helo=hun.zacchae.us) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1te9w7-0004I0-Pv for 75959@debbugs.gnu.org; Sat, 01 Feb 2025 04:37:14 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Transfer-Encoding:Content-Type: MIME-Version:Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=1Co5jEnxeXcUw96f7Z1IEBcweGN3voTJ0gUTGQfDP5E=; i=zacchae.us; b=wQuqvBfwxe0F SQI+eTjI4n6v0QUREdD+949uou1ORfob+Fawmuc+Vm4lZPxCu/S3B9SOit+pGH142C7kCIE7Bw==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Transfer-Encoding:Content-Type:MIME-Version: Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=1Co5jEnxeXcUw96f7Z1IEBcweGN3voTJ0gUTGQfDP5E=; i=zacchae.us; b=K1+i8bZNGd4X n5TtkAFWx4aztyzOfs1PC3chLns7K3f3qVFcy1CZQZ7M9ktHPvt0YjgOM7tDCyLRtg0+RTXUHoGlq m8s3RU3+t6YdjRAmnNM0pjB+q3l6NMR1QeG3m1bq07PtxGEMkzkwQssoSeAwV3XjWbkeibqn31+sO pUsk0iNUCTusWg4VdyCiwzx58w7osuOE+s26hQEWT9om5lCFeJcEJwIjkcIbcLlcfab7/o8AFvyQ+ cQN3XO2yKHSd+eOaZ5fH51jAtdvuQZni8ofJMbg4s0b6evjETzxzhYiY900iLakBzqXu8lwSqQAPr gcATJ9fdm0DFpU/5tiXBig==; Received: from localhost.home ([127.0.0.1]:49734 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1te9vz-000000005W8-43q2 for 75959@debbugs.gnu.org; Sat, 01 Feb 2025 04:37:04 -0500 From: Zacchaeus Date: Sat, 01 Feb 2025 04:37:04 -0500 Message-ID: <877c6aj9a7.fsf@zacchae.us> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From 0e0a2b727f3e898440a437edd9ed9b5924547c91 Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH] services: syncthing: Added support for [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in sa-trusted.bondedsender.org] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in bl.score.senderscore.com] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.1 URIBL_SBL_A Contains URL's A record listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 0.6 URIBL_SBL Contains an URL's NS IP listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS 0.0 T_FILL_THIS_FORM_SHORT Fill in a short form with personal information X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 1.0 (+) >From 0e0a2b727f3e898440a437edd9ed9b5924547c91 Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH] services: syncthing: Added support for config file serialization. * gnu/services/syncthing.scm: (syncthing-config-file) (syncthing-folder) (syncthing-device) (syncthing-folder-device): New records; (syncthing-service-type): added special-files-service-type extension for the config file; (syncthing-files-service): service to create config file * gnu/home/services/syncthing.scm: (home-syncthing-service-type): extended home-files-services-type and re-exported more things from gnu/services/syncthing.scm * doc/guix.texi: (syncthing-service-type): document additions Change-Id: I87eeba1ee1fdada8f29c2ee881fbc6bc4113dde9 --- Adds Syncthing config file serialization to Guix. My original patch commit string was not formatted correctly. Please see my revised patch here. More info on how I tested that everything worked can be found in a seperate email in this thread. doc/guix.texi | 281 ++++++++++++++++++- gnu/home/services/syncthing.scm | 17 +- gnu/services/syncthing.scm | 459 +++++++++++++++++++++++++++++++- 3 files changed, 752 insertions(+), 5 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index b1b6d98e74..966fe852a4 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -136,6 +136,7 @@ Copyright @copyright{} 2024 Troy Figiel@* Copyright @copyright{} 2024 Sharlatan Hellseher@* Copyright @copyright{} 2024 45mg@* Copyright @copyright{} 2025 S=C3=B6ren Tempel@* +Copyright @copyright{} 2025 Zacchaeus@* =20 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -22669,8 +22670,284 @@ This assumes that the specified group exists. Common configuration and data directory. The default configuration directory is @file{$HOME} of the specified Syncthing @code{user}. =20 -@end table -@end deftp +@item @code{syncthing-config-file} (default: @var{#f}) +Either a file-like object that resolves to a syncthing configuraton xml +file, or a syncthing-config-file record (see below). + +@end table +@end deftp + +In the below, only details specific to Guix, or related to how your +device will ``ping'' others, are presented. Otherwise, you should +consult @uref{https://docs.syncthing.net/users/config.html, Syncthing +config documentation}. Camelcase is preserved below only as to be +consistent with its appearance in Syncthing code/documentation. If you +would like to migrate to Guix-powerd Syncthing configuration, the +generated config adds newlines/whitespace to the produced config such +that your old config can be diff'ed with the new one. + +@deftp {Data Type} syncthing-config-file +Data type representing the configuration file read by the syncthing +daemon. + +@table @asis +@item @code{folders} (default: @var{(list (syncthing-folder (id "default")= (label "Default Folder") (path "~/Sync")))} +The default here is the same as Syncthing's default. The value should +be a list of @code{syncthing-folder}s. + +@item @code{devices} (default: @var{'()} +This should be a list of @code{syncthing-device}s, or strings correspondin= g to +the device ids. A device entry corresponding to the current device is +silently ignored by Syncthing. + +@item @code{gui-enabled} (default: @var{"true"}) +By default, any user on the computer can access the GUI and make changes +to Syncthing. If you leave this enabled, you should probably set +gui-user and gui-password (see belowe). + +@item @code{gui-tls} (default: @var{"false"}) +@item @code{gui-debugging} (default: @var{"false"}) +@item @code{gui-sendBasicAuthPrompt} (default: @var{"false"}) +@item @code{gui-address} (default: @var{"127.0.0.1:8384"}) +@item @code{gui-user} (default: @var{#f}) +@item @code{gui-password} (default: @var{#f}) +@item @code{gui-apikey} (default: @var{"Vuky3VHVseQEoSk9YgxhSkNTnjQmqYK9"}) +@item @code{gui-theme} (default: @var{"default"}) +@item @code{ldap-enabled} (default: @var{#f}) +@item @code{ldap-address} (default: @var{""}) +@item @code{ldap-bindDN} (default: @var{""}) +@item @code{ldap-transport} (default: @var{""}) +@item @code{ldap-insecureSkipVerify} (default: @var{""}) +@item @code{ldap-searchBaseDN} (default: @var{""}) +@item @code{ldap-searchFilter} (default: @var{""}) +@item @code{listenAddress} (default: @var{"default"}) +@item @code{globalAnnounceServer} (default: @var{"default"}) +@item @code{globalAnnounceEnabled} (default: @var{"true"}) +Global discovery servers can be used to help connect devices at unknown +IP addresses by storing the last known IP address. + +@item @code{localAnnounceEnabled} (default: @var{"true"}) +This makes devices find eachother very easily on the same LAN. Often, +this will allow you to just plug an ethernet between two devices, or +connect one device to the other's hotspot and start syncing. + +@item @code{localAnnouncePort} (default: @var{"21027"}) +@item @code{localAnnounceMCAddr} (default: @var{"[ff12::8384]:21027"}) +@item @code{maxSendKbps} (default: @var{"0"}) +@item @code{maxRecvKbps} (default: @var{"0"}) +@item @code{reconnectionIntervalS} (default: @var{"60"}) +@item @code{relaysEnabled} (default: @var{"true"}) +This option allows your Syncthing instance to coordinate with a global +network of relays to enable syncing between devices when all other +methods fail. + +@item @code{relayReconnectIntervalM} (default: @var{"10"}) +@item @code{startBrowser} (default: @var{"true"}) +@item @code{natEnabled} (default: @var{"true"}) +@item @code{natLeaseMinutes} (default: @var{"60"}) +@item @code{natRenewalMinutes} (default: @var{"30"}) +@item @code{natTimeoutSeconds} (default: @var{"10"}) +@item @code{urAccepted} (default: @var{"0"}) +ur* options control usage reporting. Set to -1 to disable, or positive +to enable. The default (0) has reporting disabled, but you will be +asked to decide in the GUI. + +@item @code{urSeen} (default: @var{"0"}) +@item @code{urUniqueID} (default: @var{""}) +@item @code{urURL} (default: @var{"https://data.syncthing.net/newdata"}) +@item @code{urPostInsecurely} (default: @var{"false"}) +@item @code{urInitialDelayS} (default: @var{"1800"}) +@item @code{autoUpgradeIntervalH} (default: @var{"12"}) +@item @code{upgradeToPreReleases} (default: @var{"false"}) +@item @code{keepTemporariesH} (default: @var{"24"}) +@item @code{cacheIgnoredFiles} (default: @var{"false"}) +@item @code{progressUpdateIntervalS} (default: @var{"5"}) +@item @code{limitBandwidthInLan} (default: @var{"false"}) +@item @code{minHomeDiskFree-unit} (default: @var{"%"}) +@item @code{minHomeDiskFree} (default: @var{"1"}) +@item @code{releasesURL} (default: @var{"https://upgrades.syncthing.net/me= ta.json"}) +@item @code{overwriteRemoteDeviceNamesOnConnect} (default: @var{"false"}) +@item @code{tempIndexMinBlocks} (default: @var{"10"}) +@item @code{unackedNotificationID} (default: @var{"authenticationUserAndPa= ssword"}) +@item @code{trafficClass} (default: @var{"0"}) +@item @code{setLowPriority} (default: @var{"true"}) +@item @code{maxFolderConcurrency} (default: @var{"0"}) +@item @code{crashReportingURL} (default: @var{"https://crash.syncthing.net= /newcrash"}) +@item @code{crashReportingEnabled} (default: @var{"true"}) +@item @code{stunKeepaliveStartS} (default: @var{"180"}) +@item @code{stunKeepaliveMinS} (default: @var{"20"}) +@item @code{stunServer} (default: @var{"default"}) +@item @code{databaseTuning} (default: @var{"auto"}) +@item @code{maxConcurrentIncomingRequestKiB} (default: @var{"0"}) +@item @code{announceLANAddresses} (default: @var{"true"}) +@item @code{sendFullIndexOnUpgrade} (default: @var{"false"}) +@item @code{connectionLimitEnough} (default: @var{"0"}) +@item @code{connectionLimitMax} (default: @var{"0"}) +@item @code{insecureAllowOldTLSVersions} (default: @var{"false"}) +@item @code{connectionPriorityTcpLan} (default: @var{"10"}) +@item @code{connectionPriorityQuicLan} (default: @var{"20"}) +@item @code{connectionPriorityTcpWan} (default: @var{"30"}) +@item @code{connectionPriorityQuicWan} (default: @var{"40"}) +@item @code{connectionPriorityRelay} (default: @var{"50"}) +@item @code{connectionPriorityUpgradeThreshold} (default: @var{"0"}) +@item @code{default-folder} (default: @var{(syncthing-folder (label ""))}) +@item @code{default-device} (default: @var{(syncthing-device (id ""))}) +@item @code{default-ignores} (default: @var{"")}) +The default-* above do not affect folders and devices added by the Guix +interface. They will, however, affect folders and devices that are +added through the GUI, or by an ``introducer''. +@end table +@end deftp + +@deftp {Data Type} syncthing-device +Data type representing a device to sync with. + +@table @asis +@item @code{id} +A long hash tied to the keys generated by Syncthing on the first launch. +You can obtain this from the Syncthing GUI or by inpsecting an existing +Syncthing configuration file. + +@item @code{name} (default: @var{""}) +Human readable device name for viewing in the GUI or in scheme. + +@item @code{compression} (default: @var{"metadata"}) +@item @code{introducer} (default: @var{"false"}) +@item @code{skipIntroductionRemovals} (default: @var{"false"}) +@item @code{introducedBy} (default: @var{""}) +@item @code{addresses} (default: @var{'("dynamic")}) +List of addresses at which to search for this device. The special value +``dynamic'' will have syncthing use several means to find the device. + +@item @code{paused} (default: @var{"false"}) +@item @code{autoAcceptFolders} (default: @var{"false"}) +@item @code{maxSendKbps} (default: @var{"0"}) +@item @code{maxRecvKbps} (default: @var{"0"}) +@item @code{maxRequestKiB} (default: @var{"0"}) +@item @code{untrusted} (default: @var{"false"}) +@item @code{remoteGUIPort} (default: @var{"0"}) +@item @code{numConnections} (default: @var{"0")}) + +@end table +@end deftp + +@deftp {Data Type} syncthing-folder +Data type representing a folder to be synced. + +@table @asis +@item @code{id} (default: @var{#f}) +This id cannot match the id of any other folder on this device. If left +unspecified, it will default to the label (see below). + +@item @code{label} +Human readable label for the folder. + +@item @code{path} +The path at which to store this folder. + +@item @code{type} (default: @var{"sendreceive"}) +@item @code{rescanIntervalS} (default: @var{"3600"}) +@item @code{fsWatcherEnabled} (default: @var{"true"}) +@item @code{fsWatcherDelayS} (default: @var{"10"}) +@item @code{ignorePerms} (default: @var{"false"}) +@item @code{autoNormalize} (default: @var{"true"}) +@item @code{devices} (default: @var{'()}) +Devices should be a list of other Syncthing devices. If the current +device is included, it is silently ignored by syncthing (which makes for +lazier scheme code). Each device can be listed as a string representing +the device id, a @code{syncthing-device} object, or a +@code{syncthing-folder-device} object. + +@item @code{filesystemType} (default: @var{"basic"}) +@item @code{minDiskFree-unit} (default: @var{"%"}) +@item @code{minDiskFree} (default: @var{"1"}) +@item @code{versioning-type} (default: @var{#f}) +@item @code{versioning-fsPath} (default: @var{""}) +@item @code{versioning-fsType} (default: @var{"basic"}) +@item @code{versioning-cleanupIntervalS} (default: @var{"3600"}) +@item @code{versioning-cleanoutDays} (default: @var{#f}) +@item @code{versioning-keep} (default: @var{#f}) +@item @code{versioning-maxAge} (default: @var{#f}) +@item @code{versioning-command} (default: @var{#f}) +@item @code{copiers} (default: @var{"0"}) +@item @code{pullerMaxPendingKiB} (default: @var{"0"}) +@item @code{hashers} (default: @var{"0"}) +@item @code{order} (default: @var{"random"}) +@item @code{ignoreDelete} (default: @var{"false"}) +@item @code{scanProgressIntervalS} (default: @var{"0"}) +@item @code{pullerPauseS} (default: @var{"0"}) +@item @code{maxConflicts} (default: @var{"10"}) +@item @code{disableSparseFiles} (default: @var{"false"}) +@item @code{disableTempIndexes} (default: @var{"false"}) +@item @code{paused} (default: @var{"false"}) +@item @code{weakHashThresholdPct} (default: @var{"25"}) +@item @code{markerName} (default: @var{".stfolder"}) +@item @code{copyOwnershipFromParent} (default: @var{"false"}) +@item @code{modTimeWindowS} (default: @var{"0"}) +@item @code{maxConcurrentWrites} (default: @var{"2"}) +@item @code{disableFsync} (default: @var{"false"}) +@item @code{blockPullOrder} (default: @var{"standard"}) +@item @code{copyRangeMethod} (default: @var{"standard"}) +@item @code{caseSensitiveFS} (default: @var{"false"}) +@item @code{junctionsAsDirs} (default: @var{"false"}) +@item @code{syncOwnership} (default: @var{"false"}) +@item @code{sendOwnership} (default: @var{"false"}) +@item @code{syncXattrs} (default: @var{"false"}) +@item @code{sendXattrs} (default: @var{"false"}) +@item @code{xattrFilter-maxSingleEntrySize} (default: @var{"1024"}) +@item @code{xattrFilter-maxTotalSize} (default: @var{"4096")}) +@end table +@end deftp + +@deftp {Data Type} syncthing-folder-device +There is some configuration which is specific to the relationship +between a specific folder and a specific device. If you are fine +leaving these as their default, then you can simply specify a +syncthing-device instead of a syncthing-folder-device. + +@table @asis +@item @code{id} (default: @var{""}) +id can be provided as a string of the id, or a @code{syncthing-device}. + +@item @code{introducedBy} (default: @var{""}) +@item @code{encryptionPassword} (default: @var{""}) +if encryptionPassword is non-empty, then it will be used as a password +to encrypt file chunks as they are synced to that device. For more info +on syncing to devices you don't totally trust, see +@uref{https://docs.syncthing.net/users/untrusted.html, Syncthing Documenta= tion Untrusted}. +Note that file transfers are always end-to-end encrypted, regardless of +this setting. + +@end table +@end deftp + +Here is a more complex example configuration for illustrative purposes: +@lisp +(service syncthing-service-type + (let ((laptop (syncthing-device (id "VHOD2D6-...-7XRMDEN"))) + (desktop (syncthing-device (id "64SAZ37-...-FZJ5GUA") + (addresses '("mydomain.com")))) + (bob-desktop "KYIMEGO-...-FT77EAO")) + (syncthing-configuration + (user "alice") + (syncthing-config-file + (folders (list (syncthing-folder + (label "some-files") + (path "~/data") + (devices (list desktop laptop))) + (syncthing-folder + (label "critical-files") + (path "~/secrets") + (devices + (list desktop + laptop + (syncthing-folder-device + (id bob-desktop) + (encryptionPassword "mypassword")))))= )) + ;; any device used above should be in this list + (devices (list laptop desktop bob-desktop)))) +@end lisp + =20 Furthermore, @code{(gnu services ssh)} provides the following services. @cindex SSH diff --git a/gnu/home/services/syncthing.scm b/gnu/home/services/syncthing.= scm index 8d66a167ce..dd6c752ee4 100644 --- a/gnu/home/services/syncthing.scm +++ b/gnu/home/services/syncthing.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2023 Ludovic Court=C3=A8s +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -24,9 +25,23 @@ (define-module (gnu home services syncthing) #:use-module (gnu home services shepherd) #:export (home-syncthing-service-type) #:re-export (syncthing-configuration - syncthing-configuration?)) + syncthing-configuration? + syncthing-config-file + syncthing-config-file? + syncthing-device + syncthing-device? + syncthing-folder + syncthing-folder? + syncthing-folder-device + syncthing-folder-device?)) =20 (define home-syncthing-service-type (service-type (inherit (system->home-service-type syncthing-service-type)) + ;; system->home-service-type does not convert special-files-service-typ= e to + ;; home-files-service-type, so redefine extensios + (extensions (list (service-extension home-files-service-type + syncthing-files-service) + (service-extension home-shepherd-service-type + syncthing-shepherd-service))) (default-value (for-home (syncthing-configuration))))) diff --git a/gnu/services/syncthing.scm b/gnu/services/syncthing.scm index a7a9c6aadd..4f0d4c1082 100644 --- a/gnu/services/syncthing.scm +++ b/gnu/services/syncthing.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2021 Oleg Pykhalov ;;; Copyright =C2=A9 2023 Justin Veilleux +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -25,9 +26,20 @@ (define-module (gnu services syncthing) #:use-module (guix records) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (sxml simple) #:export (syncthing-configuration syncthing-configuration? - syncthing-service-type)) + syncthing-device + syncthing-device? + syncthing-config-file + syncthing-config-file? + syncthing-folder-device + syncthing-folder-device? + syncthing-folder + syncthing-folder? + syncthing-service-type + syncthing-shepherd-service + syncthing-files-service)) =20 ;;; Commentary: ;;; @@ -35,6 +47,431 @@ (define-module (gnu services syncthing) ;;; ;;; Code: =20 +(define-record-type* + syncthing-device make-syncthing-device + syncthing-device? + (id syncthing-device-id) + (name syncthing-device-name (default "")) + (compression syncthing-device-compression (default "metadata")) + (introducer syncthing-device-introducer (default "false")) + (skipIntroductionRemovals syncthing-device-skipIntroductionRemovals (def= ault "false")) + (introducedBy syncthing-device-introducedBy (default "")) + (addresses syncthing-device-addresses (default '("dynamic"))) + (paused syncthing-device-paused (default "false")) + (autoAcceptFolders syncthing-device-autoAcceptFolders (default "false")) + (maxSendKbps syncthing-device-maxSendKbps (default "0")) + (maxRecvKbps syncthing-device-maxRecvKbps (default "0")) + (maxRequestKiB syncthing-device-maxRequestKiB (default "0")) + (untrusted syncthing-device-untrusted (default "false")) + (remoteGUIPort syncthing-device-remoteGUIPort (default "0")) + (numConnections syncthing-device-numConnections (default "0"))) + +(define syncthing-device->sxml + (match-record-lambda + (id name compression introducer skipIntroductionRemovals introducedB= y addresses paused autoAcceptFolders maxSendKbps maxRecvKbps maxRequestKiB = untrusted remoteGUIPort numConnections) + `(device (@ (id ,id) + (name ,name) + (compression ,compression) + (introducer ,introducer) + (skipIntroductionRemovals ,skipIntroductionRemovals) + (introducedBy ,introducedBy)) + ,@(map (lambda (address) `(address ,address)) addresses) + (paused ,paused) + (autoAcceptFolders ,autoAcceptFolders) + (maxSendKbps ,maxSendKbps) + (maxRecvKbps ,maxRecvKbps) + (maxRequestKiB ,maxRequestKiB) + (untrusted ,untrusted) + (remoteGUIPort ,remoteGUIPort) + (numConnections ,numConnections)))) + +(define (id-or-device->id id-or-device) + (if (syncthing-device? id-or-device) + (syncthing-device-id id-or-device) + id-or-device)) + +(define-record-type* + syncthing-folder-device make-syncthing-folder-device + syncthing-folder-device? + (id syncthing-folder-device-id + (sanitize id-or-device->id)) + (introducedBy syncthing-folder-device-introducedBy (default "") + (sanitize id-or-device->id)) + (encryptionPassword syncthing-folder-device-encryptionPassword (default = ""))) + +(define syncthing-folder-device->sxml + (match-record-lambda + (id introducedBy encryptionPassword) + `(device (@ (id ,id) + (introducedBy ,introducedBy)) + (encryptionPassword ,encryptionPassword)))) + +(define-record-type* + syncthing-folder make-syncthing-folder + syncthing-folder? + (id syncthing-folder-id (default #f)) + (label syncthing-folder-label) + (path syncthing-folder-path) + (type syncthing-folder-type (default "sendreceive")) + (rescanIntervalS syncthing-folder-rescanIntervalS (default "3600")) + (fsWatcherEnabled syncthing-folder-fsWatcherEnabled (default "true")) + (fsWatcherDelayS syncthing-folder-fsWatcherDelayS (default "10")) + (ignorePerms syncthing-folder-ignorePerms (default "false")) + (autoNormalize syncthing-folder-autoNormalize (default "true")) + (devices syncthing-folder-devices (default '()) + (sanitize (lambda (folder-device-list) + (map (lambda (device) + (if (syncthing-folder-device? device) + device + (syncthing-folder-device (id device)))) + folder-device-list)))) + (filesystemType syncthing-folder-filesystemType (default "basic")) + (minDiskFree-unit syncthing-folder-minDiskFree-unit (default "%")) + (minDiskFree syncthing-folder-minDiskFree (default "1")) + (versioning-type syncthing-folder-versioning-type (default #f)) + (versioning-fsPath syncthing-folder-versioning-fsPath (default "")) + (versioning-fsType syncthing-folder-versioning-fsType (default "basic")) + (versioning-cleanupIntervalS syncthing-folder-versioning-cleanupInterval= S (default "3600")) + (versioning-cleanoutDays syncthing-folder-versioning-cleanoutDays (defau= lt #f)) + (versioning-keep syncthing-folder-versioning-keep (default #f)) + (versioning-maxAge syncthing-folder-versioning-maxAge (default #f)) + (versioning-command syncthing-folder-versioning-command (default #f)) + (copiers syncthing-folder-copiers (default "0")) + (pullerMaxPendingKiB syncthing-folder-pullerMaxPendingKiB (default "0")) + (hashers syncthing-folder-hashers (default "0")) + (order syncthing-folder-order (default "random")) + (ignoreDelete syncthing-folder-ignoreDelete (default "false")) + (scanProgressIntervalS syncthing-folder-scanProgressIntervalS (default "= 0")) + (pullerPauseS syncthing-folder-pullerPauseS (default "0")) + (maxConflicts syncthing-folder-maxConflicts (default "10")) + (disableSparseFiles syncthing-folder-disableSparseFiles (default "false"= )) + (disableTempIndexes syncthing-folder-disableTempIndexes (default "false"= )) + (paused syncthing-folder-paused (default "false")) + (weakHashThresholdPct syncthing-folder-weakHashThresholdPct (default "25= ")) + (markerName syncthing-folder-markerName (default ".stfolder")) + (copyOwnershipFromParent syncthing-folder-copyOwnershipFromParent (defau= lt "false")) + (modTimeWindowS syncthing-folder-modTimeWindowS (default "0")) + (maxConcurrentWrites syncthing-folder-maxConcurrentWrites (default "2")) + (disableFsync syncthing-folder-disableFsync (default "false")) + (blockPullOrder syncthing-folder-blockPullOrder (default "standard")) + (copyRangeMethod syncthing-folder-copyRangeMethod (default "standard")) + (caseSensitiveFS syncthing-folder-caseSensitiveFS (default "false")) + (junctionsAsDirs syncthing-folder-junctionsAsDirs (default "false")) + (syncOwnership syncthing-folder-syncOwnership (default "false")) + (sendOwnership syncthing-folder-sendOwnership (default "false")) + (syncXattrs syncthing-folder-syncXattrs (default "false")) + (sendXattrs syncthing-folder-sendXattrs (default "false")) + (xattrFilter-maxSingleEntrySize syncthing-folder-xattrFilter-maxSingleEn= trySize (default "1024")) + (xattrFilter-maxTotalSize syncthing-folder-xattrFilter-maxTotalSize (def= ault "4096"))) + +;; Some parameters, when empty, are fully omitted from the config file. I= t is +;; unknown if this causes a functional difference, but stick to the normal +;; program's behavior to be safe. +(define (maybe-param symbol value) + (if value `((param (@ (key ,(symbol->string symbol)) (val ,value)) "")) = '())) + +(define syncthing-folder->sxml + (match-record-lambda + (id + label path type rescanIntervalS fsWatcherEnabled fsWatcherDelayS + ignorePerms autoNormalize devices filesystemType minDiskFree-unit + minDiskFree versioning-type versioning-fsPath versioning-fsType + versioning-cleanupIntervalS versioning-cleanoutDays versioning-keep + versioning-maxAge versioning-command copiers pullerMaxPendingKiB + hashers order ignoreDelete scanProgressIntervalS pullerPauseS + maxConflicts disableSparseFiles disableTempIndexes paused + weakHashThresholdPct markerName copyOwnershipFromParent modTimeWind= owS + maxConcurrentWrites disableFsync blockPullOrder copyRangeMethod + caseSensitiveFS junctionsAsDirs syncOwnership sendOwnership syncXat= trs + sendXattrs xattrFilter-maxSingleEntrySize xattrFilter-maxTotalSize) + `(folder (@ (id ,(if id id label)) + (label ,label) + (path ,path) + (type ,type) + (rescanIntervalS ,rescanIntervalS) + (fsWatcherEnabled ,fsWatcherEnabled) + (fsWatcherDelayS ,fsWatcherDelayS) + (ignorePerms ,ignorePerms) + (autoNormalize ,autoNormalize)) + (filesystemType ,filesystemType) + ,@(map syncthing-folder-device->sxml + devices) + (minDiskFree (@ (unit ,minDiskFree-unit)) + ,minDiskFree) + (versioning ,@(if versioning-type + `((@ (type ,versioning-type))) + '()) + ,@(maybe-param 'cleanoutDays versioning-cleanoutD= ays) + ,@(maybe-param 'keep versioning-keep) + ,@(maybe-param 'maxAge versioning-maxAge) + ,@(maybe-param 'command versioning-command) + (cleanupIntervalS ,versioning-cleanupIntervalS) + (fsPath ,versioning-fsPath) + (fsType ,versioning-fsType)) + (copiers ,copiers) + (pullerMaxPendingKiB ,pullerMaxPendingKiB) + (hashers ,hashers) + (order ,order) + (ignoreDelete ,ignoreDelete) + (scanProgressIntervalS ,scanProgressIntervalS) + (pullerPauseS ,pullerPauseS) + (maxConflicts ,maxConflicts) + (disableSparseFiles ,disableSparseFiles) + (disableTempIndexes ,disableTempIndexes) + (paused ,paused) + (weakHashThresholdPct ,weakHashThresholdPct) + (markerName ,markerName) + (copyOwnershipFromParent ,copyOwnershipFromParent) + (modTimeWindowS ,modTimeWindowS) + (maxConcurrentWrites ,maxConcurrentWrites) + (disableFsync ,disableFsync) + (blockPullOrder ,blockPullOrder) + (copyRangeMethod ,copyRangeMethod) + (caseSensitiveFS ,caseSensitiveFS) + (junctionsAsDirs ,junctionsAsDirs) + (syncOwnership ,syncOwnership) + (sendOwnership ,sendOwnership) + (syncXattrs ,syncXattrs) + (sendXattrs ,sendXattrs) + (xattrFilter (maxSingleEntrySize ,xattrFilter-maxSingleEntryS= ize) + (maxTotalSize ,xattrFilter-maxTotalSize))))) + +(define-record-type* + syncthing-config-file make-syncthing-config-file + syncthing-config-file? + (folders syncthing-config-folders + ; this matches syncthing's default + (default (list (syncthing-folder (id "default") + (label "Default Folder") + (path "~/Sync"))))) + (devices syncthing-config-devices + (default '())) + (gui-enabled syncthing-config-gui-enabled (default "true")) + (gui-tls syncthing-config-gui-tls (default "false")) + (gui-debugging syncthing-config-gui-debugging (default "false")) + (gui-sendBasicAuthPrompt syncthing-config-gui-sendBasicAuthPrompt (defau= lt "false")) + (gui-address syncthing-config-gui-address (default "127.0.0.1:8384")) + (gui-user syncthing-config-gui-user (default #f)) + (gui-password syncthing-config-gui-password (default #f)) + (gui-apikey syncthing-config-gui-apikey (default "Vuky3VHVseQEoSk9YgxhSk= NTnjQmqYK9")) + (gui-theme syncthing-config-gui-theme (default "default")) + (ldap-enabled syncthing-config-ldap-enabled (default #f)) + (ldap-address syncthing-config-ldap-address (default "")) + (ldap-bindDN syncthing-config-ldap-bindDN (default "")) + (ldap-transport syncthing-config-ldap-transport (default "")) + (ldap-insecureSkipVerify syncthing-config-ldap-insecureSkipVerify (defau= lt "")) + (ldap-searchBaseDN syncthing-config-ldap-searchBaseDN (default "")) + (ldap-searchFilter syncthing-config-ldap-searchFilter (default "")) + (listenAddress syncthing-config-listenAddress (default "default")) + (globalAnnounceServer syncthing-config-globalAnnounceServer (default "de= fault")) + (globalAnnounceEnabled syncthing-config-globalAnnounceEnabled (default "= true")) + (localAnnounceEnabled syncthing-config-localAnnounceEnabled (default "tr= ue")) + (localAnnouncePort syncthing-config-localAnnouncePort (default "21027")) + (localAnnounceMCAddr syncthing-config-localAnnounceMCAddr (default "[ff1= 2::8384]:21027")) + (maxSendKbps syncthing-config-maxSendKbps (default "0")) + (maxRecvKbps syncthing-config-maxRecvKbps (default "0")) + (reconnectionIntervalS syncthing-config-reconnectionIntervalS (default "= 60")) + (relaysEnabled syncthing-config-relaysEnabled (default "true")) + (relayReconnectIntervalM syncthing-config-relayReconnectIntervalM (defau= lt "10")) + (startBrowser syncthing-config-startBrowser (default "true")) + (natEnabled syncthing-config-natEnabled (default "true")) + (natLeaseMinutes syncthing-config-natLeaseMinutes (default "60")) + (natRenewalMinutes syncthing-config-natRenewalMinutes (default "30")) + (natTimeoutSeconds syncthing-config-natTimeoutSeconds (default "10")) + (urAccepted syncthing-config-urAccepted (default "0")) + (urSeen syncthing-config-urSeen (default "0")) + (urUniqueID syncthing-config-urUniqueID (default "")) + (urURL syncthing-config-urURL (default "https://data.syncthing.net/newda= ta")) + (urPostInsecurely syncthing-config-urPostInsecurely (default "false")) + (urInitialDelayS syncthing-config-urInitialDelayS (default "1800")) + (autoUpgradeIntervalH syncthing-config-autoUpgradeIntervalH (default "12= ")) + (upgradeToPreReleases syncthing-config-upgradeToPreReleases (default "fa= lse")) + (keepTemporariesH syncthing-config-keepTemporariesH (default "24")) + (cacheIgnoredFiles syncthing-config-cacheIgnoredFiles (default "false")) + (progressUpdateIntervalS syncthing-config-progressUpdateIntervalS (defau= lt "5")) + (limitBandwidthInLan syncthing-config-limitBandwidthInLan (default "fals= e")) + (minHomeDiskFree-unit syncthing-config-minHomeDiskFree-unit (default "%"= )) + (minHomeDiskFree syncthing-config-minHomeDiskFree (default "1")) + (releasesURL syncthing-config-releasesURL (default "https://upgrades.syn= cthing.net/meta.json")) + (overwriteRemoteDeviceNamesOnConnect syncthing-config-overwriteRemoteDev= iceNamesOnConnect (default "false")) + (tempIndexMinBlocks syncthing-config-tempIndexMinBlocks (default "10")) + (unackedNotificationID syncthing-config-unackedNotificationID (default "= authenticationUserAndPassword")) + (trafficClass syncthing-config-trafficClass (default "0")) + (setLowPriority syncthing-config-setLowPriority (default "true")) + (maxFolderConcurrency syncthing-config-maxFolderConcurrency (default "0"= )) + (crashReportingURL syncthing-config-crashReportingURL (default "https://= crash.syncthing.net/newcrash")) + (crashReportingEnabled syncthing-config-crashReportingEnabled (default "= true")) + (stunKeepaliveStartS syncthing-config-stunKeepaliveStartS (default "180"= )) + (stunKeepaliveMinS syncthing-config-stunKeepaliveMinS (default "20")) + (stunServer syncthing-config-stunServer (default "default")) + (databaseTuning syncthing-config-databaseTuning (default "auto")) + (maxConcurrentIncomingRequestKiB syncthing-config-maxConcurrentIncomingR= equestKiB (default "0")) + (announceLANAddresses syncthing-config-announceLANAddresses (default "tr= ue")) + (sendFullIndexOnUpgrade syncthing-config-sendFullIndexOnUpgrade (default= "false")) + (connectionLimitEnough syncthing-config-connectionLimitEnough (default "= 0")) + (connectionLimitMax syncthing-config-connectionLimitMax (default "0")) + (insecureAllowOldTLSVersions syncthing-config-insecureAllowOldTLSVersion= s (default "false")) + (connectionPriorityTcpLan syncthing-config-connectionPriorityTcpLan (def= ault "10")) + (connectionPriorityQuicLan syncthing-config-connectionPriorityQuicLan (d= efault "20")) + (connectionPriorityTcpWan syncthing-config-connectionPriorityTcpWan (def= ault "30")) + (connectionPriorityQuicWan syncthing-config-connectionPriorityQuicWan (d= efault "40")) + (connectionPriorityRelay syncthing-config-connectionPriorityRelay (defau= lt "50")) + (connectionPriorityUpgradeThreshold syncthing-config-connectionPriorityU= pgradeThreshold (default "0")) + (default-folder syncthing-config-defaultFolder + (default (syncthing-folder (label "") (path "~")))) + (default-device syncthing-config-defaultDevice + (default (syncthing-device (id "")))) + (default-ignores syncthing-config-defaultIgnores (default ""))) + +(define syncthing-config-file->sxml + (match-record-lambda + (folders + devices gui-enabled gui-tls gui-debugging gui-sendBasicAuthPrompt + gui-address gui-user gui-password gui-apikey gui-theme ldap-enabled + ldap-address ldap-bindDN ldap-transport ldap-insecureSkipVerify + ldap-searchBaseDN ldap-searchFilter listenAddress globalAnnounceSer= ver + globalAnnounceEnabled localAnnounceEnabled localAnnouncePort + localAnnounceMCAddr maxSendKbps maxRecvKbps reconnectionIntervalS + relaysEnabled relayReconnectIntervalM startBrowser natEnabled + natLeaseMinutes natRenewalMinutes natTimeoutSeconds urAccepted + urSeen urUniqueID urURL urPostInsecurely urInitialDelayS + autoUpgradeIntervalH upgradeToPreReleases keepTemporariesH + cacheIgnoredFiles progressUpdateIntervalS limitBandwidthInLan + minHomeDiskFree-unit minHomeDiskFree releasesURL + overwriteRemoteDeviceNamesOnConnect tempIndexMinBlocks + unackedNotificationID trafficClass setLowPriority maxFolderConcurre= ncy + crashReportingURL crashReportingEnabled stunKeepaliveStartS + stunKeepaliveMinS stunServer databaseTuning + maxConcurrentIncomingRequestKiB announceLANAddresses + sendFullIndexOnUpgrade connectionLimitEnough connectionLimitMax + insecureAllowOldTLSVersions connectionPriorityTcpLan + connectionPriorityQuicLan connectionPriorityTcpWan + connectionPriorityQuicWan connectionPriorityRelay + connectionPriorityUpgradeThreshold default-folder default-device + default-ignores) + `(configuration (@ (version "37")) + ,@(map syncthing-folder->sxml + folders) + ,@(map syncthing-device->sxml + devices) + (gui (@ (enabled ,gui-enabled) + (tls ,gui-tls) + (debugging ,gui-debugging) + (sendBasicAuthPrompt ,gui-sendBasicAuthPrompt)) + (address ,gui-address) + ,@(if gui-user `((user ,gui-user)) '()) + ,@(if gui-password `((password ,gui-password)) '(= )) + (apikey ,gui-apikey) + (theme ,gui-theme)) + (ldap ,(if ldap-enabled + `((address ,ldap-address) + (bindDN ,ldap-bindDN) + ,@(if ldap-transport + `((transport ,ldap-transport)) + '()) + ,@(if ldap-insecureSkipVerify + `((insecureSkipVerify ,ldap-insecur= eSkipVerify)) + '()) + ,@(if ldap-searchBaseDN + `((searchBaseDN ,ldap-searchBaseDN)) + '()) + ,@(if ldap-searchFilter + `((searchFilter ,ldap-searchFilter)) + '())) + "")) + (options (listenAddress ,listenAddress) + (globalAnnounceServer ,globalAnnounceServer) + (globalAnnounceEnabled ,globalAnnounceEnabled) + (localAnnounceEnabled ,localAnnounceEnabled) + (localAnnouncePort ,localAnnouncePort) + (localAnnounceMCAddr ,localAnnounceMCAddr) + (maxSendKbps ,maxSendKbps) + (maxRecvKbps ,maxRecvKbps) + (reconnectionIntervalS ,reconnectionIntervalS) + (relaysEnabled ,relaysEnabled) + (relayReconnectIntervalM ,relayReconnectInter= valM) + (startBrowser ,startBrowser) + (natEnabled ,natEnabled) + (natLeaseMinutes ,natLeaseMinutes) + (natRenewalMinutes ,natRenewalMinutes) + (natTimeoutSeconds ,natTimeoutSeconds) + (urAccepted ,urAccepted) + (urSeen ,urSeen) + (urUniqueID ,urUniqueID) + (urURL ,urURL) + (urPostInsecurely ,urPostInsecurely) + (urInitialDelayS ,urInitialDelayS) + (autoUpgradeIntervalH ,autoUpgradeIntervalH) + (upgradeToPreReleases ,upgradeToPreReleases) + (keepTemporariesH ,keepTemporariesH) + (cacheIgnoredFiles ,cacheIgnoredFiles) + (progressUpdateIntervalS ,progressUpdateInter= valS) + (limitBandwidthInLan ,limitBandwidthInLan) + (minHomeDiskFree (@ (unit ,minHomeDiskFree-un= it)) + ,minHomeDiskFree) + (releasesURL ,releasesURL) + (overwriteRemoteDeviceNamesOnConnect ,overwri= teRemoteDeviceNamesOnConnect) + (tempIndexMinBlocks ,tempIndexMinBlocks) + (unackedNotificationID ,unackedNotificationID) + (trafficClass ,trafficClass) + (setLowPriority ,setLowPriority) + (maxFolderConcurrency ,maxFolderConcurrency) + (crashReportingURL ,crashReportingURL) + (crashReportingEnabled ,crashReportingEnabled) + (stunKeepaliveStartS ,stunKeepaliveStartS) + (stunKeepaliveMinS ,stunKeepaliveMinS) + (stunServer ,stunServer) + (databaseTuning ,databaseTuning) + (maxConcurrentIncomingRequestKiB ,maxConcurre= ntIncomingRequestKiB) + (announceLANAddresses ,announceLANAddresses) + (sendFullIndexOnUpgrade ,sendFullIndexOnUpgra= de) + (connectionLimitEnough ,connectionLimitEnough) + (connectionLimitMax ,connectionLimitMax) + (insecureAllowOldTLSVersions ,insecureAllowOl= dTLSVersions) + (connectionPriorityTcpLan ,connectionPriority= TcpLan) + (connectionPriorityQuicLan ,connectionPriorit= yQuicLan) + (connectionPriorityTcpWan ,connectionPriority= TcpWan) + (connectionPriorityQuicWan ,connectionPriorit= yQuicWan) + (connectionPriorityRelay ,connectionPriorityR= elay) + (connectionPriorityUpgradeThreshold ,connecti= onPriorityUpgradeThreshold)) + (defaults + ,(syncthing-folder->sxml default-folder) + ,(syncthing-device->sxml default-device) + (ignores ,default-ignores))))) + +;; It is useful to be able to view the xml output by Guix, and to be able = to +;; diff it with a users previous config, especially when migrating one's +;; config to Guix. This function adds whitespace that matches the whitesp= ace +;; of config files managed by syncthing for easy diffing +(define (indent-sxml sxml indent-increment current-indent) + (match sxml + (((tag ('@ properties ...) (subtags ..1) ..1) sibling-tags ...) + `(,current-indent (,tag (@ ,@properties) "\n" + ,@(indent-sxml subtags indent-increment + (string-append indent-incremen= t current-indent)) + ,current-indent) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag ('@ properties ...) primitive ...) sibling-tags ...) + `(,current-indent (,tag (@ ,@properties) ,@primitive) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag (subtags ..1) ..1) sibling-tags ...) + `(,current-indent (,tag "\n" + ,@(indent-sxml subtags indent-increment + (string-append indent-incremen= t current-indent)) + ,current-indent) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag primitive ...) sibling-tags ...) + `(,current-indent (,tag ,@primitive) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (() '()))) + +(define (serialize-syncthing-config-file config) + (with-output-to-string + (lambda () + (sxml->xml (cons '*TOP* (indent-sxml (list (syncthing-config-file->s= xml config)) + " " + "")))))) + (define-record-type* syncthing-configuration make-syncthing-configuration syncthing-configuration? @@ -50,6 +487,8 @@ (define-record-type* (default "users")) (home syncthing-configuration-home ;string (default #f)) + (syncthing-config-file syncthing-configuration-syncthing-config-file + (default #f)) ; syncthing-config-file or = file-like (home-service? syncthing-configuration-home-service? (default for-home?) (innate))) =20 @@ -93,10 +532,26 @@ (define syncthing-shepherd-service (respawn? #f) (stop #~(make-kill-destructor)))))) =20 + +(define syncthing-files-service + (match-record-lambda (syncthing-config-file us= er home home-service?) + (if syncthing-config-file + `((,(if home-service? + ".config/syncthing/config.xml" + (string-join (or home (passwd:dir (getpw user))) + "/.config/syncthing/config.xml")) + ,(if (file-like? syncthing-config-file) + syncthing-config-file + (plain-file "syncthin-config.xml" (serialize-syncthing-con= fig-file + syncthing-config-file))= ))) + '()))) + (define syncthing-service-type (service-type (name 'syncthing) (extensions (list (service-extension shepherd-root-service= -type - syncthing-shepherd-se= rvice))) + syncthing-shepherd-se= rvice) + (service-extension special-files-service= -type + syncthing-files-servi= ce))) (description "Run @uref{https://github.com/syncthing/syncthing, Syncth= ing} decentralized continuous file system synchronization."))) --=20 2.45.2 From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH] (home-)syncthing-service: added support for config serialization Resent-From: Leo Famulari Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Tue, 04 Feb 2025 01:14:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Zacchaeus Cc: 75959@debbugs.gnu.org Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.173863163612928 (code B ref 75959); Tue, 04 Feb 2025 01:14:02 +0000 Received: (at 75959) by debbugs.gnu.org; 4 Feb 2025 01:13:56 +0000 Received: from localhost ([127.0.0.1]:41867 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tf7Vk-0003MS-63 for submit@debbugs.gnu.org; Mon, 03 Feb 2025 20:13:56 -0500 Received: from fout-a5-smtp.messagingengine.com ([103.168.172.148]:37527) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tf7Vg-0003MC-L8 for 75959@debbugs.gnu.org; Mon, 03 Feb 2025 20:13:53 -0500 Received: from phl-compute-01.internal (phl-compute-01.phl.internal [10.202.2.41]) by mailfout.phl.internal (Postfix) with ESMTP id 4FC9A1380241; Mon, 3 Feb 2025 20:13:47 -0500 (EST) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-01.internal (MEProxy); Mon, 03 Feb 2025 20:13:47 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=famulari.name; h=cc:cc:content-type:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=mesmtp; t=1738631627; x= 1738718027; bh=HHSEDenaTm5ZBavLxJ1MHi6lYuq8AWc3Nkn0anDJgXo=; b=T y5Ps87t+9hrOs4kUJNhqae/m7sywEqNzMD5IHzSGCSJZZrRLpXRnf/LZJamLpTdG oXU1VWnImDVnCU9v1A3kZDpZ9Q31dgpAft5F1MoHVVqqYDtTgEGW1Xm6p9gnqdrU /5kZDnNRp2oyVnqST8cI/aPFWyn+hUCiDHa0+3t2Oc= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t= 1738631627; x=1738718027; bh=HHSEDenaTm5ZBavLxJ1MHi6lYuq8AWc3Nkn 0anDJgXo=; b=wGsOqD+N4wetnBCx0yMO2f0yQGfodknmq1r6ZtceTroeMvMz0Pj BuZ3doRPdMN9ZgeH+VRvl2B4+Fw5/ShBGjW2yKrSPhKOLXTLlKvncVrODS+eEz9w vZlsKCDbSEb26KfGetl9OPf1vDzfir7AMQrEbhfuIzghh9U+KTm3+F5YY9uShaJQ wUJU4rcpf67CdywYUhKLytFsFkWTUQ4SuIPzKFiamZd4/jiEGWb3R7zAlzRlSWe0 YCxVySFNvrnlGmsJrxrENoj26BY0HxvwlK0R1gii2+O/AovHSCulP1CiWI/sBcCU 6fPpGg9C3RzEg44SODT8FPNRusE4YiKkeoA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdduleduhecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdp uffrtefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecunecujfgurhepfffhvf evuffkfhggtggujgesthdtredttddtvdenucfhrhhomhepnfgvohcuhfgrmhhulhgrrhhi uceolhgvohesfhgrmhhulhgrrhhirdhnrghmvgeqnecuggftrfgrthhtvghrnhepudekvd dutdeuledugffhieeuieekteekudehueekuefhtdfhleethfdtveevhffhnecuffhomhgr ihhnpehshihntghthhhinhhgrdhnvghtnecuvehluhhsthgvrhfuihiivgeptdenucfrrg hrrghmpehmrghilhhfrhhomheplhgvohesfhgrmhhulhgrrhhirdhnrghmvgdpnhgspghr tghpthhtohepvddpmhhouggvpehsmhhtphhouhhtpdhrtghpthhtohepvghikhgtrgiise iirggttghhrggvrdhushdprhgtphhtthhopeejheelheelseguvggssghughhsrdhgnhhu rdhorhhg X-ME-Proxy: Feedback-ID: i819c4023:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 3 Feb 2025 20:13:46 -0500 (EST) Date: Mon, 3 Feb 2025 20:13:45 -0500 From: Leo Famulari Message-ID: References: <20250130215954.9394-1-eikcaz@zacchae.us> <87bjvmjb1z.fsf@zacchae.us> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <87bjvmjb1z.fsf@zacchae.us> X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) On Sat, Feb 01, 2025 at 03:58:48AM -0500, Zacchaeus wrote: > - The default ~/Sync folder normally includes the current device. > The documentaiton makes it clear that this is OK (and also I have > tested this). For reference: "All mentioned devices are those that will be sharing the folder in question. Each mentioned device must have a separate device element later in the file. It is customary that the local device ID is included in all folders. Syncthing will currently add this automatically if it is not present in the configuration file." https://docs.syncthing.net/users/config.html#config-option-folder.device From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH] services: syncthing: Added support for config file serialization. References: <20250130215954.9394-1-eikcaz@zacchae.us> In-Reply-To: <20250130215954.9394-1-eikcaz@zacchae.us> Resent-From: Zacchaeus Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Tue, 04 Feb 2025 23:18:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 75959@debbugs.gnu.org Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.17387110512270 (code B ref 75959); Tue, 04 Feb 2025 23:18:02 +0000 Received: (at 75959) by debbugs.gnu.org; 4 Feb 2025 23:17:31 +0000 Received: from localhost ([127.0.0.1]:47204 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tfSAb-0000aV-3J for submit@debbugs.gnu.org; Tue, 04 Feb 2025 18:17:31 -0500 Received: from [47.204.136.169] (port=44522 helo=hun.zacchae.us) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tfSAW-0000aC-QE for 75959@debbugs.gnu.org; Tue, 04 Feb 2025 18:17:27 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Transfer-Encoding:Content-Type: MIME-Version:Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=yjVIz7HovcPAF0VP0mT4AOdTXjzRhoU/zRjAFCLRZVE=; i=zacchae.us; b=t2pWO0KyacEF u8lXwPYWlDcna8E7nEp3H0QVJHnX5kQ6uIDUsFdtXPX5OZ2OiZkjC8FTMAsnWdXG/+JPzfk2Cw==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Transfer-Encoding:Content-Type:MIME-Version: Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=yjVIz7HovcPAF0VP0mT4AOdTXjzRhoU/zRjAFCLRZVE=; i=zacchae.us; b=rLhBkmHV0sdg rPQKKoOehx7RmG2siCrmJC7omNyUGnHJykfwYBSYP5+mnXIKdtXdQc3tV3YSyDuTgwgJgMdMSkZRQ L783ARcswIr+9qC+uUIpZZtXmBPQrlr3WqXrB7VRZZIum2zhzYYqT3/YwUWY/xN525pq6+zvjmlcU tL1DrMDa1T8B16YZuVCpD90mnR97lah8XlpuPvZLEgbCWeUOUmKowMKCf0yJXIOoQdp/wtJBYqfes fKfvrh22eVSOvRQh72B+D3isuj44iykaX2PGWfCD6pH+x5CcfHkb3bkpEW60wAg/31Roe5LGCRivC ooo2s6R8v8v7o6mbjQmMpA==; Received: from localhost.home ([127.0.0.1]:46484 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1tfSAQ-000000006xG-2ddL for 75959@debbugs.gnu.org; Tue, 04 Feb 2025 18:17:18 -0500 From: Zacchaeus Date: Tue, 04 Feb 2025 18:17:18 -0500 Message-ID: <87lduli9kx.fsf@zacchae.us> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From cb625d0548dd97bb124ae6821f3555e095823ae7 Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH] services: syncthing: Added support for [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in bl.score.senderscore.com] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in sa-trusted.bondedsender.org] 0.1 URIBL_SBL_A Contains URL's A record listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 0.6 URIBL_SBL Contains an URL's NS IP listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS 0.0 T_FILL_THIS_FORM_SHORT Fill in a short form with personal information 0.0 T_FILL_THIS_FORM_FRAUD_PHISH Answer suspicious question(s) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 1.0 (+) >From cb625d0548dd97bb124ae6821f3555e095823ae7 Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH] services: syncthing: Added support for config file serialization. * gnu/services/syncthing.scm: (syncthing-config-file) (syncthing-folder) (syncthing-device) (syncthing-folder-device): New records; (syncthing-service-type): added special-files-service-type extension for the config file; (syncthing-files-service): service to create config file * gnu/home/services/syncthing.scm: (home-syncthing-service-type): extended home-files-services-type and re-exported more things from gnu/services/syncthing.scm * doc/guix.texi: (syncthing-service-type): document additions Change-Id: I87eeba1ee1fdada8f29c2ee881fbc6bc4113dde9 --- I realized it was silly to have users specify devices in syncthing-config-file whin 98% of the time this is obvious from the folders. (Usually each device shares at least one folder.) I added some code to extract the devices from the folders. I also updated the documentation accordingly. See earlier standalone email for details on how I verified that this service functions correctly. I followed those exact same steps this time. doc/guix.texi | 285 +++++++++++++++++++ gnu/home/services/syncthing.scm | 17 +- gnu/services/syncthing.scm | 466 +++++++++++++++++++++++++++++++- 3 files changed, 765 insertions(+), 3 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index b1b6d98e74..f9986d195a 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -136,6 +136,7 @@ Copyright @copyright{} 2024 Troy Figiel@* Copyright @copyright{} 2024 Sharlatan Hellseher@* Copyright @copyright{} 2024 45mg@* Copyright @copyright{} 2025 S=C3=B6ren Tempel@* +Copyright @copyright{} 2025 Zacchaeus@* =20 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -22669,9 +22670,293 @@ This assumes that the specified group exists. Common configuration and data directory. The default configuration directory is @file{$HOME} of the specified Syncthing @code{user}. =20 +@item @code{syncthing-config-file} (default: @var{#f}) +Either a file-like object that resolves to a syncthing configuration xml +file, or a syncthing-config-file record (see below). + +@end table +@end deftp + +In the below, only details specific to Guix, or related to how your +device will ``ping'' others, are presented. Otherwise, you should +consult @uref{https://docs.syncthing.net/users/config.html, Syncthing +config documentation}. Camelcase is preserved below only as to be +consistent with its appearance in Syncthing code/documentation. If you +would like to migrate to Guix-powered Syncthing configuration, the +generated config adds newlines/whitespace to the produced config such +that your old config can be diff'ed with the new one. You can still +modify Syncthing from the GUI or through ``introducer'' and +``autoAcceptFolders'' mechanisms, but such changes will be reset on +reconfigure. + +@deftp {Data Type} syncthing-config-file +Data type representing the configuration file read by the syncthing +daemon. + +@table @asis +@item @code{folders} (default: @var{(list (syncthing-folder (id "default")= (label "Default Folder") (path "~/Sync")))} +The default here is the same as Syncthing's default. The value should +be a list of @code{syncthing-folder}s. + +@item @code{devices} (default: @var{'()} +This should be a list of @code{syncthing-device}s. Guix will +automatically add any devices specified in any `folders' to this list. +There are instances when you want to connect to a device despite not +(initially) sharing any folders (such as a device with +autoAcceptFolders). In such instances, you should specify those devices +here. If multiple versions of the same device (same id) are discovered, +the one in this list is prioritized. Otherwise, the first instance in +the first folder is used. + +@item @code{gui-enabled} (default: @var{"true"}) +By default, any user on the computer can access the GUI and make changes +to Syncthing. If you leave this enabled, you should probably set +gui-user and gui-password (see below). + +@item @code{gui-tls} (default: @var{"false"}) +@item @code{gui-debugging} (default: @var{"false"}) +@item @code{gui-sendBasicAuthPrompt} (default: @var{"false"}) +@item @code{gui-address} (default: @var{"127.0.0.1:8384"}) +@item @code{gui-user} (default: @var{#f}) +@item @code{gui-password} (default: @var{#f}) +@item @code{gui-apikey} (default: @var{"Vuky3VHVseQEoSk9YgxhSkNTnjQmqYK9"}) +@item @code{gui-theme} (default: @var{"default"}) +@item @code{ldap-enabled} (default: @var{#f}) +@item @code{ldap-address} (default: @var{""}) +@item @code{ldap-bindDN} (default: @var{""}) +@item @code{ldap-transport} (default: @var{""}) +@item @code{ldap-insecureSkipVerify} (default: @var{""}) +@item @code{ldap-searchBaseDN} (default: @var{""}) +@item @code{ldap-searchFilter} (default: @var{""}) +@item @code{listenAddress} (default: @var{"default"}) +@item @code{globalAnnounceServer} (default: @var{"default"}) +@item @code{globalAnnounceEnabled} (default: @var{"true"}) +Global discovery servers can be used to help connect devices at unknown +IP addresses by storing the last known IP address. + +@item @code{localAnnounceEnabled} (default: @var{"true"}) +This makes devices find each other very easily on the same LAN. Often, +this will allow you to just plug an Ethernet between two devices, or +connect one device to the other's hotspot and start syncing. + +@item @code{localAnnouncePort} (default: @var{"21027"}) +@item @code{localAnnounceMCAddr} (default: @var{"[ff12::8384]:21027"}) +@item @code{maxSendKbps} (default: @var{"0"}) +@item @code{maxRecvKbps} (default: @var{"0"}) +@item @code{reconnectionIntervalS} (default: @var{"60"}) +@item @code{relaysEnabled} (default: @var{"true"}) +This option allows your Syncthing instance to coordinate with a global +network of relays to enable syncing between devices when all other +methods fail. + +@item @code{relayReconnectIntervalM} (default: @var{"10"}) +@item @code{startBrowser} (default: @var{"true"}) +@item @code{natEnabled} (default: @var{"true"}) +@item @code{natLeaseMinutes} (default: @var{"60"}) +@item @code{natRenewalMinutes} (default: @var{"30"}) +@item @code{natTimeoutSeconds} (default: @var{"10"}) +@item @code{urAccepted} (default: @var{"0"}) +ur* options control usage reporting. Set to -1 to disable, or positive +to enable. The default (0) has reporting disabled, but you will be +asked to decide in the GUI. + +@item @code{urSeen} (default: @var{"0"}) +@item @code{urUniqueID} (default: @var{""}) +@item @code{urURL} (default: @var{"https://data.syncthing.net/newdata"}) +@item @code{urPostInsecurely} (default: @var{"false"}) +@item @code{urInitialDelayS} (default: @var{"1800"}) +@item @code{autoUpgradeIntervalH} (default: @var{"12"}) +@item @code{upgradeToPreReleases} (default: @var{"false"}) +@item @code{keepTemporariesH} (default: @var{"24"}) +@item @code{cacheIgnoredFiles} (default: @var{"false"}) +@item @code{progressUpdateIntervalS} (default: @var{"5"}) +@item @code{limitBandwidthInLan} (default: @var{"false"}) +@item @code{minHomeDiskFree-unit} (default: @var{"%"}) +@item @code{minHomeDiskFree} (default: @var{"1"}) +@item @code{releasesURL} (default: @var{"https://upgrades.syncthing.net/me= ta.json"}) +@item @code{overwriteRemoteDeviceNamesOnConnect} (default: @var{"false"}) +@item @code{tempIndexMinBlocks} (default: @var{"10"}) +@item @code{unackedNotificationID} (default: @var{"authenticationUserAndPa= ssword"}) +@item @code{trafficClass} (default: @var{"0"}) +@item @code{setLowPriority} (default: @var{"true"}) +@item @code{maxFolderConcurrency} (default: @var{"0"}) +@item @code{crashReportingURL} (default: @var{"https://crash.syncthing.net= /newcrash"}) +@item @code{crashReportingEnabled} (default: @var{"true"}) +@item @code{stunKeepaliveStartS} (default: @var{"180"}) +@item @code{stunKeepaliveMinS} (default: @var{"20"}) +@item @code{stunServer} (default: @var{"default"}) +@item @code{databaseTuning} (default: @var{"auto"}) +@item @code{maxConcurrentIncomingRequestKiB} (default: @var{"0"}) +@item @code{announceLANAddresses} (default: @var{"true"}) +@item @code{sendFullIndexOnUpgrade} (default: @var{"false"}) +@item @code{connectionLimitEnough} (default: @var{"0"}) +@item @code{connectionLimitMax} (default: @var{"0"}) +@item @code{insecureAllowOldTLSVersions} (default: @var{"false"}) +@item @code{connectionPriorityTcpLan} (default: @var{"10"}) +@item @code{connectionPriorityQuicLan} (default: @var{"20"}) +@item @code{connectionPriorityTcpWan} (default: @var{"30"}) +@item @code{connectionPriorityQuicWan} (default: @var{"40"}) +@item @code{connectionPriorityRelay} (default: @var{"50"}) +@item @code{connectionPriorityUpgradeThreshold} (default: @var{"0"}) +@item @code{default-folder} (default: @var{(syncthing-folder (label ""))}) +@item @code{default-device} (default: @var{(syncthing-device (id ""))}) +@item @code{default-ignores} (default: @var{"")}) +The default-* above do not affect folders and devices added by the Guix +interface. They will, however, affect folders and devices that are +added through the GUI, by an ``introducer'', or a device with +``autoAcceptFolders''. +@end table +@end deftp + +@deftp {Data Type} syncthing-device +Data type representing a device to sync with. + +@table @asis +@item @code{id} +A long hash tied to the keys generated by Syncthing on the first launch. +You can obtain this from the Syncthing GUI or by inspecting an existing +Syncthing configuration file. + +@item @code{name} (default: @var{""}) +Human readable device name for viewing in the GUI or in scheme. + +@item @code{compression} (default: @var{"metadata"}) +@item @code{introducer} (default: @var{"false"}) +@item @code{skipIntroductionRemovals} (default: @var{"false"}) +@item @code{introducedBy} (default: @var{""}) +@item @code{addresses} (default: @var{'("dynamic")}) +List of addresses at which to search for this device. The special value +``dynamic'' will have syncthing use several means to find the device. + +@item @code{paused} (default: @var{"false"}) +@item @code{autoAcceptFolders} (default: @var{"false"}) +@item @code{maxSendKbps} (default: @var{"0"}) +@item @code{maxRecvKbps} (default: @var{"0"}) +@item @code{maxRequestKiB} (default: @var{"0"}) +@item @code{untrusted} (default: @var{"false"}) +@item @code{remoteGUIPort} (default: @var{"0"}) +@item @code{numConnections} (default: @var{"0")}) + +@end table +@end deftp + +@deftp {Data Type} syncthing-folder +Data type representing a folder to be synced. + +@table @asis +@item @code{id} (default: @var{#f}) +This id cannot match the id of any other folder on this device. If left +unspecified, it will default to the label (see below). + +@item @code{label} +Human readable label for the folder. + +@item @code{path} +The path at which to store this folder. + +@item @code{type} (default: @var{"sendreceive"}) +@item @code{rescanIntervalS} (default: @var{"3600"}) +@item @code{fsWatcherEnabled} (default: @var{"true"}) +@item @code{fsWatcherDelayS} (default: @var{"10"}) +@item @code{ignorePerms} (default: @var{"false"}) +@item @code{autoNormalize} (default: @var{"true"}) +@item @code{devices} (default: @var{'()}) +Devices should be a list of other Syncthing devices. You do not need to +specify the current device. Each device can be listed as a a +@code{syncthing-device} record or a @code{syncthing-folder-device} +record if you want files to be encrypted on disk. + +@item @code{filesystemType} (default: @var{"basic"}) +@item @code{minDiskFree-unit} (default: @var{"%"}) +@item @code{minDiskFree} (default: @var{"1"}) +@item @code{versioning-type} (default: @var{#f}) +@item @code{versioning-fsPath} (default: @var{""}) +@item @code{versioning-fsType} (default: @var{"basic"}) +@item @code{versioning-cleanupIntervalS} (default: @var{"3600"}) +@item @code{versioning-cleanoutDays} (default: @var{#f}) +@item @code{versioning-keep} (default: @var{#f}) +@item @code{versioning-maxAge} (default: @var{#f}) +@item @code{versioning-command} (default: @var{#f}) +@item @code{copiers} (default: @var{"0"}) +@item @code{pullerMaxPendingKiB} (default: @var{"0"}) +@item @code{hashers} (default: @var{"0"}) +@item @code{order} (default: @var{"random"}) +@item @code{ignoreDelete} (default: @var{"false"}) +@item @code{scanProgressIntervalS} (default: @var{"0"}) +@item @code{pullerPauseS} (default: @var{"0"}) +@item @code{maxConflicts} (default: @var{"10"}) +@item @code{disableSparseFiles} (default: @var{"false"}) +@item @code{disableTempIndexes} (default: @var{"false"}) +@item @code{paused} (default: @var{"false"}) +@item @code{weakHashThresholdPct} (default: @var{"25"}) +@item @code{markerName} (default: @var{".stfolder"}) +@item @code{copyOwnershipFromParent} (default: @var{"false"}) +@item @code{modTimeWindowS} (default: @var{"0"}) +@item @code{maxConcurrentWrites} (default: @var{"2"}) +@item @code{disableFsync} (default: @var{"false"}) +@item @code{blockPullOrder} (default: @var{"standard"}) +@item @code{copyRangeMethod} (default: @var{"standard"}) +@item @code{caseSensitiveFS} (default: @var{"false"}) +@item @code{junctionsAsDirs} (default: @var{"false"}) +@item @code{syncOwnership} (default: @var{"false"}) +@item @code{sendOwnership} (default: @var{"false"}) +@item @code{syncXattrs} (default: @var{"false"}) +@item @code{sendXattrs} (default: @var{"false"}) +@item @code{xattrFilter-maxSingleEntrySize} (default: @var{"1024"}) +@item @code{xattrFilter-maxTotalSize} (default: @var{"4096")}) +@end table +@end deftp + +@deftp {Data Type} syncthing-folder-device +There is some configuration which is specific to the relationship +between a specific folder and a specific device. If you are fine +leaving these as their default, then you can simply specify a +syncthing-device instead of a @code{syncthing-folder-device} in +@code{syncthing-folder}s. + +@table @asis +@item @code{device} +device should be a @code{syncthing-device} for which this configuration +applies. + +@item @code{introducedBy} (default: @var{""}) +@item @code{encryptionPassword} (default: @var{""}) +if encryptionPassword is non-empty, then it will be used as a password +to encrypt file chunks as they are synced to that device. For more info +on syncing to devices you don't totally trust, see +@uref{https://docs.syncthing.net/users/untrusted.html, Syncthing Documenta= tion Untrusted}. +Note that file transfers are always end-to-end encrypted, regardless of +this setting. + @end table @end deftp =20 +Here is a more complex example configuration for illustrative purposes: +@lisp +(service syncthing-service-type + (let ((laptop (syncthing-device (id "VHOD2D6-...-7XRMDEN"))) + (desktop (syncthing-device (id "64SAZ37-...-FZJ5GUA") + (addresses '("mydomain.example")= ))) + (bob-desktop (syncthing-device (id "KYIMEGO-...-FT77EAO")))) + (syncthing-configuration + (user "alice") + (syncthing-config-file + (folders (list (syncthing-folder + (label "some-files") + (path "~/data") + (devices (list desktop laptop))) + (syncthing-folder + (label "critical-files") + (path "~/secrets") + (devices + (list desktop + laptop + (syncthing-folder-device + (device bob-desktop) + (encryptionPassword "mypassword")))))= )))) +@end lisp + + Furthermore, @code{(gnu services ssh)} provides the following services. @cindex SSH @cindex SSH server diff --git a/gnu/home/services/syncthing.scm b/gnu/home/services/syncthing.= scm index 8d66a167ce..dd6c752ee4 100644 --- a/gnu/home/services/syncthing.scm +++ b/gnu/home/services/syncthing.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2023 Ludovic Court=C3=A8s +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -24,9 +25,23 @@ (define-module (gnu home services syncthing) #:use-module (gnu home services shepherd) #:export (home-syncthing-service-type) #:re-export (syncthing-configuration - syncthing-configuration?)) + syncthing-configuration? + syncthing-config-file + syncthing-config-file? + syncthing-device + syncthing-device? + syncthing-folder + syncthing-folder? + syncthing-folder-device + syncthing-folder-device?)) =20 (define home-syncthing-service-type (service-type (inherit (system->home-service-type syncthing-service-type)) + ;; system->home-service-type does not convert special-files-service-typ= e to + ;; home-files-service-type, so redefine extensios + (extensions (list (service-extension home-files-service-type + syncthing-files-service) + (service-extension home-shepherd-service-type + syncthing-shepherd-service))) (default-value (for-home (syncthing-configuration))))) diff --git a/gnu/services/syncthing.scm b/gnu/services/syncthing.scm index a7a9c6aadd..2a58da8290 100644 --- a/gnu/services/syncthing.scm +++ b/gnu/services/syncthing.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2021 Oleg Pykhalov ;;; Copyright =C2=A9 2023 Justin Veilleux +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -25,9 +26,20 @@ (define-module (gnu services syncthing) #:use-module (guix records) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (sxml simple) #:export (syncthing-configuration syncthing-configuration? - syncthing-service-type)) + syncthing-device + syncthing-device? + syncthing-config-file + syncthing-config-file? + syncthing-folder-device + syncthing-folder-device? + syncthing-folder + syncthing-folder? + syncthing-service-type + syncthing-shepherd-service + syncthing-files-service)) =20 ;;; Commentary: ;;; @@ -35,6 +47,438 @@ (define-module (gnu services syncthing) ;;; ;;; Code: =20 +(define-record-type* + syncthing-device make-syncthing-device + syncthing-device? + (id syncthing-device-id) + (name syncthing-device-name (default "")) + (compression syncthing-device-compression (default "metadata")) + (introducer syncthing-device-introducer (default "false")) + (skipIntroductionRemovals syncthing-device-skipIntroductionRemovals (def= ault "false")) + (introducedBy syncthing-device-introducedBy (default "")) + (addresses syncthing-device-addresses (default '("dynamic"))) + (paused syncthing-device-paused (default "false")) + (autoAcceptFolders syncthing-device-autoAcceptFolders (default "false")) + (maxSendKbps syncthing-device-maxSendKbps (default "0")) + (maxRecvKbps syncthing-device-maxRecvKbps (default "0")) + (maxRequestKiB syncthing-device-maxRequestKiB (default "0")) + (untrusted syncthing-device-untrusted (default "false")) + (remoteGUIPort syncthing-device-remoteGUIPort (default "0")) + (numConnections syncthing-device-numConnections (default "0"))) + +(define syncthing-device->sxml + (match-record-lambda + (id name compression introducer skipIntroductionRemovals introducedB= y addresses paused autoAcceptFolders maxSendKbps maxRecvKbps maxRequestKiB = untrusted remoteGUIPort numConnections) + `(device (@ (id ,id) + (name ,name) + (compression ,compression) + (introducer ,introducer) + (skipIntroductionRemovals ,skipIntroductionRemovals) + (introducedBy ,introducedBy)) + ,@(map (lambda (address) `(address ,address)) addresses) + (paused ,paused) + (autoAcceptFolders ,autoAcceptFolders) + (maxSendKbps ,maxSendKbps) + (maxRecvKbps ,maxRecvKbps) + (maxRequestKiB ,maxRequestKiB) + (untrusted ,untrusted) + (remoteGUIPort ,remoteGUIPort) + (numConnections ,numConnections)))) + +(define-record-type* + syncthing-folder-device make-syncthing-folder-device + syncthing-folder-device? + (device syncthing-folder-device-device) + (introducedBy syncthing-folder-device-introducedBy (default (syncthing-d= evice (id "")))) + (encryptionPassword syncthing-folder-device-encryptionPassword (default = ""))) + +(define syncthing-folder-device->sxml + (match-record-lambda + (device introducedBy encryptionPassword) + `(device (@ (id ,(syncthing-device-id device)) + (introducedBy ,(syncthing-device-id introducedBy))) + (encryptionPassword ,encryptionPassword)))) + +(define-record-type* + syncthing-folder make-syncthing-folder + syncthing-folder? + (id syncthing-folder-id (default #f)) + (label syncthing-folder-label) + (path syncthing-folder-path) + (type syncthing-folder-type (default "sendreceive")) + (rescanIntervalS syncthing-folder-rescanIntervalS (default "3600")) + (fsWatcherEnabled syncthing-folder-fsWatcherEnabled (default "true")) + (fsWatcherDelayS syncthing-folder-fsWatcherDelayS (default "10")) + (fsWatcherTimeoutS syncthing-folder-fsWatcherTimeoutS (default "0")) + (ignorePerms syncthing-folder-ignorePerms (default "false")) + (autoNormalize syncthing-folder-autoNormalize (default "true")) + (devices syncthing-folder-devices (default '()) + (sanitize (lambda (folder-device-list) + (map (lambda (device) + (if (syncthing-folder-device? device) + device + (syncthing-folder-device (device device)= ))) + folder-device-list)))) + (filesystemType syncthing-folder-filesystemType (default "basic")) + (minDiskFree-unit syncthing-folder-minDiskFree-unit (default "%")) + (minDiskFree syncthing-folder-minDiskFree (default "1")) + (versioning-type syncthing-folder-versioning-type (default #f)) + (versioning-fsPath syncthing-folder-versioning-fsPath (default "")) + (versioning-fsType syncthing-folder-versioning-fsType (default "basic")) + (versioning-cleanupIntervalS syncthing-folder-versioning-cleanupInterval= S (default "3600")) + (versioning-cleanoutDays syncthing-folder-versioning-cleanoutDays (defau= lt #f)) + (versioning-keep syncthing-folder-versioning-keep (default #f)) + (versioning-maxAge syncthing-folder-versioning-maxAge (default #f)) + (versioning-command syncthing-folder-versioning-command (default #f)) + (copiers syncthing-folder-copiers (default "0")) + (pullerMaxPendingKiB syncthing-folder-pullerMaxPendingKiB (default "0")) + (hashers syncthing-folder-hashers (default "0")) + (order syncthing-folder-order (default "random")) + (ignoreDelete syncthing-folder-ignoreDelete (default "false")) + (scanProgressIntervalS syncthing-folder-scanProgressIntervalS (default "= 0")) + (pullerPauseS syncthing-folder-pullerPauseS (default "0")) + (maxConflicts syncthing-folder-maxConflicts (default "10")) + (disableSparseFiles syncthing-folder-disableSparseFiles (default "false"= )) + (disableTempIndexes syncthing-folder-disableTempIndexes (default "false"= )) + (paused syncthing-folder-paused (default "false")) + (weakHashThresholdPct syncthing-folder-weakHashThresholdPct (default "25= ")) + (markerName syncthing-folder-markerName (default ".stfolder")) + (copyOwnershipFromParent syncthing-folder-copyOwnershipFromParent (defau= lt "false")) + (modTimeWindowS syncthing-folder-modTimeWindowS (default "0")) + (maxConcurrentWrites syncthing-folder-maxConcurrentWrites (default "2")) + (disableFsync syncthing-folder-disableFsync (default "false")) + (blockPullOrder syncthing-folder-blockPullOrder (default "standard")) + (copyRangeMethod syncthing-folder-copyRangeMethod (default "standard")) + (caseSensitiveFS syncthing-folder-caseSensitiveFS (default "false")) + (junctionsAsDirs syncthing-folder-junctionsAsDirs (default "false")) + (syncOwnership syncthing-folder-syncOwnership (default "false")) + (sendOwnership syncthing-folder-sendOwnership (default "false")) + (syncXattrs syncthing-folder-syncXattrs (default "false")) + (sendXattrs syncthing-folder-sendXattrs (default "false")) + (xattrFilter-maxSingleEntrySize syncthing-folder-xattrFilter-maxSingleEn= trySize (default "1024")) + (xattrFilter-maxTotalSize syncthing-folder-xattrFilter-maxTotalSize (def= ault "4096"))) + +;; Some parameters, when empty, are fully omitted from the config file. I= t is +;; unknown if this causes a functional difference, but stick to the normal +;; program's behavior to be safe. +(define (maybe-param symbol value) + (if value `((param (@ (key ,(symbol->string symbol)) (val ,value)) "")) = '())) + +(define syncthing-folder->sxml + (match-record-lambda + (id + label path type rescanIntervalS fsWatcherEnabled fsWatcherDelayS + fsWatcherTimeoutS ignorePerms autoNormalize devices filesystemType + minDiskFree-unit minDiskFree versioning-type versioning-fsPath + versioning-fsType versioning-cleanupIntervalS versioning-cleanoutDa= ys + versioning-keep versioning-maxAge versioning-command copiers + pullerMaxPendingKiB hashers order ignoreDelete scanProgressIntervalS + pullerPauseS maxConflicts disableSparseFiles disableTempIndexes pau= sed + weakHashThresholdPct markerName copyOwnershipFromParent modTimeWind= owS + maxConcurrentWrites disableFsync blockPullOrder copyRangeMethod + caseSensitiveFS junctionsAsDirs syncOwnership sendOwnership syncXat= trs + sendXattrs xattrFilter-maxSingleEntrySize xattrFilter-maxTotalSize) + `(folder (@ (id ,(if id id label)) + (label ,label) + (path ,path) + (type ,type) + (rescanIntervalS ,rescanIntervalS) + (fsWatcherEnabled ,fsWatcherEnabled) + (fsWatcherDelayS ,fsWatcherDelayS) + (fsWatcherTimeoutS ,fsWatcherTimeoutS) + (ignorePerms ,ignorePerms) + (autoNormalize ,autoNormalize)) + (filesystemType ,filesystemType) + ,@(map syncthing-folder-device->sxml + devices) + (minDiskFree (@ (unit ,minDiskFree-unit)) + ,minDiskFree) + (versioning ,@(if versioning-type + `((@ (type ,versioning-type))) + '()) + ,@(maybe-param 'cleanoutDays versioning-cleanoutD= ays) + ,@(maybe-param 'keep versioning-keep) + ,@(maybe-param 'maxAge versioning-maxAge) + ,@(maybe-param 'command versioning-command) + (cleanupIntervalS ,versioning-cleanupIntervalS) + (fsPath ,versioning-fsPath) + (fsType ,versioning-fsType)) + (copiers ,copiers) + (pullerMaxPendingKiB ,pullerMaxPendingKiB) + (hashers ,hashers) + (order ,order) + (ignoreDelete ,ignoreDelete) + (scanProgressIntervalS ,scanProgressIntervalS) + (pullerPauseS ,pullerPauseS) + (maxConflicts ,maxConflicts) + (disableSparseFiles ,disableSparseFiles) + (disableTempIndexes ,disableTempIndexes) + (paused ,paused) + (weakHashThresholdPct ,weakHashThresholdPct) + (markerName ,markerName) + (copyOwnershipFromParent ,copyOwnershipFromParent) + (modTimeWindowS ,modTimeWindowS) + (maxConcurrentWrites ,maxConcurrentWrites) + (disableFsync ,disableFsync) + (blockPullOrder ,blockPullOrder) + (copyRangeMethod ,copyRangeMethod) + (caseSensitiveFS ,caseSensitiveFS) + (junctionsAsDirs ,junctionsAsDirs) + (syncOwnership ,syncOwnership) + (sendOwnership ,sendOwnership) + (syncXattrs ,syncXattrs) + (sendXattrs ,sendXattrs) + (xattrFilter (maxSingleEntrySize ,xattrFilter-maxSingleEntryS= ize) + (maxTotalSize ,xattrFilter-maxTotalSize))))) + +(define-record-type* + syncthing-config-file make-syncthing-config-file + syncthing-config-file? + (folders syncthing-config-folders + ; this matches syncthing's default + (default (list (syncthing-folder (id "default") + (label "Default Folder") + (path "~/Sync"))))) + (devices syncthing-config-devices + (default '())) + (gui-enabled syncthing-config-gui-enabled (default "true")) + (gui-tls syncthing-config-gui-tls (default "false")) + (gui-debugging syncthing-config-gui-debugging (default "false")) + (gui-sendBasicAuthPrompt syncthing-config-gui-sendBasicAuthPrompt (defau= lt "false")) + (gui-address syncthing-config-gui-address (default "127.0.0.1:8384")) + (gui-user syncthing-config-gui-user (default #f)) + (gui-password syncthing-config-gui-password (default #f)) + (gui-apikey syncthing-config-gui-apikey (default "Vuky3VHVseQEoSk9YgxhSk= NTnjQmqYK9")) + (gui-theme syncthing-config-gui-theme (default "default")) + (ldap-enabled syncthing-config-ldap-enabled (default #f)) + (ldap-address syncthing-config-ldap-address (default "")) + (ldap-bindDN syncthing-config-ldap-bindDN (default "")) + (ldap-transport syncthing-config-ldap-transport (default "")) + (ldap-insecureSkipVerify syncthing-config-ldap-insecureSkipVerify (defau= lt "")) + (ldap-searchBaseDN syncthing-config-ldap-searchBaseDN (default "")) + (ldap-searchFilter syncthing-config-ldap-searchFilter (default "")) + (listenAddress syncthing-config-listenAddress (default "default")) + (globalAnnounceServer syncthing-config-globalAnnounceServer (default "de= fault")) + (globalAnnounceEnabled syncthing-config-globalAnnounceEnabled (default "= true")) + (localAnnounceEnabled syncthing-config-localAnnounceEnabled (default "tr= ue")) + (localAnnouncePort syncthing-config-localAnnouncePort (default "21027")) + (localAnnounceMCAddr syncthing-config-localAnnounceMCAddr (default "[ff1= 2::8384]:21027")) + (maxSendKbps syncthing-config-maxSendKbps (default "0")) + (maxRecvKbps syncthing-config-maxRecvKbps (default "0")) + (reconnectionIntervalS syncthing-config-reconnectionIntervalS (default "= 60")) + (relaysEnabled syncthing-config-relaysEnabled (default "true")) + (relayReconnectIntervalM syncthing-config-relayReconnectIntervalM (defau= lt "10")) + (startBrowser syncthing-config-startBrowser (default "true")) + (natEnabled syncthing-config-natEnabled (default "true")) + (natLeaseMinutes syncthing-config-natLeaseMinutes (default "60")) + (natRenewalMinutes syncthing-config-natRenewalMinutes (default "30")) + (natTimeoutSeconds syncthing-config-natTimeoutSeconds (default "10")) + (urAccepted syncthing-config-urAccepted (default "0")) + (urSeen syncthing-config-urSeen (default "0")) + (urUniqueID syncthing-config-urUniqueID (default "")) + (urURL syncthing-config-urURL (default "https://data.syncthing.net/newda= ta")) + (urPostInsecurely syncthing-config-urPostInsecurely (default "false")) + (urInitialDelayS syncthing-config-urInitialDelayS (default "1800")) + (autoUpgradeIntervalH syncthing-config-autoUpgradeIntervalH (default "12= ")) + (upgradeToPreReleases syncthing-config-upgradeToPreReleases (default "fa= lse")) + (keepTemporariesH syncthing-config-keepTemporariesH (default "24")) + (cacheIgnoredFiles syncthing-config-cacheIgnoredFiles (default "false")) + (progressUpdateIntervalS syncthing-config-progressUpdateIntervalS (defau= lt "5")) + (limitBandwidthInLan syncthing-config-limitBandwidthInLan (default "fals= e")) + (minHomeDiskFree-unit syncthing-config-minHomeDiskFree-unit (default "%"= )) + (minHomeDiskFree syncthing-config-minHomeDiskFree (default "1")) + (releasesURL syncthing-config-releasesURL (default "https://upgrades.syn= cthing.net/meta.json")) + (overwriteRemoteDeviceNamesOnConnect syncthing-config-overwriteRemoteDev= iceNamesOnConnect (default "false")) + (tempIndexMinBlocks syncthing-config-tempIndexMinBlocks (default "10")) + (unackedNotificationID syncthing-config-unackedNotificationID (default "= authenticationUserAndPassword")) + (trafficClass syncthing-config-trafficClass (default "0")) + (setLowPriority syncthing-config-setLowPriority (default "true")) + (maxFolderConcurrency syncthing-config-maxFolderConcurrency (default "0"= )) + (crashReportingURL syncthing-config-crashReportingURL (default "https://= crash.syncthing.net/newcrash")) + (crashReportingEnabled syncthing-config-crashReportingEnabled (default "= true")) + (stunKeepaliveStartS syncthing-config-stunKeepaliveStartS (default "180"= )) + (stunKeepaliveMinS syncthing-config-stunKeepaliveMinS (default "20")) + (stunServer syncthing-config-stunServer (default "default")) + (databaseTuning syncthing-config-databaseTuning (default "auto")) + (maxConcurrentIncomingRequestKiB syncthing-config-maxConcurrentIncomingR= equestKiB (default "0")) + (announceLANAddresses syncthing-config-announceLANAddresses (default "tr= ue")) + (sendFullIndexOnUpgrade syncthing-config-sendFullIndexOnUpgrade (default= "false")) + (connectionLimitEnough syncthing-config-connectionLimitEnough (default "= 0")) + (connectionLimitMax syncthing-config-connectionLimitMax (default "0")) + (insecureAllowOldTLSVersions syncthing-config-insecureAllowOldTLSVersion= s (default "false")) + (connectionPriorityTcpLan syncthing-config-connectionPriorityTcpLan (def= ault "10")) + (connectionPriorityQuicLan syncthing-config-connectionPriorityQuicLan (d= efault "20")) + (connectionPriorityTcpWan syncthing-config-connectionPriorityTcpWan (def= ault "30")) + (connectionPriorityQuicWan syncthing-config-connectionPriorityQuicWan (d= efault "40")) + (connectionPriorityRelay syncthing-config-connectionPriorityRelay (defau= lt "50")) + (connectionPriorityUpgradeThreshold syncthing-config-connectionPriorityU= pgradeThreshold (default "0")) + (default-folder syncthing-config-defaultFolder + (default (syncthing-folder (label "") (path "~")))) + (default-device syncthing-config-defaultDevice + (default (syncthing-device (id "")))) + (default-ignores syncthing-config-defaultIgnores (default ""))) + +(define syncthing-config-file->sxml + (match-record-lambda + (folders + devices gui-enabled gui-tls gui-debugging gui-sendBasicAuthPrompt + gui-address gui-user gui-password gui-apikey gui-theme ldap-enabled + ldap-address ldap-bindDN ldap-transport ldap-insecureSkipVerify + ldap-searchBaseDN ldap-searchFilter listenAddress globalAnnounceSer= ver + globalAnnounceEnabled localAnnounceEnabled localAnnouncePort + localAnnounceMCAddr maxSendKbps maxRecvKbps reconnectionIntervalS + relaysEnabled relayReconnectIntervalM startBrowser natEnabled + natLeaseMinutes natRenewalMinutes natTimeoutSeconds urAccepted + urSeen urUniqueID urURL urPostInsecurely urInitialDelayS + autoUpgradeIntervalH upgradeToPreReleases keepTemporariesH + cacheIgnoredFiles progressUpdateIntervalS limitBandwidthInLan + minHomeDiskFree-unit minHomeDiskFree releasesURL + overwriteRemoteDeviceNamesOnConnect tempIndexMinBlocks + unackedNotificationID trafficClass setLowPriority maxFolderConcurre= ncy + crashReportingURL crashReportingEnabled stunKeepaliveStartS + stunKeepaliveMinS stunServer databaseTuning + maxConcurrentIncomingRequestKiB announceLANAddresses + sendFullIndexOnUpgrade connectionLimitEnough connectionLimitMax + insecureAllowOldTLSVersions connectionPriorityTcpLan + connectionPriorityQuicLan connectionPriorityTcpWan + connectionPriorityQuicWan connectionPriorityRelay + connectionPriorityUpgradeThreshold default-folder default-device + default-ignores) + `(configuration (@ (version "37")) + ,@(map syncthing-folder->sxml + folders) + ;; collect any devices in any folders, as well as any + ;; devices explicitly added. + ,@(map syncthing-device->sxml + (delete-duplicates + (append devices + (apply append + (map (lambda (folder) + (map syncthing-folder-de= vice-device + (syncthing-folder-d= evices folder))) + folders))) + ;; devices are the same if their id's are equal + (lambda (device1 device2) + (string=3D (syncthing-device-id device1) + (syncthing-device-id device2))))) + (gui (@ (enabled ,gui-enabled) + (tls ,gui-tls) + (debugging ,gui-debugging) + (sendBasicAuthPrompt ,gui-sendBasicAuthPrompt)) + (address ,gui-address) + ,@(if gui-user `((user ,gui-user)) '()) + ,@(if gui-password `((password ,gui-password)) '(= )) + (apikey ,gui-apikey) + (theme ,gui-theme)) + (ldap ,(if ldap-enabled + `((address ,ldap-address) + (bindDN ,ldap-bindDN) + ,@(if ldap-transport + `((transport ,ldap-transport)) + '()) + ,@(if ldap-insecureSkipVerify + `((insecureSkipVerify ,ldap-insecur= eSkipVerify)) + '()) + ,@(if ldap-searchBaseDN + `((searchBaseDN ,ldap-searchBaseDN)) + '()) + ,@(if ldap-searchFilter + `((searchFilter ,ldap-searchFilter)) + '())) + "")) + (options (listenAddress ,listenAddress) + (globalAnnounceServer ,globalAnnounceServer) + (globalAnnounceEnabled ,globalAnnounceEnabled) + (localAnnounceEnabled ,localAnnounceEnabled) + (localAnnouncePort ,localAnnouncePort) + (localAnnounceMCAddr ,localAnnounceMCAddr) + (maxSendKbps ,maxSendKbps) + (maxRecvKbps ,maxRecvKbps) + (reconnectionIntervalS ,reconnectionIntervalS) + (relaysEnabled ,relaysEnabled) + (relayReconnectIntervalM ,relayReconnectInter= valM) + (startBrowser ,startBrowser) + (natEnabled ,natEnabled) + (natLeaseMinutes ,natLeaseMinutes) + (natRenewalMinutes ,natRenewalMinutes) + (natTimeoutSeconds ,natTimeoutSeconds) + (urAccepted ,urAccepted) + (urSeen ,urSeen) + (urUniqueID ,urUniqueID) + (urURL ,urURL) + (urPostInsecurely ,urPostInsecurely) + (urInitialDelayS ,urInitialDelayS) + (autoUpgradeIntervalH ,autoUpgradeIntervalH) + (upgradeToPreReleases ,upgradeToPreReleases) + (keepTemporariesH ,keepTemporariesH) + (cacheIgnoredFiles ,cacheIgnoredFiles) + (progressUpdateIntervalS ,progressUpdateInter= valS) + (limitBandwidthInLan ,limitBandwidthInLan) + (minHomeDiskFree (@ (unit ,minHomeDiskFree-un= it)) + ,minHomeDiskFree) + (releasesURL ,releasesURL) + (overwriteRemoteDeviceNamesOnConnect ,overwri= teRemoteDeviceNamesOnConnect) + (tempIndexMinBlocks ,tempIndexMinBlocks) + (unackedNotificationID ,unackedNotificationID) + (trafficClass ,trafficClass) + (setLowPriority ,setLowPriority) + (maxFolderConcurrency ,maxFolderConcurrency) + (crashReportingURL ,crashReportingURL) + (crashReportingEnabled ,crashReportingEnabled) + (stunKeepaliveStartS ,stunKeepaliveStartS) + (stunKeepaliveMinS ,stunKeepaliveMinS) + (stunServer ,stunServer) + (databaseTuning ,databaseTuning) + (maxConcurrentIncomingRequestKiB ,maxConcurre= ntIncomingRequestKiB) + (announceLANAddresses ,announceLANAddresses) + (sendFullIndexOnUpgrade ,sendFullIndexOnUpgra= de) + (connectionLimitEnough ,connectionLimitEnough) + (connectionLimitMax ,connectionLimitMax) + (insecureAllowOldTLSVersions ,insecureAllowOl= dTLSVersions) + (connectionPriorityTcpLan ,connectionPriority= TcpLan) + (connectionPriorityQuicLan ,connectionPriorit= yQuicLan) + (connectionPriorityTcpWan ,connectionPriority= TcpWan) + (connectionPriorityQuicWan ,connectionPriorit= yQuicWan) + (connectionPriorityRelay ,connectionPriorityR= elay) + (connectionPriorityUpgradeThreshold ,connecti= onPriorityUpgradeThreshold)) + (defaults + ,(syncthing-folder->sxml default-folder) + ,(syncthing-device->sxml default-device) + (ignores ,default-ignores))))) + +;; It is useful to be able to view the xml output by Guix, and to be able = to +;; diff it with a users previous config, especially when migrating one's +;; config to Guix. This function adds whitespace that matches the whitesp= ace +;; of config files managed by syncthing for easy diffing +(define (indent-sxml sxml indent-increment current-indent) + (match sxml + (((tag ('@ properties ...) (subtags ..1) ..1) sibling-tags ...) + `(,current-indent (,tag (@ ,@properties) "\n" + ,@(indent-sxml subtags indent-increment + (string-append indent-incremen= t current-indent)) + ,current-indent) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag ('@ properties ...) primitive ...) sibling-tags ...) + `(,current-indent (,tag (@ ,@properties) ,@primitive) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag (subtags ..1) ..1) sibling-tags ...) + `(,current-indent (,tag "\n" + ,@(indent-sxml subtags indent-increment + (string-append indent-incremen= t current-indent)) + ,current-indent) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag primitive ...) sibling-tags ...) + `(,current-indent (,tag ,@primitive) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (() '()))) + +(define (serialize-syncthing-config-file config) + (with-output-to-string + (lambda () + (sxml->xml (cons '*TOP* (indent-sxml (list (syncthing-config-file->s= xml config)) + " " + "")))))) + (define-record-type* syncthing-configuration make-syncthing-configuration syncthing-configuration? @@ -50,6 +494,8 @@ (define-record-type* (default "users")) (home syncthing-configuration-home ;string (default #f)) + (syncthing-config-file syncthing-configuration-syncthing-config-file + (default #f)) ; syncthing-config-file or = file-like (home-service? syncthing-configuration-home-service? (default for-home?) (innate))) =20 @@ -93,10 +539,26 @@ (define syncthing-shepherd-service (respawn? #f) (stop #~(make-kill-destructor)))))) =20 + +(define syncthing-files-service + (match-record-lambda (syncthing-config-file us= er home home-service?) + (if syncthing-config-file + `((,(if home-service? + ".config/syncthing/config.xml" + (string-join (or home (passwd:dir (getpw user))) + "/.config/syncthing/config.xml")) + ,(if (file-like? syncthing-config-file) + syncthing-config-file + (plain-file "syncthin-config.xml" (serialize-syncthing-con= fig-file + syncthing-config-file))= ))) + '()))) + (define syncthing-service-type (service-type (name 'syncthing) (extensions (list (service-extension shepherd-root-service= -type - syncthing-shepherd-se= rvice))) + syncthing-shepherd-se= rvice) + (service-extension special-files-service= -type + syncthing-files-servi= ce))) (description "Run @uref{https://github.com/syncthing/syncthing, Syncth= ing} decentralized continuous file system synchronization."))) --=20 2.45.2 From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH] services: syncthing: Added support for config file serialization. References: <20250130215954.9394-1-eikcaz@zacchae.us> In-Reply-To: <20250130215954.9394-1-eikcaz@zacchae.us> Resent-From: Zacchaeus Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Thu, 06 Feb 2025 22:16:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 75959@debbugs.gnu.org Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.173888014225002 (code B ref 75959); Thu, 06 Feb 2025 22:16:02 +0000 Received: (at 75959) by debbugs.gnu.org; 6 Feb 2025 22:15:42 +0000 Received: from localhost ([127.0.0.1]:59685 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tgA9r-0006V8-U1 for submit@debbugs.gnu.org; Thu, 06 Feb 2025 17:15:42 -0500 Received: from [47.204.136.169] (port=53130 helo=hun.zacchae.us) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tgA9l-0006Ui-Aq for 75959@debbugs.gnu.org; Thu, 06 Feb 2025 17:15:36 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Transfer-Encoding:Content-Type: MIME-Version:Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=mJ7doV/Nh9s1L8ft5BkVG7pshPsG1fOaykitFrZU0K0=; i=zacchae.us; b=bq+qKsvWnnIi u2fFYHatT8zVT5P13H6y1T9Bis7Z4Vf96pPsaB54kLF1EZK8PQzWxyIBJoIrM5Z+ZHeiyB2jDw==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Transfer-Encoding:Content-Type:MIME-Version: Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=mJ7doV/Nh9s1L8ft5BkVG7pshPsG1fOaykitFrZU0K0=; i=zacchae.us; b=IxlqJUizqVUX E4C/Wz6qKDcanbAfxPDUqgXuAZ3Y7zSvMd+8wpQti5PLTysrMOuL/AsLYfF8MegGC77G6s3J7W3WL 0zBBH4N/nBj/EPleKIuen79Zl3GXdS4OPeCEChxJSt13iqa0w88WbSsc9IaZm0KLdtaidlBB3yOOe 2bGr6D16y8MnCcKN/3qwORou40L/TzQ2M6wwrBf5A/dyzwU246GVeuXETNOQ4bCRlxWXTzJrsNDNC sF/GPe3fO9zKYjYwsqf3+4rNgZLHbJugZvflUnx3wEnCgJ7kO/B7cU0o8pUAz0oT3D35Jd3AlCjDt RSuybFcJ7JNo0Tb92LllTw==; Received: from localhost.home ([127.0.0.1]:48950 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1tgA9e-000000000C0-3UQy for 75959@debbugs.gnu.org; Thu, 06 Feb 2025 17:15:27 -0500 From: Zacchaeus Date: Thu, 06 Feb 2025 17:15:27 -0500 Message-ID: <87frkqhg8w.fsf@zacchae.us> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From 7ef311e85b1198c752b2eec57caa0256227e079c Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH] services: syncthing: Added support for [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in sa-trusted.bondedsender.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in bl.score.senderscore.com] 0.1 URIBL_SBL_A Contains URL's A record listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 0.6 URIBL_SBL Contains an URL's NS IP listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS 0.0 T_FILL_THIS_FORM_SHORT Fill in a short form with personal information 0.0 T_FILL_THIS_FORM_FRAUD_PHISH Answer suspicious question(s) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 1.0 (+) >From 7ef311e85b1198c752b2eec57caa0256227e079c Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH] services: syncthing: Added support for config file serialization. * gnu/services/syncthing.scm: (syncthing-config-file) (syncthing-folder) (syncthing-device) (syncthing-folder-device): New records; (syncthing-service-type): added special-files-service-type extension for the config file; (syncthing-files-service): service to create config file * gnu/home/services/syncthing.scm: (home-syncthing-service-type): extended home-files-services-type and re-exported more things from gnu/services/syncthing.scm * doc/guix.texi: (syncthing-service-type): document additions Change-Id: I87eeba1ee1fdada8f29c2ee881fbc6bc4113dde9 --- Fixed a bug caused by running system service (home service was fine). Also changed syncthing-config-file field of syncthing-configuration to config-file (syncthing-config-file record name unchanged). Hence, setting the config file looks something like: (syncthing-configuration (config-file (syncthing-config-file ...))) This matches the pattern observed in other services like: (connman-configuration (general-configuration (connman-general-configuratio= n ...))) doc/guix.texi | 288 ++++++++++++++++++++ gnu/home/services/syncthing.scm | 17 +- gnu/services/syncthing.scm | 466 +++++++++++++++++++++++++++++++- 3 files changed, 768 insertions(+), 3 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index b1b6d98e74..2a4829a6a6 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -136,6 +136,7 @@ Copyright @copyright{} 2024 Troy Figiel@* Copyright @copyright{} 2024 Sharlatan Hellseher@* Copyright @copyright{} 2024 45mg@* Copyright @copyright{} 2025 S=C3=B6ren Tempel@* +Copyright @copyright{} 2025 Zacchaeus@* =20 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -22669,9 +22670,296 @@ This assumes that the specified group exists. Common configuration and data directory. The default configuration directory is @file{$HOME} of the specified Syncthing @code{user}. =20 +@item @code{config-file} (default: @var{#f}) +Either a file-like object that resolves to a syncthing configuration xml +file, or a syncthing-config-file record (see below). If set to #f, Guix +will not try to generate a config file, and the syncthing will generate +a default one which will not be touched on reconfigure. + +@end table +@end deftp + +In the below, only details specific to Guix, or related to how your +device will ``ping'' others, are presented. Otherwise, you should +consult @uref{https://docs.syncthing.net/users/config.html, Syncthing +config documentation}. Camelcase is preserved below only as to be +consistent with its appearance in Syncthing code/documentation. If you +would like to migrate to Guix-powered Syncthing configuration, the +generated config adds newlines/whitespace to the produced config such +that your old config can be diff'ed with the new one. You can still +modify Syncthing from the GUI or through ``introducer'' and +``autoAcceptFolders'' mechanisms, but such changes will be reset on +reconfigure. + +@deftp {Data Type} syncthing-config-file +Data type representing the configuration file read by the syncthing +daemon. + +@table @asis +@item @code{folders} (default: @var{(list (syncthing-folder (id "default")= (label "Default Folder") (path "~/Sync")))} +The default here is the same as Syncthing's default. The value should +be a list of @code{syncthing-folder}s. + +@item @code{devices} (default: @var{'()} +This should be a list of @code{syncthing-device}s. Guix will +automatically add any devices specified in any `folders' to this list. +There are instances when you want to connect to a device despite not +(initially) sharing any folders (such as a device with +autoAcceptFolders). In such instances, you should specify those devices +here. If multiple versions of the same device (same id) are discovered, +the one in this list is prioritized. Otherwise, the first instance in +the first folder is used. + +@item @code{gui-enabled} (default: @var{"true"}) +By default, any user on the computer can access the GUI and make changes +to Syncthing. If you leave this enabled, you should probably set +gui-user and gui-password (see below). + +@item @code{gui-tls} (default: @var{"false"}) +@item @code{gui-debugging} (default: @var{"false"}) +@item @code{gui-sendBasicAuthPrompt} (default: @var{"false"}) +@item @code{gui-address} (default: @var{"127.0.0.1:8384"}) +@item @code{gui-user} (default: @var{#f}) +@item @code{gui-password} (default: @var{#f}) +@item @code{gui-apikey} (default: @var{"Vuky3VHVseQEoSk9YgxhSkNTnjQmqYK9"}) +@item @code{gui-theme} (default: @var{"default"}) +@item @code{ldap-enabled} (default: @var{#f}) +@item @code{ldap-address} (default: @var{""}) +@item @code{ldap-bindDN} (default: @var{""}) +@item @code{ldap-transport} (default: @var{""}) +@item @code{ldap-insecureSkipVerify} (default: @var{""}) +@item @code{ldap-searchBaseDN} (default: @var{""}) +@item @code{ldap-searchFilter} (default: @var{""}) +@item @code{listenAddress} (default: @var{"default"}) +@item @code{globalAnnounceServer} (default: @var{"default"}) +@item @code{globalAnnounceEnabled} (default: @var{"true"}) +Global discovery servers can be used to help connect devices at unknown +IP addresses by storing the last known IP address. + +@item @code{localAnnounceEnabled} (default: @var{"true"}) +This makes devices find each other very easily on the same LAN. Often, +this will allow you to just plug an Ethernet between two devices, or +connect one device to the other's hotspot and start syncing. + +@item @code{localAnnouncePort} (default: @var{"21027"}) +@item @code{localAnnounceMCAddr} (default: @var{"[ff12::8384]:21027"}) +@item @code{maxSendKbps} (default: @var{"0"}) +@item @code{maxRecvKbps} (default: @var{"0"}) +@item @code{reconnectionIntervalS} (default: @var{"60"}) +@item @code{relaysEnabled} (default: @var{"true"}) +This option allows your Syncthing instance to coordinate with a global +network of relays to enable syncing between devices when all other +methods fail. + +@item @code{relayReconnectIntervalM} (default: @var{"10"}) +@item @code{startBrowser} (default: @var{"true"}) +@item @code{natEnabled} (default: @var{"true"}) +@item @code{natLeaseMinutes} (default: @var{"60"}) +@item @code{natRenewalMinutes} (default: @var{"30"}) +@item @code{natTimeoutSeconds} (default: @var{"10"}) +@item @code{urAccepted} (default: @var{"0"}) +ur* options control usage reporting. Set to -1 to disable, or positive +to enable. The default (0) has reporting disabled, but you will be +asked to decide in the GUI. + +@item @code{urSeen} (default: @var{"0"}) +@item @code{urUniqueID} (default: @var{""}) +@item @code{urURL} (default: @var{"https://data.syncthing.net/newdata"}) +@item @code{urPostInsecurely} (default: @var{"false"}) +@item @code{urInitialDelayS} (default: @var{"1800"}) +@item @code{autoUpgradeIntervalH} (default: @var{"12"}) +@item @code{upgradeToPreReleases} (default: @var{"false"}) +@item @code{keepTemporariesH} (default: @var{"24"}) +@item @code{cacheIgnoredFiles} (default: @var{"false"}) +@item @code{progressUpdateIntervalS} (default: @var{"5"}) +@item @code{limitBandwidthInLan} (default: @var{"false"}) +@item @code{minHomeDiskFree-unit} (default: @var{"%"}) +@item @code{minHomeDiskFree} (default: @var{"1"}) +@item @code{releasesURL} (default: @var{"https://upgrades.syncthing.net/me= ta.json"}) +@item @code{overwriteRemoteDeviceNamesOnConnect} (default: @var{"false"}) +@item @code{tempIndexMinBlocks} (default: @var{"10"}) +@item @code{unackedNotificationID} (default: @var{"authenticationUserAndPa= ssword"}) +@item @code{trafficClass} (default: @var{"0"}) +@item @code{setLowPriority} (default: @var{"true"}) +@item @code{maxFolderConcurrency} (default: @var{"0"}) +@item @code{crashReportingURL} (default: @var{"https://crash.syncthing.net= /newcrash"}) +@item @code{crashReportingEnabled} (default: @var{"true"}) +@item @code{stunKeepaliveStartS} (default: @var{"180"}) +@item @code{stunKeepaliveMinS} (default: @var{"20"}) +@item @code{stunServer} (default: @var{"default"}) +@item @code{databaseTuning} (default: @var{"auto"}) +@item @code{maxConcurrentIncomingRequestKiB} (default: @var{"0"}) +@item @code{announceLANAddresses} (default: @var{"true"}) +@item @code{sendFullIndexOnUpgrade} (default: @var{"false"}) +@item @code{connectionLimitEnough} (default: @var{"0"}) +@item @code{connectionLimitMax} (default: @var{"0"}) +@item @code{insecureAllowOldTLSVersions} (default: @var{"false"}) +@item @code{connectionPriorityTcpLan} (default: @var{"10"}) +@item @code{connectionPriorityQuicLan} (default: @var{"20"}) +@item @code{connectionPriorityTcpWan} (default: @var{"30"}) +@item @code{connectionPriorityQuicWan} (default: @var{"40"}) +@item @code{connectionPriorityRelay} (default: @var{"50"}) +@item @code{connectionPriorityUpgradeThreshold} (default: @var{"0"}) +@item @code{default-folder} (default: @var{(syncthing-folder (label ""))}) +@item @code{default-device} (default: @var{(syncthing-device (id ""))}) +@item @code{default-ignores} (default: @var{"")}) +The default-* above do not affect folders and devices added by the Guix +interface. They will, however, affect folders and devices that are +added through the GUI, by an ``introducer'', or a device with +``autoAcceptFolders''. +@end table +@end deftp + +@deftp {Data Type} syncthing-device +Data type representing a device to sync with. + +@table @asis +@item @code{id} +A long hash tied to the keys generated by Syncthing on the first launch. +You can obtain this from the Syncthing GUI or by inspecting an existing +Syncthing configuration file. + +@item @code{name} (default: @var{""}) +Human readable device name for viewing in the GUI or in scheme. + +@item @code{compression} (default: @var{"metadata"}) +@item @code{introducer} (default: @var{"false"}) +@item @code{skipIntroductionRemovals} (default: @var{"false"}) +@item @code{introducedBy} (default: @var{""}) +@item @code{addresses} (default: @var{'("dynamic")}) +List of addresses at which to search for this device. The special value +``dynamic'' will have syncthing use several means to find the device. + +@item @code{paused} (default: @var{"false"}) +@item @code{autoAcceptFolders} (default: @var{"false"}) +@item @code{maxSendKbps} (default: @var{"0"}) +@item @code{maxRecvKbps} (default: @var{"0"}) +@item @code{maxRequestKiB} (default: @var{"0"}) +@item @code{untrusted} (default: @var{"false"}) +@item @code{remoteGUIPort} (default: @var{"0"}) +@item @code{numConnections} (default: @var{"0")}) + +@end table +@end deftp + +@deftp {Data Type} syncthing-folder +Data type representing a folder to be synced. + +@table @asis +@item @code{id} (default: @var{#f}) +This id cannot match the id of any other folder on this device. If left +unspecified, it will default to the label (see below). + +@item @code{label} +Human readable label for the folder. + +@item @code{path} +The path at which to store this folder. + +@item @code{type} (default: @var{"sendreceive"}) +@item @code{rescanIntervalS} (default: @var{"3600"}) +@item @code{fsWatcherEnabled} (default: @var{"true"}) +@item @code{fsWatcherDelayS} (default: @var{"10"}) +@item @code{ignorePerms} (default: @var{"false"}) +@item @code{autoNormalize} (default: @var{"true"}) +@item @code{devices} (default: @var{'()}) +Devices should be a list of other Syncthing devices. You do not need to +specify the current device. Each device can be listed as a a +@code{syncthing-device} record or a @code{syncthing-folder-device} +record if you want files to be encrypted on disk. + +@item @code{filesystemType} (default: @var{"basic"}) +@item @code{minDiskFree-unit} (default: @var{"%"}) +@item @code{minDiskFree} (default: @var{"1"}) +@item @code{versioning-type} (default: @var{#f}) +@item @code{versioning-fsPath} (default: @var{""}) +@item @code{versioning-fsType} (default: @var{"basic"}) +@item @code{versioning-cleanupIntervalS} (default: @var{"3600"}) +@item @code{versioning-cleanoutDays} (default: @var{#f}) +@item @code{versioning-keep} (default: @var{#f}) +@item @code{versioning-maxAge} (default: @var{#f}) +@item @code{versioning-command} (default: @var{#f}) +@item @code{copiers} (default: @var{"0"}) +@item @code{pullerMaxPendingKiB} (default: @var{"0"}) +@item @code{hashers} (default: @var{"0"}) +@item @code{order} (default: @var{"random"}) +@item @code{ignoreDelete} (default: @var{"false"}) +@item @code{scanProgressIntervalS} (default: @var{"0"}) +@item @code{pullerPauseS} (default: @var{"0"}) +@item @code{maxConflicts} (default: @var{"10"}) +@item @code{disableSparseFiles} (default: @var{"false"}) +@item @code{disableTempIndexes} (default: @var{"false"}) +@item @code{paused} (default: @var{"false"}) +@item @code{weakHashThresholdPct} (default: @var{"25"}) +@item @code{markerName} (default: @var{".stfolder"}) +@item @code{copyOwnershipFromParent} (default: @var{"false"}) +@item @code{modTimeWindowS} (default: @var{"0"}) +@item @code{maxConcurrentWrites} (default: @var{"2"}) +@item @code{disableFsync} (default: @var{"false"}) +@item @code{blockPullOrder} (default: @var{"standard"}) +@item @code{copyRangeMethod} (default: @var{"standard"}) +@item @code{caseSensitiveFS} (default: @var{"false"}) +@item @code{junctionsAsDirs} (default: @var{"false"}) +@item @code{syncOwnership} (default: @var{"false"}) +@item @code{sendOwnership} (default: @var{"false"}) +@item @code{syncXattrs} (default: @var{"false"}) +@item @code{sendXattrs} (default: @var{"false"}) +@item @code{xattrFilter-maxSingleEntrySize} (default: @var{"1024"}) +@item @code{xattrFilter-maxTotalSize} (default: @var{"4096")}) +@end table +@end deftp + +@deftp {Data Type} syncthing-folder-device +There is some configuration which is specific to the relationship +between a specific folder and a specific device. If you are fine +leaving these as their default, then you can simply specify a +syncthing-device instead of a @code{syncthing-folder-device} in +@code{syncthing-folder}s. + +@table @asis +@item @code{device} +device should be a @code{syncthing-device} for which this configuration +applies. + +@item @code{introducedBy} (default: @var{""}) +@item @code{encryptionPassword} (default: @var{""}) +if encryptionPassword is non-empty, then it will be used as a password +to encrypt file chunks as they are synced to that device. For more info +on syncing to devices you don't totally trust, see +@uref{https://docs.syncthing.net/users/untrusted.html, Syncthing Documenta= tion Untrusted}. +Note that file transfers are always end-to-end encrypted, regardless of +this setting. + @end table @end deftp =20 +Here is a more complex example configuration for illustrative purposes: +@lisp +(service syncthing-service-type + (let ((laptop (syncthing-device (id "VHOD2D6-...-7XRMDEN"))) + (desktop (syncthing-device (id "64SAZ37-...-FZJ5GUA") + (addresses '("mydomain.example")= ))) + (bob-desktop (syncthing-device (id "KYIMEGO-...-FT77EAO")))) + (syncthing-configuration + (user "alice") + (config-file + (syncthing-config-file + (folders (list (syncthing-folder + (label "some-files") + (path "~/data") + (devices (list desktop laptop))) + (syncthing-folder + (label "critical-files") + (path "~/secrets") + (devices + (list desktop + laptop + (syncthing-folder-device + (device bob-desktop) + (encryptionPassword "mypassword")))= ))))))))) +@end lisp + + Furthermore, @code{(gnu services ssh)} provides the following services. @cindex SSH @cindex SSH server diff --git a/gnu/home/services/syncthing.scm b/gnu/home/services/syncthing.= scm index 8d66a167ce..dd6c752ee4 100644 --- a/gnu/home/services/syncthing.scm +++ b/gnu/home/services/syncthing.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2023 Ludovic Court=C3=A8s +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -24,9 +25,23 @@ (define-module (gnu home services syncthing) #:use-module (gnu home services shepherd) #:export (home-syncthing-service-type) #:re-export (syncthing-configuration - syncthing-configuration?)) + syncthing-configuration? + syncthing-config-file + syncthing-config-file? + syncthing-device + syncthing-device? + syncthing-folder + syncthing-folder? + syncthing-folder-device + syncthing-folder-device?)) =20 (define home-syncthing-service-type (service-type (inherit (system->home-service-type syncthing-service-type)) + ;; system->home-service-type does not convert special-files-service-typ= e to + ;; home-files-service-type, so redefine extensios + (extensions (list (service-extension home-files-service-type + syncthing-files-service) + (service-extension home-shepherd-service-type + syncthing-shepherd-service))) (default-value (for-home (syncthing-configuration))))) diff --git a/gnu/services/syncthing.scm b/gnu/services/syncthing.scm index a7a9c6aadd..31e3dbe75f 100644 --- a/gnu/services/syncthing.scm +++ b/gnu/services/syncthing.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2021 Oleg Pykhalov ;;; Copyright =C2=A9 2023 Justin Veilleux +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -25,9 +26,20 @@ (define-module (gnu services syncthing) #:use-module (guix records) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (sxml simple) #:export (syncthing-configuration syncthing-configuration? - syncthing-service-type)) + syncthing-device + syncthing-device? + syncthing-config-file + syncthing-config-file? + syncthing-folder-device + syncthing-folder-device? + syncthing-folder + syncthing-folder? + syncthing-service-type + syncthing-shepherd-service + syncthing-files-service)) =20 ;;; Commentary: ;;; @@ -35,6 +47,438 @@ (define-module (gnu services syncthing) ;;; ;;; Code: =20 +(define-record-type* + syncthing-device make-syncthing-device + syncthing-device? + (id syncthing-device-id) + (name syncthing-device-name (default "")) + (compression syncthing-device-compression (default "metadata")) + (introducer syncthing-device-introducer (default "false")) + (skipIntroductionRemovals syncthing-device-skipIntroductionRemovals (def= ault "false")) + (introducedBy syncthing-device-introducedBy (default "")) + (addresses syncthing-device-addresses (default '("dynamic"))) + (paused syncthing-device-paused (default "false")) + (autoAcceptFolders syncthing-device-autoAcceptFolders (default "false")) + (maxSendKbps syncthing-device-maxSendKbps (default "0")) + (maxRecvKbps syncthing-device-maxRecvKbps (default "0")) + (maxRequestKiB syncthing-device-maxRequestKiB (default "0")) + (untrusted syncthing-device-untrusted (default "false")) + (remoteGUIPort syncthing-device-remoteGUIPort (default "0")) + (numConnections syncthing-device-numConnections (default "0"))) + +(define syncthing-device->sxml + (match-record-lambda + (id name compression introducer skipIntroductionRemovals introducedB= y addresses paused autoAcceptFolders maxSendKbps maxRecvKbps maxRequestKiB = untrusted remoteGUIPort numConnections) + `(device (@ (id ,id) + (name ,name) + (compression ,compression) + (introducer ,introducer) + (skipIntroductionRemovals ,skipIntroductionRemovals) + (introducedBy ,introducedBy)) + ,@(map (lambda (address) `(address ,address)) addresses) + (paused ,paused) + (autoAcceptFolders ,autoAcceptFolders) + (maxSendKbps ,maxSendKbps) + (maxRecvKbps ,maxRecvKbps) + (maxRequestKiB ,maxRequestKiB) + (untrusted ,untrusted) + (remoteGUIPort ,remoteGUIPort) + (numConnections ,numConnections)))) + +(define-record-type* + syncthing-folder-device make-syncthing-folder-device + syncthing-folder-device? + (device syncthing-folder-device-device) + (introducedBy syncthing-folder-device-introducedBy (default (syncthing-d= evice (id "")))) + (encryptionPassword syncthing-folder-device-encryptionPassword (default = ""))) + +(define syncthing-folder-device->sxml + (match-record-lambda + (device introducedBy encryptionPassword) + `(device (@ (id ,(syncthing-device-id device)) + (introducedBy ,(syncthing-device-id introducedBy))) + (encryptionPassword ,encryptionPassword)))) + +(define-record-type* + syncthing-folder make-syncthing-folder + syncthing-folder? + (id syncthing-folder-id (default #f)) + (label syncthing-folder-label) + (path syncthing-folder-path) + (type syncthing-folder-type (default "sendreceive")) + (rescanIntervalS syncthing-folder-rescanIntervalS (default "3600")) + (fsWatcherEnabled syncthing-folder-fsWatcherEnabled (default "true")) + (fsWatcherDelayS syncthing-folder-fsWatcherDelayS (default "10")) + (fsWatcherTimeoutS syncthing-folder-fsWatcherTimeoutS (default "0")) + (ignorePerms syncthing-folder-ignorePerms (default "false")) + (autoNormalize syncthing-folder-autoNormalize (default "true")) + (devices syncthing-folder-devices (default '()) + (sanitize (lambda (folder-device-list) + (map (lambda (device) + (if (syncthing-folder-device? device) + device + (syncthing-folder-device (device device)= ))) + folder-device-list)))) + (filesystemType syncthing-folder-filesystemType (default "basic")) + (minDiskFree-unit syncthing-folder-minDiskFree-unit (default "%")) + (minDiskFree syncthing-folder-minDiskFree (default "1")) + (versioning-type syncthing-folder-versioning-type (default #f)) + (versioning-fsPath syncthing-folder-versioning-fsPath (default "")) + (versioning-fsType syncthing-folder-versioning-fsType (default "basic")) + (versioning-cleanupIntervalS syncthing-folder-versioning-cleanupInterval= S (default "3600")) + (versioning-cleanoutDays syncthing-folder-versioning-cleanoutDays (defau= lt #f)) + (versioning-keep syncthing-folder-versioning-keep (default #f)) + (versioning-maxAge syncthing-folder-versioning-maxAge (default #f)) + (versioning-command syncthing-folder-versioning-command (default #f)) + (copiers syncthing-folder-copiers (default "0")) + (pullerMaxPendingKiB syncthing-folder-pullerMaxPendingKiB (default "0")) + (hashers syncthing-folder-hashers (default "0")) + (order syncthing-folder-order (default "random")) + (ignoreDelete syncthing-folder-ignoreDelete (default "false")) + (scanProgressIntervalS syncthing-folder-scanProgressIntervalS (default "= 0")) + (pullerPauseS syncthing-folder-pullerPauseS (default "0")) + (maxConflicts syncthing-folder-maxConflicts (default "10")) + (disableSparseFiles syncthing-folder-disableSparseFiles (default "false"= )) + (disableTempIndexes syncthing-folder-disableTempIndexes (default "false"= )) + (paused syncthing-folder-paused (default "false")) + (weakHashThresholdPct syncthing-folder-weakHashThresholdPct (default "25= ")) + (markerName syncthing-folder-markerName (default ".stfolder")) + (copyOwnershipFromParent syncthing-folder-copyOwnershipFromParent (defau= lt "false")) + (modTimeWindowS syncthing-folder-modTimeWindowS (default "0")) + (maxConcurrentWrites syncthing-folder-maxConcurrentWrites (default "2")) + (disableFsync syncthing-folder-disableFsync (default "false")) + (blockPullOrder syncthing-folder-blockPullOrder (default "standard")) + (copyRangeMethod syncthing-folder-copyRangeMethod (default "standard")) + (caseSensitiveFS syncthing-folder-caseSensitiveFS (default "false")) + (junctionsAsDirs syncthing-folder-junctionsAsDirs (default "false")) + (syncOwnership syncthing-folder-syncOwnership (default "false")) + (sendOwnership syncthing-folder-sendOwnership (default "false")) + (syncXattrs syncthing-folder-syncXattrs (default "false")) + (sendXattrs syncthing-folder-sendXattrs (default "false")) + (xattrFilter-maxSingleEntrySize syncthing-folder-xattrFilter-maxSingleEn= trySize (default "1024")) + (xattrFilter-maxTotalSize syncthing-folder-xattrFilter-maxTotalSize (def= ault "4096"))) + +;; Some parameters, when empty, are fully omitted from the config file. I= t is +;; unknown if this causes a functional difference, but stick to the normal +;; program's behavior to be safe. +(define (maybe-param symbol value) + (if value `((param (@ (key ,(symbol->string symbol)) (val ,value)) "")) = '())) + +(define syncthing-folder->sxml + (match-record-lambda + (id + label path type rescanIntervalS fsWatcherEnabled fsWatcherDelayS + fsWatcherTimeoutS ignorePerms autoNormalize devices filesystemType + minDiskFree-unit minDiskFree versioning-type versioning-fsPath + versioning-fsType versioning-cleanupIntervalS versioning-cleanoutDa= ys + versioning-keep versioning-maxAge versioning-command copiers + pullerMaxPendingKiB hashers order ignoreDelete scanProgressIntervalS + pullerPauseS maxConflicts disableSparseFiles disableTempIndexes pau= sed + weakHashThresholdPct markerName copyOwnershipFromParent modTimeWind= owS + maxConcurrentWrites disableFsync blockPullOrder copyRangeMethod + caseSensitiveFS junctionsAsDirs syncOwnership sendOwnership syncXat= trs + sendXattrs xattrFilter-maxSingleEntrySize xattrFilter-maxTotalSize) + `(folder (@ (id ,(if id id label)) + (label ,label) + (path ,path) + (type ,type) + (rescanIntervalS ,rescanIntervalS) + (fsWatcherEnabled ,fsWatcherEnabled) + (fsWatcherDelayS ,fsWatcherDelayS) + (fsWatcherTimeoutS ,fsWatcherTimeoutS) + (ignorePerms ,ignorePerms) + (autoNormalize ,autoNormalize)) + (filesystemType ,filesystemType) + ,@(map syncthing-folder-device->sxml + devices) + (minDiskFree (@ (unit ,minDiskFree-unit)) + ,minDiskFree) + (versioning ,@(if versioning-type + `((@ (type ,versioning-type))) + '()) + ,@(maybe-param 'cleanoutDays versioning-cleanoutD= ays) + ,@(maybe-param 'keep versioning-keep) + ,@(maybe-param 'maxAge versioning-maxAge) + ,@(maybe-param 'command versioning-command) + (cleanupIntervalS ,versioning-cleanupIntervalS) + (fsPath ,versioning-fsPath) + (fsType ,versioning-fsType)) + (copiers ,copiers) + (pullerMaxPendingKiB ,pullerMaxPendingKiB) + (hashers ,hashers) + (order ,order) + (ignoreDelete ,ignoreDelete) + (scanProgressIntervalS ,scanProgressIntervalS) + (pullerPauseS ,pullerPauseS) + (maxConflicts ,maxConflicts) + (disableSparseFiles ,disableSparseFiles) + (disableTempIndexes ,disableTempIndexes) + (paused ,paused) + (weakHashThresholdPct ,weakHashThresholdPct) + (markerName ,markerName) + (copyOwnershipFromParent ,copyOwnershipFromParent) + (modTimeWindowS ,modTimeWindowS) + (maxConcurrentWrites ,maxConcurrentWrites) + (disableFsync ,disableFsync) + (blockPullOrder ,blockPullOrder) + (copyRangeMethod ,copyRangeMethod) + (caseSensitiveFS ,caseSensitiveFS) + (junctionsAsDirs ,junctionsAsDirs) + (syncOwnership ,syncOwnership) + (sendOwnership ,sendOwnership) + (syncXattrs ,syncXattrs) + (sendXattrs ,sendXattrs) + (xattrFilter (maxSingleEntrySize ,xattrFilter-maxSingleEntryS= ize) + (maxTotalSize ,xattrFilter-maxTotalSize))))) + +(define-record-type* + syncthing-config-file make-syncthing-config-file + syncthing-config-file? + (folders syncthing-config-folders + ; this matches syncthing's default + (default (list (syncthing-folder (id "default") + (label "Default Folder") + (path "~/Sync"))))) + (devices syncthing-config-devices + (default '())) + (gui-enabled syncthing-config-gui-enabled (default "true")) + (gui-tls syncthing-config-gui-tls (default "false")) + (gui-debugging syncthing-config-gui-debugging (default "false")) + (gui-sendBasicAuthPrompt syncthing-config-gui-sendBasicAuthPrompt (defau= lt "false")) + (gui-address syncthing-config-gui-address (default "127.0.0.1:8384")) + (gui-user syncthing-config-gui-user (default #f)) + (gui-password syncthing-config-gui-password (default #f)) + (gui-apikey syncthing-config-gui-apikey (default "Vuky3VHVseQEoSk9YgxhSk= NTnjQmqYK9")) + (gui-theme syncthing-config-gui-theme (default "default")) + (ldap-enabled syncthing-config-ldap-enabled (default #f)) + (ldap-address syncthing-config-ldap-address (default "")) + (ldap-bindDN syncthing-config-ldap-bindDN (default "")) + (ldap-transport syncthing-config-ldap-transport (default "")) + (ldap-insecureSkipVerify syncthing-config-ldap-insecureSkipVerify (defau= lt "")) + (ldap-searchBaseDN syncthing-config-ldap-searchBaseDN (default "")) + (ldap-searchFilter syncthing-config-ldap-searchFilter (default "")) + (listenAddress syncthing-config-listenAddress (default "default")) + (globalAnnounceServer syncthing-config-globalAnnounceServer (default "de= fault")) + (globalAnnounceEnabled syncthing-config-globalAnnounceEnabled (default "= true")) + (localAnnounceEnabled syncthing-config-localAnnounceEnabled (default "tr= ue")) + (localAnnouncePort syncthing-config-localAnnouncePort (default "21027")) + (localAnnounceMCAddr syncthing-config-localAnnounceMCAddr (default "[ff1= 2::8384]:21027")) + (maxSendKbps syncthing-config-maxSendKbps (default "0")) + (maxRecvKbps syncthing-config-maxRecvKbps (default "0")) + (reconnectionIntervalS syncthing-config-reconnectionIntervalS (default "= 60")) + (relaysEnabled syncthing-config-relaysEnabled (default "true")) + (relayReconnectIntervalM syncthing-config-relayReconnectIntervalM (defau= lt "10")) + (startBrowser syncthing-config-startBrowser (default "true")) + (natEnabled syncthing-config-natEnabled (default "true")) + (natLeaseMinutes syncthing-config-natLeaseMinutes (default "60")) + (natRenewalMinutes syncthing-config-natRenewalMinutes (default "30")) + (natTimeoutSeconds syncthing-config-natTimeoutSeconds (default "10")) + (urAccepted syncthing-config-urAccepted (default "0")) + (urSeen syncthing-config-urSeen (default "0")) + (urUniqueID syncthing-config-urUniqueID (default "")) + (urURL syncthing-config-urURL (default "https://data.syncthing.net/newda= ta")) + (urPostInsecurely syncthing-config-urPostInsecurely (default "false")) + (urInitialDelayS syncthing-config-urInitialDelayS (default "1800")) + (autoUpgradeIntervalH syncthing-config-autoUpgradeIntervalH (default "12= ")) + (upgradeToPreReleases syncthing-config-upgradeToPreReleases (default "fa= lse")) + (keepTemporariesH syncthing-config-keepTemporariesH (default "24")) + (cacheIgnoredFiles syncthing-config-cacheIgnoredFiles (default "false")) + (progressUpdateIntervalS syncthing-config-progressUpdateIntervalS (defau= lt "5")) + (limitBandwidthInLan syncthing-config-limitBandwidthInLan (default "fals= e")) + (minHomeDiskFree-unit syncthing-config-minHomeDiskFree-unit (default "%"= )) + (minHomeDiskFree syncthing-config-minHomeDiskFree (default "1")) + (releasesURL syncthing-config-releasesURL (default "https://upgrades.syn= cthing.net/meta.json")) + (overwriteRemoteDeviceNamesOnConnect syncthing-config-overwriteRemoteDev= iceNamesOnConnect (default "false")) + (tempIndexMinBlocks syncthing-config-tempIndexMinBlocks (default "10")) + (unackedNotificationID syncthing-config-unackedNotificationID (default "= authenticationUserAndPassword")) + (trafficClass syncthing-config-trafficClass (default "0")) + (setLowPriority syncthing-config-setLowPriority (default "true")) + (maxFolderConcurrency syncthing-config-maxFolderConcurrency (default "0"= )) + (crashReportingURL syncthing-config-crashReportingURL (default "https://= crash.syncthing.net/newcrash")) + (crashReportingEnabled syncthing-config-crashReportingEnabled (default "= true")) + (stunKeepaliveStartS syncthing-config-stunKeepaliveStartS (default "180"= )) + (stunKeepaliveMinS syncthing-config-stunKeepaliveMinS (default "20")) + (stunServer syncthing-config-stunServer (default "default")) + (databaseTuning syncthing-config-databaseTuning (default "auto")) + (maxConcurrentIncomingRequestKiB syncthing-config-maxConcurrentIncomingR= equestKiB (default "0")) + (announceLANAddresses syncthing-config-announceLANAddresses (default "tr= ue")) + (sendFullIndexOnUpgrade syncthing-config-sendFullIndexOnUpgrade (default= "false")) + (connectionLimitEnough syncthing-config-connectionLimitEnough (default "= 0")) + (connectionLimitMax syncthing-config-connectionLimitMax (default "0")) + (insecureAllowOldTLSVersions syncthing-config-insecureAllowOldTLSVersion= s (default "false")) + (connectionPriorityTcpLan syncthing-config-connectionPriorityTcpLan (def= ault "10")) + (connectionPriorityQuicLan syncthing-config-connectionPriorityQuicLan (d= efault "20")) + (connectionPriorityTcpWan syncthing-config-connectionPriorityTcpWan (def= ault "30")) + (connectionPriorityQuicWan syncthing-config-connectionPriorityQuicWan (d= efault "40")) + (connectionPriorityRelay syncthing-config-connectionPriorityRelay (defau= lt "50")) + (connectionPriorityUpgradeThreshold syncthing-config-connectionPriorityU= pgradeThreshold (default "0")) + (default-folder syncthing-config-defaultFolder + (default (syncthing-folder (label "") (path "~")))) + (default-device syncthing-config-defaultDevice + (default (syncthing-device (id "")))) + (default-ignores syncthing-config-defaultIgnores (default ""))) + +(define syncthing-config-file->sxml + (match-record-lambda + (folders + devices gui-enabled gui-tls gui-debugging gui-sendBasicAuthPrompt + gui-address gui-user gui-password gui-apikey gui-theme ldap-enabled + ldap-address ldap-bindDN ldap-transport ldap-insecureSkipVerify + ldap-searchBaseDN ldap-searchFilter listenAddress globalAnnounceSer= ver + globalAnnounceEnabled localAnnounceEnabled localAnnouncePort + localAnnounceMCAddr maxSendKbps maxRecvKbps reconnectionIntervalS + relaysEnabled relayReconnectIntervalM startBrowser natEnabled + natLeaseMinutes natRenewalMinutes natTimeoutSeconds urAccepted + urSeen urUniqueID urURL urPostInsecurely urInitialDelayS + autoUpgradeIntervalH upgradeToPreReleases keepTemporariesH + cacheIgnoredFiles progressUpdateIntervalS limitBandwidthInLan + minHomeDiskFree-unit minHomeDiskFree releasesURL + overwriteRemoteDeviceNamesOnConnect tempIndexMinBlocks + unackedNotificationID trafficClass setLowPriority maxFolderConcurre= ncy + crashReportingURL crashReportingEnabled stunKeepaliveStartS + stunKeepaliveMinS stunServer databaseTuning + maxConcurrentIncomingRequestKiB announceLANAddresses + sendFullIndexOnUpgrade connectionLimitEnough connectionLimitMax + insecureAllowOldTLSVersions connectionPriorityTcpLan + connectionPriorityQuicLan connectionPriorityTcpWan + connectionPriorityQuicWan connectionPriorityRelay + connectionPriorityUpgradeThreshold default-folder default-device + default-ignores) + `(configuration (@ (version "37")) + ,@(map syncthing-folder->sxml + folders) + ;; collect any devices in any folders, as well as any + ;; devices explicitly added. + ,@(map syncthing-device->sxml + (delete-duplicates + (append devices + (apply append + (map (lambda (folder) + (map syncthing-folder-de= vice-device + (syncthing-folder-d= evices folder))) + folders))) + ;; devices are the same if their id's are equal + (lambda (device1 device2) + (string=3D (syncthing-device-id device1) + (syncthing-device-id device2))))) + (gui (@ (enabled ,gui-enabled) + (tls ,gui-tls) + (debugging ,gui-debugging) + (sendBasicAuthPrompt ,gui-sendBasicAuthPrompt)) + (address ,gui-address) + ,@(if gui-user `((user ,gui-user)) '()) + ,@(if gui-password `((password ,gui-password)) '(= )) + (apikey ,gui-apikey) + (theme ,gui-theme)) + (ldap ,(if ldap-enabled + `((address ,ldap-address) + (bindDN ,ldap-bindDN) + ,@(if ldap-transport + `((transport ,ldap-transport)) + '()) + ,@(if ldap-insecureSkipVerify + `((insecureSkipVerify ,ldap-insecur= eSkipVerify)) + '()) + ,@(if ldap-searchBaseDN + `((searchBaseDN ,ldap-searchBaseDN)) + '()) + ,@(if ldap-searchFilter + `((searchFilter ,ldap-searchFilter)) + '())) + "")) + (options (listenAddress ,listenAddress) + (globalAnnounceServer ,globalAnnounceServer) + (globalAnnounceEnabled ,globalAnnounceEnabled) + (localAnnounceEnabled ,localAnnounceEnabled) + (localAnnouncePort ,localAnnouncePort) + (localAnnounceMCAddr ,localAnnounceMCAddr) + (maxSendKbps ,maxSendKbps) + (maxRecvKbps ,maxRecvKbps) + (reconnectionIntervalS ,reconnectionIntervalS) + (relaysEnabled ,relaysEnabled) + (relayReconnectIntervalM ,relayReconnectInter= valM) + (startBrowser ,startBrowser) + (natEnabled ,natEnabled) + (natLeaseMinutes ,natLeaseMinutes) + (natRenewalMinutes ,natRenewalMinutes) + (natTimeoutSeconds ,natTimeoutSeconds) + (urAccepted ,urAccepted) + (urSeen ,urSeen) + (urUniqueID ,urUniqueID) + (urURL ,urURL) + (urPostInsecurely ,urPostInsecurely) + (urInitialDelayS ,urInitialDelayS) + (autoUpgradeIntervalH ,autoUpgradeIntervalH) + (upgradeToPreReleases ,upgradeToPreReleases) + (keepTemporariesH ,keepTemporariesH) + (cacheIgnoredFiles ,cacheIgnoredFiles) + (progressUpdateIntervalS ,progressUpdateInter= valS) + (limitBandwidthInLan ,limitBandwidthInLan) + (minHomeDiskFree (@ (unit ,minHomeDiskFree-un= it)) + ,minHomeDiskFree) + (releasesURL ,releasesURL) + (overwriteRemoteDeviceNamesOnConnect ,overwri= teRemoteDeviceNamesOnConnect) + (tempIndexMinBlocks ,tempIndexMinBlocks) + (unackedNotificationID ,unackedNotificationID) + (trafficClass ,trafficClass) + (setLowPriority ,setLowPriority) + (maxFolderConcurrency ,maxFolderConcurrency) + (crashReportingURL ,crashReportingURL) + (crashReportingEnabled ,crashReportingEnabled) + (stunKeepaliveStartS ,stunKeepaliveStartS) + (stunKeepaliveMinS ,stunKeepaliveMinS) + (stunServer ,stunServer) + (databaseTuning ,databaseTuning) + (maxConcurrentIncomingRequestKiB ,maxConcurre= ntIncomingRequestKiB) + (announceLANAddresses ,announceLANAddresses) + (sendFullIndexOnUpgrade ,sendFullIndexOnUpgra= de) + (connectionLimitEnough ,connectionLimitEnough) + (connectionLimitMax ,connectionLimitMax) + (insecureAllowOldTLSVersions ,insecureAllowOl= dTLSVersions) + (connectionPriorityTcpLan ,connectionPriority= TcpLan) + (connectionPriorityQuicLan ,connectionPriorit= yQuicLan) + (connectionPriorityTcpWan ,connectionPriority= TcpWan) + (connectionPriorityQuicWan ,connectionPriorit= yQuicWan) + (connectionPriorityRelay ,connectionPriorityR= elay) + (connectionPriorityUpgradeThreshold ,connecti= onPriorityUpgradeThreshold)) + (defaults + ,(syncthing-folder->sxml default-folder) + ,(syncthing-device->sxml default-device) + (ignores ,default-ignores))))) + +;; It is useful to be able to view the xml output by Guix, and to be able = to +;; diff it with a user's previous config, especially when migrating one's +;; config to Guix. This function adds whitespace that matches the whitesp= ace +;; of config files managed by Syncthing for easy diffing. +(define (indent-sxml sxml indent-increment current-indent) + (match sxml + (((tag ('@ properties ...) (subtags ..1) ..1) sibling-tags ...) + `(,current-indent (,tag (@ ,@properties) "\n" + ,@(indent-sxml subtags indent-increment + (string-append indent-incremen= t current-indent)) + ,current-indent) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag ('@ properties ...) primitive ...) sibling-tags ...) + `(,current-indent (,tag (@ ,@properties) ,@primitive) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag (subtags ..1) ..1) sibling-tags ...) + `(,current-indent (,tag "\n" + ,@(indent-sxml subtags indent-increment + (string-append indent-incremen= t current-indent)) + ,current-indent) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag primitive ...) sibling-tags ...) + `(,current-indent (,tag ,@primitive) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (() '()))) + +(define (serialize-syncthing-config-file config) + (with-output-to-string + (lambda () + (sxml->xml (cons '*TOP* (indent-sxml (list (syncthing-config-file->s= xml config)) + " " + "")))))) + (define-record-type* syncthing-configuration make-syncthing-configuration syncthing-configuration? @@ -50,6 +494,8 @@ (define-record-type* (default "users")) (home syncthing-configuration-home ;string (default #f)) + (config-file syncthing-configuration-config-file + (default #f)) ; syncthing-config-file or = file-like (home-service? syncthing-configuration-home-service? (default for-home?) (innate))) =20 @@ -93,10 +539,26 @@ (define syncthing-shepherd-service (respawn? #f) (stop #~(make-kill-destructor)))))) =20 + +(define syncthing-files-service + (match-record-lambda (config-file user home ho= me-service?) + (if config-file + `((,(if home-service? + ".config/syncthing/config.xml" + (string-append (or home (passwd:dir (getpw user))) + "/.config/syncthing/config.xml")) + ,(if (file-like? config-file) + config-file + (plain-file "syncthin-config.xml" (serialize-syncthing-con= fig-file + config-file))))) + '()))) + (define syncthing-service-type (service-type (name 'syncthing) (extensions (list (service-extension shepherd-root-service= -type - syncthing-shepherd-se= rvice))) + syncthing-shepherd-se= rvice) + (service-extension special-files-service= -type + syncthing-files-servi= ce))) (description "Run @uref{https://github.com/syncthing/syncthing, Syncth= ing} decentralized continuous file system synchronization."))) --=20 2.45.2 From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH] services: syncthing: Added support for config file serialization. Resent-From: Leo Famulari Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Fri, 07 Feb 2025 00:22:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Zacchaeus Cc: 75959@debbugs.gnu.org Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.173888770627241 (code B ref 75959); Fri, 07 Feb 2025 00:22:02 +0000 Received: (at 75959) by debbugs.gnu.org; 7 Feb 2025 00:21:46 +0000 Received: from localhost ([127.0.0.1]:59919 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tgC7t-00075J-RW for submit@debbugs.gnu.org; Thu, 06 Feb 2025 19:21:46 -0500 Received: from fhigh-b4-smtp.messagingengine.com ([202.12.124.155]:51971) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tgC7q-000753-Id for 75959@debbugs.gnu.org; Thu, 06 Feb 2025 19:21:43 -0500 Received: from phl-compute-01.internal (phl-compute-01.phl.internal [10.202.2.41]) by mailfhigh.stl.internal (Postfix) with ESMTP id B8E032540123; Thu, 6 Feb 2025 19:21:36 -0500 (EST) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-01.internal (MEProxy); Thu, 06 Feb 2025 19:21:36 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=famulari.name; h=cc:cc:content-type:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=mesmtp; t=1738887696; x= 1738974096; bh=q3pnzeyhIL37l3AILXzdQ7SpBjnLG/Nl2AoFdfJ99wM=; b=E DpS/zDaqMGZJhu+y7gC1ONsPZ+4gt3xMKysqZzA9E2Kf+eU10h4S7PWjYajafVJV skXsmwz+sulvhSNp/zO+ty6yVfXC/8Q7F1EWhgp6Wa0Py//uYwERjG6Xnn9oCrka T2aWj9kW0wF11F4iDND7hPPL9GUdnmB8VJrH9Osu/o= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t= 1738887696; x=1738974096; bh=q3pnzeyhIL37l3AILXzdQ7SpBjnLG/Nl2Ao FdfJ99wM=; b=UH891aW1OHM4uN7MWwy3V+vL4y8jFPe1/pjaYsVTEGSs1lHKFCA dq3qFVqiz5/4RsYdVpQrCwfn9KH+6Ub8bDjvu6Daxssc3POpUNa1XtcuE3mC3bdL 9syg9n1ShRupXMHTw5NKrwPiKSBvfeo07p3dZ6wkuutlLq4V/cZo3GmZ9vjq/vt7 auvKllzFo2roQ7JPtqOSrU8pDse7ajwGDsjcSe+dftx3N581jDGJGfJuzz+n7R4A Xjnig8HhBX/MTSQ3MWWmHUaOAqUe72SY9hnAoXRa5fZgPdw4tJkS1iQDuQAfO43F tGxoCnml84w5Bh5g0dTtuiOfW1B1zm8I+fQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddvjeejlecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdp uffrtefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecunecujfgurhepfffhvf evuffkfhggtggujgesghdtreertddtvdenucfhrhhomhepnfgvohcuhfgrmhhulhgrrhhi uceolhgvohesfhgrmhhulhgrrhhirdhnrghmvgeqnecuggftrfgrthhtvghrnheptedvtd etfefffffffeelfedvkeekfeduveduieejfeeugeelteffvdeuffejleevnecuvehluhhs thgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomheplhgvohesfhgrmhhulh grrhhirdhnrghmvgdpnhgspghrtghpthhtohepvddpmhhouggvpehsmhhtphhouhhtpdhr tghpthhtohepvghikhgtrgiiseiirggttghhrggvrdhushdprhgtphhtthhopeejheelhe elseguvggssghughhsrdhgnhhurdhorhhg X-ME-Proxy: Feedback-ID: i819c4023:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Thu, 6 Feb 2025 19:21:36 -0500 (EST) Date: Thu, 6 Feb 2025 19:21:34 -0500 From: Leo Famulari Message-ID: References: <20250130215954.9394-1-eikcaz@zacchae.us> <87frkqhg8w.fsf@zacchae.us> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="zOjsZ3goX5BS1jN8" Content-Disposition: inline In-Reply-To: <87frkqhg8w.fsf@zacchae.us> X-Spam-Score: -0.7 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) --zOjsZ3goX5BS1jN8 Content-Type: multipart/mixed; boundary="/Yve2en6Dl2hfPbu" Content-Disposition: inline --/Yve2en6Dl2hfPbu Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Thu, Feb 06, 2025 at 05:15:27PM -0500, Zacchaeus wrote: > From 7ef311e85b1198c752b2eec57caa0256227e079c Mon Sep 17 00:00:00 2001 > From: Zacchaeus > Date: Sun, 21 Jul 2024 00:54:25 -0700 > Subject: [PATCH] services: syncthing: Added support for config file > serialization. Thanks for the updated patch! By the way, when you generate the patches, please use the Git option --reroll-count, so that we can keep track of the revisions. I applied it to the current master branch, and created a VM image based on the lightweight-desktop template in our repo (attached). Then, I copied the image out of the store, made it writable, and booted it with QEMU. ------ $ ./pre-inst-env guix system image --image-type=3Dqcow2 --no-grafts doc/os-= config-lightweight-desktop.texi-syncthing --fallback --max-jobs=3D1 --cores= =3D12 --keep-going --image-size=3D10G -v3=20 /gnu/store/86zz6i1x55irgg1r74riil8avgl8hlp9-image.qcow2 $ cp /gnu/store/86zz6i1x55irgg1r74riil8avgl8hlp9-image.qcow2 ~/tmp/guix.qco= w2 && chmod 600 ~/tmp/guix.qcow2 $ qemu-system-x86_64 -nic user,model=3Dvirtio-net-pci -enable-kvm -m 1024 /= home/leo/tmp/guix.qcow2 ------ However, when I have included an instance of syncthing-service-type in the OS declaration, my user's home directory is owned by root, and I'm unable to log in as my user. When I remove syncthing-service-type, that problem does not exist. Any ideas? --/Yve2en6Dl2hfPbu Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="os-config-lightweight-desktop.texi-syncthing" ;; -*- mode: scheme; -*- ;; This is an operating system configuration template ;; for a "desktop" setup without full-blown desktop ;; environments. (use-modules (gnu) (gnu system nss)) (use-service-modules desktop syncthing) (use-package-modules bootloaders emacs emacs-xyz ratpoison suckless wm web-browsers web xdisorg xorg) (operating-system (host-name "antelope") (timezone "Europe/Paris") (locale "en_US.utf8") (kernel-arguments (list "console=ttyS0,115200")) ;; Use the UEFI variant of GRUB with the EFI System ;; Partition mounted on /boot/efi. (bootloader (bootloader-configuration (bootloader grub-bootloader) (targets '("/dev/sdX")))) ;; Assume the target root file system is labelled "my-root", ;; and the EFI System Partition has UUID 1234-ABCD. (file-systems (cons (file-system (device (file-system-label "my-root")) (mount-point "/") (type "ext4")) %base-file-systems)) (users (cons* (user-account (name "leo") (password "") (comment "leo") (group "users") (supplementary-groups '("wheel" "netdev" "audio" "video"))) %base-user-accounts)) ;; Add a bunch of window managers; we can choose one at ;; the log-in screen with F1. (packages (append (list ;; terminal emulator dillo netsurf rxvt-unicode xterm) %base-packages)) ;; Use the "desktop" services, which include the X11 ;; log-in service, networking with NetworkManager, and more. (services (cons* (service xfce-desktop-service-type) (service syncthing-service-type (let ((laptop (syncthing-device (id "M..."))) (desktop (syncthing-device (id "X...") (addresses '("tcp://foo"))))) (syncthing-configuration (user "leo") (config-file (syncthing-config-file (folders (list (syncthing-folder (label "some-files") (path "~/data") (devices (list desktop laptop))) (syncthing-folder (label "critical-files") (path "~/secrets") (devices (list desktop laptop (syncthing-folder-device (device desktop) (encryptionPassword "mypassword")))))))))))) %desktop-services)) ;; Allow resolution of '.local' host names with mDNS. (name-service-switch %mdns-host-lookup-nss)) --/Yve2en6Dl2hfPbu-- --zOjsZ3goX5BS1jN8 Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEaEByLu7k06ZO5T6saqwZY3V/R/8FAmelUgoACgkQaqwZY3V/ R/9HuRAAipDfpgEqO0zmrrmFQmaPcy1F/OSTWxQvLyLQCkInl/YH6qRY3IbPjyB7 nutSjIY6xTQnYFE9oomW7V/yVi3zXv/tMPnRvp3yi0+6Orsfbsg2ZC9jHyG76p2G MvAIbHKB59GcsZ2rZjSVVzymmDyv13KOy8FG7ZQPYATaI5kURBxIJkpB2nrszGvW kk76WHmbQFeNPOcrf/BV0AJ9zcRX7+eKvL90Vwhxb44KQbuR/4jJehwffFjL1yr1 rJ7TRqhfKbuyM31vTeh9WF1Pceifl66yzoZ8eHy635scucZUi6G1sxuSRy3ESdfo KUrOksemwmTE3dpKz6Aa5KJnfB4LWozBX0F9xmhsKbC4oaIkS9FmbVQVbY47RMSk 0JHno2g258uwRChsODLLkl5G5NGB1JcJiGaOnvD6sqtx1Z7mzboVS/G3tO6ChxaD 1VYJa1PteU/4JPUS4RrrhTvyI4asCpCohEdUhn1JnLkQ2iCGXzHmIkB8F0HlmM2u sHBXbEeMrdFIO2apqiqJmzLQGR06cIjOSh7nuMfODjoEgXK+DAsShuHGDwKPDZcl 5Ya/itPWahETcnTrv5fNq15g/NA2AukyIZyqKX2uiv4kUHvNqeAKo8DcXfxy/+z8 wlrvePVn/oZPMDZsZxE6PtylACjrpF3H60FSw44LSCzIm4hUbJw= =M/mG -----END PGP SIGNATURE----- --zOjsZ3goX5BS1jN8-- From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v5] services: syncthing: Added support for config file serialization. References: <20250130215954.9394-1-eikcaz@zacchae.us> In-Reply-To: <20250130215954.9394-1-eikcaz@zacchae.us> Resent-From: Zacchaeus Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Fri, 07 Feb 2025 04:40:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 75959@debbugs.gnu.org Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.17389032019343 (code B ref 75959); Fri, 07 Feb 2025 04:40:02 +0000 Received: (at 75959) by debbugs.gnu.org; 7 Feb 2025 04:40:01 +0000 Received: from localhost ([127.0.0.1]:60309 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tgG9n-0002QS-E3 for submit@debbugs.gnu.org; Thu, 06 Feb 2025 23:40:01 -0500 Received: from [47.204.136.169] (port=53254 helo=hun.zacchae.us) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tgG9i-0002Q9-JW for 75959@debbugs.gnu.org; Thu, 06 Feb 2025 23:39:57 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Transfer-Encoding:Content-Type: MIME-Version:Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=AUdTyVGwmWjfC7L9sbk8p6KQhJb/8tGNJvHifVJQxhg=; i=zacchae.us; b=jDMujuvWArhX ywR2iqB3qE0sH7m2l5RQZhkd7GveZBtKAMtr+U3vjcUyl3eN0I4vxGUHvlIMQiOCHz1LcJNLBA==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Transfer-Encoding:Content-Type:MIME-Version: Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=AUdTyVGwmWjfC7L9sbk8p6KQhJb/8tGNJvHifVJQxhg=; i=zacchae.us; b=SEZoaeJ0YP1y iQVrPy8qzRDRPqmXCE6W5DYvW6T6WX9ZtMp29S8a9LL3j0yghVviRubako/wgswYyHDte3xEeF8Dl tDEhmkC67KsSJ+Y/z7CrLLtUCwYQDnfveLXa371S98cJNGJZaiLB9TwgAVlzgf/RUAhM8DO/LK3bC H9uHTG7pFJTF1cVTUh4Hhjfg8YFaXNu03mxEbN+S5/BwJqOOlxLJVarKIJ7dLEhE1LZQqSoSW/TZ3 NFvFQIMAzoOcQs4s5UTfKV4N3nxg1V3iYSlbf0fUpSdi9DMQTJP46nqqSS4XIk2N2H9KaMYpZNyCd 2BrTn/XfyMK+n0w+I9Gu6Q==; Received: from localhost.home ([127.0.0.1]:46134 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1tgG9c-000000001dJ-083E for 75959@debbugs.gnu.org; Thu, 06 Feb 2025 23:39:48 -0500 From: Zacchaeus Date: Thu, 06 Feb 2025 23:39:48 -0500 Message-ID: <878qqigygb.fsf@zacchae.us> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From ad2bb352f8ff2cd93a2a1694faf353e02854ef2b Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH v5] services: syncthing: Added support [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in sa-accredit.habeas.com] 0.1 URIBL_SBL_A Contains URL's A record listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 0.6 URIBL_SBL Contains an URL's NS IP listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in bl.score.senderscore.com] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS 0.0 T_FILL_THIS_FORM_SHORT Fill in a short form with personal information 0.0 T_FILL_THIS_FORM_FRAUD_PHISH Answer suspicious question(s) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 1.0 (+) >From ad2bb352f8ff2cd93a2a1694faf353e02854ef2b Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH v5] services: syncthing: Added support for config file serialization. * gnu/services/syncthing.scm: (syncthing-config-file) (syncthing-folder) (syncthing-device) (syncthing-folder-device): New records; (syncthing-service-type): added special-files-service-type extension for the config file; (syncthing-files-service): service to create config file * gnu/home/services/syncthing.scm: (home-syncthing-service-type): extended home-files-services-type and re-exported more things from gnu/services/syncthing.scm * doc/guix.texi: (syncthing-service-type): document additions Change-Id: I87eeba1ee1fdada8f29c2ee881fbc6bc4113dde9 --- The previous patch had an issue with fresh system installs: the Syncthing service would populate ~/.config/syncthing/config.xml too early, so ~ would be owned by root, and ~ would be non-empty so skeletons would never be copied in. I addressed this by moving syncthing's config home to /var/lib/syncthing-. I only do this if it is a system service AND you are specifying a config-file. This is important for backwards compatibility. We wouldn't want people's syncthing to suddenly start looking in /var/lib/ for their gui-managed config after a system upgrade. doc/guix.texi | 290 +++++++++++++++++ gnu/home/services/syncthing.scm | 17 +- gnu/services/syncthing.scm | 533 ++++++++++++++++++++++++++++++-- 3 files changed, 810 insertions(+), 30 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index b1b6d98e74..1fdc772a1d 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -136,6 +136,7 @@ Copyright @copyright{} 2024 Troy Figiel@* Copyright @copyright{} 2024 Sharlatan Hellseher@* Copyright @copyright{} 2024 45mg@* Copyright @copyright{} 2025 S=C3=B6ren Tempel@* +Copyright @copyright{} 2025 Zacchaeus@* =20 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -22669,9 +22670,298 @@ This assumes that the specified group exists. Common configuration and data directory. The default configuration directory is @file{$HOME} of the specified Syncthing @code{user}. =20 +@item @code{config-file} (default: @var{#f}) +Either a file-like object that resolves to a syncthing configuration xml +file, or a syncthing-config-file record (see below). If set to #f, Guix +will not try to generate a config file, and the syncthing will generate +a default one which will not be touched on reconfigure. Specifying this +in a system service moves Syncthing's common configuration and data +directory to @file{/var/lib/syncthnig-}. + +@end table +@end deftp + +In the below, only details specific to Guix, or related to how your +device will ``ping'' others, are presented. Otherwise, you should +consult @uref{https://docs.syncthing.net/users/config.html, Syncthing +config documentation}. Camelcase is preserved below only as to be +consistent with its appearance in Syncthing code/documentation. If you +would like to migrate to Guix-powered Syncthing configuration, the +generated config adds newlines/whitespace to the produced config such +that your old config can be diff'ed with the new one. You can still +modify Syncthing from the GUI or through ``introducer'' and +``autoAcceptFolders'' mechanisms, but such changes will be reset on +reconfigure. + +@deftp {Data Type} syncthing-config-file +Data type representing the configuration file read by the syncthing +daemon. + +@table @asis +@item @code{folders} (default: @var{(list (syncthing-folder (id "default")= (label "Default Folder") (path "~/Sync")))} +The default here is the same as Syncthing's default. The value should +be a list of @code{syncthing-folder}s. + +@item @code{devices} (default: @var{'()} +This should be a list of @code{syncthing-device}s. Guix will +automatically add any devices specified in any `folders' to this list. +There are instances when you want to connect to a device despite not +(initially) sharing any folders (such as a device with +autoAcceptFolders). In such instances, you should specify those devices +here. If multiple versions of the same device (same id) are discovered, +the one in this list is prioritized. Otherwise, the first instance in +the first folder is used. + +@item @code{gui-enabled} (default: @var{"true"}) +By default, any user on the computer can access the GUI and make changes +to Syncthing. If you leave this enabled, you should probably set +gui-user and gui-password (see below). + +@item @code{gui-tls} (default: @var{"false"}) +@item @code{gui-debugging} (default: @var{"false"}) +@item @code{gui-sendBasicAuthPrompt} (default: @var{"false"}) +@item @code{gui-address} (default: @var{"127.0.0.1:8384"}) +@item @code{gui-user} (default: @var{#f}) +@item @code{gui-password} (default: @var{#f}) +@item @code{gui-apikey} (default: @var{"Vuky3VHVseQEoSk9YgxhSkNTnjQmqYK9"}) +@item @code{gui-theme} (default: @var{"default"}) +@item @code{ldap-enabled} (default: @var{#f}) +@item @code{ldap-address} (default: @var{""}) +@item @code{ldap-bindDN} (default: @var{""}) +@item @code{ldap-transport} (default: @var{""}) +@item @code{ldap-insecureSkipVerify} (default: @var{""}) +@item @code{ldap-searchBaseDN} (default: @var{""}) +@item @code{ldap-searchFilter} (default: @var{""}) +@item @code{listenAddress} (default: @var{"default"}) +@item @code{globalAnnounceServer} (default: @var{"default"}) +@item @code{globalAnnounceEnabled} (default: @var{"true"}) +Global discovery servers can be used to help connect devices at unknown +IP addresses by storing the last known IP address. + +@item @code{localAnnounceEnabled} (default: @var{"true"}) +This makes devices find each other very easily on the same LAN. Often, +this will allow you to just plug an Ethernet between two devices, or +connect one device to the other's hotspot and start syncing. + +@item @code{localAnnouncePort} (default: @var{"21027"}) +@item @code{localAnnounceMCAddr} (default: @var{"[ff12::8384]:21027"}) +@item @code{maxSendKbps} (default: @var{"0"}) +@item @code{maxRecvKbps} (default: @var{"0"}) +@item @code{reconnectionIntervalS} (default: @var{"60"}) +@item @code{relaysEnabled} (default: @var{"true"}) +This option allows your Syncthing instance to coordinate with a global +network of relays to enable syncing between devices when all other +methods fail. + +@item @code{relayReconnectIntervalM} (default: @var{"10"}) +@item @code{startBrowser} (default: @var{"true"}) +@item @code{natEnabled} (default: @var{"true"}) +@item @code{natLeaseMinutes} (default: @var{"60"}) +@item @code{natRenewalMinutes} (default: @var{"30"}) +@item @code{natTimeoutSeconds} (default: @var{"10"}) +@item @code{urAccepted} (default: @var{"0"}) +ur* options control usage reporting. Set to -1 to disable, or positive +to enable. The default (0) has reporting disabled, but you will be +asked to decide in the GUI. + +@item @code{urSeen} (default: @var{"0"}) +@item @code{urUniqueID} (default: @var{""}) +@item @code{urURL} (default: @var{"https://data.syncthing.net/newdata"}) +@item @code{urPostInsecurely} (default: @var{"false"}) +@item @code{urInitialDelayS} (default: @var{"1800"}) +@item @code{autoUpgradeIntervalH} (default: @var{"12"}) +@item @code{upgradeToPreReleases} (default: @var{"false"}) +@item @code{keepTemporariesH} (default: @var{"24"}) +@item @code{cacheIgnoredFiles} (default: @var{"false"}) +@item @code{progressUpdateIntervalS} (default: @var{"5"}) +@item @code{limitBandwidthInLan} (default: @var{"false"}) +@item @code{minHomeDiskFree-unit} (default: @var{"%"}) +@item @code{minHomeDiskFree} (default: @var{"1"}) +@item @code{releasesURL} (default: @var{"https://upgrades.syncthing.net/me= ta.json"}) +@item @code{overwriteRemoteDeviceNamesOnConnect} (default: @var{"false"}) +@item @code{tempIndexMinBlocks} (default: @var{"10"}) +@item @code{unackedNotificationID} (default: @var{"authenticationUserAndPa= ssword"}) +@item @code{trafficClass} (default: @var{"0"}) +@item @code{setLowPriority} (default: @var{"true"}) +@item @code{maxFolderConcurrency} (default: @var{"0"}) +@item @code{crashReportingURL} (default: @var{"https://crash.syncthing.net= /newcrash"}) +@item @code{crashReportingEnabled} (default: @var{"true"}) +@item @code{stunKeepaliveStartS} (default: @var{"180"}) +@item @code{stunKeepaliveMinS} (default: @var{"20"}) +@item @code{stunServer} (default: @var{"default"}) +@item @code{databaseTuning} (default: @var{"auto"}) +@item @code{maxConcurrentIncomingRequestKiB} (default: @var{"0"}) +@item @code{announceLANAddresses} (default: @var{"true"}) +@item @code{sendFullIndexOnUpgrade} (default: @var{"false"}) +@item @code{connectionLimitEnough} (default: @var{"0"}) +@item @code{connectionLimitMax} (default: @var{"0"}) +@item @code{insecureAllowOldTLSVersions} (default: @var{"false"}) +@item @code{connectionPriorityTcpLan} (default: @var{"10"}) +@item @code{connectionPriorityQuicLan} (default: @var{"20"}) +@item @code{connectionPriorityTcpWan} (default: @var{"30"}) +@item @code{connectionPriorityQuicWan} (default: @var{"40"}) +@item @code{connectionPriorityRelay} (default: @var{"50"}) +@item @code{connectionPriorityUpgradeThreshold} (default: @var{"0"}) +@item @code{default-folder} (default: @var{(syncthing-folder (label ""))}) +@item @code{default-device} (default: @var{(syncthing-device (id ""))}) +@item @code{default-ignores} (default: @var{"")}) +The default-* above do not affect folders and devices added by the Guix +interface. They will, however, affect folders and devices that are +added through the GUI, by an ``introducer'', or a device with +``autoAcceptFolders''. +@end table +@end deftp + +@deftp {Data Type} syncthing-device +Data type representing a device to sync with. + +@table @asis +@item @code{id} +A long hash tied to the keys generated by Syncthing on the first launch. +You can obtain this from the Syncthing GUI or by inspecting an existing +Syncthing configuration file. + +@item @code{name} (default: @var{""}) +Human readable device name for viewing in the GUI or in scheme. + +@item @code{compression} (default: @var{"metadata"}) +@item @code{introducer} (default: @var{"false"}) +@item @code{skipIntroductionRemovals} (default: @var{"false"}) +@item @code{introducedBy} (default: @var{""}) +@item @code{addresses} (default: @var{'("dynamic")}) +List of addresses at which to search for this device. The special value +``dynamic'' will have syncthing use several means to find the device. + +@item @code{paused} (default: @var{"false"}) +@item @code{autoAcceptFolders} (default: @var{"false"}) +@item @code{maxSendKbps} (default: @var{"0"}) +@item @code{maxRecvKbps} (default: @var{"0"}) +@item @code{maxRequestKiB} (default: @var{"0"}) +@item @code{untrusted} (default: @var{"false"}) +@item @code{remoteGUIPort} (default: @var{"0"}) +@item @code{numConnections} (default: @var{"0")}) + +@end table +@end deftp + +@deftp {Data Type} syncthing-folder +Data type representing a folder to be synced. + +@table @asis +@item @code{id} (default: @var{#f}) +This id cannot match the id of any other folder on this device. If left +unspecified, it will default to the label (see below). + +@item @code{label} +Human readable label for the folder. + +@item @code{path} +The path at which to store this folder. + +@item @code{type} (default: @var{"sendreceive"}) +@item @code{rescanIntervalS} (default: @var{"3600"}) +@item @code{fsWatcherEnabled} (default: @var{"true"}) +@item @code{fsWatcherDelayS} (default: @var{"10"}) +@item @code{ignorePerms} (default: @var{"false"}) +@item @code{autoNormalize} (default: @var{"true"}) +@item @code{devices} (default: @var{'()}) +Devices should be a list of other Syncthing devices. You do not need to +specify the current device. Each device can be listed as a a +@code{syncthing-device} record or a @code{syncthing-folder-device} +record if you want files to be encrypted on disk. + +@item @code{filesystemType} (default: @var{"basic"}) +@item @code{minDiskFree-unit} (default: @var{"%"}) +@item @code{minDiskFree} (default: @var{"1"}) +@item @code{versioning-type} (default: @var{#f}) +@item @code{versioning-fsPath} (default: @var{""}) +@item @code{versioning-fsType} (default: @var{"basic"}) +@item @code{versioning-cleanupIntervalS} (default: @var{"3600"}) +@item @code{versioning-cleanoutDays} (default: @var{#f}) +@item @code{versioning-keep} (default: @var{#f}) +@item @code{versioning-maxAge} (default: @var{#f}) +@item @code{versioning-command} (default: @var{#f}) +@item @code{copiers} (default: @var{"0"}) +@item @code{pullerMaxPendingKiB} (default: @var{"0"}) +@item @code{hashers} (default: @var{"0"}) +@item @code{order} (default: @var{"random"}) +@item @code{ignoreDelete} (default: @var{"false"}) +@item @code{scanProgressIntervalS} (default: @var{"0"}) +@item @code{pullerPauseS} (default: @var{"0"}) +@item @code{maxConflicts} (default: @var{"10"}) +@item @code{disableSparseFiles} (default: @var{"false"}) +@item @code{disableTempIndexes} (default: @var{"false"}) +@item @code{paused} (default: @var{"false"}) +@item @code{weakHashThresholdPct} (default: @var{"25"}) +@item @code{markerName} (default: @var{".stfolder"}) +@item @code{copyOwnershipFromParent} (default: @var{"false"}) +@item @code{modTimeWindowS} (default: @var{"0"}) +@item @code{maxConcurrentWrites} (default: @var{"2"}) +@item @code{disableFsync} (default: @var{"false"}) +@item @code{blockPullOrder} (default: @var{"standard"}) +@item @code{copyRangeMethod} (default: @var{"standard"}) +@item @code{caseSensitiveFS} (default: @var{"false"}) +@item @code{junctionsAsDirs} (default: @var{"false"}) +@item @code{syncOwnership} (default: @var{"false"}) +@item @code{sendOwnership} (default: @var{"false"}) +@item @code{syncXattrs} (default: @var{"false"}) +@item @code{sendXattrs} (default: @var{"false"}) +@item @code{xattrFilter-maxSingleEntrySize} (default: @var{"1024"}) +@item @code{xattrFilter-maxTotalSize} (default: @var{"4096")}) +@end table +@end deftp + +@deftp {Data Type} syncthing-folder-device +There is some configuration which is specific to the relationship +between a specific folder and a specific device. If you are fine +leaving these as their default, then you can simply specify a +syncthing-device instead of a @code{syncthing-folder-device} in +@code{syncthing-folder}s. + +@table @asis +@item @code{device} +device should be a @code{syncthing-device} for which this configuration +applies. + +@item @code{introducedBy} (default: @var{""}) +@item @code{encryptionPassword} (default: @var{""}) +if encryptionPassword is non-empty, then it will be used as a password +to encrypt file chunks as they are synced to that device. For more info +on syncing to devices you don't totally trust, see +@uref{https://docs.syncthing.net/users/untrusted.html, Syncthing Documenta= tion Untrusted}. +Note that file transfers are always end-to-end encrypted, regardless of +this setting. + @end table @end deftp =20 +Here is a more complex example configuration for illustrative purposes: +@lisp +(service syncthing-service-type + (let ((laptop (syncthing-device (id "VHOD2D6-...-7XRMDEN"))) + (desktop (syncthing-device (id "64SAZ37-...-FZJ5GUA") + (addresses '("mydomain.example")= ))) + (bob-desktop (syncthing-device (id "KYIMEGO-...-FT77EAO")))) + (syncthing-configuration + (user "alice") + (config-file + (syncthing-config-file + (folders (list (syncthing-folder + (label "some-files") + (path "~/data") + (devices (list desktop laptop))) + (syncthing-folder + (label "critical-files") + (path "~/secrets") + (devices + (list desktop + laptop + (syncthing-folder-device + (device bob-desktop) + (encryptionPassword "mypassword")))= ))))))))) +@end lisp + + Furthermore, @code{(gnu services ssh)} provides the following services. @cindex SSH @cindex SSH server diff --git a/gnu/home/services/syncthing.scm b/gnu/home/services/syncthing.= scm index 8d66a167ce..dd6c752ee4 100644 --- a/gnu/home/services/syncthing.scm +++ b/gnu/home/services/syncthing.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2023 Ludovic Court=C3=A8s +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -24,9 +25,23 @@ (define-module (gnu home services syncthing) #:use-module (gnu home services shepherd) #:export (home-syncthing-service-type) #:re-export (syncthing-configuration - syncthing-configuration?)) + syncthing-configuration? + syncthing-config-file + syncthing-config-file? + syncthing-device + syncthing-device? + syncthing-folder + syncthing-folder? + syncthing-folder-device + syncthing-folder-device?)) =20 (define home-syncthing-service-type (service-type (inherit (system->home-service-type syncthing-service-type)) + ;; system->home-service-type does not convert special-files-service-typ= e to + ;; home-files-service-type, so redefine extensios + (extensions (list (service-extension home-files-service-type + syncthing-files-service) + (service-extension home-shepherd-service-type + syncthing-shepherd-service))) (default-value (for-home (syncthing-configuration))))) diff --git a/gnu/services/syncthing.scm b/gnu/services/syncthing.scm index a7a9c6aadd..5b9567b716 100644 --- a/gnu/services/syncthing.scm +++ b/gnu/services/syncthing.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2021 Oleg Pykhalov ;;; Copyright =C2=A9 2023 Justin Veilleux +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -25,9 +26,20 @@ (define-module (gnu services syncthing) #:use-module (guix records) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (sxml simple) #:export (syncthing-configuration syncthing-configuration? - syncthing-service-type)) + syncthing-device + syncthing-device? + syncthing-config-file + syncthing-config-file? + syncthing-folder-device + syncthing-folder-device? + syncthing-folder + syncthing-folder? + syncthing-service-type + syncthing-shepherd-service + syncthing-files-service)) =20 ;;; Commentary: ;;; @@ -35,6 +47,438 @@ (define-module (gnu services syncthing) ;;; ;;; Code: =20 +(define-record-type* + syncthing-device make-syncthing-device + syncthing-device? + (id syncthing-device-id) + (name syncthing-device-name (default "")) + (compression syncthing-device-compression (default "metadata")) + (introducer syncthing-device-introducer (default "false")) + (skipIntroductionRemovals syncthing-device-skipIntroductionRemovals (def= ault "false")) + (introducedBy syncthing-device-introducedBy (default "")) + (addresses syncthing-device-addresses (default '("dynamic"))) + (paused syncthing-device-paused (default "false")) + (autoAcceptFolders syncthing-device-autoAcceptFolders (default "false")) + (maxSendKbps syncthing-device-maxSendKbps (default "0")) + (maxRecvKbps syncthing-device-maxRecvKbps (default "0")) + (maxRequestKiB syncthing-device-maxRequestKiB (default "0")) + (untrusted syncthing-device-untrusted (default "false")) + (remoteGUIPort syncthing-device-remoteGUIPort (default "0")) + (numConnections syncthing-device-numConnections (default "0"))) + +(define syncthing-device->sxml + (match-record-lambda + (id name compression introducer skipIntroductionRemovals introducedB= y addresses paused autoAcceptFolders maxSendKbps maxRecvKbps maxRequestKiB = untrusted remoteGUIPort numConnections) + `(device (@ (id ,id) + (name ,name) + (compression ,compression) + (introducer ,introducer) + (skipIntroductionRemovals ,skipIntroductionRemovals) + (introducedBy ,introducedBy)) + ,@(map (lambda (address) `(address ,address)) addresses) + (paused ,paused) + (autoAcceptFolders ,autoAcceptFolders) + (maxSendKbps ,maxSendKbps) + (maxRecvKbps ,maxRecvKbps) + (maxRequestKiB ,maxRequestKiB) + (untrusted ,untrusted) + (remoteGUIPort ,remoteGUIPort) + (numConnections ,numConnections)))) + +(define-record-type* + syncthing-folder-device make-syncthing-folder-device + syncthing-folder-device? + (device syncthing-folder-device-device) + (introducedBy syncthing-folder-device-introducedBy (default (syncthing-d= evice (id "")))) + (encryptionPassword syncthing-folder-device-encryptionPassword (default = ""))) + +(define syncthing-folder-device->sxml + (match-record-lambda + (device introducedBy encryptionPassword) + `(device (@ (id ,(syncthing-device-id device)) + (introducedBy ,(syncthing-device-id introducedBy))) + (encryptionPassword ,encryptionPassword)))) + +(define-record-type* + syncthing-folder make-syncthing-folder + syncthing-folder? + (id syncthing-folder-id (default #f)) + (label syncthing-folder-label) + (path syncthing-folder-path) + (type syncthing-folder-type (default "sendreceive")) + (rescanIntervalS syncthing-folder-rescanIntervalS (default "3600")) + (fsWatcherEnabled syncthing-folder-fsWatcherEnabled (default "true")) + (fsWatcherDelayS syncthing-folder-fsWatcherDelayS (default "10")) + (fsWatcherTimeoutS syncthing-folder-fsWatcherTimeoutS (default "0")) + (ignorePerms syncthing-folder-ignorePerms (default "false")) + (autoNormalize syncthing-folder-autoNormalize (default "true")) + (devices syncthing-folder-devices (default '()) + (sanitize (lambda (folder-device-list) + (map (lambda (device) + (if (syncthing-folder-device? device) + device + (syncthing-folder-device (device device)= ))) + folder-device-list)))) + (filesystemType syncthing-folder-filesystemType (default "basic")) + (minDiskFree-unit syncthing-folder-minDiskFree-unit (default "%")) + (minDiskFree syncthing-folder-minDiskFree (default "1")) + (versioning-type syncthing-folder-versioning-type (default #f)) + (versioning-fsPath syncthing-folder-versioning-fsPath (default "")) + (versioning-fsType syncthing-folder-versioning-fsType (default "basic")) + (versioning-cleanupIntervalS syncthing-folder-versioning-cleanupInterval= S (default "3600")) + (versioning-cleanoutDays syncthing-folder-versioning-cleanoutDays (defau= lt #f)) + (versioning-keep syncthing-folder-versioning-keep (default #f)) + (versioning-maxAge syncthing-folder-versioning-maxAge (default #f)) + (versioning-command syncthing-folder-versioning-command (default #f)) + (copiers syncthing-folder-copiers (default "0")) + (pullerMaxPendingKiB syncthing-folder-pullerMaxPendingKiB (default "0")) + (hashers syncthing-folder-hashers (default "0")) + (order syncthing-folder-order (default "random")) + (ignoreDelete syncthing-folder-ignoreDelete (default "false")) + (scanProgressIntervalS syncthing-folder-scanProgressIntervalS (default "= 0")) + (pullerPauseS syncthing-folder-pullerPauseS (default "0")) + (maxConflicts syncthing-folder-maxConflicts (default "10")) + (disableSparseFiles syncthing-folder-disableSparseFiles (default "false"= )) + (disableTempIndexes syncthing-folder-disableTempIndexes (default "false"= )) + (paused syncthing-folder-paused (default "false")) + (weakHashThresholdPct syncthing-folder-weakHashThresholdPct (default "25= ")) + (markerName syncthing-folder-markerName (default ".stfolder")) + (copyOwnershipFromParent syncthing-folder-copyOwnershipFromParent (defau= lt "false")) + (modTimeWindowS syncthing-folder-modTimeWindowS (default "0")) + (maxConcurrentWrites syncthing-folder-maxConcurrentWrites (default "2")) + (disableFsync syncthing-folder-disableFsync (default "false")) + (blockPullOrder syncthing-folder-blockPullOrder (default "standard")) + (copyRangeMethod syncthing-folder-copyRangeMethod (default "standard")) + (caseSensitiveFS syncthing-folder-caseSensitiveFS (default "false")) + (junctionsAsDirs syncthing-folder-junctionsAsDirs (default "false")) + (syncOwnership syncthing-folder-syncOwnership (default "false")) + (sendOwnership syncthing-folder-sendOwnership (default "false")) + (syncXattrs syncthing-folder-syncXattrs (default "false")) + (sendXattrs syncthing-folder-sendXattrs (default "false")) + (xattrFilter-maxSingleEntrySize syncthing-folder-xattrFilter-maxSingleEn= trySize (default "1024")) + (xattrFilter-maxTotalSize syncthing-folder-xattrFilter-maxTotalSize (def= ault "4096"))) + +;; Some parameters, when empty, are fully omitted from the config file. I= t is +;; unknown if this causes a functional difference, but stick to the normal +;; program's behavior to be safe. +(define (maybe-param symbol value) + (if value `((param (@ (key ,(symbol->string symbol)) (val ,value)) "")) = '())) + +(define syncthing-folder->sxml + (match-record-lambda + (id + label path type rescanIntervalS fsWatcherEnabled fsWatcherDelayS + fsWatcherTimeoutS ignorePerms autoNormalize devices filesystemType + minDiskFree-unit minDiskFree versioning-type versioning-fsPath + versioning-fsType versioning-cleanupIntervalS versioning-cleanoutDa= ys + versioning-keep versioning-maxAge versioning-command copiers + pullerMaxPendingKiB hashers order ignoreDelete scanProgressIntervalS + pullerPauseS maxConflicts disableSparseFiles disableTempIndexes pau= sed + weakHashThresholdPct markerName copyOwnershipFromParent modTimeWind= owS + maxConcurrentWrites disableFsync blockPullOrder copyRangeMethod + caseSensitiveFS junctionsAsDirs syncOwnership sendOwnership syncXat= trs + sendXattrs xattrFilter-maxSingleEntrySize xattrFilter-maxTotalSize) + `(folder (@ (id ,(if id id label)) + (label ,label) + (path ,path) + (type ,type) + (rescanIntervalS ,rescanIntervalS) + (fsWatcherEnabled ,fsWatcherEnabled) + (fsWatcherDelayS ,fsWatcherDelayS) + (fsWatcherTimeoutS ,fsWatcherTimeoutS) + (ignorePerms ,ignorePerms) + (autoNormalize ,autoNormalize)) + (filesystemType ,filesystemType) + ,@(map syncthing-folder-device->sxml + devices) + (minDiskFree (@ (unit ,minDiskFree-unit)) + ,minDiskFree) + (versioning ,@(if versioning-type + `((@ (type ,versioning-type))) + '()) + ,@(maybe-param 'cleanoutDays versioning-cleanoutD= ays) + ,@(maybe-param 'keep versioning-keep) + ,@(maybe-param 'maxAge versioning-maxAge) + ,@(maybe-param 'command versioning-command) + (cleanupIntervalS ,versioning-cleanupIntervalS) + (fsPath ,versioning-fsPath) + (fsType ,versioning-fsType)) + (copiers ,copiers) + (pullerMaxPendingKiB ,pullerMaxPendingKiB) + (hashers ,hashers) + (order ,order) + (ignoreDelete ,ignoreDelete) + (scanProgressIntervalS ,scanProgressIntervalS) + (pullerPauseS ,pullerPauseS) + (maxConflicts ,maxConflicts) + (disableSparseFiles ,disableSparseFiles) + (disableTempIndexes ,disableTempIndexes) + (paused ,paused) + (weakHashThresholdPct ,weakHashThresholdPct) + (markerName ,markerName) + (copyOwnershipFromParent ,copyOwnershipFromParent) + (modTimeWindowS ,modTimeWindowS) + (maxConcurrentWrites ,maxConcurrentWrites) + (disableFsync ,disableFsync) + (blockPullOrder ,blockPullOrder) + (copyRangeMethod ,copyRangeMethod) + (caseSensitiveFS ,caseSensitiveFS) + (junctionsAsDirs ,junctionsAsDirs) + (syncOwnership ,syncOwnership) + (sendOwnership ,sendOwnership) + (syncXattrs ,syncXattrs) + (sendXattrs ,sendXattrs) + (xattrFilter (maxSingleEntrySize ,xattrFilter-maxSingleEntryS= ize) + (maxTotalSize ,xattrFilter-maxTotalSize))))) + +(define-record-type* + syncthing-config-file make-syncthing-config-file + syncthing-config-file? + (folders syncthing-config-folders + ; this matches syncthing's default + (default (list (syncthing-folder (id "default") + (label "Default Folder") + (path "~/Sync"))))) + (devices syncthing-config-devices + (default '())) + (gui-enabled syncthing-config-gui-enabled (default "true")) + (gui-tls syncthing-config-gui-tls (default "false")) + (gui-debugging syncthing-config-gui-debugging (default "false")) + (gui-sendBasicAuthPrompt syncthing-config-gui-sendBasicAuthPrompt (defau= lt "false")) + (gui-address syncthing-config-gui-address (default "127.0.0.1:8384")) + (gui-user syncthing-config-gui-user (default #f)) + (gui-password syncthing-config-gui-password (default #f)) + (gui-apikey syncthing-config-gui-apikey (default "Vuky3VHVseQEoSk9YgxhSk= NTnjQmqYK9")) + (gui-theme syncthing-config-gui-theme (default "default")) + (ldap-enabled syncthing-config-ldap-enabled (default #f)) + (ldap-address syncthing-config-ldap-address (default "")) + (ldap-bindDN syncthing-config-ldap-bindDN (default "")) + (ldap-transport syncthing-config-ldap-transport (default "")) + (ldap-insecureSkipVerify syncthing-config-ldap-insecureSkipVerify (defau= lt "")) + (ldap-searchBaseDN syncthing-config-ldap-searchBaseDN (default "")) + (ldap-searchFilter syncthing-config-ldap-searchFilter (default "")) + (listenAddress syncthing-config-listenAddress (default "default")) + (globalAnnounceServer syncthing-config-globalAnnounceServer (default "de= fault")) + (globalAnnounceEnabled syncthing-config-globalAnnounceEnabled (default "= true")) + (localAnnounceEnabled syncthing-config-localAnnounceEnabled (default "tr= ue")) + (localAnnouncePort syncthing-config-localAnnouncePort (default "21027")) + (localAnnounceMCAddr syncthing-config-localAnnounceMCAddr (default "[ff1= 2::8384]:21027")) + (maxSendKbps syncthing-config-maxSendKbps (default "0")) + (maxRecvKbps syncthing-config-maxRecvKbps (default "0")) + (reconnectionIntervalS syncthing-config-reconnectionIntervalS (default "= 60")) + (relaysEnabled syncthing-config-relaysEnabled (default "true")) + (relayReconnectIntervalM syncthing-config-relayReconnectIntervalM (defau= lt "10")) + (startBrowser syncthing-config-startBrowser (default "true")) + (natEnabled syncthing-config-natEnabled (default "true")) + (natLeaseMinutes syncthing-config-natLeaseMinutes (default "60")) + (natRenewalMinutes syncthing-config-natRenewalMinutes (default "30")) + (natTimeoutSeconds syncthing-config-natTimeoutSeconds (default "10")) + (urAccepted syncthing-config-urAccepted (default "0")) + (urSeen syncthing-config-urSeen (default "0")) + (urUniqueID syncthing-config-urUniqueID (default "")) + (urURL syncthing-config-urURL (default "https://data.syncthing.net/newda= ta")) + (urPostInsecurely syncthing-config-urPostInsecurely (default "false")) + (urInitialDelayS syncthing-config-urInitialDelayS (default "1800")) + (autoUpgradeIntervalH syncthing-config-autoUpgradeIntervalH (default "12= ")) + (upgradeToPreReleases syncthing-config-upgradeToPreReleases (default "fa= lse")) + (keepTemporariesH syncthing-config-keepTemporariesH (default "24")) + (cacheIgnoredFiles syncthing-config-cacheIgnoredFiles (default "false")) + (progressUpdateIntervalS syncthing-config-progressUpdateIntervalS (defau= lt "5")) + (limitBandwidthInLan syncthing-config-limitBandwidthInLan (default "fals= e")) + (minHomeDiskFree-unit syncthing-config-minHomeDiskFree-unit (default "%"= )) + (minHomeDiskFree syncthing-config-minHomeDiskFree (default "1")) + (releasesURL syncthing-config-releasesURL (default "https://upgrades.syn= cthing.net/meta.json")) + (overwriteRemoteDeviceNamesOnConnect syncthing-config-overwriteRemoteDev= iceNamesOnConnect (default "false")) + (tempIndexMinBlocks syncthing-config-tempIndexMinBlocks (default "10")) + (unackedNotificationID syncthing-config-unackedNotificationID (default "= authenticationUserAndPassword")) + (trafficClass syncthing-config-trafficClass (default "0")) + (setLowPriority syncthing-config-setLowPriority (default "true")) + (maxFolderConcurrency syncthing-config-maxFolderConcurrency (default "0"= )) + (crashReportingURL syncthing-config-crashReportingURL (default "https://= crash.syncthing.net/newcrash")) + (crashReportingEnabled syncthing-config-crashReportingEnabled (default "= true")) + (stunKeepaliveStartS syncthing-config-stunKeepaliveStartS (default "180"= )) + (stunKeepaliveMinS syncthing-config-stunKeepaliveMinS (default "20")) + (stunServer syncthing-config-stunServer (default "default")) + (databaseTuning syncthing-config-databaseTuning (default "auto")) + (maxConcurrentIncomingRequestKiB syncthing-config-maxConcurrentIncomingR= equestKiB (default "0")) + (announceLANAddresses syncthing-config-announceLANAddresses (default "tr= ue")) + (sendFullIndexOnUpgrade syncthing-config-sendFullIndexOnUpgrade (default= "false")) + (connectionLimitEnough syncthing-config-connectionLimitEnough (default "= 0")) + (connectionLimitMax syncthing-config-connectionLimitMax (default "0")) + (insecureAllowOldTLSVersions syncthing-config-insecureAllowOldTLSVersion= s (default "false")) + (connectionPriorityTcpLan syncthing-config-connectionPriorityTcpLan (def= ault "10")) + (connectionPriorityQuicLan syncthing-config-connectionPriorityQuicLan (d= efault "20")) + (connectionPriorityTcpWan syncthing-config-connectionPriorityTcpWan (def= ault "30")) + (connectionPriorityQuicWan syncthing-config-connectionPriorityQuicWan (d= efault "40")) + (connectionPriorityRelay syncthing-config-connectionPriorityRelay (defau= lt "50")) + (connectionPriorityUpgradeThreshold syncthing-config-connectionPriorityU= pgradeThreshold (default "0")) + (default-folder syncthing-config-defaultFolder + (default (syncthing-folder (label "") (path "~")))) + (default-device syncthing-config-defaultDevice + (default (syncthing-device (id "")))) + (default-ignores syncthing-config-defaultIgnores (default ""))) + +(define syncthing-config-file->sxml + (match-record-lambda + (folders + devices gui-enabled gui-tls gui-debugging gui-sendBasicAuthPrompt + gui-address gui-user gui-password gui-apikey gui-theme ldap-enabled + ldap-address ldap-bindDN ldap-transport ldap-insecureSkipVerify + ldap-searchBaseDN ldap-searchFilter listenAddress globalAnnounceSer= ver + globalAnnounceEnabled localAnnounceEnabled localAnnouncePort + localAnnounceMCAddr maxSendKbps maxRecvKbps reconnectionIntervalS + relaysEnabled relayReconnectIntervalM startBrowser natEnabled + natLeaseMinutes natRenewalMinutes natTimeoutSeconds urAccepted + urSeen urUniqueID urURL urPostInsecurely urInitialDelayS + autoUpgradeIntervalH upgradeToPreReleases keepTemporariesH + cacheIgnoredFiles progressUpdateIntervalS limitBandwidthInLan + minHomeDiskFree-unit minHomeDiskFree releasesURL + overwriteRemoteDeviceNamesOnConnect tempIndexMinBlocks + unackedNotificationID trafficClass setLowPriority maxFolderConcurre= ncy + crashReportingURL crashReportingEnabled stunKeepaliveStartS + stunKeepaliveMinS stunServer databaseTuning + maxConcurrentIncomingRequestKiB announceLANAddresses + sendFullIndexOnUpgrade connectionLimitEnough connectionLimitMax + insecureAllowOldTLSVersions connectionPriorityTcpLan + connectionPriorityQuicLan connectionPriorityTcpWan + connectionPriorityQuicWan connectionPriorityRelay + connectionPriorityUpgradeThreshold default-folder default-device + default-ignores) + `(configuration (@ (version "37")) + ,@(map syncthing-folder->sxml + folders) + ;; collect any devices in any folders, as well as any + ;; devices explicitly added. + ,@(map syncthing-device->sxml + (delete-duplicates + (append devices + (apply append + (map (lambda (folder) + (map syncthing-folder-de= vice-device + (syncthing-folder-d= evices folder))) + folders))) + ;; devices are the same if their id's are equal + (lambda (device1 device2) + (string=3D (syncthing-device-id device1) + (syncthing-device-id device2))))) + (gui (@ (enabled ,gui-enabled) + (tls ,gui-tls) + (debugging ,gui-debugging) + (sendBasicAuthPrompt ,gui-sendBasicAuthPrompt)) + (address ,gui-address) + ,@(if gui-user `((user ,gui-user)) '()) + ,@(if gui-password `((password ,gui-password)) '(= )) + (apikey ,gui-apikey) + (theme ,gui-theme)) + (ldap ,(if ldap-enabled + `((address ,ldap-address) + (bindDN ,ldap-bindDN) + ,@(if ldap-transport + `((transport ,ldap-transport)) + '()) + ,@(if ldap-insecureSkipVerify + `((insecureSkipVerify ,ldap-insecur= eSkipVerify)) + '()) + ,@(if ldap-searchBaseDN + `((searchBaseDN ,ldap-searchBaseDN)) + '()) + ,@(if ldap-searchFilter + `((searchFilter ,ldap-searchFilter)) + '())) + "")) + (options (listenAddress ,listenAddress) + (globalAnnounceServer ,globalAnnounceServer) + (globalAnnounceEnabled ,globalAnnounceEnabled) + (localAnnounceEnabled ,localAnnounceEnabled) + (localAnnouncePort ,localAnnouncePort) + (localAnnounceMCAddr ,localAnnounceMCAddr) + (maxSendKbps ,maxSendKbps) + (maxRecvKbps ,maxRecvKbps) + (reconnectionIntervalS ,reconnectionIntervalS) + (relaysEnabled ,relaysEnabled) + (relayReconnectIntervalM ,relayReconnectInter= valM) + (startBrowser ,startBrowser) + (natEnabled ,natEnabled) + (natLeaseMinutes ,natLeaseMinutes) + (natRenewalMinutes ,natRenewalMinutes) + (natTimeoutSeconds ,natTimeoutSeconds) + (urAccepted ,urAccepted) + (urSeen ,urSeen) + (urUniqueID ,urUniqueID) + (urURL ,urURL) + (urPostInsecurely ,urPostInsecurely) + (urInitialDelayS ,urInitialDelayS) + (autoUpgradeIntervalH ,autoUpgradeIntervalH) + (upgradeToPreReleases ,upgradeToPreReleases) + (keepTemporariesH ,keepTemporariesH) + (cacheIgnoredFiles ,cacheIgnoredFiles) + (progressUpdateIntervalS ,progressUpdateInter= valS) + (limitBandwidthInLan ,limitBandwidthInLan) + (minHomeDiskFree (@ (unit ,minHomeDiskFree-un= it)) + ,minHomeDiskFree) + (releasesURL ,releasesURL) + (overwriteRemoteDeviceNamesOnConnect ,overwri= teRemoteDeviceNamesOnConnect) + (tempIndexMinBlocks ,tempIndexMinBlocks) + (unackedNotificationID ,unackedNotificationID) + (trafficClass ,trafficClass) + (setLowPriority ,setLowPriority) + (maxFolderConcurrency ,maxFolderConcurrency) + (crashReportingURL ,crashReportingURL) + (crashReportingEnabled ,crashReportingEnabled) + (stunKeepaliveStartS ,stunKeepaliveStartS) + (stunKeepaliveMinS ,stunKeepaliveMinS) + (stunServer ,stunServer) + (databaseTuning ,databaseTuning) + (maxConcurrentIncomingRequestKiB ,maxConcurre= ntIncomingRequestKiB) + (announceLANAddresses ,announceLANAddresses) + (sendFullIndexOnUpgrade ,sendFullIndexOnUpgra= de) + (connectionLimitEnough ,connectionLimitEnough) + (connectionLimitMax ,connectionLimitMax) + (insecureAllowOldTLSVersions ,insecureAllowOl= dTLSVersions) + (connectionPriorityTcpLan ,connectionPriority= TcpLan) + (connectionPriorityQuicLan ,connectionPriorit= yQuicLan) + (connectionPriorityTcpWan ,connectionPriority= TcpWan) + (connectionPriorityQuicWan ,connectionPriorit= yQuicWan) + (connectionPriorityRelay ,connectionPriorityR= elay) + (connectionPriorityUpgradeThreshold ,connecti= onPriorityUpgradeThreshold)) + (defaults + ,(syncthing-folder->sxml default-folder) + ,(syncthing-device->sxml default-device) + (ignores ,default-ignores))))) + +;; It is useful to be able to view the xml output by Guix, and to be able = to +;; diff it with a user's previous config, especially when migrating one's +;; config to Guix. This function adds whitespace that matches the whitesp= ace +;; of config files managed by Syncthing for easy diffing. +(define (indent-sxml sxml indent-increment current-indent) + (match sxml + (((tag ('@ properties ...) (subtags ..1) ..1) sibling-tags ...) + `(,current-indent (,tag (@ ,@properties) "\n" + ,@(indent-sxml subtags indent-increment + (string-append indent-incremen= t current-indent)) + ,current-indent) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag ('@ properties ...) primitive ...) sibling-tags ...) + `(,current-indent (,tag (@ ,@properties) ,@primitive) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag (subtags ..1) ..1) sibling-tags ...) + `(,current-indent (,tag "\n" + ,@(indent-sxml subtags indent-increment + (string-append indent-incremen= t current-indent)) + ,current-indent) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag primitive ...) sibling-tags ...) + `(,current-indent (,tag ,@primitive) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (() '()))) + +(define (serialize-syncthing-config-file config) + (with-output-to-string + (lambda () + (sxml->xml (cons '*TOP* (indent-sxml (list (syncthing-config-file->s= xml config)) + " " + "")))))) + (define-record-type* syncthing-configuration make-syncthing-configuration syncthing-configuration? @@ -50,12 +494,14 @@ (define-record-type* (default "users")) (home syncthing-configuration-home ;string (default #f)) + (config-file syncthing-configuration-config-file + (default #f)) ; syncthing-config-file or = file-like (home-service? syncthing-configuration-home-service? (default for-home?) (innate))) =20 (define syncthing-shepherd-service (match-record-lambda - (syncthing arguments logflags user group home home-service?) + (syncthing arguments logflags user group home home-service? config-f= ile) (list (shepherd-service (provision (if home-service? @@ -64,39 +510,68 @@ (define syncthing-shepherd-service (string-append "syncthing-" user))))) (documentation "Run syncthing.") (requirement (if home-service? '() '(loopback user-processes))) - (start #~(make-forkexec-constructor - (append (list (string-append #$syncthing "/bin/syncthing") - "--no-browser" - "--no-restart" - (string-append "--logflags=3D" (number->stri= ng #$logflags))) - '#$arguments) - #:user #$(and (not home-service?) user) - #:group #$(and (not home-service?) group) - #:environment-variables - (append - (list - (string-append "HOME=3D" - (or #$home - (passwd:dir - (getpw (if (and #$home-service? - (not #$user)) - (getuid) - #$user))))) - "SSL_CERT_DIR=3D/etc/ssl/certs" - "SSL_CERT_FILE=3D/etc/ssl/certs/ca-certifica= tes.crt") - (filter (negate ;XXX: 'remove' is not in (gu= ile) - (lambda (str) - (or (string-prefix? "HOME=3D" str) - (string-prefix? "SSL_CERT_DIR=3D" s= tr) - (string-prefix? "SSL_CERT_FILE=3D" = str)))) - (environ))))) + (start #~(lambda _ + ;; if we are managing the config, and it's not a home + ;; service, then exepect the config file at + ;; /var/lib/syncthing-. This makes sure the owners= hip + ;; is correct + (unless (or #$(not config-file) #$home-service?) + (system* "chown" #$user (string-append "/var/lib/syncth= ing-" #$user)) + (system* "chmod" "700" (string-append "/var/lib/syncthi= ng-" #$user))) + (make-forkexec-constructor + (append (list (string-append #$syncthing "/bin/syncthing= ") + "--no-browser" + "--no-restart" + (string-append "--logflags=3D" (number->st= ring #$logflags))) + (if (or #$(not config-file) #$home-service?) '() + (list (string-append "--home=3D/var/lib/sync= thing-" #$user))) + '#$arguments) + #:user #$(and (not home-service?) user) + #:group #$(and (not home-service?) group) + #:environment-variables + (append + (list + (string-append "HOME=3D" + (or #$home + (passwd:dir + (getpw (if (and #$home-service? + (not #$user)) + (getuid) + #$user))))) + "SSL_CERT_DIR=3D/etc/ssl/certs" + "SSL_CERT_FILE=3D/etc/ssl/certs/ca-certificates.crt") + (filter (negate ;XXX: 'remove' is not in (guile) + (lambda (str) + (or (string-prefix? "HOME=3D" str) + (string-prefix? "SSL_CERT_DIR=3D" str) + (string-prefix? "SSL_CERT_FILE=3D" str))= )) + (environ)))))) (respawn? #f) (stop #~(make-kill-destructor)))))) =20 + +(define syncthing-files-service + (match-record-lambda (config-file user home ho= me-service?) + (if config-file + ;; when used as a system service, this service might be executed + ;; before a user's home even exists, causing it to be owned by roo= t, + ;; and the skeletons to never be applied to that user's home. In = such + ;; cases, put the config at /var/lib/syncthnig-/config.xml + `((,(if home-service? + ".config/syncthing/config.xml" + (string-append "/var/lib/syncthing-" user "/config.xml")) + ,(if (file-like? config-file) + config-file + (plain-file "syncthin-config.xml" (serialize-syncthing-con= fig-file + config-file))))) + '()))) + (define syncthing-service-type (service-type (name 'syncthing) (extensions (list (service-extension shepherd-root-service= -type - syncthing-shepherd-se= rvice))) + syncthing-shepherd-se= rvice) + (service-extension special-files-service= -type + syncthing-files-servi= ce))) (description "Run @uref{https://github.com/syncthing/syncthing, Syncth= ing} decentralized continuous file system synchronization."))) --=20 2.45.2 From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v5] services: syncthing: Added support for config file serialization. Resent-From: Leo Famulari Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Fri, 07 Feb 2025 22:46:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Zacchaeus Cc: 75959@debbugs.gnu.org Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.17389683117920 (code B ref 75959); Fri, 07 Feb 2025 22:46:02 +0000 Received: (at 75959) by debbugs.gnu.org; 7 Feb 2025 22:45:11 +0000 Received: from localhost ([127.0.0.1]:37192 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tgX5y-00023a-Je for submit@debbugs.gnu.org; Fri, 07 Feb 2025 17:45:11 -0500 Received: from fhigh-b1-smtp.messagingengine.com ([202.12.124.152]:37909) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tgX5v-0001xQ-JQ for 75959@debbugs.gnu.org; Fri, 07 Feb 2025 17:45:08 -0500 Received: from phl-compute-05.internal (phl-compute-05.phl.internal [10.202.2.45]) by mailfhigh.stl.internal (Postfix) with ESMTP id C44592540150; Fri, 7 Feb 2025 17:45:01 -0500 (EST) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-05.internal (MEProxy); Fri, 07 Feb 2025 17:45:01 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=famulari.name; h=cc:cc:content-type:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=mesmtp; t=1738968301; x= 1739054701; bh=gOGpv2AmNZJ4sT/a5DmHc4XiyHmq8ptC4rdDI8EPbBc=; b=W gSYdX64bG49YUP9Ags5k2esHPdbc/ABki+CM4GD0Rd+Xxz9IO0YFYqqGxrOs9GM8 UmTLw1mlNEEBe/H8iNARphlA1+lzyE4ISixpB8lbIhhshVqHLRWr3nZNiD8u7WAu OZzNLf1vZ2x5ZM71gdm+Q4Nm9892lgxkRwOxjOL1JU= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t= 1738968301; x=1739054701; bh=gOGpv2AmNZJ4sT/a5DmHc4XiyHmq8ptC4rd DI8EPbBc=; b=iR7KRfe5dz1JXshoSftyaH4QzLBlUPIiB649RE77PSmQhWpWMdN Jip9Izf+ShGpTwMucKCoet0AnRFwUewLLvZ7+Z/oyyhvnbC3a0YMRU1y9iS+pn3i pxc7JN3RWYyvqU54dBLyNAHozlskoCtqA02Iz+2DcUdj3TQaYWcCFlRjrYgf94C8 ts/OsboCky681NCaQa10fqRSCtX2t3IBT/oDM7SztImrOFHxEuDy4i4yN/vnLta1 sEBv2mPo20IEEeH8LluQqxOjQYQL14UxkdiaSjo8bgMds0uFicRi+uPQXUDwPSyg swlToSfZ4FDESazqqYMLs5sqvDq51G+tCwA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdeftdehudcutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdp uffrtefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecunecujfgurhepfffhvf evuffkfhggtggujgesthdtredttddtvdenucfhrhhomhepnfgvohcuhfgrmhhulhgrrhhi uceolhgvohesfhgrmhhulhgrrhhirdhnrghmvgeqnecuggftrfgrthhtvghrnhepfffhff ehgfetgfegteejgeegfeetleeihfefueevgedvleelhfdtkeeiuefgvdfgnecuffhomhgr ihhnpehgnhhurdhorhhgpdhshihntghthhhinhhgrdhnvghtnecuvehluhhsthgvrhfuih iivgeptdenucfrrghrrghmpehmrghilhhfrhhomheplhgvohesfhgrmhhulhgrrhhirdhn rghmvgdpnhgspghrtghpthhtohepvddpmhhouggvpehsmhhtphhouhhtpdhrtghpthhtoh epvghikhgtrgiiseiirggttghhrggvrdhushdprhgtphhtthhopeejheelheelseguvggs sghughhsrdhgnhhurdhorhhg X-ME-Proxy: Feedback-ID: i819c4023:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 7 Feb 2025 17:45:00 -0500 (EST) Date: Fri, 7 Feb 2025 17:44:55 -0500 From: Leo Famulari Message-ID: References: <20250130215954.9394-1-eikcaz@zacchae.us> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20250130215954.9394-1-eikcaz@zacchae.us> X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) > Subject: [PATCH v5] services: syncthing: Added support for config file > serialization. Great! I tested the system-level service according to the config in my last email and was able to successfully integrate into my existing Syncthing cluster. Since we have already worked out the bugs on IRC, my feedback here will be largely cosmetic. I think of this patch as being more about generating Syncthing config files, rather than serializing them. > * gnu/services/syncthing.scm: (syncthing-config-file) (syncthing-folder) > (syncthing-device) (syncthing-folder-device): New records; > (syncthing-service-type): added special-files-service-type extension for the > config file; (syncthing-files-service): service to create config file > * gnu/home/services/syncthing.scm: (home-syncthing-service-type): extended > home-files-services-type and re-exported more things from > gnu/services/syncthing.scm > * doc/guix.texi: (syncthing-service-type): document additions In the commit title and message, please capitalize and punctuate sentences normally, and avoid unecessary abbreviations. Try to write imperative sentences. For example, "Add support for configuration file serialization [or generation]". When listing the new records / variables, they can be contained in the same parenthetical list, like (syncthing-config-file, syncthing-folder, [...]): New records. > @@ -22669,9 +22670,298 @@ This assumes that the specified group exists. > Common configuration and data directory. The default configuration > directory is @file{$HOME} of the specified Syncthing @code{user}. > > +@item @code{config-file} (default: @var{#f}) > +Either a file-like object that resolves to a syncthing configuration xml > +file, or a syncthing-config-file record (see below). If set to #f, Guix > +will not try to generate a config file, and the syncthing will generate > +a default one which will not be touched on reconfigure. Specifying this > +in a system service moves Syncthing's common configuration and data > +directory to @file{/var/lib/syncthnig-}. Again, use standard capitalization, etc. Also, use texinfo markup and cross-references when useful: https://www.gnu.org/software/texinfo/manual/texinfo/html_node/Cross-References.html For example, "Either a file-like object that resolves to a Syncthing configuration XML file, or a @code{syncthing-config-file} record (see below). When set to @code{#f} [...]" If you like, I can copy-edit the documentation portion of this patch for spelling, style, and grammar, as well as mark it up with texinfo. Let me know. If you'd prefer I don't, I'll send another review with feedback on those subjects. > +In the below, only details specific to Guix, or related to how your > +device will ``ping'' others, are presented. Otherwise, you should > +consult @uref{https://docs.syncthing.net/users/config.html, Syncthing > +config documentation}. Camelcase is preserved below only as to be > +consistent with its appearance in Syncthing code/documentation. If you > +would like to migrate to Guix-powered Syncthing configuration, the > +generated config adds newlines/whitespace to the produced config such > +that your old config can be diff'ed with the new one. You can still > +modify Syncthing from the GUI or through ``introducer'' and > +``autoAcceptFolders'' mechanisms, but such changes will be reset on > +reconfigure. I have some misgivings about the use of camel case in user-facing interfaces. I do understand the utility of preserving the upstream names, but I wonder how much utility it really provides. In my experience, it's not typical to edit Syncthing's config.xml "by hand" (I did it some when I first started with Syncthing), so I'd expect users' to have little familiarity with these names, nor for them to desire a direct mapping between them. Additionally, there is utility in all Guix interfaces sharing a consistent style, and the camel case is not surfaced in Syncthing's own GUI. What do you think? > +@item @code{localAnnouncePort} (default: @var{"21027"}) > +@item @code{localAnnounceMCAddr} (default: @var{"[ff12::8384]:21027"}) Not important for this patch, but do you have any ideas to facilitate multi-user systems, with respect to automatically using alternate ports? > +@deftp {Data Type} syncthing-folder-device > +There is some configuration which is specific to the relationship > +between a specific folder and a specific device. If you are fine > +leaving these as their default, then you can simply specify a > +syncthing-device instead of a @code{syncthing-folder-device} in > +@code{syncthing-folder}s. I think this paragraph is not clear enough, although it starts to make sense after reading about the parameters. Still I think there is room for improvement. > +if encryptionPassword is non-empty, then it will be used as a password > +to encrypt file chunks as they are synced to that device. For more info > +on syncing to devices you don't totally trust, see > +@uref{https://docs.syncthing.net/users/untrusted.html, Syncthing Documentation Untrusted}. I would write the hyperlink as "Syncthing Documentation on Untrusted Devices". > +Here is a more complex example configuration for illustrative purposes: > +@lisp > +(service syncthing-service-type > + (let ((laptop (syncthing-device (id "VHOD2D6-...-7XRMDEN"))) > + (desktop (syncthing-device (id "64SAZ37-...-FZJ5GUA") > + (addresses '("mydomain.example")))) Let's use the reserved domain name 'example.com'. Also, Syncthing requires these addresses to use a "protocol specific prefix", so how about "tcp://example.com"? https://docs.syncthing.net/users/config.html#config-option-device.address > @@ -24,9 +25,23 @@ (define-module (gnu home services syncthing) Okay. Sounds like you've tested the home service satisfactorily. > @@ -25,9 +26,20 @@ (define-module (gnu services syncthing) > +;; Some parameters, when empty, are fully omitted from the config file. It is > +;; unknown if this causes a functional difference, but stick to the normal > +;; program's behavior to be safe. Agreed > + (gui-apikey syncthing-config-gui-apikey (default "Vuky3VHVseQEoSk9YgxhSkNTnjQmqYK9")) I've never used the GUI API, but shouldn't this key be generated per-device, rather than hard-coded here? > +;; It is useful to be able to view the xml output by Guix, and to be able to > +;; diff it with a user's previous config, especially when migrating one's > +;; config to Guix. This function adds whitespace that matches the whitespace > +;; of config files managed by Syncthing for easy diffing. > +(define (indent-sxml sxml indent-increment current-indent) Nice. Hopefully this doesn't go stale anytime soon. Overall, it's looking good. Thanks a lot for this contribution! Let me know what you think about the feedback I've given here. From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v5] services: syncthing: Added support for config file serialization. Resent-From: Zacchaeus Scheffer Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sat, 08 Feb 2025 01:12:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Leo Famulari Cc: 75959@debbugs.gnu.org Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.17389770782303 (code B ref 75959); Sat, 08 Feb 2025 01:12:02 +0000 Received: (at 75959) by debbugs.gnu.org; 8 Feb 2025 01:11:18 +0000 Received: from localhost ([127.0.0.1]:37465 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tgZNN-0000b4-7H for submit@debbugs.gnu.org; Fri, 07 Feb 2025 20:11:18 -0500 Received: from [47.204.136.169] (port=47538 helo=hun.zacchae.us) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tgZNJ-0000aj-9p for 75959@debbugs.gnu.org; Fri, 07 Feb 2025 20:11:15 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=odL4VEsDcsWTknOg0TE0F2HI5vgxbodWgLftjK9vc5M=; i=zacchae.us; b=jMIbRWPtwCCN vqir5KzBxJ8Bv5XKO7jCuJ40ygAHfRXE45X4mMl1yyBI/EgnKZPuZ3scQc3ZlRnmjSXkOqWYDQ==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Type:MIME-Version:Message-ID:Date:References: In-Reply-To:Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=odL4VEsDcsWTknOg0TE0F2HI5vgxbodWgLftjK9vc5M=; i=zacchae.us; b=O5INUmgMOVk5 I83gNzlhYk01jlU82KMTkORj9CKgi0BBpCNKH6SJNhB5pc94tiSjkikbI11O3Lz/ArG/dYkFSHycG 181zb4tUY0ZTzHXOUXwrFzGksS4D3ti2FxZ7CgEhaNnIRRp5+Q4MNm+IASF/9gfK78lVk8ZQ+z/vp qOAyDwzZlick8pqqrQa98lO776obovFxhyeLS1YKcs/46SMlwDkHzSCLt2D83I5plQeJBwBe7pOf+ 6dy3Iu2+Wp4LP9SrSWWuqrP0z85xS0n/3rsuciLXzZCpo1mixpl+hfc7dXllfYuZPn1lrsPfYW8cK 1Op683ssMpjcwgyiKJFmqQ==; Received: from localhost.home ([127.0.0.1]:60782 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1tgZNC-000000005NQ-2sMs; Fri, 07 Feb 2025 20:11:07 -0500 From: Zacchaeus Scheffer In-Reply-To: (Leo Famulari's message of "Fri, 7 Feb 2025 17:44:55 -0500") References: <20250130215954.9394-1-eikcaz@zacchae.us> Date: Fri, 07 Feb 2025 20:11:06 -0500 Message-ID: <874j15gs0l.fsf@zacchae.us> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Leo Famulari writes: >> Subject: [PATCH v5] services: syncthing: Added support for config file >> serialization. > > Great! I tested the system-level service according to the config in my > last email and was able to succ [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in sa-accredit.habeas.com] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in bl.score.senderscore.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 URIBL_SBL_A Contains URL's A record listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 0.6 URIBL_SBL Contains an URL's NS IP listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 1.0 (+) Leo Famulari writes: >> Subject: [PATCH v5] services: syncthing: Added support for config file >> serialization. > > Great! I tested the system-level service according to the config in my > last email and was able to successfully integrate into my existing > Syncthing cluster. > > Since we have already worked out the bugs on IRC, my feedback here will > be largely cosmetic. > > I think of this patch as being more about generating Syncthing config > files, rather than serializing them. Makes sense. I'll update serialization -> generation >> * gnu/services/syncthing.scm: (syncthing-config-file) (syncthing-folder) >> (syncthing-device) (syncthing-folder-device): New records; >> (syncthing-service-type): added special-files-service-type extension for the >> config file; (syncthing-files-service): service to create config file >> * gnu/home/services/syncthing.scm: (home-syncthing-service-type): extended >> home-files-services-type and re-exported more things from >> gnu/services/syncthing.scm >> * doc/guix.texi: (syncthing-service-type): document additions > > In the commit title and message, please capitalize and punctuate > sentences normally, and avoid unecessary abbreviations. Try to write > imperative sentences. For example, "Add support for configuration file > serialization [or generation]". Will do. > When listing the new records / variables, they can be contained in the > same parenthetical list, like (syncthing-config-file, syncthing-folder, > [...]): New records. Interesting. I'll do as you suggest, but that's not what I've seen in other commit messages. e.g. commit e73cf57a204f2bf430c90930394afa08e9ec3399 >> @@ -22669,9 +22670,298 @@ This assumes that the specified group exists. >> Common configuration and data directory. The default configuration >> directory is @file{$HOME} of the specified Syncthing @code{user}. >> >> +@item @code{config-file} (default: @var{#f}) >> +Either a file-like object that resolves to a syncthing configuration xml >> +file, or a syncthing-config-file record (see below). If set to #f, Guix >> +will not try to generate a config file, and the syncthing will generate >> +a default one which will not be touched on reconfigure. Specifying this >> +in a system service moves Syncthing's common configuration and data >> +directory to @file{/var/lib/syncthnig-}. > > Again, use standard capitalization, etc. Also, use texinfo markup and > cross-references when useful: > > https://www.gnu.org/software/texinfo/manual/texinfo/html_node/Cross-References.html > > For example, "Either a file-like object that resolves to a Syncthing > configuration XML file, or a @code{syncthing-config-file} record (see > below). When set to @code{#f} [...]" > > If you like, I can copy-edit the documentation portion of this patch for > spelling, style, and grammar, as well as mark it up with texinfo. Let me > know. If you'd prefer I don't, I'll send another review with feedback on > those subjects. I'll try to clean up these points myself first (I feel bad giving you more work), but feel free to make changes as you see fit. I'm aware that my writing needs work... >> +In the below, only details specific to Guix, or related to how your >> +device will ``ping'' others, are presented. Otherwise, you should >> +consult @uref{https://docs.syncthing.net/users/config.html, Syncthing >> +config documentation}. Camelcase is preserved below only as to be >> +consistent with its appearance in Syncthing code/documentation. If you >> +would like to migrate to Guix-powered Syncthing configuration, the >> +generated config adds newlines/whitespace to the produced config such >> +that your old config can be diff'ed with the new one. You can still >> +modify Syncthing from the GUI or through ``introducer'' and >> +``autoAcceptFolders'' mechanisms, but such changes will be reset on >> +reconfigure. > > I have some misgivings about the use of camel case in user-facing > interfaces. I do understand the utility of preserving the upstream > names, but I wonder how much utility it really provides. In my > experience, it's not typical to edit Syncthing's config.xml "by hand" (I > did it some when I first started with Syncthing), so I'd expect users' > to have little familiarity with these names, nor for them to desire a > direct mapping between them. Additionally, there is utility in all Guix > interfaces sharing a consistent style, and the camel case is not > surfaced in Syncthing's own GUI. > > What do you think? I explained my reasoning in this thread and in the IRC, and didn't recieve much pushback. However, I hadn't even realized that the Syncthing GUI doesn't use camelcase... I've been generating config files via Emacs Org Mode src blocks with heavy use of noweb-refs, so my experience is probably skewed. If this were my library, I would definitely use camelcase because I think that is clearest, but it's not that important to me, and I don't think the draw-backs are that large. I'll just put more effort into adding links to syncthing documentation for things that don't map so obviously (e.g. ldap-transport is not found in the documentation as ldapTransport, it is the transport field of the ldap element). >> +@item @code{localAnnouncePort} (default: @var{"21027"}) >> +@item @code{localAnnounceMCAddr} (default: @var{"[ff12::8384]:21027"}) > > Not important for this patch, but do you have any ideas to facilitate > multi-user systems, with respect to automatically using alternate > ports? No, and I'm not sure you should as automatically changing a port means another machine doesn't know which port to look at (or so I assume, maybe nameservers fix this issue, but I'd rather not bake in a dependancy on third-party services). Maybe this would make sense if using guix-deploy because then you could tell each machine how the ports match up. >> +@deftp {Data Type} syncthing-folder-device >> +There is some configuration which is specific to the relationship >> +between a specific folder and a specific device. If you are fine >> +leaving these as their default, then you can simply specify a >> +syncthing-device instead of a @code{syncthing-folder-device} in >> +@code{syncthing-folder}s. > > I think this paragraph is not clear enough, although it starts to make > sense after reading about the parameters. Still I think there is room > for improvement. Basically, if you have D devices and F folders, then there are D*F relationships between those folders. Specifically, we need to know, for a given folder, if a device should only recieve encrypted data, and from where we know that device (so we can automatically remove this device if the introducing device is removed). This could be accomplished by having devices be listed in a folder as a tuple (device password introducer), but I think that would be abusing lists, so a record seems appropriate here. I'll try and make this text more clear as to this record's function. >> +if encryptionPassword is non-empty, then it will be used as a password >> +to encrypt file chunks as they are synced to that device. For more info >> +on syncing to devices you don't totally trust, see >> +@uref{https://docs.syncthing.net/users/untrusted.html, Syncthing Documentation Untrusted}. > > I would write the hyperlink as "Syncthing Documentation on Untrusted > Devices". Will do >> +Here is a more complex example configuration for illustrative purposes: >> +@lisp >> +(service syncthing-service-type >> + (let ((laptop (syncthing-device (id "VHOD2D6-...-7XRMDEN"))) >> + (desktop (syncthing-device (id "64SAZ37-...-FZJ5GUA") >> + (addresses '("mydomain.example")))) > > Let's use the reserved domain name 'example.com'. Also, Syncthing > requires these addresses to use a "protocol specific prefix", so how > about "tcp://example.com"? > > https://docs.syncthing.net/users/config.html#config-option-device.address Yes that's right >> @@ -24,9 +25,23 @@ (define-module (gnu home services syncthing) > > Okay. Sounds like you've tested the home service satisfactorily. > >> @@ -25,9 +26,20 @@ (define-module (gnu services syncthing) >> +;; Some parameters, when empty, are fully omitted from the config file. It is >> +;; unknown if this causes a functional difference, but stick to the normal >> +;; program's behavior to be safe. > > Agreed > >> + (gui-apikey syncthing-config-gui-apikey (default "Vuky3VHVseQEoSk9YgxhSkNTnjQmqYK9")) > > I've never used the GUI API, but shouldn't this key be generated > per-device, rather than hard-coded here? That's a good point. It's probably bad to have ANY default here. I just tested, and syncthing does not complain when apikey is omitted, so I've made that change. I'll add notes to this, the GUI password, and encryption passwords that these are stored in /gnu/store and are globally readable (GUI password is encrypted, but encryption passwords are plain-text). >> +;; It is useful to be able to view the xml output by Guix, and to be able to >> +;; diff it with a user's previous config, especially when migrating one's >> +;; config to Guix. This function adds whitespace that matches the whitespace >> +;; of config files managed by Syncthing for easy diffing. >> +(define (indent-sxml sxml indent-increment current-indent) > > Nice. Hopefully this doesn't go stale anytime soon. The whitespace rules have been consistent for as long as I've used syncthing, so my hopes are high. > Overall, it's looking good. Thanks a lot for this contribution! Let me > know what you think about the feedback I've given here. Thank you for reviewing! I'll submit another patch shortly implementing what we have discussed. From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v6] services: syncthing: Add support for config file generation. References: <20250130215954.9394-1-eikcaz@zacchae.us> In-Reply-To: <20250130215954.9394-1-eikcaz@zacchae.us> Resent-From: Zacchaeus Scheffer Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sat, 08 Feb 2025 03:32:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 75959@debbugs.gnu.org, Leo Famulari Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.173898549227913 (code B ref 75959); Sat, 08 Feb 2025 03:32:02 +0000 Received: (at 75959) by debbugs.gnu.org; 8 Feb 2025 03:31:32 +0000 Received: from localhost ([127.0.0.1]:37679 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tgbZ4-0007G4-18 for submit@debbugs.gnu.org; Fri, 07 Feb 2025 22:31:32 -0500 Received: from [47.204.136.169] (port=35300 helo=hun.zacchae.us) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tgbZ0-0007Fl-Cb for 75959@debbugs.gnu.org; Fri, 07 Feb 2025 22:31:29 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Transfer-Encoding:Content-Type: MIME-Version:Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=SvljkI/qtCuTnw5XWfIGZL0PDwlNtlftQ3pqO9JOsIg=; i=zacchae.us; b=oCeoXPkWuotG KnM1c7VEwLzwHkl5U720df0t0FdBBmNDoZhLL5dZJx+dtyI24V1RWC8N49KyleuG8zwMlVZvAg==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Transfer-Encoding:Content-Type:MIME-Version: Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=SvljkI/qtCuTnw5XWfIGZL0PDwlNtlftQ3pqO9JOsIg=; i=zacchae.us; b=Oi67HKr8cOk9 2B9jkkp5b7k6c261zeYSv/dR343BvsSuE27pWLMsOz9FtRcqYxc426or0/ygphzcM3tUYzVY5Giix zGXEdOPLZMGypOf5mo99WA/uTO4KqJnSmdP8xKmeYZISwJ/HMn0jU/gRSGchTgIE8EoKrR8YG43+w oU+9IHA7W+RoFU44t89EZ8k0JpTxgrqXI9KQs62rFyRy/6gVpFQ3SOt70WCrDeSdKySgdWL5CMQBE fqs+LdvEVhP29xbbWwWr/EIITSRMIsrjTh5rbO1XmIA+SVCTvmzhy7gU0aaMunAdg+71MKsxcoA7m socV4s7T+Oz+7AUFm5ebTg==; Received: from localhost.home ([127.0.0.1]:42370 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1tgbYt-000000005i8-1pcF; Fri, 07 Feb 2025 22:31:19 -0500 From: Zacchaeus Scheffer Date: Fri, 07 Feb 2025 22:31:19 -0500 Message-ID: <87zfixf6yg.fsf@zacchae.us> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From c63deb42caf24f34a22b1a56c37146d1cfdff4ae Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH v6] services: syncthing: Add support fo [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in sa-accredit.habeas.com] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in bl.score.senderscore.com] 0.1 URIBL_SBL_A Contains URL's A record listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 0.6 URIBL_SBL Contains an URL's NS IP listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS 0.0 T_FILL_THIS_FORM_SHORT Fill in a short form with personal information X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 1.0 (+) >From c63deb42caf24f34a22b1a56c37146d1cfdff4ae Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH v6] services: syncthing: Add support for config file generation. * gnu/services/syncthing.scm: (syncthing-config-file, syncthing-folder, syncthing-device, syncthing-folder-device): New records; (syncthing-service-type): Add special-files-service-type extension for the config file; (syncthing-files-service): Add service to create config file. * gnu/home/services/syncthing.scm: (home-syncthing-service-type): Extend home-files-services-type and re-exported more things from gnu/services/syncthing.scm. * doc/guix.texi: (syncthing-service-type): Document changes. Change-Id: I87eeba1ee1fdada8f29c2ee881fbc6bc4113dde9 --- I noticed a bug in the documentation; the syncthing-configuration home field does (and did) not do what it claimed. I went ahead and updated that documentation since I was already updating the Syncthing section. I translated camelCase to kebab-case. Hopefully this does not cause much confusion for the end user. I tried to improve my grammar from my previous patch, but I don't think I was successful; feel free to make any of those corrections/additions as you see fit. I also remembered to warn the user about any sensitive information they may be putting in /gnu/store. I wrapped all the record instances I could find in @code{...}, but I may have missed some. I also updated the commit comment as per lfam's request. doc/guix.texi | 308 +++++++++++++++++- gnu/home/services/syncthing.scm | 17 +- gnu/services/syncthing.scm | 533 ++++++++++++++++++++++++++++++-- 3 files changed, 826 insertions(+), 32 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index b1b6d98e74..d8f35c5b16 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -136,6 +136,7 @@ Copyright @copyright{} 2024 Troy Figiel@* Copyright @copyright{} 2024 Sharlatan Hellseher@* Copyright @copyright{} 2024 45mg@* Copyright @copyright{} 2025 S=C3=B6ren Tempel@* +Copyright @copyright{} 2025 Zacchaeus@* =20 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -22666,12 +22667,315 @@ The group as which the Syncthing service is to b= e run. This assumes that the specified group exists. =20 @item @code{home} (default: @var{#f}) -Common configuration and data directory. The default configuration -directory is @file{$HOME} of the specified Syncthing @code{user}. +Sets the @code{HOME} variable for the syncthing daemon. The default is +@file{$HOME} of the specified Syncthing @code{user}. + +@item @code{config-file} (default: @var{#f}) +Either a file-like object that resolves to a Syncthing configuration xml +file, or a @code{syncthing-config-file} record (see below). If set to +@code{#f}, Guix will not try to generate a config file, and Syncthing +will generate a default one which will not be touched on reconfigure. +Specifying this in a system service moves Syncthing's common +configuration and data directory (@code{--home} in +@uref{https://docs.syncthing.net/users/syncthing.html}) to +@file{/var/lib/syncthnig-}. + +@end table +@end deftp + +In the below, only details specific to Guix, or related to how your +device will connect to unrelated devices (relays, nameservers), are +presented. Otherwise, you should consult +@uref{https://docs.syncthing.net/users/config.html, Syncthing config +documentation}; camelCase there is converted to kebab-case here. If +you would like to migrate to a Guix-powered Syncthing configuration, the +generated config adds newlines/whitespace to the produced config such +that your old config can be @code{diff}'ed with the new one. You can +still modify Syncthing from the GUI or through @code{introducer} and +@code{autoAcceptFolders} mechanisms, but such changes will be reset on +reconfigure. + +@deftp {Data Type} syncthing-config-file +Data type representing the configuration file read by the Syncthing +daemon. + +@table @asis +@item @code{folders} (default: @var{(list (syncthing-folder (id "default")= (label "Default Folder") (path "~/Sync")))} +The default here is the same as Syncthing's default. The value should +be a list of @code{syncthing-folder}s. + +@item @code{devices} (default: @var{'()} +This should be a list of @code{syncthing-device}s. Guix will +automatically add any devices specified in any `folders' to this list. +There are instances when you want to connect to a device despite not +(initially) sharing any folders (such as a device with +autoAcceptFolders). In such instances, you should specify those devices +here. If multiple versions of the same device (as determined by +comparing device id) are discovered, the one in this list is +prioritized. Otherwise, the first instance in the first folder is used. + +@item @code{gui-enabled} (default: @var{"true"}) +By default, any user on the computer can access the GUI and make changes +to Syncthing. If you leave this enabled, you should probably set +gui-user and gui-password (see below). + +@item @code{gui-tls} (default: @var{"false"}) +@item @code{gui-debugging} (default: @var{"false"}) +@item @code{gui-send-basic-auth-prompt} (default: @var{"false"}) +@item @code{gui-address} (default: @var{"127.0.0.1:8384"}) +@item @code{gui-user} (default: @var{#f}) +@item @code{gui-password} (default: @var{#f}) +A bcrypt hash of the GUI password. Remember that this will be globally +exposed in @file{/gnu/store}. +@item @code{gui-apikey} (default: @var{#f}) +You must specify this to use the Syncthing REST interface. Also exposed +in @file{/gnu/store}. + +@item @code{gui-theme} (default: @var{"default"}) +@item @code{ldap-enabled} (default: @var{#f}) +@item @code{ldap-address} (default: @var{""}) +@item @code{ldap-bind-dn} (default: @var{""}) +@item @code{ldap-transport} (default: @var{""}) +@item @code{ldap-insecure-skip-verify} (default: @var{""}) +@item @code{ldap-search-base-dn} (default: @var{""}) +@item @code{ldap-search-filter} (default: @var{""}) +@item @code{listen-address} (default: @var{"default"}) +@item @code{global-announce-server} (default: @var{"default"}) +@item @code{global-announce-enabled} (default: @var{"true"}) +Global discovery servers can be used to help connect devices at unknown +IP addresses by storing the last known IP address. + +@item @code{local-announce-enabled} (default: @var{"true"}) +This makes devices find each other very easily on the same LAN. Often, +this will allow you to just plug an Ethernet between two devices, or +connect one device to the other's hotspot and start syncing. + +@item @code{local-announce-port} (default: @var{"21027"}) +@item @code{local-announce-mcaddr} (default: @var{"[ff12::8384]:21027"}) +@item @code{max-send-kbps} (default: @var{"0"}) +@item @code{max-recv-kbps} (default: @var{"0"}) +@item @code{reconnection-interval-s} (default: @var{"60"}) +@item @code{relays-enabled} (default: @var{"true"}) +This option allows your Syncthing instance to coordinate with a global +network of relays to enable syncing between devices when all other +methods fail. + +@item @code{relay-reconnect-interval-m} (default: @var{"10"}) +@item @code{start-browser} (default: @var{"true"}) +@item @code{nat-enabled} (default: @var{"true"}) +@item @code{nat-lease-minutes} (default: @var{"60"}) +@item @code{nat-renewal-minutes} (default: @var{"30"}) +@item @code{nat-timeout-seconds} (default: @var{"10"}) +@item @code{ur-accepted} (default: @var{"0"}) +ur* options control usage reporting. Set to -1 to disable, or positive +to enable. The default (0) has reporting disabled, but you will be +asked to decide in the GUI. + +@item @code{ur-seen} (default: @var{"0"}) +@item @code{ur-unique-id} (default: @var{""}) +@item @code{ur-url} (default: @var{"https://data.syncthing.net/newdata"}) +@item @code{ur-post-insecurely} (default: @var{"false"}) +@item @code{ur-initial-delay-s} (default: @var{"1800"}) +@item @code{auto-upgrade-interval-h} (default: @var{"12"}) +@item @code{upgrade-to-pre-releases} (default: @var{"false"}) +@item @code{keep-temporaries-h} (default: @var{"24"}) +@item @code{cache-ignored-files} (default: @var{"false"}) +@item @code{progress-update-interval-s} (default: @var{"5"}) +@item @code{limit-bandwidth-in-lan} (default: @var{"false"}) +@item @code{min-home-disk-free-unit} (default: @var{"%"}) +@item @code{min-home-disk-free} (default: @var{"1"}) +@item @code{releases-url} (default: @var{"https://upgrades.syncthing.net/m= eta.json"}) +@item @code{overwrite-remote-device-names-on-connect} (default: @var{"fals= e"}) +@item @code{temp-index-min-blocks} (default: @var{"10"}) +@item @code{unacked-notification-id} (default: @var{"authenticationUserAnd= Password"}) +@item @code{traffic-class} (default: @var{"0"}) +@item @code{set-low-priority} (default: @var{"true"}) +@item @code{max-folder-concurrency} (default: @var{"0"}) +@item @code{crash-reporting-url} (default: @var{"https://crash.syncthing.n= et/newcrash"}) +@item @code{crash-reporting-enabled} (default: @var{"true"}) +@item @code{stun-keepalive-start-s} (default: @var{"180"}) +@item @code{stun-keepalive-min-s} (default: @var{"20"}) +@item @code{stun-server} (default: @var{"default"}) +@item @code{database-tuning} (default: @var{"auto"}) +@item @code{max-concurrent-incoming-request-kib} (default: @var{"0"}) +@item @code{announce-lan-addresses} (default: @var{"true"}) +@item @code{send-full-index-on-upgrade} (default: @var{"false"}) +@item @code{connection-limit-enough} (default: @var{"0"}) +@item @code{connection-limit-max} (default: @var{"0"}) +@item @code{insecure-allow-old-tls-versions} (default: @var{"false"}) +@item @code{connection-priority-tcp-lan} (default: @var{"10"}) +@item @code{connection-priority-quic-lan} (default: @var{"20"}) +@item @code{connection-priority-tcp-wan} (default: @var{"30"}) +@item @code{connection-priority-quic-wan} (default: @var{"40"}) +@item @code{connection-priority-relay} (default: @var{"50"}) +@item @code{connection-priority-upgrade-threshold} (default: @var{"0"}) +@item @code{default-folder} (default: @var{(syncthing-folder (label ""))}) +@item @code{default-device} (default: @var{(syncthing-device (id ""))}) +@item @code{default-ignores} (default: @var{"")}) +The default-* above do not affect folders and devices added by the Guix +interface. They will, however, affect folders and devices that are +added through the GUI, by an @code{introducer}, or a device with +@code{auto-accept-folders}. +@end table +@end deftp + +@deftp {Data Type} syncthing-folder +Data type representing a folder to be synced. + +@table @asis +@item @code{id} (default: @var{#f}) +This id cannot match the id of any other folder on this device. If left +unspecified, it will default to the label (see below). + +@item @code{label} +Human readable label for the folder. + +@item @code{path} +The path at which to store this folder. + +@item @code{type} (default: @var{"sendreceive"}) +@item @code{rescan-interval-s} (default: @var{"3600"}) +@item @code{fs-watcher-enabled} (default: @var{"true"}) +@item @code{fs-watcher-delay-s} (default: @var{"10"}) +@item @code{ignore-perms} (default: @var{"false"}) +@item @code{auto-normalize} (default: @var{"true"}) +@item @code{devices} (default: @var{'()}) +This should be a list of other Syncthing devices. You do not need to +specify the current device. Each device can be listed as a a +@code{syncthing-device} record or a @code{syncthing-folder-device} +record if you want files to be encrypted on disk. See below. + +@item @code{filesystem-type} (default: @var{"basic"}) +@item @code{min-disk-free-unit} (default: @var{"%"}) +@item @code{min-disk-free} (default: @var{"1"}) +@item @code{versioning-type} (default: @var{#f}) +@item @code{versioning-fs-path} (default: @var{""}) +@item @code{versioning-fs-type} (default: @var{"basic"}) +@item @code{versioning-cleanup-interval-s} (default: @var{"3600"}) +@item @code{versioning-cleanout-days} (default: @var{#f}) +@item @code{versioning-keep} (default: @var{#f}) +@item @code{versioning-max-age} (default: @var{#f}) +@item @code{versioning-command} (default: @var{#f}) +@item @code{copiers} (default: @var{"0"}) +@item @code{puller-max-pending-kib} (default: @var{"0"}) +@item @code{hashers} (default: @var{"0"}) +@item @code{order} (default: @var{"random"}) +@item @code{ignore-delete} (default: @var{"false"}) +@item @code{scan-progress-interval-s} (default: @var{"0"}) +@item @code{puller-pause-s} (default: @var{"0"}) +@item @code{max-conflicts} (default: @var{"10"}) +@item @code{disable-sparse-files} (default: @var{"false"}) +@item @code{disable-temp-indexes} (default: @var{"false"}) +@item @code{paused} (default: @var{"false"}) +@item @code{weak-hash-threshold-pct} (default: @var{"25"}) +@item @code{marker-name} (default: @var{".stfolder"}) +@item @code{copy-ownership-from-parent} (default: @var{"false"}) +@item @code{mod-time-window-s} (default: @var{"0"}) +@item @code{max-concurrent-writes} (default: @var{"2"}) +@item @code{disable-fsync} (default: @var{"false"}) +@item @code{block-pull-order} (default: @var{"standard"}) +@item @code{copy-range-method} (default: @var{"standard"}) +@item @code{case-sensitive-fs} (default: @var{"false"}) +@item @code{junctions-as-dirs} (default: @var{"false"}) +@item @code{sync-ownership} (default: @var{"false"}) +@item @code{send-ownership} (default: @var{"false"}) +@item @code{sync-xattrs} (default: @var{"false"}) +@item @code{send-xattrs} (default: @var{"false"}) +@item @code{xattr-filter-max-single-entry-size} (default: @var{"1024"}) +@item @code{xattr-filter-max-total-size} (default: @var{"4096")}) +@end table +@end deftp + +@deftp {Data Type} syncthing-device +Data type representing a device to sync with. + +@table @asis +@item @code{id} +A long hash tied to the keys generated by Syncthing on the first launch. +You can obtain this from the Syncthing GUI or by inspecting an existing +Syncthing configuration file. + +@item @code{name} (default: @var{""}) +Human readable device name for viewing in the GUI or in scheme. + +@item @code{compression} (default: @var{"metadata"}) +@item @code{introducer} (default: @var{"false"}) +@item @code{skip-introduction-removals} (default: @var{"false"}) +@item @code{introduced-by} (default: @var{""}) +@item @code{addresses} (default: @var{'("dynamic")}) +List of addresses at which to search for this device. The special value +``dynamic'' will have syncthing use several means to find the device. + +@item @code{paused} (default: @var{"false"}) +@item @code{auto-accept-folders} (default: @var{"false"}) +@item @code{max-send-kbps} (default: @var{"0"}) +@item @code{max-recv-kbps} (default: @var{"0"}) +@item @code{max-request-kib} (default: @var{"0"}) +@item @code{untrusted} (default: @var{"false"}) +@item @code{remote-gui-port} (default: @var{"0"}) +@item @code{num-connections} (default: @var{"0")}) + +@end table +@end deftp + +@deftp {Data Type} syncthing-folder-device +There are two pieces of configuration specific to the relationship +between a specific folder and a specific device. First, syncthing needs +to know if the remote device should be able to see the files given to +it. Second, syncthing needs to know from where that device originates. +See +@href{https://docs.syncthing.net/users/config.html#config-option-folder.de= vice, +the Syncthing Documentation on this}. If you leave these default, then +you can just specify @code{syncthing-device}s instead of +@code{syncthing-folder-device}s in a @code{syncthing-folder}'s +@code{devices} field. + +@table @asis +@item @code{device} +device should be a @code{syncthing-device} for which this configuration +applies. + +@item @code{introduced-by} (default: @var{""}) +@item @code{encryption-password} (default: @var{""}) +Beware: specifying this field will include this password as plain text +(not encrypted) and globally visible in @file{/gnu/store/}. If +encryption-password is non-empty, then it will be used as a password to +encrypt file chunks as they are synced to that device. For more info on +syncing to devices you don't totally trust, see +@uref{https://docs.syncthing.net/users/untrusted.html, Syncthing +Documentation on Untrusted Devices}. Note that file transfers are +always end-to-end encrypted, regardless of this setting. =20 @end table @end deftp =20 +Here is a more complex example configuration for illustrative purposes: +@lisp +(service syncthing-service-type + (let ((laptop (syncthing-device (id "VHOD2D6-...-7XRMDEN"))) + (desktop (syncthing-device (id "64SAZ37-...-FZJ5GUA") + (addresses '("tcp://example.com"= )))) + (bob-desktop (syncthing-device (id "KYIMEGO-...-FT77EAO")))) + (syncthing-configuration + (user "alice") + (config-file + (syncthing-config-file + (folders (list (syncthing-folder + (label "some-files") + (path "~/data") + (devices (list desktop laptop))) + (syncthing-folder + (label "critical-files") + (path "~/secrets") + (devices + (list desktop + laptop + (syncthing-folder-device + (device bob-desktop) + (encryption-password "mypassword"))= )))))))))) +@end lisp + + Furthermore, @code{(gnu services ssh)} provides the following services. @cindex SSH @cindex SSH server diff --git a/gnu/home/services/syncthing.scm b/gnu/home/services/syncthing.= scm index 8d66a167ce..dd6c752ee4 100644 --- a/gnu/home/services/syncthing.scm +++ b/gnu/home/services/syncthing.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2023 Ludovic Court=C3=A8s +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -24,9 +25,23 @@ (define-module (gnu home services syncthing) #:use-module (gnu home services shepherd) #:export (home-syncthing-service-type) #:re-export (syncthing-configuration - syncthing-configuration?)) + syncthing-configuration? + syncthing-config-file + syncthing-config-file? + syncthing-device + syncthing-device? + syncthing-folder + syncthing-folder? + syncthing-folder-device + syncthing-folder-device?)) =20 (define home-syncthing-service-type (service-type (inherit (system->home-service-type syncthing-service-type)) + ;; system->home-service-type does not convert special-files-service-typ= e to + ;; home-files-service-type, so redefine extensios + (extensions (list (service-extension home-files-service-type + syncthing-files-service) + (service-extension home-shepherd-service-type + syncthing-shepherd-service))) (default-value (for-home (syncthing-configuration))))) diff --git a/gnu/services/syncthing.scm b/gnu/services/syncthing.scm index a7a9c6aadd..bdc00ec51f 100644 --- a/gnu/services/syncthing.scm +++ b/gnu/services/syncthing.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2021 Oleg Pykhalov ;;; Copyright =C2=A9 2023 Justin Veilleux +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -25,9 +26,20 @@ (define-module (gnu services syncthing) #:use-module (guix records) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (sxml simple) #:export (syncthing-configuration syncthing-configuration? - syncthing-service-type)) + syncthing-device + syncthing-device? + syncthing-config-file + syncthing-config-file? + syncthing-folder-device + syncthing-folder-device? + syncthing-folder + syncthing-folder? + syncthing-service-type + syncthing-shepherd-service + syncthing-files-service)) =20 ;;; Commentary: ;;; @@ -35,6 +47,438 @@ (define-module (gnu services syncthing) ;;; ;;; Code: =20 +(define-record-type* + syncthing-device make-syncthing-device + syncthing-device? + (id syncthing-device-id) + (name syncthing-device-name (default "")) + (compression syncthing-device-compression (default "metadata")) + (introducer syncthing-device-introducer (default "false")) + (skip-introduction-removals syncthing-device-skip-introduction-removals = (default "false")) + (introduced-by syncthing-device-introduced-by (default "")) + (addresses syncthing-device-addresses (default '("dynamic"))) + (paused syncthing-device-paused (default "false")) + (auto-accept-folders syncthing-device-auto-accept-folders (default "fals= e")) + (max-send-kbps syncthing-device-max-send-kbps (default "0")) + (max-recv-kbps syncthing-device-max-recv-kbps (default "0")) + (max-request-kib syncthing-device-max-request-kib (default "0")) + (untrusted syncthing-device-untrusted (default "false")) + (remote-gui-port syncthing-device-remote-gui-port (default "0")) + (num-connections syncthing-device-num-connections (default "0"))) + +(define syncthing-device->sxml + (match-record-lambda + (id name compression introducer skip-introduction-removals introduce= d-by addresses paused auto-accept-folders max-send-kbps max-recv-kbps max-r= equest-kib untrusted remote-gui-port num-connections) + `(device (@ (id ,id) + (name ,name) + (compression ,compression) + (introducer ,introducer) + (skipIntroductionRemovals ,skip-introduction-removals) + (introducedBy ,introduced-by)) + ,@(map (lambda (address) `(address ,address)) addresses) + (paused ,paused) + (autoAcceptFolders ,auto-accept-folders) + (maxSendKbps ,max-send-kbps) + (maxRecvKbps ,max-recv-kbps) + (maxRequestKiB ,max-request-kib) + (untrusted ,untrusted) + (remoteGUIPort ,remote-gui-port) + (numConnections ,num-connections)))) + +(define-record-type* + syncthing-folder-device make-syncthing-folder-device + syncthing-folder-device? + (device syncthing-folder-device-device) + (introduced-by syncthing-folder-device-introduced-by (default (syncthing= -device (id "")))) + (encryption-password syncthing-folder-device-encryption-password (defaul= t ""))) + +(define syncthing-folder-device->sxml + (match-record-lambda + (device introduced-by encryption-password) + `(device (@ (id ,(syncthing-device-id device)) + (introducedBy ,(syncthing-device-id introduced-by))) + (encryptionPassword ,encryption-password)))) + +(define-record-type* + syncthing-folder make-syncthing-folder + syncthing-folder? + (id syncthing-folder-id (default #f)) + (label syncthing-folder-label) + (path syncthing-folder-path) + (type syncthing-folder-type (default "sendreceive")) + (rescan-interval-s syncthing-folder-rescan-interval-s (default "3600")) + (fs-watcher-enabled syncthing-folder-fs-watcher-enabled (default "true")) + (fs-watcher-delay-s syncthing-folder-fs-watcher-delay-s (default "10")) + (fs-watcher-timeout-s syncthing-folder-fs-watcher-timeout-s (default "0"= )) + (ignore-perms syncthing-folder-ignore-perms (default "false")) + (auto-normalize syncthing-folder-auto-normalize (default "true")) + (devices syncthing-folder-devices (default '()) + (sanitize (lambda (folder-device-list) + (map (lambda (device) + (if (syncthing-folder-device? device) + device + (syncthing-folder-device (device device)= ))) + folder-device-list)))) + (filesystem-type syncthing-folder-filesystem-type (default "basic")) + (min-disk-free-unit syncthing-folder-min-disk-free-unit (default "%")) + (min-disk-free syncthing-folder-min-disk-free (default "1")) + (versioning-type syncthing-folder-versioning-type (default #f)) + (versioning-fs-path syncthing-folder-versioning-fs-path (default "")) + (versioning-fs-type syncthing-folder-versioning-fs-type (default "basic"= )) + (versioning-cleanup-interval-s syncthing-folder-versioning-cleanup-inter= val-s (default "3600")) + (versioning-cleanout-days syncthing-folder-versioning-cleanout-days (def= ault #f)) + (versioning-keep syncthing-folder-versioning-keep (default #f)) + (versioning-max-age syncthing-folder-versioning-max-age (default #f)) + (versioning-command syncthing-folder-versioning-command (default #f)) + (copiers syncthing-folder-copiers (default "0")) + (puller-max-pending-kib syncthing-folder-puller-max-pending-kib (default= "0")) + (hashers syncthing-folder-hashers (default "0")) + (order syncthing-folder-order (default "random")) + (ignore-delete syncthing-folder-ignore-delete (default "false")) + (scan-progress-interval-s syncthing-folder-scan-progress-interval-s (def= ault "0")) + (puller-pause-s syncthing-folder-puller-pause-s (default "0")) + (max-conflicts syncthing-folder-max-conflicts (default "10")) + (disable-sparse-files syncthing-folder-disable-sparse-files (default "fa= lse")) + (disable-temp-indexes syncthing-folder-disable-temp-indexes (default "fa= lse")) + (paused syncthing-folder-paused (default "false")) + (weak-hash-threshold-pct syncthing-folder-weak-hash-threshold-pct (defau= lt "25")) + (marker-name syncthing-folder-marker-name (default ".stfolder")) + (copy-ownership-from-parent syncthing-folder-copy-ownership-from-parent = (default "false")) + (mod-time-window-s syncthing-folder-mod-time-window-s (default "0")) + (max-concurrent-writes syncthing-folder-max-concurrent-writes (default "= 2")) + (disable-fsync syncthing-folder-disable-fsync (default "false")) + (block-pull-order syncthing-folder-block-pull-order (default "standard")) + (copy-range-method syncthing-folder-copy-range-method (default "standard= ")) + (case-sensitive-fs syncthing-folder-case-sensitive-fs (default "false")) + (junctions-as-dirs syncthing-folder-junctions-as-dirs (default "false")) + (sync-ownership syncthing-folder-sync-ownership (default "false")) + (send-ownership syncthing-folder-send-ownership (default "false")) + (sync-xattrs syncthing-folder-sync-xattrs (default "false")) + (send-xattrs syncthing-folder-send-xattrs (default "false")) + (xattr-filter-max-single-entry-size syncthing-folder-xattr-filter-max-si= ngle-entry-size (default "1024")) + (xattr-filter-max-total-size syncthing-folder-xattr-filter-max-total-siz= e (default "4096"))) + +;; Some parameters, when empty, are fully omitted from the config file. I= t is +;; unknown if this causes a functional difference, but stick to the normal +;; program's behavior to be safe. +(define (maybe-param symbol value) + (if value `((param (@ (key ,(symbol->string symbol)) (val ,value)) "")) = '())) + +(define syncthing-folder->sxml + (match-record-lambda + (id + label path type rescan-interval-s fs-watcher-enabled fs-watcher-del= ay-s + fs-watcher-timeout-s ignore-perms auto-normalize devices filesystem= -type + min-disk-free-unit min-disk-free versioning-type versioning-fs-path + versioning-fs-type versioning-cleanup-interval-s versioning-cleanou= t-days + versioning-keep versioning-max-age versioning-command copiers + puller-max-pending-kib hashers order ignore-delete scan-progress-in= terval-s + puller-pause-s max-conflicts disable-sparse-files disable-temp-inde= xes paused + weak-hash-threshold-pct marker-name copy-ownership-from-parent mod-= time-window-s + max-concurrent-writes disable-fsync block-pull-order copy-range-met= hod + case-sensitive-fs junctions-as-dirs sync-ownership send-ownership s= ync-xattrs + send-xattrs xattr-filter-max-single-entry-size xattr-filter-max-tot= al-size) + `(folder (@ (id ,(if id id label)) + (label ,label) + (path ,path) + (type ,type) + (rescanIntervalS ,rescan-interval-s) + (fsWatcherEnabled ,fs-watcher-enabled) + (fsWatcherDelayS ,fs-watcher-delay-s) + (fsWatcherTimeoutS ,fs-watcher-timeout-s) + (ignorePerms ,ignore-perms) + (autoNormalize ,auto-normalize)) + (filesystemType ,filesystem-type) + ,@(map syncthing-folder-device->sxml + devices) + (minDiskFree (@ (unit ,min-disk-free-unit)) + ,min-disk-free) + (versioning ,@(if versioning-type + `((@ (type ,versioning-type))) + '()) + ,@(maybe-param 'cleanoutDays versioning-cleanout-= days) + ,@(maybe-param 'keep versioning-keep) + ,@(maybe-param 'maxAge versioning-max-age) + ,@(maybe-param 'command versioning-command) + (cleanupIntervalS ,versioning-cleanup-interval-s) + (fsPath ,versioning-fs-path) + (fsType ,versioning-fs-type)) + (copiers ,copiers) + (pullerMaxPendingKiB ,puller-max-pending-kib) + (hashers ,hashers) + (order ,order) + (ignoreDelete ,ignore-delete) + (scanProgressIntervalS ,scan-progress-interval-s) + (pullerPauseS ,puller-pause-s) + (maxConflicts ,max-conflicts) + (disableSparseFiles ,disable-sparse-files) + (disableTempIndexes ,disable-temp-indexes) + (paused ,paused) + (weakHashThresholdPct ,weak-hash-threshold-pct) + (markerName ,marker-name) + (copyOwnershipFromParent ,copy-ownership-from-parent) + (modTimeWindowS ,mod-time-window-s) + (maxConcurrentWrites ,max-concurrent-writes) + (disableFsync ,disable-fsync) + (blockPullOrder ,block-pull-order) + (copyRangeMethod ,copy-range-method) + (caseSensitiveFS ,case-sensitive-fs) + (junctionsAsDirs ,junctions-as-dirs) + (syncOwnership ,sync-ownership) + (sendOwnership ,send-ownership) + (syncXattrs ,sync-xattrs) + (sendXattrs ,send-xattrs) + (xattrFilter (maxSingleEntrySize ,xattr-filter-max-single-ent= ry-size) + (maxTotalSize ,xattr-filter-max-total-size))))) + +(define-record-type* + syncthing-config-file make-syncthing-config-file + syncthing-config-file? + (folders syncthing-config-folders + ; this matches syncthing's default + (default (list (syncthing-folder (id "default") + (label "Default Folder") + (path "~/Sync"))))) + (devices syncthing-config-devices + (default '())) + (gui-enabled syncthing-config-gui-enabled (default "true")) + (gui-tls syncthing-config-gui-tls (default "false")) + (gui-debugging syncthing-config-gui-debugging (default "false")) + (gui-send-basic-auth-prompt syncthing-config-gui-send-basic-auth-prompt = (default "false")) + (gui-address syncthing-config-gui-address (default "127.0.0.1:8384")) + (gui-user syncthing-config-gui-user (default #f)) + (gui-password syncthing-config-gui-password (default #f)) + (gui-apikey syncthing-config-gui-apikey (default #f)) + (gui-theme syncthing-config-gui-theme (default "default")) + (ldap-enabled syncthing-config-ldap-enabled (default #f)) + (ldap-address syncthing-config-ldap-address (default "")) + (ldap-bind-dn syncthing-config-ldap-bind-dn (default "")) + (ldap-transport syncthing-config-ldap-transport (default "")) + (ldap-insecure-skip-verify syncthing-config-ldap-insecure-skip-verify (d= efault "")) + (ldap-search-base-dn syncthing-config-ldap-search-base-dn (default "")) + (ldap-search-filter syncthing-config-ldap-search-filter (default "")) + (listen-address syncthing-config-listen-address (default "default")) + (global-announce-server syncthing-config-global-announce-server (default= "default")) + (global-announce-enabled syncthing-config-global-announce-enabled (defau= lt "true")) + (local-announce-enabled syncthing-config-local-announce-enabled (default= "true")) + (local-announce-port syncthing-config-local-announce-port (default "2102= 7")) + (local-announce-mcaddr syncthing-config-local-announce-mcaddr (default "= [ff12::8384]:21027")) + (max-send-kbps syncthing-config-max-send-kbps (default "0")) + (max-recv-kbps syncthing-config-max-recv-kbps (default "0")) + (reconnection-interval-s syncthing-config-reconnection-interval-s (defau= lt "60")) + (relays-enabled syncthing-config-relays-enabled (default "true")) + (relay-reconnect-interval-m syncthing-config-relay-reconnect-interval-m = (default "10")) + (start-browser syncthing-config-start-browser (default "true")) + (nat-enabled syncthing-config-nat-enabled (default "true")) + (nat-lease-minutes syncthing-config-nat-lease-minutes (default "60")) + (nat-renewal-minutes syncthing-config-nat-renewal-minutes (default "30")) + (nat-timeout-seconds syncthing-config-nat-timeout-seconds (default "10")) + (ur-accepted syncthing-config-ur-accepted (default "0")) + (ur-seen syncthing-config-ur-seen (default "0")) + (ur-unique-id syncthing-config-ur-unique-id (default "")) + (ur-url syncthing-config-ur-url (default "https://data.syncthing.net/new= data")) + (ur-post-insecurely syncthing-config-ur-post-insecurely (default "false"= )) + (ur-initial-delay-s syncthing-config-ur-initial-delay-s (default "1800")) + (auto-upgrade-interval-h syncthing-config-auto-upgrade-interval-h (defau= lt "12")) + (upgrade-to-pre-releases syncthing-config-upgrade-to-pre-releases (defau= lt "false")) + (keep-temporaries-h syncthing-config-keep-temporaries-h (default "24")) + (cache-ignored-files syncthing-config-cache-ignored-files (default "fals= e")) + (progress-update-interval-s syncthing-config-progress-update-interval-s = (default "5")) + (limit-bandwidth-in-lan syncthing-config-limit-bandwidth-in-lan (default= "false")) + (min-home-disk-free-unit syncthing-config-min-home-disk-free-unit (defau= lt "%")) + (min-home-disk-free syncthing-config-min-home-disk-free (default "1")) + (releases-url syncthing-config-releases-url (default "https://upgrades.s= yncthing.net/meta.json")) + (overwrite-remote-device-names-on-connect syncthing-config-overwrite-rem= ote-device-names-on-connect (default "false")) + (temp-index-min-blocks syncthing-config-temp-index-min-blocks (default "= 10")) + (unacked-notification-id syncthing-config-unacked-notification-id (defau= lt "authenticationUserAndPassword")) + (traffic-class syncthing-config-traffic-class (default "0")) + (set-low-priority syncthing-config-set-low-priority (default "true")) + (max-folder-concurrency syncthing-config-max-folder-concurrency (default= "0")) + (crash-reporting-url syncthing-config-crash-reporting-url (default "http= s://crash.syncthing.net/newcrash")) + (crash-reporting-enabled syncthing-config-crash-reporting-enabled (defau= lt "true")) + (stun-keepalive-start-s syncthing-config-stun-keepalive-start-s (default= "180")) + (stun-keepalive-min-s syncthing-config-stun-keepalive-min-s (default "20= ")) + (stun-server syncthing-config-stun-server (default "default")) + (database-tuning syncthing-config-database-tuning (default "auto")) + (max-concurrent-incoming-request-kib syncthing-config-max-concurrent-inc= oming-request-kib (default "0")) + (announce-lan-addresses syncthing-config-announce-lan-addresses (default= "true")) + (send-full-index-on-upgrade syncthing-config-send-full-index-on-upgrade = (default "false")) + (connection-limit-enough syncthing-config-connection-limit-enough (defau= lt "0")) + (connection-limit-max syncthing-config-connection-limit-max (default "0"= )) + (insecure-allow-old-tlsVersions syncthing-config-insecure-allow-old-tlsV= ersions (default "false")) + (connection-priority-tcp-lan syncthing-config-connection-priority-tcp-la= n (default "10")) + (connection-priority-quic-lan syncthing-config-connection-priority-quic-= lan (default "20")) + (connection-priority-tcp-wan syncthing-config-connection-priority-tcp-wa= n (default "30")) + (connection-priority-quic-wan syncthing-config-connection-priority-quic-= wan (default "40")) + (connection-priority-relay syncthing-config-connection-priority-relay (d= efault "50")) + (connection-priority-upgrade-threshold syncthing-config-connection-prior= ity-upgrade-threshold (default "0")) + (default-folder syncthing-config-default-folder + (default (syncthing-folder (label "") (path "~")))) + (default-device syncthing-config-default-device + (default (syncthing-device (id "")))) + (default-ignores syncthing-config-default-ignores (default ""))) + +(define syncthing-config-file->sxml + (match-record-lambda + (folders + devices gui-enabled gui-tls gui-debugging gui-send-basic-auth-prompt + gui-address gui-user gui-password gui-apikey gui-theme ldap-enabled + ldap-address ldap-bind-dn ldap-transport ldap-insecure-skip-verify + ldap-search-base-dn ldap-search-filter listen-address global-announ= ce-server + global-announce-enabled local-announce-enabled local-announce-port + local-announce-mcaddr max-send-kbps max-recv-kbps reconnection-inte= rval-s + relays-enabled relay-reconnect-interval-m start-browser nat-enabled + nat-lease-minutes nat-renewal-minutes nat-timeout-seconds ur-accept= ed + ur-seen ur-unique-id ur-url ur-post-insecurely ur-initial-delay-s + auto-upgrade-interval-h upgrade-to-pre-releases keep-temporaries-h + cache-ignored-files progress-update-interval-s limit-bandwidth-in-l= an + min-home-disk-free-unit min-home-disk-free releases-url + overwrite-remote-device-names-on-connect temp-index-min-blocks + unacked-notification-id traffic-class set-low-priority max-folder-c= oncurrency + crash-reporting-url crash-reporting-enabled stun-keepalive-start-s + stun-keepalive-min-s stun-server database-tuning + max-concurrent-incoming-request-kib announce-lan-addresses + send-full-index-on-upgrade connection-limit-enough connection-limit= -max + insecure-allow-old-tlsVersions connection-priority-tcp-lan + connection-priority-quic-lan connection-priority-tcp-wan + connection-priority-quic-wan connection-priority-relay + connection-priority-upgrade-threshold default-folder default-device + default-ignores) + `(configuration (@ (version "37")) + ,@(map syncthing-folder->sxml + folders) + ;; collect any devices in any folders, as well as any + ;; devices explicitly added. + ,@(map syncthing-device->sxml + (delete-duplicates + (append devices + (apply append + (map (lambda (folder) + (map syncthing-folder-de= vice-device + (syncthing-folder-d= evices folder))) + folders))) + ;; devices are the same if their id's are equal + (lambda (device1 device2) + (string=3D (syncthing-device-id device1) + (syncthing-device-id device2))))) + (gui (@ (enabled ,gui-enabled) + (tls ,gui-tls) + (debugging ,gui-debugging) + (sendBasicAuthPrompt ,gui-send-basic-auth-prom= pt)) + (address ,gui-address) + ,@(if gui-user `((user ,gui-user)) '()) + ,@(if gui-password `((password ,gui-password)) '(= )) + ,@(if gui-apikey `((apikey ,gui-apikey)) '()) + (theme ,gui-theme)) + (ldap ,(if ldap-enabled + `((address ,ldap-address) + (bindDN ,ldap-bind-dn) + ,@(if ldap-transport + `((transport ,ldap-transport)) + '()) + ,@(if ldap-insecure-skip-verify + `((insecureSkipVerify ,ldap-insecur= e-skip-verify)) + '()) + ,@(if ldap-search-base-dn + `((searchBaseDN ,ldap-search-base-d= n)) + '()) + ,@(if ldap-search-filter + `((searchFilter ,ldap-search-filter= )) + '())) + "")) + (options (listenAddress ,listen-address) + (globalAnnounceServer ,global-announce-server) + (globalAnnounceEnabled ,global-announce-enabl= ed) + (localAnnounceEnabled ,local-announce-enabled) + (localAnnouncePort ,local-announce-port) + (localAnnounceMCAddr ,local-announce-mcaddr) + (maxSendKbps ,max-send-kbps) + (maxRecvKbps ,max-recv-kbps) + (reconnectionIntervalS ,reconnection-interval= -s) + (relaysEnabled ,relays-enabled) + (relayReconnectIntervalM ,relay-reconnect-int= erval-m) + (startBrowser ,start-browser) + (natEnabled ,nat-enabled) + (natLeaseMinutes ,nat-lease-minutes) + (natRenewalMinutes ,nat-renewal-minutes) + (natTimeoutSeconds ,nat-timeout-seconds) + (urAccepted ,ur-accepted) + (urSeen ,ur-seen) + (urUniqueID ,ur-unique-id) + (urURL ,ur-url) + (urPostInsecurely ,ur-post-insecurely) + (urInitialDelayS ,ur-initial-delay-s) + (autoUpgradeIntervalH ,auto-upgrade-interval-= h) + (upgradeToPreReleases ,upgrade-to-pre-release= s) + (keepTemporariesH ,keep-temporaries-h) + (cacheIgnoredFiles ,cache-ignored-files) + (progressUpdateIntervalS ,progress-update-int= erval-s) + (limitBandwidthInLan ,limit-bandwidth-in-lan) + (minHomeDiskFree (@ (unit ,min-home-disk-free= -unit)) + ,min-home-disk-free) + (releasesURL ,releases-url) + (overwriteRemoteDeviceNamesOnConnect ,overwri= te-remote-device-names-on-connect) + (tempIndexMinBlocks ,temp-index-min-blocks) + (unackedNotificationID ,unacked-notification-= id) + (trafficClass ,traffic-class) + (setLowPriority ,set-low-priority) + (maxFolderConcurrency ,max-folder-concurrency) + (crashReportingURL ,crash-reporting-url) + (crashReportingEnabled ,crash-reporting-enabl= ed) + (stunKeepaliveStartS ,stun-keepalive-start-s) + (stunKeepaliveMinS ,stun-keepalive-min-s) + (stunServer ,stun-server) + (databaseTuning ,database-tuning) + (maxConcurrentIncomingRequestKiB ,max-concurr= ent-incoming-request-kib) + (announceLANAddresses ,announce-lan-addresses) + (sendFullIndexOnUpgrade ,send-full-index-on-u= pgrade) + (connectionLimitEnough ,connection-limit-enou= gh) + (connectionLimitMax ,connection-limit-max) + (insecureAllowOldTLSVersions ,insecure-allow-= old-tlsVersions) + (connectionPriorityTcpLan ,connection-priorit= y-tcp-lan) + (connectionPriorityQuicLan ,connection-priori= ty-quic-lan) + (connectionPriorityTcpWan ,connection-priorit= y-tcp-wan) + (connectionPriorityQuicWan ,connection-priori= ty-quic-wan) + (connectionPriorityRelay ,connection-priority= -relay) + (connectionPriorityUpgradeThreshold ,connecti= on-priority-upgrade-threshold)) + (defaults + ,(syncthing-folder->sxml default-folder) + ,(syncthing-device->sxml default-device) + (ignores ,default-ignores))))) + +;; It is useful to be able to view the xml output by Guix, and to be able = to +;; diff it with a user's previous config, especially when migrating one's +;; config to Guix. This function adds whitespace that matches the whitesp= ace +;; of config files managed by Syncthing for easy diffing. +(define (indent-sxml sxml indent-increment current-indent) + (match sxml + (((tag ('@ properties ...) (subtags ..1) ..1) sibling-tags ...) + `(,current-indent (,tag (@ ,@properties) "\n" + ,@(indent-sxml subtags indent-increment + (string-append indent-incremen= t current-indent)) + ,current-indent) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag ('@ properties ...) primitive ...) sibling-tags ...) + `(,current-indent (,tag (@ ,@properties) ,@primitive) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag (subtags ..1) ..1) sibling-tags ...) + `(,current-indent (,tag "\n" + ,@(indent-sxml subtags indent-increment + (string-append indent-incremen= t current-indent)) + ,current-indent) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag primitive ...) sibling-tags ...) + `(,current-indent (,tag ,@primitive) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (() '()))) + +(define (serialize-syncthing-config-file config) + (with-output-to-string + (lambda () + (sxml->xml (cons '*TOP* (indent-sxml (list (syncthing-config-file->s= xml config)) + " " + "")))))) + (define-record-type* syncthing-configuration make-syncthing-configuration syncthing-configuration? @@ -50,12 +494,14 @@ (define-record-type* (default "users")) (home syncthing-configuration-home ;string (default #f)) + (config-file syncthing-configuration-config-file + (default #f)) ; syncthing-config-file or = file-like (home-service? syncthing-configuration-home-service? (default for-home?) (innate))) =20 (define syncthing-shepherd-service (match-record-lambda - (syncthing arguments logflags user group home home-service?) + (syncthing arguments logflags user group home home-service? config-f= ile) (list (shepherd-service (provision (if home-service? @@ -64,39 +510,68 @@ (define syncthing-shepherd-service (string-append "syncthing-" user))))) (documentation "Run syncthing.") (requirement (if home-service? '() '(loopback user-processes))) - (start #~(make-forkexec-constructor - (append (list (string-append #$syncthing "/bin/syncthing") - "--no-browser" - "--no-restart" - (string-append "--logflags=3D" (number->stri= ng #$logflags))) - '#$arguments) - #:user #$(and (not home-service?) user) - #:group #$(and (not home-service?) group) - #:environment-variables - (append - (list - (string-append "HOME=3D" - (or #$home - (passwd:dir - (getpw (if (and #$home-service? - (not #$user)) - (getuid) - #$user))))) - "SSL_CERT_DIR=3D/etc/ssl/certs" - "SSL_CERT_FILE=3D/etc/ssl/certs/ca-certifica= tes.crt") - (filter (negate ;XXX: 'remove' is not in (gu= ile) - (lambda (str) - (or (string-prefix? "HOME=3D" str) - (string-prefix? "SSL_CERT_DIR=3D" s= tr) - (string-prefix? "SSL_CERT_FILE=3D" = str)))) - (environ))))) + (start #~(lambda _ + ;; if we are managing the config, and it's not a home + ;; service, then exepect the config file at + ;; /var/lib/syncthing-. This makes sure the owners= hip + ;; is correct + (unless (or #$(not config-file) #$home-service?) + (system* "chown" #$user (string-append "/var/lib/syncth= ing-" #$user)) + (system* "chmod" "700" (string-append "/var/lib/syncthi= ng-" #$user))) + (make-forkexec-constructor + (append (list (string-append #$syncthing "/bin/syncthing= ") + "--no-browser" + "--no-restart" + (string-append "--logflags=3D" (number->st= ring #$logflags))) + (if (or #$(not config-file) #$home-service?) '() + (list (string-append "--home=3D/var/lib/sync= thing-" #$user))) + '#$arguments) + #:user #$(and (not home-service?) user) + #:group #$(and (not home-service?) group) + #:environment-variables + (append + (list + (string-append "HOME=3D" + (or #$home + (passwd:dir + (getpw (if (and #$home-service? + (not #$user)) + (getuid) + #$user))))) + "SSL_CERT_DIR=3D/etc/ssl/certs" + "SSL_CERT_FILE=3D/etc/ssl/certs/ca-certificates.crt") + (filter (negate ;XXX: 'remove' is not in (guile) + (lambda (str) + (or (string-prefix? "HOME=3D" str) + (string-prefix? "SSL_CERT_DIR=3D" str) + (string-prefix? "SSL_CERT_FILE=3D" str))= )) + (environ)))))) (respawn? #f) (stop #~(make-kill-destructor)))))) =20 + +(define syncthing-files-service + (match-record-lambda (config-file user home ho= me-service?) + (if config-file + ;; when used as a system service, this service might be executed + ;; before a user's home even exists, causing it to be owned by roo= t, + ;; and the skeletons to never be applied to that user's home. In = such + ;; cases, put the config at /var/lib/syncthnig-/config.xml + `((,(if home-service? + ".config/syncthing/config.xml" + (string-append "/var/lib/syncthing-" user "/config.xml")) + ,(if (file-like? config-file) + config-file + (plain-file "syncthin-config.xml" (serialize-syncthing-con= fig-file + config-file))))) + '()))) + (define syncthing-service-type (service-type (name 'syncthing) (extensions (list (service-extension shepherd-root-service= -type - syncthing-shepherd-se= rvice))) + syncthing-shepherd-se= rvice) + (service-extension special-files-service= -type + syncthing-files-servi= ce))) (description "Run @uref{https://github.com/syncthing/syncthing, Syncth= ing} decentralized continuous file system synchronization."))) --=20 2.45.2 From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v5] services: syncthing: Added support for config file serialization. Resent-From: Bruno Victal Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sat, 08 Feb 2025 12:15:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Leo Famulari , Zacchaeus Cc: 75959@debbugs.gnu.org Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.173901689220483 (code B ref 75959); Sat, 08 Feb 2025 12:15:02 +0000 Received: (at 75959) by debbugs.gnu.org; 8 Feb 2025 12:14:52 +0000 Received: from localhost ([127.0.0.1]:38954 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tgjjY-0005KJ-3X for submit@debbugs.gnu.org; Sat, 08 Feb 2025 07:14:52 -0500 Received: from smtpmciv2.myservices.hosting ([185.26.107.238]:41868) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tgjjV-0005K4-8S for 75959@debbugs.gnu.org; Sat, 08 Feb 2025 07:14:50 -0500 Received: from mail1.netim.hosting (unknown [185.26.106.173]) by smtpmciv2.myservices.hosting (Postfix) with ESMTP id 130F22032F; Sat, 8 Feb 2025 13:14:46 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by mail1.netim.hosting (Postfix) with ESMTP id 286B680099; Sat, 8 Feb 2025 13:14:37 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at mail1.netim.hosting Received: from mail1.netim.hosting ([127.0.0.1]) by localhost (mail1-2.netim.hosting [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id l0csNZRX_XdM; Sat, 8 Feb 2025 13:14:36 +0100 (CET) Received: from [192.168.1.239] (unknown [10.192.1.83]) (Authenticated sender: lumen@makinata.eu) by mail1.netim.hosting (Postfix) with ESMTPSA id A0C0A80096; Sat, 8 Feb 2025 13:14:36 +0100 (CET) Message-ID: <72eb5b99-dd8d-4fa9-95fd-9054980ec92b@makinata.eu> Date: Sat, 8 Feb 2025 12:14:36 +0000 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird References: <20250130215954.9394-1-eikcaz@zacchae.us> Content-Language: en-US From: Bruno Victal In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) On 2025-02-07 22:44, Leo Famulari wrote: >> +;; It is useful to be able to view the xml output by Guix, and to be able to >> +;; diff it with a user's previous config, especially when migrating one's >> +;; config to Guix. This function adds whitespace that matches the whitespace >> +;; of config files managed by Syncthing for easy diffing. >> +(define (indent-sxml sxml indent-increment current-indent) > > Nice. Hopefully this doesn't go stale anytime soon. > > Overall, it's looking good. Thanks a lot for this contribution! Let me > know what you think about the feedback I've given here. I think this addition is unnecessary since there's a well-known command to pretty-print any XML file: xmllint --format Admittedly to my untrained eyes, this indent-sxml looks complex at a superficial glance and just adds maintenance burden without necessity in light of xmllint existence IMO. My 2¢, -- Bruno. From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v5] services: syncthing: Added support for config file serialization. Resent-From: Zacchaeus Scheffer Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sat, 08 Feb 2025 20:02:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Bruno Victal , 75959@debbugs.gnu.org Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.17390449117140 (code B ref 75959); Sat, 08 Feb 2025 20:02:02 +0000 Received: (at 75959) by debbugs.gnu.org; 8 Feb 2025 20:01:51 +0000 Received: from localhost ([127.0.0.1]:41613 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tgr1Q-0001r4-Mt for submit@debbugs.gnu.org; Sat, 08 Feb 2025 15:01:50 -0500 Received: from [47.204.136.169] (port=44360 helo=hun.zacchae.us) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tgr1M-0001ql-8e for 75959@debbugs.gnu.org; Sat, 08 Feb 2025 15:01:46 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Transfer-Encoding:Content-Type: MIME-Version:Message-ID:Date:References:In-Reply-To:Subject:To:From:Sender: Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=E065l/5TfJVQX2NOVlzK/Ng5qc6ioH31+/weJkEHbDg=; i=zacchae.us; b=F3CvVGSxEY9B MyCT2yKDMo9NbmiDwBQMBB7wFZ6FDvZz0JQprM+4gB6NAXuHiGgcnbROvq9upKmdc6ASuhHzAg==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Transfer-Encoding:Content-Type:MIME-Version: Message-ID:Date:References:In-Reply-To:Subject:To:From:Sender:Reply-To:Cc: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=E065l/5TfJVQX2NOVlzK/Ng5qc6ioH31+/weJkEHbDg=; i=zacchae.us; b=rlCMO6ePJpy1 nnU8i30xElQcpgW9CEQwN5A55hX2Ffb3lQ+zSjIWMzDjUd67RGUhytOkBbFAUiUVQXDX1beK+vA26 fCxazV0G0xLDjfFpE4Fss0YnP1cwQfmoOUuKLNL+h4trstEXQEogM/UbuBvPeSfuDHgO5oMbcxYQJ wiKM8XSmvSc956ru2dgutPKRpMOKDcREw3RaADAR/AejBw+ni+wSZvCpbdfmeZnw/Zhndx+XcttF/ GiZFMh/6X7m9jAf4DYFph40uvtltFfB6tKW7FtmysgZtopeLu8DNVx6HqWKFbei24Wo2pLuRAuQKl x0fdQZ3VvWVBDlR5yJMZSA==; Received: from localhost.home ([127.0.0.1]:57462 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1tgr1E-000000000c4-2NxV; Sat, 08 Feb 2025 15:01:36 -0500 From: Zacchaeus Scheffer In-Reply-To: <72eb5b99-dd8d-4fa9-95fd-9054980ec92b@makinata.eu> (Bruno Victal's message of "Sat, 8 Feb 2025 12:14:36 +0000") References: <20250130215954.9394-1-eikcaz@zacchae.us> <72eb5b99-dd8d-4fa9-95fd-9054980ec92b@makinata.eu> Date: Sat, 08 Feb 2025 15:01:36 -0500 Message-ID: <87v7tkfbof.fsf@zacchae.us> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From 45e289b4960e04c07dafedd39140ed2331b2be81 Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH v7] services: syncthing: Add support fo [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in sa-trusted.bondedsender.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in bl.score.senderscore.com] 0.1 URIBL_SBL_A Contains URL's A record listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 0.6 URIBL_SBL Contains an URL's NS IP listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS 0.0 T_FILL_THIS_FORM_SHORT Fill in a short form with personal information X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 1.0 (+) >From 45e289b4960e04c07dafedd39140ed2331b2be81 Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH v7] services: syncthing: Add support for config file generation. * gnu/services/syncthing.scm: (syncthing-config-file, syncthing-folder, syncthing-device, syncthing-folder-device): New records; (syncthing-service-type): Add special-files-service-type extension for the config file; (syncthing-files-service): Add service to create config file. * gnu/home/services/syncthing.scm: (home-syncthing-service-type): Extend home-files-services-type and re-exported more things from gnu/services/syncthing.scm. * doc/guix.texi: (syncthing-service-type): Document changes. Change-Id: I87eeba1ee1fdada8f29c2ee881fbc6bc4113dde9 --- As per Bruno's suggestion, I removed the (indent-sxml ...) function, and added intstructions in the documentation for how to get the same results with libxml2. I like my configs auto-indented, but Guix isn't really the place for that functionality. If I feel inspired at some point, maybe I'll try to add that functionality to sxml, but those chances are low. eikcaz- doc/guix.texi | 316 +++++++++++++++++++- gnu/home/services/syncthing.scm | 17 +- gnu/services/syncthing.scm | 506 ++++++++++++++++++++++++++++++-- 3 files changed, 807 insertions(+), 32 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index b1b6d98e74..d5fdda733e 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -136,6 +136,7 @@ Copyright @copyright{} 2024 Troy Figiel@* Copyright @copyright{} 2024 Sharlatan Hellseher@* Copyright @copyright{} 2024 45mg@* Copyright @copyright{} 2025 S=C3=B6ren Tempel@* +Copyright @copyright{} 2025 Zacchaeus@* =20 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -22666,12 +22667,323 @@ The group as which the Syncthing service is to b= e run. This assumes that the specified group exists. =20 @item @code{home} (default: @var{#f}) -Common configuration and data directory. The default configuration -directory is @file{$HOME} of the specified Syncthing @code{user}. +Sets the @code{HOME} variable for the syncthing daemon. The default is +@file{$HOME} of the specified Syncthing @code{user}. + +@item @code{config-file} (default: @var{#f}) +Either a file-like object that resolves to a Syncthing configuration xml +file, or a @code{syncthing-config-file} record (see below). If set to +@code{#f}, Guix will not try to generate a config file, and Syncthing +will generate a default one which will not be touched on reconfigure. +Specifying this in a system service moves Syncthing's common +configuration and data directory (@code{--home} in +@uref{https://docs.syncthing.net/users/syncthing.html}) to +@file{/var/lib/syncthnig-}. + +@end table +@end deftp + +In the below, only details specific to Guix, or related to how your +device will connect to unrelated devices (relays, nameservers), are +presented. Otherwise, you should consult +@uref{https://docs.syncthing.net/users/config.html, Syncthing config +documentation}; camelCase there is converted to kebab-case here. If you +are migrating to a Guix-powered Syncthing config file from a +GUI-configured one, you can see what changes were introduced by +@code{diff}ing them. Note that you will need to add whitespace with +4-space indentation to the one generated by Guix. This can be done +(requires @code{libxml2}) like so: + +@example +XMLLINT_INDENT=3D" " xmllint --format /path/to/new/config.xml | diff /p= ath/to/old/config.xml - +@end example + +When generating a config file through Guix, you can still modify +Syncthing from the GUI or through @code{introducer} and +@code{autoAcceptFolders} mechanisms, but such changes will be reset on +reconfigure. + +@deftp {Data Type} syncthing-config-file +Data type representing the configuration file read by the Syncthing +daemon. + +@table @asis +@item @code{folders} (default: @var{(list (syncthing-folder (id "default")= (label "Default Folder") (path "~/Sync")))} +The default here is the same as Syncthing's default. The value should +be a list of @code{syncthing-folder}s. + +@item @code{devices} (default: @var{'()} +This should be a list of @code{syncthing-device}s. Guix will +automatically add any devices specified in any `folders' to this list. +There are instances when you want to connect to a device despite not +(initially) sharing any folders (such as a device with +autoAcceptFolders). In such instances, you should specify those devices +here. If multiple versions of the same device (as determined by +comparing device id) are discovered, the one in this list is +prioritized. Otherwise, the first instance in the first folder is used. + +@item @code{gui-enabled} (default: @var{"true"}) +By default, any user on the computer can access the GUI and make changes +to Syncthing. If you leave this enabled, you should probably set +gui-user and gui-password (see below). + +@item @code{gui-tls} (default: @var{"false"}) +@item @code{gui-debugging} (default: @var{"false"}) +@item @code{gui-send-basic-auth-prompt} (default: @var{"false"}) +@item @code{gui-address} (default: @var{"127.0.0.1:8384"}) +@item @code{gui-user} (default: @var{#f}) +@item @code{gui-password} (default: @var{#f}) +A bcrypt hash of the GUI password. Remember that this will be globally +exposed in @file{/gnu/store}. +@item @code{gui-apikey} (default: @var{#f}) +You must specify this to use the Syncthing REST interface. Also exposed +in @file{/gnu/store}. + +@item @code{gui-theme} (default: @var{"default"}) +@item @code{ldap-enabled} (default: @var{#f}) +@item @code{ldap-address} (default: @var{""}) +@item @code{ldap-bind-dn} (default: @var{""}) +@item @code{ldap-transport} (default: @var{""}) +@item @code{ldap-insecure-skip-verify} (default: @var{""}) +@item @code{ldap-search-base-dn} (default: @var{""}) +@item @code{ldap-search-filter} (default: @var{""}) +@item @code{listen-address} (default: @var{"default"}) +@item @code{global-announce-server} (default: @var{"default"}) +@item @code{global-announce-enabled} (default: @var{"true"}) +Global discovery servers can be used to help connect devices at unknown +IP addresses by storing the last known IP address. + +@item @code{local-announce-enabled} (default: @var{"true"}) +This makes devices find each other very easily on the same LAN. Often, +this will allow you to just plug an Ethernet between two devices, or +connect one device to the other's hotspot and start syncing. + +@item @code{local-announce-port} (default: @var{"21027"}) +@item @code{local-announce-mcaddr} (default: @var{"[ff12::8384]:21027"}) +@item @code{max-send-kbps} (default: @var{"0"}) +@item @code{max-recv-kbps} (default: @var{"0"}) +@item @code{reconnection-interval-s} (default: @var{"60"}) +@item @code{relays-enabled} (default: @var{"true"}) +This option allows your Syncthing instance to coordinate with a global +network of relays to enable syncing between devices when all other +methods fail. + +@item @code{relay-reconnect-interval-m} (default: @var{"10"}) +@item @code{start-browser} (default: @var{"true"}) +@item @code{nat-enabled} (default: @var{"true"}) +@item @code{nat-lease-minutes} (default: @var{"60"}) +@item @code{nat-renewal-minutes} (default: @var{"30"}) +@item @code{nat-timeout-seconds} (default: @var{"10"}) +@item @code{ur-accepted} (default: @var{"0"}) +ur* options control usage reporting. Set to -1 to disable, or positive +to enable. The default (0) has reporting disabled, but you will be +asked to decide in the GUI. + +@item @code{ur-seen} (default: @var{"0"}) +@item @code{ur-unique-id} (default: @var{""}) +@item @code{ur-url} (default: @var{"https://data.syncthing.net/newdata"}) +@item @code{ur-post-insecurely} (default: @var{"false"}) +@item @code{ur-initial-delay-s} (default: @var{"1800"}) +@item @code{auto-upgrade-interval-h} (default: @var{"12"}) +@item @code{upgrade-to-pre-releases} (default: @var{"false"}) +@item @code{keep-temporaries-h} (default: @var{"24"}) +@item @code{cache-ignored-files} (default: @var{"false"}) +@item @code{progress-update-interval-s} (default: @var{"5"}) +@item @code{limit-bandwidth-in-lan} (default: @var{"false"}) +@item @code{min-home-disk-free-unit} (default: @var{"%"}) +@item @code{min-home-disk-free} (default: @var{"1"}) +@item @code{releases-url} (default: @var{"https://upgrades.syncthing.net/m= eta.json"}) +@item @code{overwrite-remote-device-names-on-connect} (default: @var{"fals= e"}) +@item @code{temp-index-min-blocks} (default: @var{"10"}) +@item @code{unacked-notification-id} (default: @var{"authenticationUserAnd= Password"}) +@item @code{traffic-class} (default: @var{"0"}) +@item @code{set-low-priority} (default: @var{"true"}) +@item @code{max-folder-concurrency} (default: @var{"0"}) +@item @code{crash-reporting-url} (default: @var{"https://crash.syncthing.n= et/newcrash"}) +@item @code{crash-reporting-enabled} (default: @var{"true"}) +@item @code{stun-keepalive-start-s} (default: @var{"180"}) +@item @code{stun-keepalive-min-s} (default: @var{"20"}) +@item @code{stun-server} (default: @var{"default"}) +@item @code{database-tuning} (default: @var{"auto"}) +@item @code{max-concurrent-incoming-request-kib} (default: @var{"0"}) +@item @code{announce-lan-addresses} (default: @var{"true"}) +@item @code{send-full-index-on-upgrade} (default: @var{"false"}) +@item @code{connection-limit-enough} (default: @var{"0"}) +@item @code{connection-limit-max} (default: @var{"0"}) +@item @code{insecure-allow-old-tls-versions} (default: @var{"false"}) +@item @code{connection-priority-tcp-lan} (default: @var{"10"}) +@item @code{connection-priority-quic-lan} (default: @var{"20"}) +@item @code{connection-priority-tcp-wan} (default: @var{"30"}) +@item @code{connection-priority-quic-wan} (default: @var{"40"}) +@item @code{connection-priority-relay} (default: @var{"50"}) +@item @code{connection-priority-upgrade-threshold} (default: @var{"0"}) +@item @code{default-folder} (default: @var{(syncthing-folder (label ""))}) +@item @code{default-device} (default: @var{(syncthing-device (id ""))}) +@item @code{default-ignores} (default: @var{"")}) +The default-* above do not affect folders and devices added by the Guix +interface. They will, however, affect folders and devices that are +added through the GUI, by an @code{introducer}, or a device with +@code{auto-accept-folders}. +@end table +@end deftp + +@deftp {Data Type} syncthing-folder +Data type representing a folder to be synced. + +@table @asis +@item @code{id} (default: @var{#f}) +This id cannot match the id of any other folder on this device. If left +unspecified, it will default to the label (see below). + +@item @code{label} +Human readable label for the folder. + +@item @code{path} +The path at which to store this folder. + +@item @code{type} (default: @var{"sendreceive"}) +@item @code{rescan-interval-s} (default: @var{"3600"}) +@item @code{fs-watcher-enabled} (default: @var{"true"}) +@item @code{fs-watcher-delay-s} (default: @var{"10"}) +@item @code{ignore-perms} (default: @var{"false"}) +@item @code{auto-normalize} (default: @var{"true"}) +@item @code{devices} (default: @var{'()}) +This should be a list of other Syncthing devices. You do not need to +specify the current device. Each device can be listed as a a +@code{syncthing-device} record or a @code{syncthing-folder-device} +record if you want files to be encrypted on disk. See below. + +@item @code{filesystem-type} (default: @var{"basic"}) +@item @code{min-disk-free-unit} (default: @var{"%"}) +@item @code{min-disk-free} (default: @var{"1"}) +@item @code{versioning-type} (default: @var{#f}) +@item @code{versioning-fs-path} (default: @var{""}) +@item @code{versioning-fs-type} (default: @var{"basic"}) +@item @code{versioning-cleanup-interval-s} (default: @var{"3600"}) +@item @code{versioning-cleanout-days} (default: @var{#f}) +@item @code{versioning-keep} (default: @var{#f}) +@item @code{versioning-max-age} (default: @var{#f}) +@item @code{versioning-command} (default: @var{#f}) +@item @code{copiers} (default: @var{"0"}) +@item @code{puller-max-pending-kib} (default: @var{"0"}) +@item @code{hashers} (default: @var{"0"}) +@item @code{order} (default: @var{"random"}) +@item @code{ignore-delete} (default: @var{"false"}) +@item @code{scan-progress-interval-s} (default: @var{"0"}) +@item @code{puller-pause-s} (default: @var{"0"}) +@item @code{max-conflicts} (default: @var{"10"}) +@item @code{disable-sparse-files} (default: @var{"false"}) +@item @code{disable-temp-indexes} (default: @var{"false"}) +@item @code{paused} (default: @var{"false"}) +@item @code{weak-hash-threshold-pct} (default: @var{"25"}) +@item @code{marker-name} (default: @var{".stfolder"}) +@item @code{copy-ownership-from-parent} (default: @var{"false"}) +@item @code{mod-time-window-s} (default: @var{"0"}) +@item @code{max-concurrent-writes} (default: @var{"2"}) +@item @code{disable-fsync} (default: @var{"false"}) +@item @code{block-pull-order} (default: @var{"standard"}) +@item @code{copy-range-method} (default: @var{"standard"}) +@item @code{case-sensitive-fs} (default: @var{"false"}) +@item @code{junctions-as-dirs} (default: @var{"false"}) +@item @code{sync-ownership} (default: @var{"false"}) +@item @code{send-ownership} (default: @var{"false"}) +@item @code{sync-xattrs} (default: @var{"false"}) +@item @code{send-xattrs} (default: @var{"false"}) +@item @code{xattr-filter-max-single-entry-size} (default: @var{"1024"}) +@item @code{xattr-filter-max-total-size} (default: @var{"4096")}) +@end table +@end deftp + +@deftp {Data Type} syncthing-device +Data type representing a device to sync with. + +@table @asis +@item @code{id} +A long hash tied to the keys generated by Syncthing on the first launch. +You can obtain this from the Syncthing GUI or by inspecting an existing +Syncthing configuration file. + +@item @code{name} (default: @var{""}) +Human readable device name for viewing in the GUI or in scheme. + +@item @code{compression} (default: @var{"metadata"}) +@item @code{introducer} (default: @var{"false"}) +@item @code{skip-introduction-removals} (default: @var{"false"}) +@item @code{introduced-by} (default: @var{""}) +@item @code{addresses} (default: @var{'("dynamic")}) +List of addresses at which to search for this device. The special value +``dynamic'' will have syncthing use several means to find the device. + +@item @code{paused} (default: @var{"false"}) +@item @code{auto-accept-folders} (default: @var{"false"}) +@item @code{max-send-kbps} (default: @var{"0"}) +@item @code{max-recv-kbps} (default: @var{"0"}) +@item @code{max-request-kib} (default: @var{"0"}) +@item @code{untrusted} (default: @var{"false"}) +@item @code{remote-gui-port} (default: @var{"0"}) +@item @code{num-connections} (default: @var{"0")}) + +@end table +@end deftp + +@deftp {Data Type} syncthing-folder-device +There are two pieces of configuration specific to the relationship +between a specific folder and a specific device. First, syncthing needs +to know if the remote device should be able to see the files given to +it. Second, syncthing needs to know from where that device originates. +See +@href{https://docs.syncthing.net/users/config.html#config-option-folder.de= vice, +the Syncthing Documentation on this}. If you leave these default, then +you can just specify @code{syncthing-device}s instead of +@code{syncthing-folder-device}s in a @code{syncthing-folder}'s +@code{devices} field. + +@table @asis +@item @code{device} +device should be a @code{syncthing-device} for which this configuration +applies. + +@item @code{introduced-by} (default: @var{""}) +@item @code{encryption-password} (default: @var{""}) +Beware: specifying this field will include this password as plain text +(not encrypted) and globally visible in @file{/gnu/store/}. If +encryption-password is non-empty, then it will be used as a password to +encrypt file chunks as they are synced to that device. For more info on +syncing to devices you don't totally trust, see +@uref{https://docs.syncthing.net/users/untrusted.html, Syncthing +Documentation on Untrusted Devices}. Note that file transfers are +always end-to-end encrypted, regardless of this setting. =20 @end table @end deftp =20 +Here is a more complex example configuration for illustrative purposes: +@lisp +(service syncthing-service-type + (let ((laptop (syncthing-device (id "VHOD2D6-...-7XRMDEN"))) + (desktop (syncthing-device (id "64SAZ37-...-FZJ5GUA") + (addresses '("tcp://example.com"= )))) + (bob-desktop (syncthing-device (id "KYIMEGO-...-FT77EAO")))) + (syncthing-configuration + (user "alice") + (config-file + (syncthing-config-file + (folders (list (syncthing-folder + (label "some-files") + (path "~/data") + (devices (list desktop laptop))) + (syncthing-folder + (label "critical-files") + (path "~/secrets") + (devices + (list desktop + laptop + (syncthing-folder-device + (device bob-desktop) + (encryption-password "mypassword"))= )))))))))) +@end lisp + + Furthermore, @code{(gnu services ssh)} provides the following services. @cindex SSH @cindex SSH server diff --git a/gnu/home/services/syncthing.scm b/gnu/home/services/syncthing.= scm index 8d66a167ce..dd6c752ee4 100644 --- a/gnu/home/services/syncthing.scm +++ b/gnu/home/services/syncthing.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2023 Ludovic Court=C3=A8s +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -24,9 +25,23 @@ (define-module (gnu home services syncthing) #:use-module (gnu home services shepherd) #:export (home-syncthing-service-type) #:re-export (syncthing-configuration - syncthing-configuration?)) + syncthing-configuration? + syncthing-config-file + syncthing-config-file? + syncthing-device + syncthing-device? + syncthing-folder + syncthing-folder? + syncthing-folder-device + syncthing-folder-device?)) =20 (define home-syncthing-service-type (service-type (inherit (system->home-service-type syncthing-service-type)) + ;; system->home-service-type does not convert special-files-service-typ= e to + ;; home-files-service-type, so redefine extensios + (extensions (list (service-extension home-files-service-type + syncthing-files-service) + (service-extension home-shepherd-service-type + syncthing-shepherd-service))) (default-value (for-home (syncthing-configuration))))) diff --git a/gnu/services/syncthing.scm b/gnu/services/syncthing.scm index a7a9c6aadd..2707591d51 100644 --- a/gnu/services/syncthing.scm +++ b/gnu/services/syncthing.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2021 Oleg Pykhalov ;;; Copyright =C2=A9 2023 Justin Veilleux +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -25,9 +26,20 @@ (define-module (gnu services syncthing) #:use-module (guix records) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (sxml simple) #:export (syncthing-configuration syncthing-configuration? - syncthing-service-type)) + syncthing-device + syncthing-device? + syncthing-config-file + syncthing-config-file? + syncthing-folder-device + syncthing-folder-device? + syncthing-folder + syncthing-folder? + syncthing-service-type + syncthing-shepherd-service + syncthing-files-service)) =20 ;;; Commentary: ;;; @@ -35,6 +47,411 @@ (define-module (gnu services syncthing) ;;; ;;; Code: =20 +(define-record-type* + syncthing-device make-syncthing-device + syncthing-device? + (id syncthing-device-id) + (name syncthing-device-name (default "")) + (compression syncthing-device-compression (default "metadata")) + (introducer syncthing-device-introducer (default "false")) + (skip-introduction-removals syncthing-device-skip-introduction-removals = (default "false")) + (introduced-by syncthing-device-introduced-by (default "")) + (addresses syncthing-device-addresses (default '("dynamic"))) + (paused syncthing-device-paused (default "false")) + (auto-accept-folders syncthing-device-auto-accept-folders (default "fals= e")) + (max-send-kbps syncthing-device-max-send-kbps (default "0")) + (max-recv-kbps syncthing-device-max-recv-kbps (default "0")) + (max-request-kib syncthing-device-max-request-kib (default "0")) + (untrusted syncthing-device-untrusted (default "false")) + (remote-gui-port syncthing-device-remote-gui-port (default "0")) + (num-connections syncthing-device-num-connections (default "0"))) + +(define syncthing-device->sxml + (match-record-lambda + (id name compression introducer skip-introduction-removals introduce= d-by addresses paused auto-accept-folders max-send-kbps max-recv-kbps max-r= equest-kib untrusted remote-gui-port num-connections) + `(device (@ (id ,id) + (name ,name) + (compression ,compression) + (introducer ,introducer) + (skipIntroductionRemovals ,skip-introduction-removals) + (introducedBy ,introduced-by)) + ,@(map (lambda (address) `(address ,address)) addresses) + (paused ,paused) + (autoAcceptFolders ,auto-accept-folders) + (maxSendKbps ,max-send-kbps) + (maxRecvKbps ,max-recv-kbps) + (maxRequestKiB ,max-request-kib) + (untrusted ,untrusted) + (remoteGUIPort ,remote-gui-port) + (numConnections ,num-connections)))) + +(define-record-type* + syncthing-folder-device make-syncthing-folder-device + syncthing-folder-device? + (device syncthing-folder-device-device) + (introduced-by syncthing-folder-device-introduced-by (default (syncthing= -device (id "")))) + (encryption-password syncthing-folder-device-encryption-password (defaul= t ""))) + +(define syncthing-folder-device->sxml + (match-record-lambda + (device introduced-by encryption-password) + `(device (@ (id ,(syncthing-device-id device)) + (introducedBy ,(syncthing-device-id introduced-by))) + (encryptionPassword ,encryption-password)))) + +(define-record-type* + syncthing-folder make-syncthing-folder + syncthing-folder? + (id syncthing-folder-id (default #f)) + (label syncthing-folder-label) + (path syncthing-folder-path) + (type syncthing-folder-type (default "sendreceive")) + (rescan-interval-s syncthing-folder-rescan-interval-s (default "3600")) + (fs-watcher-enabled syncthing-folder-fs-watcher-enabled (default "true")) + (fs-watcher-delay-s syncthing-folder-fs-watcher-delay-s (default "10")) + (fs-watcher-timeout-s syncthing-folder-fs-watcher-timeout-s (default "0"= )) + (ignore-perms syncthing-folder-ignore-perms (default "false")) + (auto-normalize syncthing-folder-auto-normalize (default "true")) + (devices syncthing-folder-devices (default '()) + (sanitize (lambda (folder-device-list) + (map (lambda (device) + (if (syncthing-folder-device? device) + device + (syncthing-folder-device (device device)= ))) + folder-device-list)))) + (filesystem-type syncthing-folder-filesystem-type (default "basic")) + (min-disk-free-unit syncthing-folder-min-disk-free-unit (default "%")) + (min-disk-free syncthing-folder-min-disk-free (default "1")) + (versioning-type syncthing-folder-versioning-type (default #f)) + (versioning-fs-path syncthing-folder-versioning-fs-path (default "")) + (versioning-fs-type syncthing-folder-versioning-fs-type (default "basic"= )) + (versioning-cleanup-interval-s syncthing-folder-versioning-cleanup-inter= val-s (default "3600")) + (versioning-cleanout-days syncthing-folder-versioning-cleanout-days (def= ault #f)) + (versioning-keep syncthing-folder-versioning-keep (default #f)) + (versioning-max-age syncthing-folder-versioning-max-age (default #f)) + (versioning-command syncthing-folder-versioning-command (default #f)) + (copiers syncthing-folder-copiers (default "0")) + (puller-max-pending-kib syncthing-folder-puller-max-pending-kib (default= "0")) + (hashers syncthing-folder-hashers (default "0")) + (order syncthing-folder-order (default "random")) + (ignore-delete syncthing-folder-ignore-delete (default "false")) + (scan-progress-interval-s syncthing-folder-scan-progress-interval-s (def= ault "0")) + (puller-pause-s syncthing-folder-puller-pause-s (default "0")) + (max-conflicts syncthing-folder-max-conflicts (default "10")) + (disable-sparse-files syncthing-folder-disable-sparse-files (default "fa= lse")) + (disable-temp-indexes syncthing-folder-disable-temp-indexes (default "fa= lse")) + (paused syncthing-folder-paused (default "false")) + (weak-hash-threshold-pct syncthing-folder-weak-hash-threshold-pct (defau= lt "25")) + (marker-name syncthing-folder-marker-name (default ".stfolder")) + (copy-ownership-from-parent syncthing-folder-copy-ownership-from-parent = (default "false")) + (mod-time-window-s syncthing-folder-mod-time-window-s (default "0")) + (max-concurrent-writes syncthing-folder-max-concurrent-writes (default "= 2")) + (disable-fsync syncthing-folder-disable-fsync (default "false")) + (block-pull-order syncthing-folder-block-pull-order (default "standard")) + (copy-range-method syncthing-folder-copy-range-method (default "standard= ")) + (case-sensitive-fs syncthing-folder-case-sensitive-fs (default "false")) + (junctions-as-dirs syncthing-folder-junctions-as-dirs (default "false")) + (sync-ownership syncthing-folder-sync-ownership (default "false")) + (send-ownership syncthing-folder-send-ownership (default "false")) + (sync-xattrs syncthing-folder-sync-xattrs (default "false")) + (send-xattrs syncthing-folder-send-xattrs (default "false")) + (xattr-filter-max-single-entry-size syncthing-folder-xattr-filter-max-si= ngle-entry-size (default "1024")) + (xattr-filter-max-total-size syncthing-folder-xattr-filter-max-total-siz= e (default "4096"))) + +;; Some parameters, when empty, are fully omitted from the config file. I= t is +;; unknown if this causes a functional difference, but stick to the normal +;; program's behavior to be safe. +(define (maybe-param symbol value) + (if value `((param (@ (key ,(symbol->string symbol)) (val ,value)) "")) = '())) + +(define syncthing-folder->sxml + (match-record-lambda + (id + label path type rescan-interval-s fs-watcher-enabled fs-watcher-del= ay-s + fs-watcher-timeout-s ignore-perms auto-normalize devices filesystem= -type + min-disk-free-unit min-disk-free versioning-type versioning-fs-path + versioning-fs-type versioning-cleanup-interval-s versioning-cleanou= t-days + versioning-keep versioning-max-age versioning-command copiers + puller-max-pending-kib hashers order ignore-delete scan-progress-in= terval-s + puller-pause-s max-conflicts disable-sparse-files disable-temp-inde= xes paused + weak-hash-threshold-pct marker-name copy-ownership-from-parent mod-= time-window-s + max-concurrent-writes disable-fsync block-pull-order copy-range-met= hod + case-sensitive-fs junctions-as-dirs sync-ownership send-ownership s= ync-xattrs + send-xattrs xattr-filter-max-single-entry-size xattr-filter-max-tot= al-size) + `(folder (@ (id ,(if id id label)) + (label ,label) + (path ,path) + (type ,type) + (rescanIntervalS ,rescan-interval-s) + (fsWatcherEnabled ,fs-watcher-enabled) + (fsWatcherDelayS ,fs-watcher-delay-s) + (fsWatcherTimeoutS ,fs-watcher-timeout-s) + (ignorePerms ,ignore-perms) + (autoNormalize ,auto-normalize)) + (filesystemType ,filesystem-type) + ,@(map syncthing-folder-device->sxml + devices) + (minDiskFree (@ (unit ,min-disk-free-unit)) + ,min-disk-free) + (versioning ,@(if versioning-type + `((@ (type ,versioning-type))) + '()) + ,@(maybe-param 'cleanoutDays versioning-cleanout-= days) + ,@(maybe-param 'keep versioning-keep) + ,@(maybe-param 'maxAge versioning-max-age) + ,@(maybe-param 'command versioning-command) + (cleanupIntervalS ,versioning-cleanup-interval-s) + (fsPath ,versioning-fs-path) + (fsType ,versioning-fs-type)) + (copiers ,copiers) + (pullerMaxPendingKiB ,puller-max-pending-kib) + (hashers ,hashers) + (order ,order) + (ignoreDelete ,ignore-delete) + (scanProgressIntervalS ,scan-progress-interval-s) + (pullerPauseS ,puller-pause-s) + (maxConflicts ,max-conflicts) + (disableSparseFiles ,disable-sparse-files) + (disableTempIndexes ,disable-temp-indexes) + (paused ,paused) + (weakHashThresholdPct ,weak-hash-threshold-pct) + (markerName ,marker-name) + (copyOwnershipFromParent ,copy-ownership-from-parent) + (modTimeWindowS ,mod-time-window-s) + (maxConcurrentWrites ,max-concurrent-writes) + (disableFsync ,disable-fsync) + (blockPullOrder ,block-pull-order) + (copyRangeMethod ,copy-range-method) + (caseSensitiveFS ,case-sensitive-fs) + (junctionsAsDirs ,junctions-as-dirs) + (syncOwnership ,sync-ownership) + (sendOwnership ,send-ownership) + (syncXattrs ,sync-xattrs) + (sendXattrs ,send-xattrs) + (xattrFilter (maxSingleEntrySize ,xattr-filter-max-single-ent= ry-size) + (maxTotalSize ,xattr-filter-max-total-size))))) + +(define-record-type* + syncthing-config-file make-syncthing-config-file + syncthing-config-file? + (folders syncthing-config-folders + ; this matches syncthing's default + (default (list (syncthing-folder (id "default") + (label "Default Folder") + (path "~/Sync"))))) + (devices syncthing-config-devices + (default '())) + (gui-enabled syncthing-config-gui-enabled (default "true")) + (gui-tls syncthing-config-gui-tls (default "false")) + (gui-debugging syncthing-config-gui-debugging (default "false")) + (gui-send-basic-auth-prompt syncthing-config-gui-send-basic-auth-prompt = (default "false")) + (gui-address syncthing-config-gui-address (default "127.0.0.1:8384")) + (gui-user syncthing-config-gui-user (default #f)) + (gui-password syncthing-config-gui-password (default #f)) + (gui-apikey syncthing-config-gui-apikey (default #f)) + (gui-theme syncthing-config-gui-theme (default "default")) + (ldap-enabled syncthing-config-ldap-enabled (default #f)) + (ldap-address syncthing-config-ldap-address (default "")) + (ldap-bind-dn syncthing-config-ldap-bind-dn (default "")) + (ldap-transport syncthing-config-ldap-transport (default "")) + (ldap-insecure-skip-verify syncthing-config-ldap-insecure-skip-verify (d= efault "")) + (ldap-search-base-dn syncthing-config-ldap-search-base-dn (default "")) + (ldap-search-filter syncthing-config-ldap-search-filter (default "")) + (listen-address syncthing-config-listen-address (default "default")) + (global-announce-server syncthing-config-global-announce-server (default= "default")) + (global-announce-enabled syncthing-config-global-announce-enabled (defau= lt "true")) + (local-announce-enabled syncthing-config-local-announce-enabled (default= "true")) + (local-announce-port syncthing-config-local-announce-port (default "2102= 7")) + (local-announce-mcaddr syncthing-config-local-announce-mcaddr (default "= [ff12::8384]:21027")) + (max-send-kbps syncthing-config-max-send-kbps (default "0")) + (max-recv-kbps syncthing-config-max-recv-kbps (default "0")) + (reconnection-interval-s syncthing-config-reconnection-interval-s (defau= lt "60")) + (relays-enabled syncthing-config-relays-enabled (default "true")) + (relay-reconnect-interval-m syncthing-config-relay-reconnect-interval-m = (default "10")) + (start-browser syncthing-config-start-browser (default "true")) + (nat-enabled syncthing-config-nat-enabled (default "true")) + (nat-lease-minutes syncthing-config-nat-lease-minutes (default "60")) + (nat-renewal-minutes syncthing-config-nat-renewal-minutes (default "30")) + (nat-timeout-seconds syncthing-config-nat-timeout-seconds (default "10")) + (ur-accepted syncthing-config-ur-accepted (default "0")) + (ur-seen syncthing-config-ur-seen (default "0")) + (ur-unique-id syncthing-config-ur-unique-id (default "")) + (ur-url syncthing-config-ur-url (default "https://data.syncthing.net/new= data")) + (ur-post-insecurely syncthing-config-ur-post-insecurely (default "false"= )) + (ur-initial-delay-s syncthing-config-ur-initial-delay-s (default "1800")) + (auto-upgrade-interval-h syncthing-config-auto-upgrade-interval-h (defau= lt "12")) + (upgrade-to-pre-releases syncthing-config-upgrade-to-pre-releases (defau= lt "false")) + (keep-temporaries-h syncthing-config-keep-temporaries-h (default "24")) + (cache-ignored-files syncthing-config-cache-ignored-files (default "fals= e")) + (progress-update-interval-s syncthing-config-progress-update-interval-s = (default "5")) + (limit-bandwidth-in-lan syncthing-config-limit-bandwidth-in-lan (default= "false")) + (min-home-disk-free-unit syncthing-config-min-home-disk-free-unit (defau= lt "%")) + (min-home-disk-free syncthing-config-min-home-disk-free (default "1")) + (releases-url syncthing-config-releases-url (default "https://upgrades.s= yncthing.net/meta.json")) + (overwrite-remote-device-names-on-connect syncthing-config-overwrite-rem= ote-device-names-on-connect (default "false")) + (temp-index-min-blocks syncthing-config-temp-index-min-blocks (default "= 10")) + (unacked-notification-id syncthing-config-unacked-notification-id (defau= lt "authenticationUserAndPassword")) + (traffic-class syncthing-config-traffic-class (default "0")) + (set-low-priority syncthing-config-set-low-priority (default "true")) + (max-folder-concurrency syncthing-config-max-folder-concurrency (default= "0")) + (crash-reporting-url syncthing-config-crash-reporting-url (default "http= s://crash.syncthing.net/newcrash")) + (crash-reporting-enabled syncthing-config-crash-reporting-enabled (defau= lt "true")) + (stun-keepalive-start-s syncthing-config-stun-keepalive-start-s (default= "180")) + (stun-keepalive-min-s syncthing-config-stun-keepalive-min-s (default "20= ")) + (stun-server syncthing-config-stun-server (default "default")) + (database-tuning syncthing-config-database-tuning (default "auto")) + (max-concurrent-incoming-request-kib syncthing-config-max-concurrent-inc= oming-request-kib (default "0")) + (announce-lan-addresses syncthing-config-announce-lan-addresses (default= "true")) + (send-full-index-on-upgrade syncthing-config-send-full-index-on-upgrade = (default "false")) + (connection-limit-enough syncthing-config-connection-limit-enough (defau= lt "0")) + (connection-limit-max syncthing-config-connection-limit-max (default "0"= )) + (insecure-allow-old-tlsVersions syncthing-config-insecure-allow-old-tlsV= ersions (default "false")) + (connection-priority-tcp-lan syncthing-config-connection-priority-tcp-la= n (default "10")) + (connection-priority-quic-lan syncthing-config-connection-priority-quic-= lan (default "20")) + (connection-priority-tcp-wan syncthing-config-connection-priority-tcp-wa= n (default "30")) + (connection-priority-quic-wan syncthing-config-connection-priority-quic-= wan (default "40")) + (connection-priority-relay syncthing-config-connection-priority-relay (d= efault "50")) + (connection-priority-upgrade-threshold syncthing-config-connection-prior= ity-upgrade-threshold (default "0")) + (default-folder syncthing-config-default-folder + (default (syncthing-folder (label "") (path "~")))) + (default-device syncthing-config-default-device + (default (syncthing-device (id "")))) + (default-ignores syncthing-config-default-ignores (default ""))) + +(define syncthing-config-file->sxml + (match-record-lambda + (folders + devices gui-enabled gui-tls gui-debugging gui-send-basic-auth-prompt + gui-address gui-user gui-password gui-apikey gui-theme ldap-enabled + ldap-address ldap-bind-dn ldap-transport ldap-insecure-skip-verify + ldap-search-base-dn ldap-search-filter listen-address global-announ= ce-server + global-announce-enabled local-announce-enabled local-announce-port + local-announce-mcaddr max-send-kbps max-recv-kbps reconnection-inte= rval-s + relays-enabled relay-reconnect-interval-m start-browser nat-enabled + nat-lease-minutes nat-renewal-minutes nat-timeout-seconds ur-accept= ed + ur-seen ur-unique-id ur-url ur-post-insecurely ur-initial-delay-s + auto-upgrade-interval-h upgrade-to-pre-releases keep-temporaries-h + cache-ignored-files progress-update-interval-s limit-bandwidth-in-l= an + min-home-disk-free-unit min-home-disk-free releases-url + overwrite-remote-device-names-on-connect temp-index-min-blocks + unacked-notification-id traffic-class set-low-priority max-folder-c= oncurrency + crash-reporting-url crash-reporting-enabled stun-keepalive-start-s + stun-keepalive-min-s stun-server database-tuning + max-concurrent-incoming-request-kib announce-lan-addresses + send-full-index-on-upgrade connection-limit-enough connection-limit= -max + insecure-allow-old-tlsVersions connection-priority-tcp-lan + connection-priority-quic-lan connection-priority-tcp-wan + connection-priority-quic-wan connection-priority-relay + connection-priority-upgrade-threshold default-folder default-device + default-ignores) + `(configuration (@ (version "37")) + ,@(map syncthing-folder->sxml + folders) + ;; collect any devices in any folders, as well as any + ;; devices explicitly added. + ,@(map syncthing-device->sxml + (delete-duplicates + (append devices + (apply append + (map (lambda (folder) + (map syncthing-folder-de= vice-device + (syncthing-folder-d= evices folder))) + folders))) + ;; devices are the same if their id's are equal + (lambda (device1 device2) + (string=3D (syncthing-device-id device1) + (syncthing-device-id device2))))) + (gui (@ (enabled ,gui-enabled) + (tls ,gui-tls) + (debugging ,gui-debugging) + (sendBasicAuthPrompt ,gui-send-basic-auth-prom= pt)) + (address ,gui-address) + ,@(if gui-user `((user ,gui-user)) '()) + ,@(if gui-password `((password ,gui-password)) '(= )) + ,@(if gui-apikey `((apikey ,gui-apikey)) '()) + (theme ,gui-theme)) + (ldap ,(if ldap-enabled + `((address ,ldap-address) + (bindDN ,ldap-bind-dn) + ,@(if ldap-transport + `((transport ,ldap-transport)) + '()) + ,@(if ldap-insecure-skip-verify + `((insecureSkipVerify ,ldap-insecur= e-skip-verify)) + '()) + ,@(if ldap-search-base-dn + `((searchBaseDN ,ldap-search-base-d= n)) + '()) + ,@(if ldap-search-filter + `((searchFilter ,ldap-search-filter= )) + '())) + "")) + (options (listenAddress ,listen-address) + (globalAnnounceServer ,global-announce-server) + (globalAnnounceEnabled ,global-announce-enabl= ed) + (localAnnounceEnabled ,local-announce-enabled) + (localAnnouncePort ,local-announce-port) + (localAnnounceMCAddr ,local-announce-mcaddr) + (maxSendKbps ,max-send-kbps) + (maxRecvKbps ,max-recv-kbps) + (reconnectionIntervalS ,reconnection-interval= -s) + (relaysEnabled ,relays-enabled) + (relayReconnectIntervalM ,relay-reconnect-int= erval-m) + (startBrowser ,start-browser) + (natEnabled ,nat-enabled) + (natLeaseMinutes ,nat-lease-minutes) + (natRenewalMinutes ,nat-renewal-minutes) + (natTimeoutSeconds ,nat-timeout-seconds) + (urAccepted ,ur-accepted) + (urSeen ,ur-seen) + (urUniqueID ,ur-unique-id) + (urURL ,ur-url) + (urPostInsecurely ,ur-post-insecurely) + (urInitialDelayS ,ur-initial-delay-s) + (autoUpgradeIntervalH ,auto-upgrade-interval-= h) + (upgradeToPreReleases ,upgrade-to-pre-release= s) + (keepTemporariesH ,keep-temporaries-h) + (cacheIgnoredFiles ,cache-ignored-files) + (progressUpdateIntervalS ,progress-update-int= erval-s) + (limitBandwidthInLan ,limit-bandwidth-in-lan) + (minHomeDiskFree (@ (unit ,min-home-disk-free= -unit)) + ,min-home-disk-free) + (releasesURL ,releases-url) + (overwriteRemoteDeviceNamesOnConnect ,overwri= te-remote-device-names-on-connect) + (tempIndexMinBlocks ,temp-index-min-blocks) + (unackedNotificationID ,unacked-notification-= id) + (trafficClass ,traffic-class) + (setLowPriority ,set-low-priority) + (maxFolderConcurrency ,max-folder-concurrency) + (crashReportingURL ,crash-reporting-url) + (crashReportingEnabled ,crash-reporting-enabl= ed) + (stunKeepaliveStartS ,stun-keepalive-start-s) + (stunKeepaliveMinS ,stun-keepalive-min-s) + (stunServer ,stun-server) + (databaseTuning ,database-tuning) + (maxConcurrentIncomingRequestKiB ,max-concurr= ent-incoming-request-kib) + (announceLANAddresses ,announce-lan-addresses) + (sendFullIndexOnUpgrade ,send-full-index-on-u= pgrade) + (connectionLimitEnough ,connection-limit-enou= gh) + (connectionLimitMax ,connection-limit-max) + (insecureAllowOldTLSVersions ,insecure-allow-= old-tlsVersions) + (connectionPriorityTcpLan ,connection-priorit= y-tcp-lan) + (connectionPriorityQuicLan ,connection-priori= ty-quic-lan) + (connectionPriorityTcpWan ,connection-priorit= y-tcp-wan) + (connectionPriorityQuicWan ,connection-priori= ty-quic-wan) + (connectionPriorityRelay ,connection-priority= -relay) + (connectionPriorityUpgradeThreshold ,connecti= on-priority-upgrade-threshold)) + (defaults + ,(syncthing-folder->sxml default-folder) + ,(syncthing-device->sxml default-device) + (ignores ,default-ignores))))) + + +(define (serialize-syncthing-config-file config) + (with-output-to-string + (lambda () + (sxml->xml (cons '*TOP* (list (syncthing-config-file->sxml config)))= )))) + (define-record-type* syncthing-configuration make-syncthing-configuration syncthing-configuration? @@ -50,12 +467,14 @@ (define-record-type* (default "users")) (home syncthing-configuration-home ;string (default #f)) + (config-file syncthing-configuration-config-file + (default #f)) ; syncthing-config-file or = file-like (home-service? syncthing-configuration-home-service? (default for-home?) (innate))) =20 (define syncthing-shepherd-service (match-record-lambda - (syncthing arguments logflags user group home home-service?) + (syncthing arguments logflags user group home home-service? config-f= ile) (list (shepherd-service (provision (if home-service? @@ -64,39 +483,68 @@ (define syncthing-shepherd-service (string-append "syncthing-" user))))) (documentation "Run syncthing.") (requirement (if home-service? '() '(loopback user-processes))) - (start #~(make-forkexec-constructor - (append (list (string-append #$syncthing "/bin/syncthing") - "--no-browser" - "--no-restart" - (string-append "--logflags=3D" (number->stri= ng #$logflags))) - '#$arguments) - #:user #$(and (not home-service?) user) - #:group #$(and (not home-service?) group) - #:environment-variables - (append - (list - (string-append "HOME=3D" - (or #$home - (passwd:dir - (getpw (if (and #$home-service? - (not #$user)) - (getuid) - #$user))))) - "SSL_CERT_DIR=3D/etc/ssl/certs" - "SSL_CERT_FILE=3D/etc/ssl/certs/ca-certifica= tes.crt") - (filter (negate ;XXX: 'remove' is not in (gu= ile) - (lambda (str) - (or (string-prefix? "HOME=3D" str) - (string-prefix? "SSL_CERT_DIR=3D" s= tr) - (string-prefix? "SSL_CERT_FILE=3D" = str)))) - (environ))))) + (start #~(lambda _ + ;; if we are managing the config, and it's not a home + ;; service, then exepect the config file at + ;; /var/lib/syncthing-. This makes sure the owners= hip + ;; is correct + (unless (or #$(not config-file) #$home-service?) + (system* "chown" #$user (string-append "/var/lib/syncth= ing-" #$user)) + (system* "chmod" "700" (string-append "/var/lib/syncthi= ng-" #$user))) + (make-forkexec-constructor + (append (list (string-append #$syncthing "/bin/syncthing= ") + "--no-browser" + "--no-restart" + (string-append "--logflags=3D" (number->st= ring #$logflags))) + (if (or #$(not config-file) #$home-service?) '() + (list (string-append "--home=3D/var/lib/sync= thing-" #$user))) + '#$arguments) + #:user #$(and (not home-service?) user) + #:group #$(and (not home-service?) group) + #:environment-variables + (append + (list + (string-append "HOME=3D" + (or #$home + (passwd:dir + (getpw (if (and #$home-service? + (not #$user)) + (getuid) + #$user))))) + "SSL_CERT_DIR=3D/etc/ssl/certs" + "SSL_CERT_FILE=3D/etc/ssl/certs/ca-certificates.crt") + (filter (negate ;XXX: 'remove' is not in (guile) + (lambda (str) + (or (string-prefix? "HOME=3D" str) + (string-prefix? "SSL_CERT_DIR=3D" str) + (string-prefix? "SSL_CERT_FILE=3D" str))= )) + (environ)))))) (respawn? #f) (stop #~(make-kill-destructor)))))) =20 + +(define syncthing-files-service + (match-record-lambda (config-file user home ho= me-service?) + (if config-file + ;; when used as a system service, this service might be executed + ;; before a user's home even exists, causing it to be owned by roo= t, + ;; and the skeletons to never be applied to that user's home. In = such + ;; cases, put the config at /var/lib/syncthnig-/config.xml + `((,(if home-service? + ".config/syncthing/config.xml" + (string-append "/var/lib/syncthing-" user "/config.xml")) + ,(if (file-like? config-file) + config-file + (plain-file "syncthin-config.xml" (serialize-syncthing-con= fig-file + config-file))))) + '()))) + (define syncthing-service-type (service-type (name 'syncthing) (extensions (list (service-extension shepherd-root-service= -type - syncthing-shepherd-se= rvice))) + syncthing-shepherd-se= rvice) + (service-extension special-files-service= -type + syncthing-files-servi= ce))) (description "Run @uref{https://github.com/syncthing/syncthing, Syncth= ing} decentralized continuous file system synchronization."))) --=20 2.45.2 From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v5] services: syncthing: Added support for config file serialization. Resent-From: Zacchaeus Scheffer Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Tue, 11 Feb 2025 04:04:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Bruno Victal Cc: 75959@debbugs.gnu.org, Leo Famulari Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.173924659923679 (code B ref 75959); Tue, 11 Feb 2025 04:04:02 +0000 Received: (at 75959) by debbugs.gnu.org; 11 Feb 2025 04:03:19 +0000 Received: from localhost ([127.0.0.1]:53392 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1thhUU-00069q-RB for submit@debbugs.gnu.org; Mon, 10 Feb 2025 23:03:19 -0500 Received: from [47.204.136.169] (port=33038 helo=hun.zacchae.us) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1thhUR-00069Z-LN for 75959@debbugs.gnu.org; Mon, 10 Feb 2025 23:03:16 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=XGPvQxyFamHkbBHj3/cz6DZcjGNj2T0L5a+xdjqlZbQ=; i=zacchae.us; b=r2SbfJIlO1hZ vt2AZvjtiyszvNLWHKziww2jK4Eno+C3Kpqtiu+1uo9Lb6bGgKB53d1ia4vWl4YEjK7qrP7cDQ==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Type:MIME-Version:Message-ID:Date:References: In-Reply-To:Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=XGPvQxyFamHkbBHj3/cz6DZcjGNj2T0L5a+xdjqlZbQ=; i=zacchae.us; b=Qtu4XT35A8Vr 2G9OJYwlT0DDrnFvdxj0zeDjdTpmFRy+4LOzs4dcxZtk4ZGEJhiYlqyturoXbMWfz5AidFVrs9w8K oBe2yU3ayeKbiXRADLPXYWY0eFrAgFouFMKvHGCc+Bs2QrkkZwPNRqWmaPuRvrhTrA4iLMeKtcjfM TPGKJfgC71iaZrcSwfsXA+/mawiM69IdLSEwlixM8mOn1VAh/4kkWD6HQUbEoZI4CoXCzmD8GhL6R KXeFpw1g1rC6pq6sGZivhX+SxIiebC9P4h+/JwS+vJVGSsSWbjmbg9rl50Jimf2tzyZ0x5FqdxpwP 4EMC+ZBIDLy5PvCFE3bN0w==; Received: from localhost.home ([127.0.0.1]:43316 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1thhUI-0000000058G-4BUJ; Mon, 10 Feb 2025 23:03:07 -0500 From: Zacchaeus Scheffer In-Reply-To: <72eb5b99-dd8d-4fa9-95fd-9054980ec92b@makinata.eu> (Bruno Victal's message of "Sat, 8 Feb 2025 12:14:36 +0000") References: <20250130215954.9394-1-eikcaz@zacchae.us> <72eb5b99-dd8d-4fa9-95fd-9054980ec92b@makinata.eu> Date: Mon, 10 Feb 2025 23:03:07 -0500 Message-ID: <87r045f7r8.fsf@zacchae.us> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: 1.3 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Urgent: I only tested with pre-inst-env and didn't realize the updates to doc/guix.texi cause guix to not build, so don't push upstream until that's fixed. eikcaz- Content analysis details: (1.3 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in sa-trusted.bondedsender.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in bl.score.senderscore.com] 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 0.3 (/) Urgent: I only tested with pre-inst-env and didn't realize the updates to doc/guix.texi cause guix to not build, so don't push upstream until that's fixed. eikcaz- From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v8] services: syncthing: Add support for config file generation. References: <20250130215954.9394-1-eikcaz@zacchae.us> In-Reply-To: <20250130215954.9394-1-eikcaz@zacchae.us> Resent-From: Zacchaeus Scheffer Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Tue, 11 Feb 2025 05:32:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Leo Famulari , Bruno Victal Cc: 75959@debbugs.gnu.org Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.17392518988318 (code B ref 75959); Tue, 11 Feb 2025 05:32:02 +0000 Received: (at 75959) by debbugs.gnu.org; 11 Feb 2025 05:31:38 +0000 Received: from localhost ([127.0.0.1]:53623 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1thirv-0002A1-Oy for submit@debbugs.gnu.org; Tue, 11 Feb 2025 00:31:38 -0500 Received: from [47.204.136.169] (port=52392 helo=hun.zacchae.us) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1thirq-00029c-PZ for 75959@debbugs.gnu.org; Tue, 11 Feb 2025 00:31:33 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Transfer-Encoding:Content-Type: MIME-Version:Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=utCsWaRV4Ea+dWES17TSBgRz+F7tmFLCo7VZIIgooDQ=; i=zacchae.us; b=V8a/UipX4tus feDiM6Kvvl7zF/tPIsEbNdD6fw/OwDrolxh43maTzc1nNuS3BizQ5ZhXSVrvAlXDEgJMy5IIBw==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Transfer-Encoding:Content-Type:MIME-Version: Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=utCsWaRV4Ea+dWES17TSBgRz+F7tmFLCo7VZIIgooDQ=; i=zacchae.us; b=XibAnCicWKJp wKKurAB8Ow2kxrGlxxYyaxlkZITWNobEyW5qB6/R/tax5ywCx9YvUxEOcsUbsQ4NCSWa+Ms9kIoDH o4QfwFjIeXVj+pjkckSJgxvCBBg/yRlG+GB3i1TQXnxDp3Dsa58/cd+VZYYl7H+nm++XZVhWJ1tfM DO/3rVV1LB1K1r1Mk/8iQlbFOTGrYpDyROQQLh/ISzhViy/3Zy2Y3yxfBCyfHrd3NShuiWJ64qbG0 klaEU3Dc9L8tIlqN+O5cfo+4VqFBaoqHjVEsWqc0RSFcm0hGU42oX/iEEO3HvSCW3Ksj8S8weADy9 OzJXyJVSC/SLm6P8dkpWlQ==; Received: from localhost.home ([127.0.0.1]:35872 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1thirj-000000005Qz-2fhZ; Tue, 11 Feb 2025 00:31:24 -0500 From: Zacchaeus Scheffer Date: Tue, 11 Feb 2025 00:31:23 -0500 Message-ID: <87o6z9f3o4.fsf@zacchae.us> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From dff3153afdd31c754d7d3ddb640a2d33d43f1242 Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH v8] services: syncthing: Add support fo [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in sa-trusted.bondedsender.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in bl.score.senderscore.com] 0.1 URIBL_SBL_A Contains URL's A record listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 0.6 URIBL_SBL Contains an URL's NS IP listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS 0.0 T_FILL_THIS_FORM_SHORT Fill in a short form with personal information X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 1.0 (+) >From dff3153afdd31c754d7d3ddb640a2d33d43f1242 Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH v8] services: syncthing: Add support for config file generation. * gnu/services/syncthing.scm: (syncthing-config-file, syncthing-folder, syncthing-device, syncthing-folder-device): New records; (syncthing-service-type): Add special-files-service-type extension for the config file; (syncthing-files-service): Add service to create config file. * gnu/home/services/syncthing.scm: (home-syncthing-service-type): Extend home-files-services-type and re-exported more things from gnu/services/syncthing.scm. * doc/guix.texi: (syncthing-service-type): Document changes. Change-Id: I87eeba1ee1fdada8f29c2ee881fbc6bc4113dde9 --- All this testing and deploying with pre-inst-env, and I never even ran make... This version builds successfully. Feel free to correct any grammar errors. (I did try.) eikcaz- doc/guix.texi | 317 +++++++++++++++++++- gnu/home/services/syncthing.scm | 17 +- gnu/services/syncthing.scm | 506 ++++++++++++++++++++++++++++++-- 3 files changed, 808 insertions(+), 32 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index b1b6d98e74..4756db30c0 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -136,6 +136,7 @@ Copyright @copyright{} 2024 Troy Figiel@* Copyright @copyright{} 2024 Sharlatan Hellseher@* Copyright @copyright{} 2024 45mg@* Copyright @copyright{} 2025 S=C3=B6ren Tempel@* +Copyright @copyright{} 2025 Zacchaeus@* =20 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -22666,12 +22667,324 @@ The group as which the Syncthing service is to b= e run. This assumes that the specified group exists. =20 @item @code{home} (default: @var{#f}) -Common configuration and data directory. The default configuration -directory is @file{$HOME} of the specified Syncthing @code{user}. +Sets the @code{HOME} variable for the syncthing daemon. The default is +@file{$HOME} of the specified Syncthing @code{user}. + +@item @code{config-file} (default: @var{#f}) +Either a file-like object that resolves to a Syncthing configuration xml +file, or a @code{syncthing-config-file} record (see below). If set to +@code{#f}, Guix will not try to generate a config file, and Syncthing +will generate a default one which will not be touched on reconfigure. +Specifying this in a system service moves Syncthing's common +configuration and data directory (@code{--home} in +@uref{https://docs.syncthing.net/users/syncthing.html}) to +@file{/var/lib/syncthnig-}. + +@end table +@end deftp + +In the below, only details specific to Guix, or related to how your +device will connect to unrelated devices (relays, nameservers), are +presented. Otherwise, you should consult +@uref{https://docs.syncthing.net/users/config.html, Syncthing config +documentation}; camelCase there is converted to kebab-case here. If you +are migrating to a Guix-powered Syncthing config file from a +GUI-configured one, you can see what changes were introduced by +@code{diff}ing them. Note that you will need to add whitespace with +4-space indentation to the one generated by Guix. This can be done +(requires @code{libxml2}) like so: + +@example +XMLLINT_INDENT=3D" " xmllint --format /path/to/new/config.xml | diff /p= ath/to/old/config.xml - +@end example + +When generating a config file through Guix, you can still modify +Syncthing from the GUI or through @code{introducer} and +@code{autoAcceptFolders} mechanisms, but such changes will be reset on +reconfigure. + +@deftp {Data Type} syncthing-config-file +Data type representing the configuration file read by the Syncthing +daemon. + +@table @asis +@item @code{folders} (default: @var{(list (syncthing-folder (id "default")= (label "Default Folder") (path "~/Sync")))} +The default here is the same as Syncthing's default. The value should +be a list of @code{syncthing-folder}s. + +@item @code{devices} (default: @var{'()} +This should be a list of @code{syncthing-device}s. Guix will +automatically add any devices specified in any `folders' to this list. +There are instances when you want to connect to a device despite not +(initially) sharing any folders (such as a device with +autoAcceptFolders). In such instances, you should specify those devices +here. If multiple versions of the same device (as determined by +comparing device id) are discovered, the one in this list is +prioritized. Otherwise, the first instance in the first folder is used. + +@item @code{gui-enabled} (default: @var{"true"}) +By default, any user on the computer can access the GUI and make changes +to Syncthing. If you leave this enabled, you should probably set +gui-user and gui-password (see below). + +@item @code{gui-tls} (default: @var{"false"}) +@item @code{gui-debugging} (default: @var{"false"}) +@item @code{gui-send-basic-auth-prompt} (default: @var{"false"}) +@item @code{gui-address} (default: @var{"127.0.0.1:8384"}) +@item @code{gui-user} (default: @var{#f}) +@item @code{gui-password} (default: @var{#f}) +A bcrypt hash of the GUI password. Remember that this will be globally +exposed in @file{/gnu/store}. +@item @code{gui-apikey} (default: @var{#f}) +You must specify this to use the Syncthing REST interface. Also exposed +in @file{/gnu/store}. + +@item @code{gui-theme} (default: @var{"default"}) +@item @code{ldap-enabled} (default: @var{#f}) +@item @code{ldap-address} (default: @var{""}) +@item @code{ldap-bind-dn} (default: @var{""}) +@item @code{ldap-transport} (default: @var{""}) +@item @code{ldap-insecure-skip-verify} (default: @var{""}) +@item @code{ldap-search-base-dn} (default: @var{""}) +@item @code{ldap-search-filter} (default: @var{""}) +@item @code{listen-address} (default: @var{"default"}) +@item @code{global-announce-server} (default: @var{"default"}) +@item @code{global-announce-enabled} (default: @var{"true"}) +Global discovery servers can be used to help connect devices at unknown +IP addresses by storing the last known IP address. + +@item @code{local-announce-enabled} (default: @var{"true"}) +This makes devices find each other very easily on the same LAN. Often, +this will allow you to just plug an Ethernet between two devices, or +connect one device to the other's hotspot and start syncing. + +@item @code{local-announce-port} (default: @var{"21027"}) +@item @code{local-announce-mcaddr} (default: @var{"[ff12::8384]:21027"}) +@item @code{max-send-kbps} (default: @var{"0"}) +@item @code{max-recv-kbps} (default: @var{"0"}) +@item @code{reconnection-interval-s} (default: @var{"60"}) +@item @code{relays-enabled} (default: @var{"true"}) +This option allows your Syncthing instance to coordinate with a global +network of relays to enable syncing between devices when all other +methods fail. + +@item @code{relay-reconnect-interval-m} (default: @var{"10"}) +@item @code{start-browser} (default: @var{"true"}) +@item @code{nat-enabled} (default: @var{"true"}) +@item @code{nat-lease-minutes} (default: @var{"60"}) +@item @code{nat-renewal-minutes} (default: @var{"30"}) +@item @code{nat-timeout-seconds} (default: @var{"10"}) +@item @code{ur-accepted} (default: @var{"0"}) +ur* options control usage reporting. Set to -1 to disable, or positive +to enable. The default (0) has reporting disabled, but you will be +asked to decide in the GUI. + +@item @code{ur-seen} (default: @var{"0"}) +@item @code{ur-unique-id} (default: @var{""}) +@item @code{ur-url} (default: @var{"https://data.syncthing.net/newdata"}) +@item @code{ur-post-insecurely} (default: @var{"false"}) +@item @code{ur-initial-delay-s} (default: @var{"1800"}) +@item @code{auto-upgrade-interval-h} (default: @var{"12"}) +@item @code{upgrade-to-pre-releases} (default: @var{"false"}) +@item @code{keep-temporaries-h} (default: @var{"24"}) +@item @code{cache-ignored-files} (default: @var{"false"}) +@item @code{progress-update-interval-s} (default: @var{"5"}) +@item @code{limit-bandwidth-in-lan} (default: @var{"false"}) +@item @code{min-home-disk-free-unit} (default: @var{"%"}) +@item @code{min-home-disk-free} (default: @var{"1"}) +@item @code{releases-url} (default: @var{"https://upgrades.syncthing.net/m= eta.json"}) +@item @code{overwrite-remote-device-names-on-connect} (default: @var{"fals= e"}) +@item @code{temp-index-min-blocks} (default: @var{"10"}) +@item @code{unacked-notification-id} (default: @var{"authenticationUserAnd= Password"}) +@item @code{traffic-class} (default: @var{"0"}) +@item @code{set-low-priority} (default: @var{"true"}) +@item @code{max-folder-concurrency} (default: @var{"0"}) +@item @code{crash-reporting-url} (default: @var{"https://crash.syncthing.n= et/newcrash"}) +@item @code{crash-reporting-enabled} (default: @var{"true"}) +@item @code{stun-keepalive-start-s} (default: @var{"180"}) +@item @code{stun-keepalive-min-s} (default: @var{"20"}) +@item @code{stun-server} (default: @var{"default"}) +@item @code{database-tuning} (default: @var{"auto"}) +@item @code{max-concurrent-incoming-request-kib} (default: @var{"0"}) +@item @code{announce-lan-addresses} (default: @var{"true"}) +@item @code{send-full-index-on-upgrade} (default: @var{"false"}) +@item @code{connection-limit-enough} (default: @var{"0"}) +@item @code{connection-limit-max} (default: @var{"0"}) +@item @code{insecure-allow-old-tls-versions} (default: @var{"false"}) +@item @code{connection-priority-tcp-lan} (default: @var{"10"}) +@item @code{connection-priority-quic-lan} (default: @var{"20"}) +@item @code{connection-priority-tcp-wan} (default: @var{"30"}) +@item @code{connection-priority-quic-wan} (default: @var{"40"}) +@item @code{connection-priority-relay} (default: @var{"50"}) +@item @code{connection-priority-upgrade-threshold} (default: @var{"0"}) +@item @code{default-folder} (default: @var{(syncthing-folder (label ""))}) +@item @code{default-device} (default: @var{(syncthing-device (id ""))}) +@item @code{default-ignores} (default: @var{"")}) +The default-* above do not affect folders and devices added by the Guix +interface. They will, however, affect folders and devices that are +added through the GUI, by an @code{introducer}, or a device with +@code{auto-accept-folders}. +@end table +@end deftp + +@deftp {Data Type} syncthing-folder +Data type representing a folder to be synced. + +@table @asis +@item @code{id} (default: @var{#f}) +This id cannot match the id of any other folder on this device. If left +unspecified, it will default to the label (see below). + +@item @code{label} +Human readable label for the folder. + +@item @code{path} +The path at which to store this folder. + +@item @code{type} (default: @var{"sendreceive"}) +@item @code{rescan-interval-s} (default: @var{"3600"}) +@item @code{fs-watcher-enabled} (default: @var{"true"}) +@item @code{fs-watcher-delay-s} (default: @var{"10"}) +@item @code{ignore-perms} (default: @var{"false"}) +@item @code{auto-normalize} (default: @var{"true"}) +@item @code{devices} (default: @var{'()}) +This should be a list of other Syncthing devices. You do not need to +specify the current device. Each device can be listed as a a +@code{syncthing-device} record or a @code{syncthing-folder-device} +record if you want files to be encrypted on disk. See below. + +@item @code{filesystem-type} (default: @var{"basic"}) +@item @code{min-disk-free-unit} (default: @var{"%"}) +@item @code{min-disk-free} (default: @var{"1"}) +@item @code{versioning-type} (default: @var{#f}) +@item @code{versioning-fs-path} (default: @var{""}) +@item @code{versioning-fs-type} (default: @var{"basic"}) +@item @code{versioning-cleanup-interval-s} (default: @var{"3600"}) +@item @code{versioning-cleanout-days} (default: @var{#f}) +@item @code{versioning-keep} (default: @var{#f}) +@item @code{versioning-max-age} (default: @var{#f}) +@item @code{versioning-command} (default: @var{#f}) +@item @code{copiers} (default: @var{"0"}) +@item @code{puller-max-pending-kib} (default: @var{"0"}) +@item @code{hashers} (default: @var{"0"}) +@item @code{order} (default: @var{"random"}) +@item @code{ignore-delete} (default: @var{"false"}) +@item @code{scan-progress-interval-s} (default: @var{"0"}) +@item @code{puller-pause-s} (default: @var{"0"}) +@item @code{max-conflicts} (default: @var{"10"}) +@item @code{disable-sparse-files} (default: @var{"false"}) +@item @code{disable-temp-indexes} (default: @var{"false"}) +@item @code{paused} (default: @var{"false"}) +@item @code{weak-hash-threshold-pct} (default: @var{"25"}) +@item @code{marker-name} (default: @var{".stfolder"}) +@item @code{copy-ownership-from-parent} (default: @var{"false"}) +@item @code{mod-time-window-s} (default: @var{"0"}) +@item @code{max-concurrent-writes} (default: @var{"2"}) +@item @code{disable-fsync} (default: @var{"false"}) +@item @code{block-pull-order} (default: @var{"standard"}) +@item @code{copy-range-method} (default: @var{"standard"}) +@item @code{case-sensitive-fs} (default: @var{"false"}) +@item @code{junctions-as-dirs} (default: @var{"false"}) +@item @code{sync-ownership} (default: @var{"false"}) +@item @code{send-ownership} (default: @var{"false"}) +@item @code{sync-xattrs} (default: @var{"false"}) +@item @code{send-xattrs} (default: @var{"false"}) +@item @code{xattr-filter-max-single-entry-size} (default: @var{"1024"}) +@item @code{xattr-filter-max-total-size} (default: @var{"4096")}) +@end table +@end deftp + +@deftp {Data Type} syncthing-device +Data type representing a device to sync with. + +@table @asis +@item @code{id} +A long hash tied to the keys generated by Syncthing on the first launch. +You can obtain this from the Syncthing GUI or by inspecting an existing +Syncthing configuration file. + +@item @code{name} (default: @var{""}) +Human readable device name for viewing in the GUI or in scheme. + +@item @code{compression} (default: @var{"metadata"}) +@item @code{introducer} (default: @var{"false"}) +@item @code{skip-introduction-removals} (default: @var{"false"}) +@item @code{introduced-by} (default: @var{""}) +@item @code{addresses} (default: @var{'("dynamic")}) +List of addresses at which to search for this device. The special value +``dynamic'' will have syncthing use several means to find the device. + +@item @code{paused} (default: @var{"false"}) +@item @code{auto-accept-folders} (default: @var{"false"}) +@item @code{max-send-kbps} (default: @var{"0"}) +@item @code{max-recv-kbps} (default: @var{"0"}) +@item @code{max-request-kib} (default: @var{"0"}) +@item @code{untrusted} (default: @var{"false"}) +@item @code{remote-gui-port} (default: @var{"0"}) +@item @code{num-connections} (default: @var{"0")}) + +@end table +@end deftp + +@deftp {Data Type} syncthing-folder-device +There are two pieces of configuration specific to the relationship +between a specific folder and a specific device. First, syncthing needs +to know if the remote device should be able to see the files given to +it. Second, syncthing needs to know from where that device originates. +See +@uref{https://docs.syncthing.net/users/config.html#config-option-folder.de= vice, +the Syncthing Documentation on this}. If you leave these default, then +you can just specify @code{syncthing-device}s instead of +@code{syncthing-folder-device}s in a @code{syncthing-folder}'s +@code{devices} field. + +@table @asis +@item @code{device} +device should be a @code{syncthing-device} for which this configuration +applies. + +@item @code{introduced-by} (default: @var{""}) +@item @code{encryption-password} (default: @var{""}) +Beware: specifying this field will include this password as plain text +(not encrypted) and globally visible in @file{/gnu/store/}. If +encryption-password is non-empty, then it will be used as a password to +encrypt file chunks as they are synced to that device. For more info on +syncing to devices you don't totally trust, see +@uref{https://docs.syncthing.net/users/untrusted.html, Syncthing +Documentation on Untrusted Devices}. Note that file transfers are +always end-to-end encrypted, regardless of this setting. =20 @end table @end deftp =20 +Here is a more complex example configuration for illustrative purposes: + +@lisp +(service syncthing-service-type + (let ((laptop (syncthing-device (id "VHOD2D6-...-7XRMDEN"))) + (desktop (syncthing-device (id "64SAZ37-...-FZJ5GUA") + (addresses '("tcp://example.com"= )))) + (bob-desktop (syncthing-device (id "KYIMEGO-...-FT77EAO")))) + (syncthing-configuration + (user "alice") + (config-file + (syncthing-config-file + (folders (list (syncthing-folder + (label "some-files") + (path "~/data") + (devices (list desktop laptop))) + (syncthing-folder + (label "critical-files") + (path "~/secrets") + (devices + (list desktop + laptop + (syncthing-folder-device + (device bob-desktop) + (encryption-password "mypassword"))= )))))))))) +@end lisp + + Furthermore, @code{(gnu services ssh)} provides the following services. @cindex SSH @cindex SSH server diff --git a/gnu/home/services/syncthing.scm b/gnu/home/services/syncthing.= scm index 8d66a167ce..dd6c752ee4 100644 --- a/gnu/home/services/syncthing.scm +++ b/gnu/home/services/syncthing.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2023 Ludovic Court=C3=A8s +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -24,9 +25,23 @@ (define-module (gnu home services syncthing) #:use-module (gnu home services shepherd) #:export (home-syncthing-service-type) #:re-export (syncthing-configuration - syncthing-configuration?)) + syncthing-configuration? + syncthing-config-file + syncthing-config-file? + syncthing-device + syncthing-device? + syncthing-folder + syncthing-folder? + syncthing-folder-device + syncthing-folder-device?)) =20 (define home-syncthing-service-type (service-type (inherit (system->home-service-type syncthing-service-type)) + ;; system->home-service-type does not convert special-files-service-typ= e to + ;; home-files-service-type, so redefine extensios + (extensions (list (service-extension home-files-service-type + syncthing-files-service) + (service-extension home-shepherd-service-type + syncthing-shepherd-service))) (default-value (for-home (syncthing-configuration))))) diff --git a/gnu/services/syncthing.scm b/gnu/services/syncthing.scm index a7a9c6aadd..2707591d51 100644 --- a/gnu/services/syncthing.scm +++ b/gnu/services/syncthing.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2021 Oleg Pykhalov ;;; Copyright =C2=A9 2023 Justin Veilleux +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -25,9 +26,20 @@ (define-module (gnu services syncthing) #:use-module (guix records) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (sxml simple) #:export (syncthing-configuration syncthing-configuration? - syncthing-service-type)) + syncthing-device + syncthing-device? + syncthing-config-file + syncthing-config-file? + syncthing-folder-device + syncthing-folder-device? + syncthing-folder + syncthing-folder? + syncthing-service-type + syncthing-shepherd-service + syncthing-files-service)) =20 ;;; Commentary: ;;; @@ -35,6 +47,411 @@ (define-module (gnu services syncthing) ;;; ;;; Code: =20 +(define-record-type* + syncthing-device make-syncthing-device + syncthing-device? + (id syncthing-device-id) + (name syncthing-device-name (default "")) + (compression syncthing-device-compression (default "metadata")) + (introducer syncthing-device-introducer (default "false")) + (skip-introduction-removals syncthing-device-skip-introduction-removals = (default "false")) + (introduced-by syncthing-device-introduced-by (default "")) + (addresses syncthing-device-addresses (default '("dynamic"))) + (paused syncthing-device-paused (default "false")) + (auto-accept-folders syncthing-device-auto-accept-folders (default "fals= e")) + (max-send-kbps syncthing-device-max-send-kbps (default "0")) + (max-recv-kbps syncthing-device-max-recv-kbps (default "0")) + (max-request-kib syncthing-device-max-request-kib (default "0")) + (untrusted syncthing-device-untrusted (default "false")) + (remote-gui-port syncthing-device-remote-gui-port (default "0")) + (num-connections syncthing-device-num-connections (default "0"))) + +(define syncthing-device->sxml + (match-record-lambda + (id name compression introducer skip-introduction-removals introduce= d-by addresses paused auto-accept-folders max-send-kbps max-recv-kbps max-r= equest-kib untrusted remote-gui-port num-connections) + `(device (@ (id ,id) + (name ,name) + (compression ,compression) + (introducer ,introducer) + (skipIntroductionRemovals ,skip-introduction-removals) + (introducedBy ,introduced-by)) + ,@(map (lambda (address) `(address ,address)) addresses) + (paused ,paused) + (autoAcceptFolders ,auto-accept-folders) + (maxSendKbps ,max-send-kbps) + (maxRecvKbps ,max-recv-kbps) + (maxRequestKiB ,max-request-kib) + (untrusted ,untrusted) + (remoteGUIPort ,remote-gui-port) + (numConnections ,num-connections)))) + +(define-record-type* + syncthing-folder-device make-syncthing-folder-device + syncthing-folder-device? + (device syncthing-folder-device-device) + (introduced-by syncthing-folder-device-introduced-by (default (syncthing= -device (id "")))) + (encryption-password syncthing-folder-device-encryption-password (defaul= t ""))) + +(define syncthing-folder-device->sxml + (match-record-lambda + (device introduced-by encryption-password) + `(device (@ (id ,(syncthing-device-id device)) + (introducedBy ,(syncthing-device-id introduced-by))) + (encryptionPassword ,encryption-password)))) + +(define-record-type* + syncthing-folder make-syncthing-folder + syncthing-folder? + (id syncthing-folder-id (default #f)) + (label syncthing-folder-label) + (path syncthing-folder-path) + (type syncthing-folder-type (default "sendreceive")) + (rescan-interval-s syncthing-folder-rescan-interval-s (default "3600")) + (fs-watcher-enabled syncthing-folder-fs-watcher-enabled (default "true")) + (fs-watcher-delay-s syncthing-folder-fs-watcher-delay-s (default "10")) + (fs-watcher-timeout-s syncthing-folder-fs-watcher-timeout-s (default "0"= )) + (ignore-perms syncthing-folder-ignore-perms (default "false")) + (auto-normalize syncthing-folder-auto-normalize (default "true")) + (devices syncthing-folder-devices (default '()) + (sanitize (lambda (folder-device-list) + (map (lambda (device) + (if (syncthing-folder-device? device) + device + (syncthing-folder-device (device device)= ))) + folder-device-list)))) + (filesystem-type syncthing-folder-filesystem-type (default "basic")) + (min-disk-free-unit syncthing-folder-min-disk-free-unit (default "%")) + (min-disk-free syncthing-folder-min-disk-free (default "1")) + (versioning-type syncthing-folder-versioning-type (default #f)) + (versioning-fs-path syncthing-folder-versioning-fs-path (default "")) + (versioning-fs-type syncthing-folder-versioning-fs-type (default "basic"= )) + (versioning-cleanup-interval-s syncthing-folder-versioning-cleanup-inter= val-s (default "3600")) + (versioning-cleanout-days syncthing-folder-versioning-cleanout-days (def= ault #f)) + (versioning-keep syncthing-folder-versioning-keep (default #f)) + (versioning-max-age syncthing-folder-versioning-max-age (default #f)) + (versioning-command syncthing-folder-versioning-command (default #f)) + (copiers syncthing-folder-copiers (default "0")) + (puller-max-pending-kib syncthing-folder-puller-max-pending-kib (default= "0")) + (hashers syncthing-folder-hashers (default "0")) + (order syncthing-folder-order (default "random")) + (ignore-delete syncthing-folder-ignore-delete (default "false")) + (scan-progress-interval-s syncthing-folder-scan-progress-interval-s (def= ault "0")) + (puller-pause-s syncthing-folder-puller-pause-s (default "0")) + (max-conflicts syncthing-folder-max-conflicts (default "10")) + (disable-sparse-files syncthing-folder-disable-sparse-files (default "fa= lse")) + (disable-temp-indexes syncthing-folder-disable-temp-indexes (default "fa= lse")) + (paused syncthing-folder-paused (default "false")) + (weak-hash-threshold-pct syncthing-folder-weak-hash-threshold-pct (defau= lt "25")) + (marker-name syncthing-folder-marker-name (default ".stfolder")) + (copy-ownership-from-parent syncthing-folder-copy-ownership-from-parent = (default "false")) + (mod-time-window-s syncthing-folder-mod-time-window-s (default "0")) + (max-concurrent-writes syncthing-folder-max-concurrent-writes (default "= 2")) + (disable-fsync syncthing-folder-disable-fsync (default "false")) + (block-pull-order syncthing-folder-block-pull-order (default "standard")) + (copy-range-method syncthing-folder-copy-range-method (default "standard= ")) + (case-sensitive-fs syncthing-folder-case-sensitive-fs (default "false")) + (junctions-as-dirs syncthing-folder-junctions-as-dirs (default "false")) + (sync-ownership syncthing-folder-sync-ownership (default "false")) + (send-ownership syncthing-folder-send-ownership (default "false")) + (sync-xattrs syncthing-folder-sync-xattrs (default "false")) + (send-xattrs syncthing-folder-send-xattrs (default "false")) + (xattr-filter-max-single-entry-size syncthing-folder-xattr-filter-max-si= ngle-entry-size (default "1024")) + (xattr-filter-max-total-size syncthing-folder-xattr-filter-max-total-siz= e (default "4096"))) + +;; Some parameters, when empty, are fully omitted from the config file. I= t is +;; unknown if this causes a functional difference, but stick to the normal +;; program's behavior to be safe. +(define (maybe-param symbol value) + (if value `((param (@ (key ,(symbol->string symbol)) (val ,value)) "")) = '())) + +(define syncthing-folder->sxml + (match-record-lambda + (id + label path type rescan-interval-s fs-watcher-enabled fs-watcher-del= ay-s + fs-watcher-timeout-s ignore-perms auto-normalize devices filesystem= -type + min-disk-free-unit min-disk-free versioning-type versioning-fs-path + versioning-fs-type versioning-cleanup-interval-s versioning-cleanou= t-days + versioning-keep versioning-max-age versioning-command copiers + puller-max-pending-kib hashers order ignore-delete scan-progress-in= terval-s + puller-pause-s max-conflicts disable-sparse-files disable-temp-inde= xes paused + weak-hash-threshold-pct marker-name copy-ownership-from-parent mod-= time-window-s + max-concurrent-writes disable-fsync block-pull-order copy-range-met= hod + case-sensitive-fs junctions-as-dirs sync-ownership send-ownership s= ync-xattrs + send-xattrs xattr-filter-max-single-entry-size xattr-filter-max-tot= al-size) + `(folder (@ (id ,(if id id label)) + (label ,label) + (path ,path) + (type ,type) + (rescanIntervalS ,rescan-interval-s) + (fsWatcherEnabled ,fs-watcher-enabled) + (fsWatcherDelayS ,fs-watcher-delay-s) + (fsWatcherTimeoutS ,fs-watcher-timeout-s) + (ignorePerms ,ignore-perms) + (autoNormalize ,auto-normalize)) + (filesystemType ,filesystem-type) + ,@(map syncthing-folder-device->sxml + devices) + (minDiskFree (@ (unit ,min-disk-free-unit)) + ,min-disk-free) + (versioning ,@(if versioning-type + `((@ (type ,versioning-type))) + '()) + ,@(maybe-param 'cleanoutDays versioning-cleanout-= days) + ,@(maybe-param 'keep versioning-keep) + ,@(maybe-param 'maxAge versioning-max-age) + ,@(maybe-param 'command versioning-command) + (cleanupIntervalS ,versioning-cleanup-interval-s) + (fsPath ,versioning-fs-path) + (fsType ,versioning-fs-type)) + (copiers ,copiers) + (pullerMaxPendingKiB ,puller-max-pending-kib) + (hashers ,hashers) + (order ,order) + (ignoreDelete ,ignore-delete) + (scanProgressIntervalS ,scan-progress-interval-s) + (pullerPauseS ,puller-pause-s) + (maxConflicts ,max-conflicts) + (disableSparseFiles ,disable-sparse-files) + (disableTempIndexes ,disable-temp-indexes) + (paused ,paused) + (weakHashThresholdPct ,weak-hash-threshold-pct) + (markerName ,marker-name) + (copyOwnershipFromParent ,copy-ownership-from-parent) + (modTimeWindowS ,mod-time-window-s) + (maxConcurrentWrites ,max-concurrent-writes) + (disableFsync ,disable-fsync) + (blockPullOrder ,block-pull-order) + (copyRangeMethod ,copy-range-method) + (caseSensitiveFS ,case-sensitive-fs) + (junctionsAsDirs ,junctions-as-dirs) + (syncOwnership ,sync-ownership) + (sendOwnership ,send-ownership) + (syncXattrs ,sync-xattrs) + (sendXattrs ,send-xattrs) + (xattrFilter (maxSingleEntrySize ,xattr-filter-max-single-ent= ry-size) + (maxTotalSize ,xattr-filter-max-total-size))))) + +(define-record-type* + syncthing-config-file make-syncthing-config-file + syncthing-config-file? + (folders syncthing-config-folders + ; this matches syncthing's default + (default (list (syncthing-folder (id "default") + (label "Default Folder") + (path "~/Sync"))))) + (devices syncthing-config-devices + (default '())) + (gui-enabled syncthing-config-gui-enabled (default "true")) + (gui-tls syncthing-config-gui-tls (default "false")) + (gui-debugging syncthing-config-gui-debugging (default "false")) + (gui-send-basic-auth-prompt syncthing-config-gui-send-basic-auth-prompt = (default "false")) + (gui-address syncthing-config-gui-address (default "127.0.0.1:8384")) + (gui-user syncthing-config-gui-user (default #f)) + (gui-password syncthing-config-gui-password (default #f)) + (gui-apikey syncthing-config-gui-apikey (default #f)) + (gui-theme syncthing-config-gui-theme (default "default")) + (ldap-enabled syncthing-config-ldap-enabled (default #f)) + (ldap-address syncthing-config-ldap-address (default "")) + (ldap-bind-dn syncthing-config-ldap-bind-dn (default "")) + (ldap-transport syncthing-config-ldap-transport (default "")) + (ldap-insecure-skip-verify syncthing-config-ldap-insecure-skip-verify (d= efault "")) + (ldap-search-base-dn syncthing-config-ldap-search-base-dn (default "")) + (ldap-search-filter syncthing-config-ldap-search-filter (default "")) + (listen-address syncthing-config-listen-address (default "default")) + (global-announce-server syncthing-config-global-announce-server (default= "default")) + (global-announce-enabled syncthing-config-global-announce-enabled (defau= lt "true")) + (local-announce-enabled syncthing-config-local-announce-enabled (default= "true")) + (local-announce-port syncthing-config-local-announce-port (default "2102= 7")) + (local-announce-mcaddr syncthing-config-local-announce-mcaddr (default "= [ff12::8384]:21027")) + (max-send-kbps syncthing-config-max-send-kbps (default "0")) + (max-recv-kbps syncthing-config-max-recv-kbps (default "0")) + (reconnection-interval-s syncthing-config-reconnection-interval-s (defau= lt "60")) + (relays-enabled syncthing-config-relays-enabled (default "true")) + (relay-reconnect-interval-m syncthing-config-relay-reconnect-interval-m = (default "10")) + (start-browser syncthing-config-start-browser (default "true")) + (nat-enabled syncthing-config-nat-enabled (default "true")) + (nat-lease-minutes syncthing-config-nat-lease-minutes (default "60")) + (nat-renewal-minutes syncthing-config-nat-renewal-minutes (default "30")) + (nat-timeout-seconds syncthing-config-nat-timeout-seconds (default "10")) + (ur-accepted syncthing-config-ur-accepted (default "0")) + (ur-seen syncthing-config-ur-seen (default "0")) + (ur-unique-id syncthing-config-ur-unique-id (default "")) + (ur-url syncthing-config-ur-url (default "https://data.syncthing.net/new= data")) + (ur-post-insecurely syncthing-config-ur-post-insecurely (default "false"= )) + (ur-initial-delay-s syncthing-config-ur-initial-delay-s (default "1800")) + (auto-upgrade-interval-h syncthing-config-auto-upgrade-interval-h (defau= lt "12")) + (upgrade-to-pre-releases syncthing-config-upgrade-to-pre-releases (defau= lt "false")) + (keep-temporaries-h syncthing-config-keep-temporaries-h (default "24")) + (cache-ignored-files syncthing-config-cache-ignored-files (default "fals= e")) + (progress-update-interval-s syncthing-config-progress-update-interval-s = (default "5")) + (limit-bandwidth-in-lan syncthing-config-limit-bandwidth-in-lan (default= "false")) + (min-home-disk-free-unit syncthing-config-min-home-disk-free-unit (defau= lt "%")) + (min-home-disk-free syncthing-config-min-home-disk-free (default "1")) + (releases-url syncthing-config-releases-url (default "https://upgrades.s= yncthing.net/meta.json")) + (overwrite-remote-device-names-on-connect syncthing-config-overwrite-rem= ote-device-names-on-connect (default "false")) + (temp-index-min-blocks syncthing-config-temp-index-min-blocks (default "= 10")) + (unacked-notification-id syncthing-config-unacked-notification-id (defau= lt "authenticationUserAndPassword")) + (traffic-class syncthing-config-traffic-class (default "0")) + (set-low-priority syncthing-config-set-low-priority (default "true")) + (max-folder-concurrency syncthing-config-max-folder-concurrency (default= "0")) + (crash-reporting-url syncthing-config-crash-reporting-url (default "http= s://crash.syncthing.net/newcrash")) + (crash-reporting-enabled syncthing-config-crash-reporting-enabled (defau= lt "true")) + (stun-keepalive-start-s syncthing-config-stun-keepalive-start-s (default= "180")) + (stun-keepalive-min-s syncthing-config-stun-keepalive-min-s (default "20= ")) + (stun-server syncthing-config-stun-server (default "default")) + (database-tuning syncthing-config-database-tuning (default "auto")) + (max-concurrent-incoming-request-kib syncthing-config-max-concurrent-inc= oming-request-kib (default "0")) + (announce-lan-addresses syncthing-config-announce-lan-addresses (default= "true")) + (send-full-index-on-upgrade syncthing-config-send-full-index-on-upgrade = (default "false")) + (connection-limit-enough syncthing-config-connection-limit-enough (defau= lt "0")) + (connection-limit-max syncthing-config-connection-limit-max (default "0"= )) + (insecure-allow-old-tlsVersions syncthing-config-insecure-allow-old-tlsV= ersions (default "false")) + (connection-priority-tcp-lan syncthing-config-connection-priority-tcp-la= n (default "10")) + (connection-priority-quic-lan syncthing-config-connection-priority-quic-= lan (default "20")) + (connection-priority-tcp-wan syncthing-config-connection-priority-tcp-wa= n (default "30")) + (connection-priority-quic-wan syncthing-config-connection-priority-quic-= wan (default "40")) + (connection-priority-relay syncthing-config-connection-priority-relay (d= efault "50")) + (connection-priority-upgrade-threshold syncthing-config-connection-prior= ity-upgrade-threshold (default "0")) + (default-folder syncthing-config-default-folder + (default (syncthing-folder (label "") (path "~")))) + (default-device syncthing-config-default-device + (default (syncthing-device (id "")))) + (default-ignores syncthing-config-default-ignores (default ""))) + +(define syncthing-config-file->sxml + (match-record-lambda + (folders + devices gui-enabled gui-tls gui-debugging gui-send-basic-auth-prompt + gui-address gui-user gui-password gui-apikey gui-theme ldap-enabled + ldap-address ldap-bind-dn ldap-transport ldap-insecure-skip-verify + ldap-search-base-dn ldap-search-filter listen-address global-announ= ce-server + global-announce-enabled local-announce-enabled local-announce-port + local-announce-mcaddr max-send-kbps max-recv-kbps reconnection-inte= rval-s + relays-enabled relay-reconnect-interval-m start-browser nat-enabled + nat-lease-minutes nat-renewal-minutes nat-timeout-seconds ur-accept= ed + ur-seen ur-unique-id ur-url ur-post-insecurely ur-initial-delay-s + auto-upgrade-interval-h upgrade-to-pre-releases keep-temporaries-h + cache-ignored-files progress-update-interval-s limit-bandwidth-in-l= an + min-home-disk-free-unit min-home-disk-free releases-url + overwrite-remote-device-names-on-connect temp-index-min-blocks + unacked-notification-id traffic-class set-low-priority max-folder-c= oncurrency + crash-reporting-url crash-reporting-enabled stun-keepalive-start-s + stun-keepalive-min-s stun-server database-tuning + max-concurrent-incoming-request-kib announce-lan-addresses + send-full-index-on-upgrade connection-limit-enough connection-limit= -max + insecure-allow-old-tlsVersions connection-priority-tcp-lan + connection-priority-quic-lan connection-priority-tcp-wan + connection-priority-quic-wan connection-priority-relay + connection-priority-upgrade-threshold default-folder default-device + default-ignores) + `(configuration (@ (version "37")) + ,@(map syncthing-folder->sxml + folders) + ;; collect any devices in any folders, as well as any + ;; devices explicitly added. + ,@(map syncthing-device->sxml + (delete-duplicates + (append devices + (apply append + (map (lambda (folder) + (map syncthing-folder-de= vice-device + (syncthing-folder-d= evices folder))) + folders))) + ;; devices are the same if their id's are equal + (lambda (device1 device2) + (string=3D (syncthing-device-id device1) + (syncthing-device-id device2))))) + (gui (@ (enabled ,gui-enabled) + (tls ,gui-tls) + (debugging ,gui-debugging) + (sendBasicAuthPrompt ,gui-send-basic-auth-prom= pt)) + (address ,gui-address) + ,@(if gui-user `((user ,gui-user)) '()) + ,@(if gui-password `((password ,gui-password)) '(= )) + ,@(if gui-apikey `((apikey ,gui-apikey)) '()) + (theme ,gui-theme)) + (ldap ,(if ldap-enabled + `((address ,ldap-address) + (bindDN ,ldap-bind-dn) + ,@(if ldap-transport + `((transport ,ldap-transport)) + '()) + ,@(if ldap-insecure-skip-verify + `((insecureSkipVerify ,ldap-insecur= e-skip-verify)) + '()) + ,@(if ldap-search-base-dn + `((searchBaseDN ,ldap-search-base-d= n)) + '()) + ,@(if ldap-search-filter + `((searchFilter ,ldap-search-filter= )) + '())) + "")) + (options (listenAddress ,listen-address) + (globalAnnounceServer ,global-announce-server) + (globalAnnounceEnabled ,global-announce-enabl= ed) + (localAnnounceEnabled ,local-announce-enabled) + (localAnnouncePort ,local-announce-port) + (localAnnounceMCAddr ,local-announce-mcaddr) + (maxSendKbps ,max-send-kbps) + (maxRecvKbps ,max-recv-kbps) + (reconnectionIntervalS ,reconnection-interval= -s) + (relaysEnabled ,relays-enabled) + (relayReconnectIntervalM ,relay-reconnect-int= erval-m) + (startBrowser ,start-browser) + (natEnabled ,nat-enabled) + (natLeaseMinutes ,nat-lease-minutes) + (natRenewalMinutes ,nat-renewal-minutes) + (natTimeoutSeconds ,nat-timeout-seconds) + (urAccepted ,ur-accepted) + (urSeen ,ur-seen) + (urUniqueID ,ur-unique-id) + (urURL ,ur-url) + (urPostInsecurely ,ur-post-insecurely) + (urInitialDelayS ,ur-initial-delay-s) + (autoUpgradeIntervalH ,auto-upgrade-interval-= h) + (upgradeToPreReleases ,upgrade-to-pre-release= s) + (keepTemporariesH ,keep-temporaries-h) + (cacheIgnoredFiles ,cache-ignored-files) + (progressUpdateIntervalS ,progress-update-int= erval-s) + (limitBandwidthInLan ,limit-bandwidth-in-lan) + (minHomeDiskFree (@ (unit ,min-home-disk-free= -unit)) + ,min-home-disk-free) + (releasesURL ,releases-url) + (overwriteRemoteDeviceNamesOnConnect ,overwri= te-remote-device-names-on-connect) + (tempIndexMinBlocks ,temp-index-min-blocks) + (unackedNotificationID ,unacked-notification-= id) + (trafficClass ,traffic-class) + (setLowPriority ,set-low-priority) + (maxFolderConcurrency ,max-folder-concurrency) + (crashReportingURL ,crash-reporting-url) + (crashReportingEnabled ,crash-reporting-enabl= ed) + (stunKeepaliveStartS ,stun-keepalive-start-s) + (stunKeepaliveMinS ,stun-keepalive-min-s) + (stunServer ,stun-server) + (databaseTuning ,database-tuning) + (maxConcurrentIncomingRequestKiB ,max-concurr= ent-incoming-request-kib) + (announceLANAddresses ,announce-lan-addresses) + (sendFullIndexOnUpgrade ,send-full-index-on-u= pgrade) + (connectionLimitEnough ,connection-limit-enou= gh) + (connectionLimitMax ,connection-limit-max) + (insecureAllowOldTLSVersions ,insecure-allow-= old-tlsVersions) + (connectionPriorityTcpLan ,connection-priorit= y-tcp-lan) + (connectionPriorityQuicLan ,connection-priori= ty-quic-lan) + (connectionPriorityTcpWan ,connection-priorit= y-tcp-wan) + (connectionPriorityQuicWan ,connection-priori= ty-quic-wan) + (connectionPriorityRelay ,connection-priority= -relay) + (connectionPriorityUpgradeThreshold ,connecti= on-priority-upgrade-threshold)) + (defaults + ,(syncthing-folder->sxml default-folder) + ,(syncthing-device->sxml default-device) + (ignores ,default-ignores))))) + + +(define (serialize-syncthing-config-file config) + (with-output-to-string + (lambda () + (sxml->xml (cons '*TOP* (list (syncthing-config-file->sxml config)))= )))) + (define-record-type* syncthing-configuration make-syncthing-configuration syncthing-configuration? @@ -50,12 +467,14 @@ (define-record-type* (default "users")) (home syncthing-configuration-home ;string (default #f)) + (config-file syncthing-configuration-config-file + (default #f)) ; syncthing-config-file or = file-like (home-service? syncthing-configuration-home-service? (default for-home?) (innate))) =20 (define syncthing-shepherd-service (match-record-lambda - (syncthing arguments logflags user group home home-service?) + (syncthing arguments logflags user group home home-service? config-f= ile) (list (shepherd-service (provision (if home-service? @@ -64,39 +483,68 @@ (define syncthing-shepherd-service (string-append "syncthing-" user))))) (documentation "Run syncthing.") (requirement (if home-service? '() '(loopback user-processes))) - (start #~(make-forkexec-constructor - (append (list (string-append #$syncthing "/bin/syncthing") - "--no-browser" - "--no-restart" - (string-append "--logflags=3D" (number->stri= ng #$logflags))) - '#$arguments) - #:user #$(and (not home-service?) user) - #:group #$(and (not home-service?) group) - #:environment-variables - (append - (list - (string-append "HOME=3D" - (or #$home - (passwd:dir - (getpw (if (and #$home-service? - (not #$user)) - (getuid) - #$user))))) - "SSL_CERT_DIR=3D/etc/ssl/certs" - "SSL_CERT_FILE=3D/etc/ssl/certs/ca-certifica= tes.crt") - (filter (negate ;XXX: 'remove' is not in (gu= ile) - (lambda (str) - (or (string-prefix? "HOME=3D" str) - (string-prefix? "SSL_CERT_DIR=3D" s= tr) - (string-prefix? "SSL_CERT_FILE=3D" = str)))) - (environ))))) + (start #~(lambda _ + ;; if we are managing the config, and it's not a home + ;; service, then exepect the config file at + ;; /var/lib/syncthing-. This makes sure the owners= hip + ;; is correct + (unless (or #$(not config-file) #$home-service?) + (system* "chown" #$user (string-append "/var/lib/syncth= ing-" #$user)) + (system* "chmod" "700" (string-append "/var/lib/syncthi= ng-" #$user))) + (make-forkexec-constructor + (append (list (string-append #$syncthing "/bin/syncthing= ") + "--no-browser" + "--no-restart" + (string-append "--logflags=3D" (number->st= ring #$logflags))) + (if (or #$(not config-file) #$home-service?) '() + (list (string-append "--home=3D/var/lib/sync= thing-" #$user))) + '#$arguments) + #:user #$(and (not home-service?) user) + #:group #$(and (not home-service?) group) + #:environment-variables + (append + (list + (string-append "HOME=3D" + (or #$home + (passwd:dir + (getpw (if (and #$home-service? + (not #$user)) + (getuid) + #$user))))) + "SSL_CERT_DIR=3D/etc/ssl/certs" + "SSL_CERT_FILE=3D/etc/ssl/certs/ca-certificates.crt") + (filter (negate ;XXX: 'remove' is not in (guile) + (lambda (str) + (or (string-prefix? "HOME=3D" str) + (string-prefix? "SSL_CERT_DIR=3D" str) + (string-prefix? "SSL_CERT_FILE=3D" str))= )) + (environ)))))) (respawn? #f) (stop #~(make-kill-destructor)))))) =20 + +(define syncthing-files-service + (match-record-lambda (config-file user home ho= me-service?) + (if config-file + ;; when used as a system service, this service might be executed + ;; before a user's home even exists, causing it to be owned by roo= t, + ;; and the skeletons to never be applied to that user's home. In = such + ;; cases, put the config at /var/lib/syncthnig-/config.xml + `((,(if home-service? + ".config/syncthing/config.xml" + (string-append "/var/lib/syncthing-" user "/config.xml")) + ,(if (file-like? config-file) + config-file + (plain-file "syncthin-config.xml" (serialize-syncthing-con= fig-file + config-file))))) + '()))) + (define syncthing-service-type (service-type (name 'syncthing) (extensions (list (service-extension shepherd-root-service= -type - syncthing-shepherd-se= rvice))) + syncthing-shepherd-se= rvice) + (service-extension special-files-service= -type + syncthing-files-servi= ce))) (description "Run @uref{https://github.com/syncthing/syncthing, Syncth= ing} decentralized continuous file system synchronization."))) --=20 2.48.1 From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v8] services: syncthing: Add support for config file generation. Resent-From: Leo Famulari Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Fri, 14 Feb 2025 08:10:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Zacchaeus Scheffer Cc: Bruno Victal , 75959@debbugs.gnu.org Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.173952059919769 (code B ref 75959); Fri, 14 Feb 2025 08:10:02 +0000 Received: (at 75959) by debbugs.gnu.org; 14 Feb 2025 08:09:59 +0000 Received: from localhost ([127.0.0.1]:46894 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tiqlq-00058m-1G for submit@debbugs.gnu.org; Fri, 14 Feb 2025 03:09:59 -0500 Received: from fout-a5-smtp.messagingengine.com ([103.168.172.148]:43655) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tiqlm-00058Q-EU for 75959@debbugs.gnu.org; Fri, 14 Feb 2025 03:09:55 -0500 Received: from phl-compute-13.internal (phl-compute-13.phl.internal [10.202.2.53]) by mailfout.phl.internal (Postfix) with ESMTP id 2DF11138088F; Fri, 14 Feb 2025 03:09:49 -0500 (EST) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-13.internal (MEProxy); Fri, 14 Feb 2025 03:09:49 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=famulari.name; h=cc:cc:content-transfer-encoding:content-type:content-type :date:date:from:from:in-reply-to:in-reply-to:message-id :mime-version:references:reply-to:subject:subject:to:to; s= mesmtp; t=1739520589; x=1739606989; bh=UoRtBfD/EutqZELGLOTA1x4JO zcWb6WZDTIqvxgZhtc=; b=OZl3kvppcJDuK31eAMY5bMEh9s0ap0HkKp/ZBxI8K 1dv7aJ5LI1PQiGZHMIp4z9sZx7DHgUDhOWkXy9MUheex81Q+gFRvEB6WmUj+62O+ ViNzkSu1xW5u5C84TRjbZ9jPyhqPgIjxQaWPXdWpaCKqMEbWJdQ3g2OiPtMO8SI/ n8= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1739520589; x= 1739606989; bh=UoRtBfD/EutqZELGLOTA1x4JOzcWb6WZDTIqvxgZhtc=; b=J rkagRvY8ai2ybuw/+DZ5ceJbtnkTJxB3jOMWy3n8BkwpTKYyeSIMeVd++N2GeN5l omORfUTHUl2ORaCtb22+5pViodYp8Fgvdt+rCeuNmW4eI8N4yykmrMr0FFeobrKC ms3uzxm0kusty0wG17+3/vlFQ7vLY0SRMO0h6+HvfHJk9SrtfuKQ2QxrVqBZoAKv v7yFDA027zhbYlGoZygUurJTwaGMZsYcxUrtmWBEpaBxiIxYU+nSNTAzUHmpPub8 zUMLyma8CpI/kJ2y3ldCX1gUmJqzyBT8jNQeU8NgUfG1a28oqiVMxtX0ADr+M2qZ Q/0B3427ZnPFvXXJ7SlPg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdegledufecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdp uffrtefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecunecujfgurhepfffhvf evuffkfhggtggugfgjsehmkeerredttddvnecuhfhrohhmpefnvghoucfhrghmuhhlrghr ihcuoehlvghosehfrghmuhhlrghrihdrnhgrmhgvqeenucggtffrrghtthgvrhhnpeegte duteeuueefuddtvdffleejkeelieetleeigeffhfeuhfdvhfejtddugefggeenucffohhm rghinhepghhnuhdrohhrghenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmh grihhlfhhrohhmpehlvghosehfrghmuhhlrghrihdrnhgrmhgvpdhnsggprhgtphhtthho peefpdhmohguvgepshhmthhpohhuthdprhgtphhtthhopegvihhktggriiesiigrtggthh grvgdruhhspdhrtghpthhtohepmhhirhgrihesmhgrkhhinhgrthgrrdgvuhdprhgtphht thhopeejheelheelseguvggssghughhsrdhgnhhurdhorhhg X-ME-Proxy: Feedback-ID: i819c4023:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 14 Feb 2025 03:09:48 -0500 (EST) Date: Fri, 14 Feb 2025 03:09:46 -0500 From: Leo Famulari Message-ID: References: <87o6z9f3o4.fsf@zacchae.us> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="TZ7VRsB/KqHHHo74" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <87o6z9f3o4.fsf@zacchae.us> X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) --TZ7VRsB/KqHHHo74 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Tue, Feb 11, 2025 at 12:31:23AM -0500, Zacchaeus Scheffer wrote: > Subject: [PATCH v8] services: syncthing: Add support for config file > generation. > > * gnu/services/syncthing.scm: (syncthing-config-file, > syncthing-folder, syncthing-device, syncthing-folder-device): New > records; (syncthing-service-type): Add special-files-service-type > extension for the config file; (syncthing-files-service): Add service > to create config file. > * gnu/home/services/syncthing.scm: (home-syncthing-service-type): > Extend home-files-services-type and re-exported more things from > gnu/services/syncthing.scm. > * doc/guix.texi: (syncthing-service-type): Document changes. Great! I read through the documentation and made numerous stylistic edits, and also added some references, links, and markup. See the attached diff. I did not change the structure of the docs. Please let me know what you think. > + (start #~(lambda _ > + ;; if we are managing the config, and it's not a home > + ;; service, then exepect the config file at > + ;; /var/lib/syncthing-. This makes sure the ownership > + ;; is correct > + (unless (or #$(not config-file) #$home-service?) > + (system* "chown" #$user (string-append "/var/lib/syncthing-" #$user)) > + (system* "chmod" "700" (string-append "/var/lib/syncthing-" #$user))) Please use the Guile procedures chown and chmod here, rather than shelling out. Also, I think the folder's group should be set as well using the chown procedure; right now it remains owned by root. There are examples in 'gnu/services'. https://www.gnu.org/software/guile/manual/html_node/File-System.html#index-chmod https://www.gnu.org/software/guile/manual/html_node/File-System.html#index-chown > + (make-forkexec-constructor > + (append (list (string-append #$syncthing "/bin/syncthing") > + "--no-browser" > + "--no-restart" It will be helpful to add brief Scheme code comments explaining what these options do. --TZ7VRsB/KqHHHo74 Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="guix.texi.diff" Content-Transfer-Encoding: 8bit diff --git a/doc/guix.texi b/doc/guix.texi index cf7c6e276a..112056e8ca 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -22739,7 +22739,7 @@ Networking Services The @code{(gnu services syncthing)} module provides the following services: @cindex syncthing -You might want a syncthing daemon if you have files between two or more +You might want a Syncthing daemon if you have files between two or more computers and want to sync them in real time, safely protected from prying eyes. @@ -22785,41 +22785,43 @@ Networking Services This assumes that the specified group exists. @item @code{home} (default: @var{#f}) -Sets the @code{HOME} variable for the syncthing daemon. The default is +Sets the @code{HOME} variable for the Syncthing daemon. The default is @file{$HOME} of the specified Syncthing @code{user}. @item @code{config-file} (default: @var{#f}) -Either a file-like object that resolves to a Syncthing configuration xml +Either a file-like object that resolves to a Syncthing configuration XML file, or a @code{syncthing-config-file} record (see below). If set to @code{#f}, Guix will not try to generate a config file, and Syncthing -will generate a default one which will not be touched on reconfigure. -Specifying this in a system service moves Syncthing's common -configuration and data directory (@code{--home} in +will generate a default configuration which will not be touched on +reconfigure. Specifying this in a system service moves Syncthing's +common configuration and data directory (@code{--home} in @uref{https://docs.syncthing.net/users/syncthing.html}) to -@file{/var/lib/syncthnig-}. +@file{/var/lib/syncthing-}. @end table @end deftp -In the below, only details specific to Guix, or related to how your -device will connect to unrelated devices (relays, nameservers), are -presented. Otherwise, you should consult +This section documents a subset of the Syncthing configuration +options—specifically those related to Guix or those affecting how your +computer will connect to other computers over the network (such as +Syncthing relays or discovery servers). The configuration is fully +documented in the upstream @uref{https://docs.syncthing.net/users/config.html, Syncthing config -documentation}; camelCase there is converted to kebab-case here. If you -are migrating to a Guix-powered Syncthing config file from a -GUI-configured one, you can see what changes were introduced by -@code{diff}ing them. Note that you will need to add whitespace with -4-space indentation to the one generated by Guix. This can be done -(requires @code{libxml2}) like so: +documentation}. camelCase there is converted to kebab-case here. If you +are migrating from a Syncthing-managed configuration to one managed by +Guix, you can check what changes were introduced by @code{diff}ing the +respective @file{config.xml} files. Note that you will need to add +whitespace with 4-space indentation to the file generated by Guix, using +the @code{xmllint} program from the @code{libxml2} package like so: @example XMLLINT_INDENT=" " xmllint --format /path/to/new/config.xml | diff /path/to/old/config.xml - @end example -When generating a config file through Guix, you can still modify -Syncthing from the GUI or through @code{introducer} and -@code{autoAcceptFolders} mechanisms, but such changes will be reset on -reconfigure. +When generating a configuration file through Guix, you can still +temporarily modify Syncthing from the GUI or through @code{introducer} +and @code{autoAcceptFolders} mechanisms, but such changes will be reset +on reconfigure. @deftp {Data Type} syncthing-config-file Data type representing the configuration file read by the Syncthing @@ -22837,13 +22839,13 @@ Networking Services (initially) sharing any folders (such as a device with autoAcceptFolders). In such instances, you should specify those devices here. If multiple versions of the same device (as determined by -comparing device id) are discovered, the one in this list is +comparing device ID) are discovered, the one in this list is prioritized. Otherwise, the first instance in the first folder is used. @item @code{gui-enabled} (default: @var{"true"}) By default, any user on the computer can access the GUI and make changes to Syncthing. If you leave this enabled, you should probably set -gui-user and gui-password (see below). +@code{gui-user} and @code{gui-password} (see below). @item @code{gui-tls} (default: @var{"false"}) @item @code{gui-debugging} (default: @var{"false"}) @@ -22854,8 +22856,8 @@ Networking Services A bcrypt hash of the GUI password. Remember that this will be globally exposed in @file{/gnu/store}. @item @code{gui-apikey} (default: @var{#f}) -You must specify this to use the Syncthing REST interface. Also exposed -in @file{/gnu/store}. +You must specify this to use the Syncthing REST interface. This key is +kept in @file{/gnu/store} and is accessible to all users of the system. @item @code{gui-theme} (default: @var{"default"}) @item @code{ldap-enabled} (default: @var{#f}) @@ -22882,9 +22884,11 @@ Networking Services @item @code{max-recv-kbps} (default: @var{"0"}) @item @code{reconnection-interval-s} (default: @var{"60"}) @item @code{relays-enabled} (default: @var{"true"}) -This option allows your Syncthing instance to coordinate with a global -network of relays to enable syncing between devices when all other -methods fail. +This option allows your Syncthing instance to use a global network of +@uref{https://docs.syncthing.net/users/relaying.html, relays} to enable +syncing between devices when all other methods fail. As always, +Syncthing traffic is encrypted in transport and the relays are unable to +decrypt it. @item @code{relay-reconnect-interval-m} (default: @var{"10"}) @item @code{start-browser} (default: @var{"true"}) @@ -22893,9 +22897,10 @@ Networking Services @item @code{nat-renewal-minutes} (default: @var{"30"}) @item @code{nat-timeout-seconds} (default: @var{"10"}) @item @code{ur-accepted} (default: @var{"0"}) -ur* options control usage reporting. Set to -1 to disable, or positive -to enable. The default (0) has reporting disabled, but you will be -asked to decide in the GUI. +Options whose names begin with `ur-' control usage reporting. Set to -1 +to disable, or to a positive value to enable. The default (0) disables +reporting, but causes a usage reporting consent prompt to be displayed +in the Syncthing GUI. @item @code{ur-seen} (default: @var{"0"}) @item @code{ur-unique-id} (default: @var{""}) @@ -22938,23 +22943,24 @@ Networking Services @item @code{default-folder} (default: @var{(syncthing-folder (label ""))}) @item @code{default-device} (default: @var{(syncthing-device (id ""))}) @item @code{default-ignores} (default: @var{"")}) -The default-* above do not affect folders and devices added by the Guix -interface. They will, however, affect folders and devices that are -added through the GUI, by an @code{introducer}, or a device with +Options whose names begin with `default-' above do not affect folders +and devices added through the Guix configuration interface. They will, +however, affect folders and devices that are added through the Syncthing +GUI, by an @code{introducer}, or a device with @code{auto-accept-folders}. @end table @end deftp @deftp {Data Type} syncthing-folder -Data type representing a folder to be synced. +Data type representing a folder to be synchronized. @table @asis @item @code{id} (default: @var{#f}) -This id cannot match the id of any other folder on this device. If left +This ID cannot match the ID of any other folder on this device. If left unspecified, it will default to the label (see below). @item @code{label} -Human readable label for the folder. +A human readable label for the folder. @item @code{path} The path at which to store this folder. @@ -23013,24 +23019,27 @@ Networking Services @end deftp @deftp {Data Type} syncthing-device -Data type representing a device to sync with. +Data type representing a device to synchronize folders with. @table @asis @item @code{id} -A long hash tied to the keys generated by Syncthing on the first launch. -You can obtain this from the Syncthing GUI or by inspecting an existing -Syncthing configuration file. +A long hash representing the keys generated by Syncthing on the first +launch. You can obtain this from the Syncthing GUI or by inspecting an +existing Syncthing configuration file. @item @code{name} (default: @var{""}) -Human readable device name for viewing in the GUI or in scheme. +A human readable device name for viewing in the GUI or in Scheme. @item @code{compression} (default: @var{"metadata"}) @item @code{introducer} (default: @var{"false"}) @item @code{skip-introduction-removals} (default: @var{"false"}) @item @code{introduced-by} (default: @var{""}) @item @code{addresses} (default: @var{'("dynamic")}) -List of addresses at which to search for this device. The special value -``dynamic'' will have syncthing use several means to find the device. +List of addresses at which to search for this device. When the special +value ``dynamic'' is included, Syncthing will search for the device +locally as well as via the Syncthing project's +@uref{https://docs.syncthing.net/users/security.html#global-discovery, +global discovery} servers. @item @code{paused} (default: @var{"false"}) @item @code{auto-accept-folders} (default: @var{"false"}) @@ -23045,32 +23054,37 @@ Networking Services @end deftp @deftp {Data Type} syncthing-folder-device -There are two pieces of configuration specific to the relationship -between a specific folder and a specific device. First, syncthing needs -to know if the remote device should be able to see the files given to -it. Second, syncthing needs to know from where that device originates. -See +This data type offers two folder-specific device options. First, it +offers @code{introduced-by}, which is a record of Syncthing +@uref{https://docs.syncthing.net/users/introducer.html, introductions}. +Second, it offers @code{encryption-password}, by which you can set the +password used to encrypt data that is synced with +@uref{https://docs.syncthing.net/users/untrusted.html, untrusted +devices}. + +@code{syncthing-folder-device} corresponds to the @uref{https://docs.syncthing.net/users/config.html#config-option-folder.device, -the Syncthing Documentation on this}. If you leave these default, then -you can just specify @code{syncthing-device}s instead of -@code{syncthing-folder-device}s in a @code{syncthing-folder}'s -@code{devices} field. +`device'} option in the upstream `folder' element. + +If you don't need to use these options, then you can just specify +@code{syncthing-device}s instead of @code{syncthing-folder-device}s in a +@code{syncthing-folder}'s @code{devices} field. @table @asis @item @code{device} -device should be a @code{syncthing-device} for which this configuration -applies. +The @code{syncthing-device} for which this configuration applies. @item @code{introduced-by} (default: @var{""}) @item @code{encryption-password} (default: @var{""}) Beware: specifying this field will include this password as plain text -(not encrypted) and globally visible in @file{/gnu/store/}. If +(not encrypted) and globally visible in @file{/gnu/store/}. If the encryption-password is non-empty, then it will be used as a password to -encrypt file chunks as they are synced to that device. For more info on -syncing to devices you don't totally trust, see -@uref{https://docs.syncthing.net/users/untrusted.html, Syncthing -Documentation on Untrusted Devices}. Note that file transfers are -always end-to-end encrypted, regardless of this setting. +encrypt file chunks as they are synchronized to untrusted devices. For +more information on syncing to devices you don't totally trust, see +Syncthing's documentation on +@uref{https://docs.syncthing.net/users/untrusted.html, Untrusted +(Encrypted) Devices}. Note that data transfer is always encrypted while +in transport ("end-to-end encryption"), regardless of this setting. @end table @end deftp --TZ7VRsB/KqHHHo74-- From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v9] services: syncthing: Add support for config file generation. References: <20250130215954.9394-1-eikcaz@zacchae.us> In-Reply-To: <20250130215954.9394-1-eikcaz@zacchae.us> Resent-From: Zacchaeus Scheffer Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sun, 16 Feb 2025 01:07:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Leo Famulari Cc: Bruno Victal , 75959@debbugs.gnu.org Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.173966801822138 (code B ref 75959); Sun, 16 Feb 2025 01:07:02 +0000 Received: (at 75959) by debbugs.gnu.org; 16 Feb 2025 01:06:58 +0000 Received: from localhost ([127.0.0.1]:59095 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tjT7X-0005kt-Tr for submit@debbugs.gnu.org; Sat, 15 Feb 2025 20:06:58 -0500 Received: from [47.204.136.169] (port=35872 helo=hun.zacchae.us) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tjT7R-0005kJ-Qf for 75959@debbugs.gnu.org; Sat, 15 Feb 2025 20:06:53 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Transfer-Encoding:Content-Type: MIME-Version:Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=+jjuU8vsGXUg+XVJuVtQK3kXLr/Ymv62ZqboMrADfwQ=; i=zacchae.us; b=VR4ak+UWj6SZ 9/aLLfYdDJ9nvxA1Pr+hD+iAJWBnTxNTF4g1cFAMhyUvn6GfhVjsxS14wPlRl0BB5J7bDcpwDg==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Transfer-Encoding:Content-Type:MIME-Version: Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=+jjuU8vsGXUg+XVJuVtQK3kXLr/Ymv62ZqboMrADfwQ=; i=zacchae.us; b=py4bj7267+IX 6zUCU614C5HLow4XBQlzy1GKAQxmZ4+gDYytBXTcDWqDr9RIH1RV9Z736hWYgfn/4CvCCA/DxitRS NHuyxNSDM3CvAQNRh70UGVj7/6+tS6EVdwRh5pdhqrpoQV6rS8xfr8thr9hQwGB1AhRmNCAHEhNDm X0q9vx4XnIpwNnFUyPrRexIBnwAQNmeAQgzCOyHMpxwGsrCOTk96XoLMbBSOS7lcxbTmU6OjYpYut lwghR5hgrFH8ArdSlAAUSrNUXaQwTJkjoFA4tubFT2G1akhqJuzCLUJzOCx+4zJhE3lJfmTT0rNln YHOcldc/XGYaGqOJ7ufrzQ==; Received: from localhost.home ([127.0.0.1]:53860 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1tjT7K-000000006n8-2alj; Sat, 15 Feb 2025 20:06:42 -0500 From: Zacchaeus Scheffer Date: Sat, 15 Feb 2025 20:06:42 -0500 Message-ID: <871pvyg0kd.fsf@zacchae.us> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From 1f38aeb8e2b1c5384ac915a09bad7df1f97b2543 Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH v9] services: syncthing: Add support fo [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.1 URIBL_SBL_A Contains URL's A record listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 0.6 URIBL_SBL Contains an URL's NS IP listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in sa-trusted.bondedsender.org] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in bl.score.senderscore.com] 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS 0.0 T_FILL_THIS_FORM_SHORT Fill in a short form with personal information X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 1.0 (+) >From 1f38aeb8e2b1c5384ac915a09bad7df1f97b2543 Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH v9] services: syncthing: Add support for config file generation. * gnu/services/syncthing.scm: (syncthing-config-file, syncthing-folder, syncthing-device, syncthing-folder-device): New records; (syncthing-service-type): Add special-files-service-type extension for the config file; (syncthing-files-service): Add service to create config file. * gnu/home/services/syncthing.scm: (home-syncthing-service-type): Extend home-files-services-type and re-exported more things from gnu/services/syncthing.scm. * doc/guix.texi: (syncthing-service-type): Document changes. Change-Id: I87eeba1ee1fdada8f29c2ee881fbc6bc4113dde9 --- I incorporated the changes suggested by lfam, except that I kept the semi-colon. I double-checked that it was gramatically correct, and I think it makes to where "there" refers clear. I converted chmod/chown to guile procedures, and added documentation on some of the flags used to launch Syncthing. doc/guix.texi | 334 ++++++++++++++++++++- gnu/home/services/syncthing.scm | 17 +- gnu/services/syncthing.scm | 515 ++++++++++++++++++++++++++++++-- 3 files changed, 833 insertions(+), 33 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index b1b6d98e74..d1fbe5ffd3 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -136,6 +136,7 @@ Copyright @copyright{} 2024 Troy Figiel@* Copyright @copyright{} 2024 Sharlatan Hellseher@* Copyright @copyright{} 2024 45mg@* Copyright @copyright{} 2025 S=C3=B6ren Tempel@* +Copyright @copyright{} 2025 Zacchaeus@* =20 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -22620,7 +22621,7 @@ client. The @code{(gnu services syncthing)} module provides the following services: @cindex syncthing =20 -You might want a syncthing daemon if you have files between two or more +You might want a Syncthing daemon if you have files between two or more computers and want to sync them in real time, safely protected from prying eyes. =20 @@ -22666,12 +22667,339 @@ The group as which the Syncthing service is to b= e run. This assumes that the specified group exists. =20 @item @code{home} (default: @var{#f}) -Common configuration and data directory. The default configuration -directory is @file{$HOME} of the specified Syncthing @code{user}. +Sets the @code{HOME} variable for the Syncthing daemon. The default is +@file{$HOME} of the specified Syncthing @code{user}. + +@item @code{config-file} (default: @var{#f}) +Either a file-like object that resolves to a Syncthing configuration XML +file, or a @code{syncthing-config-file} record (see below). If set to +@code{#f}, Guix will not try to generate a config file, and Syncthing +will generate a default configuration which will not be touched on +reconfigure. Specifying this in a system service moves Syncthing's +common configuration and data directory (@code{--home} in +@uref{https://docs.syncthing.net/users/syncthing.html}) to +@file{/var/lib/syncthing-}. + +@end table +@end deftp + +This section documents a subset of the Syncthing configuration +options=E2=80=94specifically those related to Guix or those affecting how = your +computer will connect to other computers over the network (such as +Syncthing relays or discovery servers). The configuration is fully +documented in the upstream +@uref{https://docs.syncthing.net/users/config.html, Syncthing config +documentation}; camelCase there is converted to kebab-case here. If you +are migrating from a Syncthing-managed configuration to one managed by +Guix, you can check what changes were introduced by @code{diff}ing the +respective @file{config.xml} files. Note that you will need to add +whitespace with 4-space indentation to the file generated by Guix, using +the @code{xmllint} program from the @code{libxml2} package like so: + +@example +XMLLINT_INDENT=3D" " xmllint --format /path/to/new/config.xml | diff /p= ath/to/old/config.xml - +@end example + +When generating a configuration file through Guix, you can still +temporarily modify Syncthing from the GUI or through @code{introducer} +and @code{autoAcceptFolders} mechanisms, but such changes will be reset +on reconfigure. + +@deftp {Data Type} syncthing-config-file +Data type representing the configuration file read by the Syncthing +daemon. + +@table @asis +@item @code{folders} (default: @var{(list (syncthing-folder (id "default")= (label "Default Folder") (path "~/Sync")))} +The default here is the same as Syncthing's default. The value should +be a list of @code{syncthing-folder}s. + +@item @code{devices} (default: @var{'()} +This should be a list of @code{syncthing-device}s. Guix will +automatically add any devices specified in any `folders' to this list. +There are instances when you want to connect to a device despite not +(initially) sharing any folders (such as a device with +autoAcceptFolders). In such instances, you should specify those devices +here. If multiple versions of the same device (as determined by +comparing device ID) are discovered, the one in this list is +prioritized. Otherwise, the first instance in the first folder is used. + +@item @code{gui-enabled} (default: @var{"true"}) +By default, any user on the computer can access the GUI and make changes +to Syncthing. If you leave this enabled, you should probably set +@code{gui-user} and @code{gui-password} (see below). + +@item @code{gui-tls} (default: @var{"false"}) +@item @code{gui-debugging} (default: @var{"false"}) +@item @code{gui-send-basic-auth-prompt} (default: @var{"false"}) +@item @code{gui-address} (default: @var{"127.0.0.1:8384"}) +@item @code{gui-user} (default: @var{#f}) +@item @code{gui-password} (default: @var{#f}) +A bcrypt hash of the GUI password. Remember that this will be globally +exposed in @file{/gnu/store}. + +@item @code{gui-apikey} (default: @var{#f}) +You must specify this to use the Syncthing REST interface. This key is +kept in @file{/gnu/store} and is accessible to all users of the system. + +@item @code{gui-theme} (default: @var{"default"}) +@item @code{ldap-enabled} (default: @var{#f}) +@item @code{ldap-address} (default: @var{""}) +@item @code{ldap-bind-dn} (default: @var{""}) +@item @code{ldap-transport} (default: @var{""}) +@item @code{ldap-insecure-skip-verify} (default: @var{""}) +@item @code{ldap-search-base-dn} (default: @var{""}) +@item @code{ldap-search-filter} (default: @var{""}) +@item @code{listen-address} (default: @var{"default"}) +@item @code{global-announce-server} (default: @var{"default"}) +@item @code{global-announce-enabled} (default: @var{"true"}) +Global discovery servers can be used to help connect devices at unknown +IP addresses by storing the last known IP address. + +@item @code{local-announce-enabled} (default: @var{"true"}) +This makes devices find each other very easily on the same LAN. Often, +this will allow you to just plug an Ethernet between two devices, or +connect one device to the other's hotspot and start syncing. + +@item @code{local-announce-port} (default: @var{"21027"}) +@item @code{local-announce-mcaddr} (default: @var{"[ff12::8384]:21027"}) +@item @code{max-send-kbps} (default: @var{"0"}) +@item @code{max-recv-kbps} (default: @var{"0"}) +@item @code{reconnection-interval-s} (default: @var{"60"}) +@item @code{relays-enabled} (default: @var{"true"}) +This option allows your Syncthing instance to use a global network of +@uref{https://docs.syncthing.net/users/relaying.html, relays} to enable +syncing between devices when all other methods fail. As always, +Syncthing traffic is encrypted in transport and the relays are unable to +decrypt it. + +@item @code{relay-reconnect-interval-m} (default: @var{"10"}) +@item @code{start-browser} (default: @var{"true"}) +@item @code{nat-enabled} (default: @var{"true"}) +@item @code{nat-lease-minutes} (default: @var{"60"}) +@item @code{nat-renewal-minutes} (default: @var{"30"}) +@item @code{nat-timeout-seconds} (default: @var{"10"}) +@item @code{ur-accepted} (default: @var{"0"}) +Options whose names begin with `ur-' control usage reporting. Set to -1 +to disable, or to a positive value to enable. The default (0) disables +reporting, but causes a usage reporting consent prompt to be displayed +in the Syncthing GUI. + +@item @code{ur-seen} (default: @var{"0"}) +@item @code{ur-unique-id} (default: @var{""}) +@item @code{ur-url} (default: @var{"https://data.syncthing.net/newdata"}) +@item @code{ur-post-insecurely} (default: @var{"false"}) +@item @code{ur-initial-delay-s} (default: @var{"1800"}) +@item @code{auto-upgrade-interval-h} (default: @var{"12"}) +@item @code{upgrade-to-pre-releases} (default: @var{"false"}) +@item @code{keep-temporaries-h} (default: @var{"24"}) +@item @code{cache-ignored-files} (default: @var{"false"}) +@item @code{progress-update-interval-s} (default: @var{"5"}) +@item @code{limit-bandwidth-in-lan} (default: @var{"false"}) +@item @code{min-home-disk-free-unit} (default: @var{"%"}) +@item @code{min-home-disk-free} (default: @var{"1"}) +@item @code{releases-url} (default: @var{"https://upgrades.syncthing.net/m= eta.json"}) +@item @code{overwrite-remote-device-names-on-connect} (default: @var{"fals= e"}) +@item @code{temp-index-min-blocks} (default: @var{"10"}) +@item @code{unacked-notification-id} (default: @var{"authenticationUserAnd= Password"}) +@item @code{traffic-class} (default: @var{"0"}) +@item @code{set-low-priority} (default: @var{"true"}) +@item @code{max-folder-concurrency} (default: @var{"0"}) +@item @code{crash-reporting-url} (default: @var{"https://crash.syncthing.n= et/newcrash"}) +@item @code{crash-reporting-enabled} (default: @var{"true"}) +@item @code{stun-keepalive-start-s} (default: @var{"180"}) +@item @code{stun-keepalive-min-s} (default: @var{"20"}) +@item @code{stun-server} (default: @var{"default"}) +@item @code{database-tuning} (default: @var{"auto"}) +@item @code{max-concurrent-incoming-request-kib} (default: @var{"0"}) +@item @code{announce-lan-addresses} (default: @var{"true"}) +@item @code{send-full-index-on-upgrade} (default: @var{"false"}) +@item @code{connection-limit-enough} (default: @var{"0"}) +@item @code{connection-limit-max} (default: @var{"0"}) +@item @code{insecure-allow-old-tls-versions} (default: @var{"false"}) +@item @code{connection-priority-tcp-lan} (default: @var{"10"}) +@item @code{connection-priority-quic-lan} (default: @var{"20"}) +@item @code{connection-priority-tcp-wan} (default: @var{"30"}) +@item @code{connection-priority-quic-wan} (default: @var{"40"}) +@item @code{connection-priority-relay} (default: @var{"50"}) +@item @code{connection-priority-upgrade-threshold} (default: @var{"0"}) +@item @code{default-folder} (default: @var{(syncthing-folder (label ""))}) +@item @code{default-device} (default: @var{(syncthing-device (id ""))}) +@item @code{default-ignores} (default: @var{"")}) +Options whose names begin with `default-' above do not affect folders +and devices added through the Guix configuration interface. They will, +however, affect folders and devices that are added through the Syncthing +GUI, by an @code{introducer}, or a device with +@code{auto-accept-folders}. +@end table +@end deftp + +@deftp {Data Type} syncthing-folder +Data type representing a folder to be synchronized. + +@table @asis +@item @code{id} (default: @var{#f}) +This ID cannot match the ID of any other folder on this device. If left +unspecified, it will default to the label (see below). + +@item @code{label} +A human readable label for the folder. + +@item @code{path} +The path at which to store this folder. + +@item @code{type} (default: @var{"sendreceive"}) +@item @code{rescan-interval-s} (default: @var{"3600"}) +@item @code{fs-watcher-enabled} (default: @var{"true"}) +@item @code{fs-watcher-delay-s} (default: @var{"10"}) +@item @code{ignore-perms} (default: @var{"false"}) +@item @code{auto-normalize} (default: @var{"true"}) +@item @code{devices} (default: @var{'()}) +This should be a list of other Syncthing devices. You do not need to +specify the current device. Each device can be listed as a a +@code{syncthing-device} record or a @code{syncthing-folder-device} +record if you want files to be encrypted on disk. See below. + +@item @code{filesystem-type} (default: @var{"basic"}) +@item @code{min-disk-free-unit} (default: @var{"%"}) +@item @code{min-disk-free} (default: @var{"1"}) +@item @code{versioning-type} (default: @var{#f}) +@item @code{versioning-fs-path} (default: @var{""}) +@item @code{versioning-fs-type} (default: @var{"basic"}) +@item @code{versioning-cleanup-interval-s} (default: @var{"3600"}) +@item @code{versioning-cleanout-days} (default: @var{#f}) +@item @code{versioning-keep} (default: @var{#f}) +@item @code{versioning-max-age} (default: @var{#f}) +@item @code{versioning-command} (default: @var{#f}) +@item @code{copiers} (default: @var{"0"}) +@item @code{puller-max-pending-kib} (default: @var{"0"}) +@item @code{hashers} (default: @var{"0"}) +@item @code{order} (default: @var{"random"}) +@item @code{ignore-delete} (default: @var{"false"}) +@item @code{scan-progress-interval-s} (default: @var{"0"}) +@item @code{puller-pause-s} (default: @var{"0"}) +@item @code{max-conflicts} (default: @var{"10"}) +@item @code{disable-sparse-files} (default: @var{"false"}) +@item @code{disable-temp-indexes} (default: @var{"false"}) +@item @code{paused} (default: @var{"false"}) +@item @code{weak-hash-threshold-pct} (default: @var{"25"}) +@item @code{marker-name} (default: @var{".stfolder"}) +@item @code{copy-ownership-from-parent} (default: @var{"false"}) +@item @code{mod-time-window-s} (default: @var{"0"}) +@item @code{max-concurrent-writes} (default: @var{"2"}) +@item @code{disable-fsync} (default: @var{"false"}) +@item @code{block-pull-order} (default: @var{"standard"}) +@item @code{copy-range-method} (default: @var{"standard"}) +@item @code{case-sensitive-fs} (default: @var{"false"}) +@item @code{junctions-as-dirs} (default: @var{"false"}) +@item @code{sync-ownership} (default: @var{"false"}) +@item @code{send-ownership} (default: @var{"false"}) +@item @code{sync-xattrs} (default: @var{"false"}) +@item @code{send-xattrs} (default: @var{"false"}) +@item @code{xattr-filter-max-single-entry-size} (default: @var{"1024"}) +@item @code{xattr-filter-max-total-size} (default: @var{"4096")}) +@end table +@end deftp + +@deftp {Data Type} syncthing-device +Data type representing a device to synchronize folders with. + +@table @asis +@item @code{id} +A long hash representing the keys generated by Syncthing on the first +launch. You can obtain this from the Syncthing GUI or by inspecting an +existing Syncthing configuration file. + +@item @code{name} (default: @var{""}) +A human readable device name for viewing in the GUI or in Scheme. + +@item @code{compression} (default: @var{"metadata"}) +@item @code{introducer} (default: @var{"false"}) +@item @code{skip-introduction-removals} (default: @var{"false"}) +@item @code{introduced-by} (default: @var{""}) +@item @code{addresses} (default: @var{'("dynamic")}) +List of addresses at which to search for this device. When the special +value ``dynamic'' is included, Syncthing will search for the device +locally as well as via the Syncthing project's +@uref{https://docs.syncthing.net/users/security.html#global-discovery, +global discovery} servers. + +@item @code{paused} (default: @var{"false"}) +@item @code{auto-accept-folders} (default: @var{"false"}) +@item @code{max-send-kbps} (default: @var{"0"}) +@item @code{max-recv-kbps} (default: @var{"0"}) +@item @code{max-request-kib} (default: @var{"0"}) +@item @code{untrusted} (default: @var{"false"}) +@item @code{remote-gui-port} (default: @var{"0"}) +@item @code{num-connections} (default: @var{"0")}) + +@end table +@end deftp + +@deftp {Data Type} syncthing-folder-device +This data type offers two folder-specific device options. First, it +offers @code{introduced-by}, which is a record of Syncthing +@uref{https://docs.syncthing.net/users/introducer.html, introductions}. +Second, it offers @code{encryption-password}, by which you can set the +password used to encrypt data that is synced with +@uref{https://docs.syncthing.net/users/untrusted.html, untrusted +devices}. + +@code{syncthing-folder-device} corresponds to the +@uref{https://docs.syncthing.net/users/config.html#config-option-folder.de= vice, +`device'} option in the upstream `folder' element. + +If you don't need to use these options, then you can just specify +@code{syncthing-device}s instead of @code{syncthing-folder-device}s in a +@code{syncthing-folder}'s @code{devices} field. + +@table @asis +@item @code{device} +The @code{syncthing-device} for which this configuration applies. + +@item @code{introduced-by} (default: @var{""}) +@item @code{encryption-password} (default: @var{""}) +Beware: specifying this field will include this password as plain text +(not encrypted) and globally visible in @file{/gnu/store/}. If the +encryption-password is non-empty, then it will be used as a password to +encrypt file chunks as they are synchronized to untrusted devices. For +more information on syncing to devices you don't totally trust, see +Syncthing's documentation on +@uref{https://docs.syncthing.net/users/untrusted.html, Untrusted +(Encrypted) Devices}. Note that data transfer is always encrypted while +in transport ("end-to-end encryption"), regardless of this setting. =20 @end table @end deftp =20 +Here is a more complex example configuration for illustrative purposes: + +@lisp +(service syncthing-service-type + (let ((laptop (syncthing-device (id "VHOD2D6-...-7XRMDEN"))) + (desktop (syncthing-device (id "64SAZ37-...-FZJ5GUA") + (addresses '("tcp://example.com"= )))) + (bob-desktop (syncthing-device (id "KYIMEGO-...-FT77EAO")))) + (syncthing-configuration + (user "alice") + (config-file + (syncthing-config-file + (folders (list (syncthing-folder + (label "some-files") + (path "~/data") + (devices (list desktop laptop))) + (syncthing-folder + (label "critical-files") + (path "~/secrets") + (devices + (list desktop + laptop + (syncthing-folder-device + (device bob-desktop) + (encryption-password "mypassword"))= )))))))))) +@end lisp + + Furthermore, @code{(gnu services ssh)} provides the following services. @cindex SSH @cindex SSH server diff --git a/gnu/home/services/syncthing.scm b/gnu/home/services/syncthing.= scm index 8d66a167ce..dd6c752ee4 100644 --- a/gnu/home/services/syncthing.scm +++ b/gnu/home/services/syncthing.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2023 Ludovic Court=C3=A8s +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -24,9 +25,23 @@ (define-module (gnu home services syncthing) #:use-module (gnu home services shepherd) #:export (home-syncthing-service-type) #:re-export (syncthing-configuration - syncthing-configuration?)) + syncthing-configuration? + syncthing-config-file + syncthing-config-file? + syncthing-device + syncthing-device? + syncthing-folder + syncthing-folder? + syncthing-folder-device + syncthing-folder-device?)) =20 (define home-syncthing-service-type (service-type (inherit (system->home-service-type syncthing-service-type)) + ;; system->home-service-type does not convert special-files-service-typ= e to + ;; home-files-service-type, so redefine extensios + (extensions (list (service-extension home-files-service-type + syncthing-files-service) + (service-extension home-shepherd-service-type + syncthing-shepherd-service))) (default-value (for-home (syncthing-configuration))))) diff --git a/gnu/services/syncthing.scm b/gnu/services/syncthing.scm index a7a9c6aadd..cc88bf7925 100644 --- a/gnu/services/syncthing.scm +++ b/gnu/services/syncthing.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2021 Oleg Pykhalov ;;; Copyright =C2=A9 2023 Justin Veilleux +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -25,9 +26,20 @@ (define-module (gnu services syncthing) #:use-module (guix records) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (sxml simple) #:export (syncthing-configuration syncthing-configuration? - syncthing-service-type)) + syncthing-device + syncthing-device? + syncthing-config-file + syncthing-config-file? + syncthing-folder-device + syncthing-folder-device? + syncthing-folder + syncthing-folder? + syncthing-service-type + syncthing-shepherd-service + syncthing-files-service)) =20 ;;; Commentary: ;;; @@ -35,6 +47,414 @@ (define-module (gnu services syncthing) ;;; ;;; Code: =20 +(define-record-type* + syncthing-device make-syncthing-device + syncthing-device? + (id syncthing-device-id) + (name syncthing-device-name (default "")) + (compression syncthing-device-compression (default "metadata")) + (introducer syncthing-device-introducer (default "false")) + (skip-introduction-removals syncthing-device-skip-introduction-removals = (default "false")) + (introduced-by syncthing-device-introduced-by (default "")) + (addresses syncthing-device-addresses (default '("dynamic"))) + (paused syncthing-device-paused (default "false")) + (auto-accept-folders syncthing-device-auto-accept-folders (default "fals= e")) + (max-send-kbps syncthing-device-max-send-kbps (default "0")) + (max-recv-kbps syncthing-device-max-recv-kbps (default "0")) + (max-request-kib syncthing-device-max-request-kib (default "0")) + (untrusted syncthing-device-untrusted (default "false")) + (remote-gui-port syncthing-device-remote-gui-port (default "0")) + (num-connections syncthing-device-num-connections (default "0"))) + +(define syncthing-device->sxml + (match-record-lambda + (id + name compression introducer skip-introduction-removals introduced-by + addresses paused auto-accept-folders max-send-kbps max-recv-kbps + max-request-kib untrusted remote-gui-port num-connections) + `(device (@ (id ,id) + (name ,name) + (compression ,compression) + (introducer ,introducer) + (skipIntroductionRemovals ,skip-introduction-removals) + (introducedBy ,introduced-by)) + ,@(map (lambda (address) `(address ,address)) addresses) + (paused ,paused) + (autoAcceptFolders ,auto-accept-folders) + (maxSendKbps ,max-send-kbps) + (maxRecvKbps ,max-recv-kbps) + (maxRequestKiB ,max-request-kib) + (untrusted ,untrusted) + (remoteGUIPort ,remote-gui-port) + (numConnections ,num-connections)))) + +(define-record-type* + syncthing-folder-device make-syncthing-folder-device + syncthing-folder-device? + (device syncthing-folder-device-device) + (introduced-by syncthing-folder-device-introduced-by (default (syncthing= -device (id "")))) + (encryption-password syncthing-folder-device-encryption-password (defaul= t ""))) + +(define syncthing-folder-device->sxml + (match-record-lambda + (device introduced-by encryption-password) + `(device (@ (id ,(syncthing-device-id device)) + (introducedBy ,(syncthing-device-id introduced-by))) + (encryptionPassword ,encryption-password)))) + +(define-record-type* + syncthing-folder make-syncthing-folder + syncthing-folder? + (id syncthing-folder-id (default #f)) + (label syncthing-folder-label) + (path syncthing-folder-path) + (type syncthing-folder-type (default "sendreceive")) + (rescan-interval-s syncthing-folder-rescan-interval-s (default "3600")) + (fs-watcher-enabled syncthing-folder-fs-watcher-enabled (default "true")) + (fs-watcher-delay-s syncthing-folder-fs-watcher-delay-s (default "10")) + (fs-watcher-timeout-s syncthing-folder-fs-watcher-timeout-s (default "0"= )) + (ignore-perms syncthing-folder-ignore-perms (default "false")) + (auto-normalize syncthing-folder-auto-normalize (default "true")) + (devices syncthing-folder-devices (default '()) + (sanitize (lambda (folder-device-list) + (map (lambda (device) + (if (syncthing-folder-device? device) + device + (syncthing-folder-device (device device)= ))) + folder-device-list)))) + (filesystem-type syncthing-folder-filesystem-type (default "basic")) + (min-disk-free-unit syncthing-folder-min-disk-free-unit (default "%")) + (min-disk-free syncthing-folder-min-disk-free (default "1")) + (versioning-type syncthing-folder-versioning-type (default #f)) + (versioning-fs-path syncthing-folder-versioning-fs-path (default "")) + (versioning-fs-type syncthing-folder-versioning-fs-type (default "basic"= )) + (versioning-cleanup-interval-s syncthing-folder-versioning-cleanup-inter= val-s (default "3600")) + (versioning-cleanout-days syncthing-folder-versioning-cleanout-days (def= ault #f)) + (versioning-keep syncthing-folder-versioning-keep (default #f)) + (versioning-max-age syncthing-folder-versioning-max-age (default #f)) + (versioning-command syncthing-folder-versioning-command (default #f)) + (copiers syncthing-folder-copiers (default "0")) + (puller-max-pending-kib syncthing-folder-puller-max-pending-kib (default= "0")) + (hashers syncthing-folder-hashers (default "0")) + (order syncthing-folder-order (default "random")) + (ignore-delete syncthing-folder-ignore-delete (default "false")) + (scan-progress-interval-s syncthing-folder-scan-progress-interval-s (def= ault "0")) + (puller-pause-s syncthing-folder-puller-pause-s (default "0")) + (max-conflicts syncthing-folder-max-conflicts (default "10")) + (disable-sparse-files syncthing-folder-disable-sparse-files (default "fa= lse")) + (disable-temp-indexes syncthing-folder-disable-temp-indexes (default "fa= lse")) + (paused syncthing-folder-paused (default "false")) + (weak-hash-threshold-pct syncthing-folder-weak-hash-threshold-pct (defau= lt "25")) + (marker-name syncthing-folder-marker-name (default ".stfolder")) + (copy-ownership-from-parent syncthing-folder-copy-ownership-from-parent = (default "false")) + (mod-time-window-s syncthing-folder-mod-time-window-s (default "0")) + (max-concurrent-writes syncthing-folder-max-concurrent-writes (default "= 2")) + (disable-fsync syncthing-folder-disable-fsync (default "false")) + (block-pull-order syncthing-folder-block-pull-order (default "standard")) + (copy-range-method syncthing-folder-copy-range-method (default "standard= ")) + (case-sensitive-fs syncthing-folder-case-sensitive-fs (default "false")) + (junctions-as-dirs syncthing-folder-junctions-as-dirs (default "false")) + (sync-ownership syncthing-folder-sync-ownership (default "false")) + (send-ownership syncthing-folder-send-ownership (default "false")) + (sync-xattrs syncthing-folder-sync-xattrs (default "false")) + (send-xattrs syncthing-folder-send-xattrs (default "false")) + (xattr-filter-max-single-entry-size syncthing-folder-xattr-filter-max-si= ngle-entry-size (default "1024")) + (xattr-filter-max-total-size syncthing-folder-xattr-filter-max-total-siz= e (default "4096"))) + +;; Some parameters, when empty, are fully omitted from the config file. I= t is +;; unknown if this causes a functional difference, but stick to the normal +;; program's behavior to be safe. +(define (maybe-param symbol value) + (if value `((param (@ (key ,(symbol->string symbol)) (val ,value)) "")) = '())) + +(define syncthing-folder->sxml + (match-record-lambda + (id + label path type rescan-interval-s fs-watcher-enabled fs-watcher-del= ay-s + fs-watcher-timeout-s ignore-perms auto-normalize devices filesystem= -type + min-disk-free-unit min-disk-free versioning-type versioning-fs-path + versioning-fs-type versioning-cleanup-interval-s versioning-cleanou= t-days + versioning-keep versioning-max-age versioning-command copiers + puller-max-pending-kib hashers order ignore-delete scan-progress-in= terval-s + puller-pause-s max-conflicts disable-sparse-files disable-temp-inde= xes paused + weak-hash-threshold-pct marker-name copy-ownership-from-parent mod-= time-window-s + max-concurrent-writes disable-fsync block-pull-order copy-range-met= hod + case-sensitive-fs junctions-as-dirs sync-ownership send-ownership s= ync-xattrs + send-xattrs xattr-filter-max-single-entry-size xattr-filter-max-tot= al-size) + `(folder (@ (id ,(if id id label)) + (label ,label) + (path ,path) + (type ,type) + (rescanIntervalS ,rescan-interval-s) + (fsWatcherEnabled ,fs-watcher-enabled) + (fsWatcherDelayS ,fs-watcher-delay-s) + (fsWatcherTimeoutS ,fs-watcher-timeout-s) + (ignorePerms ,ignore-perms) + (autoNormalize ,auto-normalize)) + (filesystemType ,filesystem-type) + ,@(map syncthing-folder-device->sxml + devices) + (minDiskFree (@ (unit ,min-disk-free-unit)) + ,min-disk-free) + (versioning ,@(if versioning-type + `((@ (type ,versioning-type))) + '()) + ,@(maybe-param 'cleanoutDays versioning-cleanout-= days) + ,@(maybe-param 'keep versioning-keep) + ,@(maybe-param 'maxAge versioning-max-age) + ,@(maybe-param 'command versioning-command) + (cleanupIntervalS ,versioning-cleanup-interval-s) + (fsPath ,versioning-fs-path) + (fsType ,versioning-fs-type)) + (copiers ,copiers) + (pullerMaxPendingKiB ,puller-max-pending-kib) + (hashers ,hashers) + (order ,order) + (ignoreDelete ,ignore-delete) + (scanProgressIntervalS ,scan-progress-interval-s) + (pullerPauseS ,puller-pause-s) + (maxConflicts ,max-conflicts) + (disableSparseFiles ,disable-sparse-files) + (disableTempIndexes ,disable-temp-indexes) + (paused ,paused) + (weakHashThresholdPct ,weak-hash-threshold-pct) + (markerName ,marker-name) + (copyOwnershipFromParent ,copy-ownership-from-parent) + (modTimeWindowS ,mod-time-window-s) + (maxConcurrentWrites ,max-concurrent-writes) + (disableFsync ,disable-fsync) + (blockPullOrder ,block-pull-order) + (copyRangeMethod ,copy-range-method) + (caseSensitiveFS ,case-sensitive-fs) + (junctionsAsDirs ,junctions-as-dirs) + (syncOwnership ,sync-ownership) + (sendOwnership ,send-ownership) + (syncXattrs ,sync-xattrs) + (sendXattrs ,send-xattrs) + (xattrFilter (maxSingleEntrySize ,xattr-filter-max-single-ent= ry-size) + (maxTotalSize ,xattr-filter-max-total-size))))) + +(define-record-type* + syncthing-config-file make-syncthing-config-file + syncthing-config-file? + (folders syncthing-config-folders + ; this matches syncthing's default + (default (list (syncthing-folder (id "default") + (label "Default Folder") + (path "~/Sync"))))) + (devices syncthing-config-devices + (default '())) + (gui-enabled syncthing-config-gui-enabled (default "true")) + (gui-tls syncthing-config-gui-tls (default "false")) + (gui-debugging syncthing-config-gui-debugging (default "false")) + (gui-send-basic-auth-prompt syncthing-config-gui-send-basic-auth-prompt = (default "false")) + (gui-address syncthing-config-gui-address (default "127.0.0.1:8384")) + (gui-user syncthing-config-gui-user (default #f)) + (gui-password syncthing-config-gui-password (default #f)) + (gui-apikey syncthing-config-gui-apikey (default #f)) + (gui-theme syncthing-config-gui-theme (default "default")) + (ldap-enabled syncthing-config-ldap-enabled (default #f)) + (ldap-address syncthing-config-ldap-address (default "")) + (ldap-bind-dn syncthing-config-ldap-bind-dn (default "")) + (ldap-transport syncthing-config-ldap-transport (default "")) + (ldap-insecure-skip-verify syncthing-config-ldap-insecure-skip-verify (d= efault "")) + (ldap-search-base-dn syncthing-config-ldap-search-base-dn (default "")) + (ldap-search-filter syncthing-config-ldap-search-filter (default "")) + (listen-address syncthing-config-listen-address (default "default")) + (global-announce-server syncthing-config-global-announce-server (default= "default")) + (global-announce-enabled syncthing-config-global-announce-enabled (defau= lt "true")) + (local-announce-enabled syncthing-config-local-announce-enabled (default= "true")) + (local-announce-port syncthing-config-local-announce-port (default "2102= 7")) + (local-announce-mcaddr syncthing-config-local-announce-mcaddr (default "= [ff12::8384]:21027")) + (max-send-kbps syncthing-config-max-send-kbps (default "0")) + (max-recv-kbps syncthing-config-max-recv-kbps (default "0")) + (reconnection-interval-s syncthing-config-reconnection-interval-s (defau= lt "60")) + (relays-enabled syncthing-config-relays-enabled (default "true")) + (relay-reconnect-interval-m syncthing-config-relay-reconnect-interval-m = (default "10")) + (start-browser syncthing-config-start-browser (default "true")) + (nat-enabled syncthing-config-nat-enabled (default "true")) + (nat-lease-minutes syncthing-config-nat-lease-minutes (default "60")) + (nat-renewal-minutes syncthing-config-nat-renewal-minutes (default "30")) + (nat-timeout-seconds syncthing-config-nat-timeout-seconds (default "10")) + (ur-accepted syncthing-config-ur-accepted (default "0")) + (ur-seen syncthing-config-ur-seen (default "0")) + (ur-unique-id syncthing-config-ur-unique-id (default "")) + (ur-url syncthing-config-ur-url (default "https://data.syncthing.net/new= data")) + (ur-post-insecurely syncthing-config-ur-post-insecurely (default "false"= )) + (ur-initial-delay-s syncthing-config-ur-initial-delay-s (default "1800")) + (auto-upgrade-interval-h syncthing-config-auto-upgrade-interval-h (defau= lt "12")) + (upgrade-to-pre-releases syncthing-config-upgrade-to-pre-releases (defau= lt "false")) + (keep-temporaries-h syncthing-config-keep-temporaries-h (default "24")) + (cache-ignored-files syncthing-config-cache-ignored-files (default "fals= e")) + (progress-update-interval-s syncthing-config-progress-update-interval-s = (default "5")) + (limit-bandwidth-in-lan syncthing-config-limit-bandwidth-in-lan (default= "false")) + (min-home-disk-free-unit syncthing-config-min-home-disk-free-unit (defau= lt "%")) + (min-home-disk-free syncthing-config-min-home-disk-free (default "1")) + (releases-url syncthing-config-releases-url (default "https://upgrades.s= yncthing.net/meta.json")) + (overwrite-remote-device-names-on-connect syncthing-config-overwrite-rem= ote-device-names-on-connect (default "false")) + (temp-index-min-blocks syncthing-config-temp-index-min-blocks (default "= 10")) + (unacked-notification-id syncthing-config-unacked-notification-id (defau= lt "authenticationUserAndPassword")) + (traffic-class syncthing-config-traffic-class (default "0")) + (set-low-priority syncthing-config-set-low-priority (default "true")) + (max-folder-concurrency syncthing-config-max-folder-concurrency (default= "0")) + (crash-reporting-url syncthing-config-crash-reporting-url (default "http= s://crash.syncthing.net/newcrash")) + (crash-reporting-enabled syncthing-config-crash-reporting-enabled (defau= lt "true")) + (stun-keepalive-start-s syncthing-config-stun-keepalive-start-s (default= "180")) + (stun-keepalive-min-s syncthing-config-stun-keepalive-min-s (default "20= ")) + (stun-server syncthing-config-stun-server (default "default")) + (database-tuning syncthing-config-database-tuning (default "auto")) + (max-concurrent-incoming-request-kib syncthing-config-max-concurrent-inc= oming-request-kib (default "0")) + (announce-lan-addresses syncthing-config-announce-lan-addresses (default= "true")) + (send-full-index-on-upgrade syncthing-config-send-full-index-on-upgrade = (default "false")) + (connection-limit-enough syncthing-config-connection-limit-enough (defau= lt "0")) + (connection-limit-max syncthing-config-connection-limit-max (default "0"= )) + (insecure-allow-old-tlsVersions syncthing-config-insecure-allow-old-tlsV= ersions (default "false")) + (connection-priority-tcp-lan syncthing-config-connection-priority-tcp-la= n (default "10")) + (connection-priority-quic-lan syncthing-config-connection-priority-quic-= lan (default "20")) + (connection-priority-tcp-wan syncthing-config-connection-priority-tcp-wa= n (default "30")) + (connection-priority-quic-wan syncthing-config-connection-priority-quic-= wan (default "40")) + (connection-priority-relay syncthing-config-connection-priority-relay (d= efault "50")) + (connection-priority-upgrade-threshold syncthing-config-connection-prior= ity-upgrade-threshold (default "0")) + (default-folder syncthing-config-default-folder + (default (syncthing-folder (label "") (path "~")))) + (default-device syncthing-config-default-device + (default (syncthing-device (id "")))) + (default-ignores syncthing-config-default-ignores (default ""))) + +(define syncthing-config-file->sxml + (match-record-lambda + (folders + devices gui-enabled gui-tls gui-debugging gui-send-basic-auth-prompt + gui-address gui-user gui-password gui-apikey gui-theme ldap-enabled + ldap-address ldap-bind-dn ldap-transport ldap-insecure-skip-verify + ldap-search-base-dn ldap-search-filter listen-address global-announ= ce-server + global-announce-enabled local-announce-enabled local-announce-port + local-announce-mcaddr max-send-kbps max-recv-kbps reconnection-inte= rval-s + relays-enabled relay-reconnect-interval-m start-browser nat-enabled + nat-lease-minutes nat-renewal-minutes nat-timeout-seconds ur-accept= ed + ur-seen ur-unique-id ur-url ur-post-insecurely ur-initial-delay-s + auto-upgrade-interval-h upgrade-to-pre-releases keep-temporaries-h + cache-ignored-files progress-update-interval-s limit-bandwidth-in-l= an + min-home-disk-free-unit min-home-disk-free releases-url + overwrite-remote-device-names-on-connect temp-index-min-blocks + unacked-notification-id traffic-class set-low-priority max-folder-c= oncurrency + crash-reporting-url crash-reporting-enabled stun-keepalive-start-s + stun-keepalive-min-s stun-server database-tuning + max-concurrent-incoming-request-kib announce-lan-addresses + send-full-index-on-upgrade connection-limit-enough connection-limit= -max + insecure-allow-old-tlsVersions connection-priority-tcp-lan + connection-priority-quic-lan connection-priority-tcp-wan + connection-priority-quic-wan connection-priority-relay + connection-priority-upgrade-threshold default-folder default-device + default-ignores) + `(configuration (@ (version "37")) + ,@(map syncthing-folder->sxml + folders) + ;; collect any devices in any folders, as well as any + ;; devices explicitly added. + ,@(map syncthing-device->sxml + (delete-duplicates + (append devices + (apply append + (map (lambda (folder) + (map syncthing-folder-de= vice-device + (syncthing-folder-d= evices folder))) + folders))) + ;; devices are the same if their id's are equal + (lambda (device1 device2) + (string=3D (syncthing-device-id device1) + (syncthing-device-id device2))))) + (gui (@ (enabled ,gui-enabled) + (tls ,gui-tls) + (debugging ,gui-debugging) + (sendBasicAuthPrompt ,gui-send-basic-auth-prom= pt)) + (address ,gui-address) + ,@(if gui-user `((user ,gui-user)) '()) + ,@(if gui-password `((password ,gui-password)) '(= )) + ,@(if gui-apikey `((apikey ,gui-apikey)) '()) + (theme ,gui-theme)) + (ldap ,(if ldap-enabled + `((address ,ldap-address) + (bindDN ,ldap-bind-dn) + ,@(if ldap-transport + `((transport ,ldap-transport)) + '()) + ,@(if ldap-insecure-skip-verify + `((insecureSkipVerify ,ldap-insecur= e-skip-verify)) + '()) + ,@(if ldap-search-base-dn + `((searchBaseDN ,ldap-search-base-d= n)) + '()) + ,@(if ldap-search-filter + `((searchFilter ,ldap-search-filter= )) + '())) + "")) + (options (listenAddress ,listen-address) + (globalAnnounceServer ,global-announce-server) + (globalAnnounceEnabled ,global-announce-enabl= ed) + (localAnnounceEnabled ,local-announce-enabled) + (localAnnouncePort ,local-announce-port) + (localAnnounceMCAddr ,local-announce-mcaddr) + (maxSendKbps ,max-send-kbps) + (maxRecvKbps ,max-recv-kbps) + (reconnectionIntervalS ,reconnection-interval= -s) + (relaysEnabled ,relays-enabled) + (relayReconnectIntervalM ,relay-reconnect-int= erval-m) + (startBrowser ,start-browser) + (natEnabled ,nat-enabled) + (natLeaseMinutes ,nat-lease-minutes) + (natRenewalMinutes ,nat-renewal-minutes) + (natTimeoutSeconds ,nat-timeout-seconds) + (urAccepted ,ur-accepted) + (urSeen ,ur-seen) + (urUniqueID ,ur-unique-id) + (urURL ,ur-url) + (urPostInsecurely ,ur-post-insecurely) + (urInitialDelayS ,ur-initial-delay-s) + (autoUpgradeIntervalH ,auto-upgrade-interval-= h) + (upgradeToPreReleases ,upgrade-to-pre-release= s) + (keepTemporariesH ,keep-temporaries-h) + (cacheIgnoredFiles ,cache-ignored-files) + (progressUpdateIntervalS ,progress-update-int= erval-s) + (limitBandwidthInLan ,limit-bandwidth-in-lan) + (minHomeDiskFree (@ (unit ,min-home-disk-free= -unit)) + ,min-home-disk-free) + (releasesURL ,releases-url) + (overwriteRemoteDeviceNamesOnConnect ,overwri= te-remote-device-names-on-connect) + (tempIndexMinBlocks ,temp-index-min-blocks) + (unackedNotificationID ,unacked-notification-= id) + (trafficClass ,traffic-class) + (setLowPriority ,set-low-priority) + (maxFolderConcurrency ,max-folder-concurrency) + (crashReportingURL ,crash-reporting-url) + (crashReportingEnabled ,crash-reporting-enabl= ed) + (stunKeepaliveStartS ,stun-keepalive-start-s) + (stunKeepaliveMinS ,stun-keepalive-min-s) + (stunServer ,stun-server) + (databaseTuning ,database-tuning) + (maxConcurrentIncomingRequestKiB ,max-concurr= ent-incoming-request-kib) + (announceLANAddresses ,announce-lan-addresses) + (sendFullIndexOnUpgrade ,send-full-index-on-u= pgrade) + (connectionLimitEnough ,connection-limit-enou= gh) + (connectionLimitMax ,connection-limit-max) + (insecureAllowOldTLSVersions ,insecure-allow-= old-tlsVersions) + (connectionPriorityTcpLan ,connection-priorit= y-tcp-lan) + (connectionPriorityQuicLan ,connection-priori= ty-quic-lan) + (connectionPriorityTcpWan ,connection-priorit= y-tcp-wan) + (connectionPriorityQuicWan ,connection-priori= ty-quic-wan) + (connectionPriorityRelay ,connection-priority= -relay) + (connectionPriorityUpgradeThreshold ,connecti= on-priority-upgrade-threshold)) + (defaults + ,(syncthing-folder->sxml default-folder) + ,(syncthing-device->sxml default-device) + (ignores ,default-ignores))))) + + +(define (serialize-syncthing-config-file config) + (with-output-to-string + (lambda () + (sxml->xml (cons '*TOP* (list (syncthing-config-file->sxml config)))= )))) + (define-record-type* syncthing-configuration make-syncthing-configuration syncthing-configuration? @@ -50,12 +470,14 @@ (define-record-type* (default "users")) (home syncthing-configuration-home ;string (default #f)) + (config-file syncthing-configuration-config-file + (default #f)) ; syncthing-config-file or = file-like (home-service? syncthing-configuration-home-service? (default for-home?) (innate))) =20 (define syncthing-shepherd-service (match-record-lambda - (syncthing arguments logflags user group home home-service?) + (syncthing arguments logflags user group home home-service? config-f= ile) (list (shepherd-service (provision (if home-service? @@ -64,39 +486,74 @@ (define syncthing-shepherd-service (string-append "syncthing-" user))))) (documentation "Run syncthing.") (requirement (if home-service? '() '(loopback user-processes))) - (start #~(make-forkexec-constructor - (append (list (string-append #$syncthing "/bin/syncthing") - "--no-browser" - "--no-restart" - (string-append "--logflags=3D" (number->stri= ng #$logflags))) - '#$arguments) - #:user #$(and (not home-service?) user) - #:group #$(and (not home-service?) group) - #:environment-variables - (append - (list - (string-append "HOME=3D" - (or #$home - (passwd:dir - (getpw (if (and #$home-service? - (not #$user)) - (getuid) - #$user))))) - "SSL_CERT_DIR=3D/etc/ssl/certs" - "SSL_CERT_FILE=3D/etc/ssl/certs/ca-certifica= tes.crt") - (filter (negate ;XXX: 'remove' is not in (gu= ile) - (lambda (str) - (or (string-prefix? "HOME=3D" str) - (string-prefix? "SSL_CERT_DIR=3D" s= tr) - (string-prefix? "SSL_CERT_FILE=3D" = str)))) - (environ))))) + (start #~(lambda _ + ;; If we are managing the config, and it's not a home + ;; service, then exepect the config file at + ;; /var/lib/syncthing-. This makes sure the owners= hip + ;; is correct + (unless (or #$(not config-file) #$home-service?) + (chown (string-append "/var/lib/syncthing-" #$user) + (passwd:uid #$user) + (passwd:gid #$user)) + (chmod (string-append "/var/lib/syncthing-" #$user) #o7= 00)) + (make-forkexec-constructor + (append (list (string-append #$syncthing "/bin/syncthing= ") + ;; Do not try to try to lauch a browser on= startup. + "--no-browser" + ;; If syncthing crashes, let the service f= ail. + "--no-restart" + (string-append "--logflags=3D" (number->st= ring #$logflags))) + ;; Optionally move data and configuration home to + ;; /var/lib/syncthing-. + (if (or #$(not config-file) #$home-service?) '() + (list (string-append "--home=3D/var/lib/sync= thing-" #$user))) + '#$arguments) + #:user #$(and (not home-service?) user) + #:group #$(and (not home-service?) group) + #:environment-variables + (append + (list + (string-append "HOME=3D" + (or #$home + (passwd:dir + (getpw (if (and #$home-service? + (not #$user)) + (getuid) + #$user))))) + "SSL_CERT_DIR=3D/etc/ssl/certs" + "SSL_CERT_FILE=3D/etc/ssl/certs/ca-certificates.crt") + (filter (negate ;XXX: 'remove' is not in (guile) + (lambda (str) + (or (string-prefix? "HOME=3D" str) + (string-prefix? "SSL_CERT_DIR=3D" str) + (string-prefix? "SSL_CERT_FILE=3D" str))= )) + (environ)))))) (respawn? #f) (stop #~(make-kill-destructor)))))) =20 + +(define syncthing-files-service + (match-record-lambda (config-file user home ho= me-service?) + (if config-file + ;; When used as a system service, this service might be executed + ;; before a user's home even exists, causing it to be owned by roo= t, + ;; and the skeletons to never be applied to that user's home. In = such + ;; cases, put the config at /var/lib/syncthnig-/config.xml + `((,(if home-service? + ".config/syncthing/config.xml" + (string-append "/var/lib/syncthing-" user "/config.xml")) + ,(if (file-like? config-file) + config-file + (plain-file "syncthin-config.xml" (serialize-syncthing-con= fig-file + config-file))))) + '()))) + (define syncthing-service-type (service-type (name 'syncthing) (extensions (list (service-extension shepherd-root-service= -type - syncthing-shepherd-se= rvice))) + syncthing-shepherd-se= rvice) + (service-extension special-files-service= -type + syncthing-files-servi= ce))) (description "Run @uref{https://github.com/syncthing/syncthing, Syncth= ing} decentralized continuous file system synchronization."))) --=20 2.48.1 From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v9] services: syncthing: Add support for config file generation. Resent-From: Leo Famulari Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sun, 16 Feb 2025 07:14:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Zacchaeus Scheffer Cc: Bruno Victal , 75959@debbugs.gnu.org Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.173969003316748 (code B ref 75959); Sun, 16 Feb 2025 07:14:02 +0000 Received: (at 75959) by debbugs.gnu.org; 16 Feb 2025 07:13:53 +0000 Received: from localhost ([127.0.0.1]:59775 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tjYqe-0004M3-NY for submit@debbugs.gnu.org; Sun, 16 Feb 2025 02:13:53 -0500 Received: from fhigh-a6-smtp.messagingengine.com ([103.168.172.157]:33789) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tjYqb-0004Ll-NL for 75959@debbugs.gnu.org; Sun, 16 Feb 2025 02:13:51 -0500 Received: from phl-compute-04.internal (phl-compute-04.phl.internal [10.202.2.44]) by mailfhigh.phl.internal (Postfix) with ESMTP id 4810811401B4; Sun, 16 Feb 2025 02:13:44 -0500 (EST) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-04.internal (MEProxy); Sun, 16 Feb 2025 02:13:44 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=famulari.name; h=cc:cc:content-type:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=mesmtp; t=1739690024; x= 1739776424; bh=HLdjuiWdHrFnrrYzajuCuCxWnr4OCnARAzQEuI9qHSo=; b=g hXN701SQMG8Wjo1xHG4MZJ6fSuOTVRQp8XtsHgrx9p97r8GfdUbEfM/AwZXO9lJB FdH4EStgZEIy3TXhye+NtTPffigZWV/t40W+8HrdiALdQeAKPtXQDtYP77759/Bn 0ywXXmIyjJPdLsNf2EXgNCwJKdhtHMxH5OV52ZjHHc= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t= 1739690024; x=1739776424; bh=HLdjuiWdHrFnrrYzajuCuCxWnr4OCnARAzQ EuI9qHSo=; b=UbEhBSPWZ/Oy/6nNvaGU8O/uZO7nHE4ITyhFKSGFnWdWtHkY9HK 4CRQ+PJoJSHa4nmUGKem4rpvEJwzNZhq7os0LqLrDoF2u+MhgJF5/mKab9+W7f8V h1pAzTmAzULVI/l+x3bUuM6qL6zWfRdA/oGJ6cARLxT091WPPy/PHkJ4OIKYQNNL NQOCEx1ynBtYBezlMuXwR6ipdCsvATMwOXjsXEfpGxkMNJknCZH4ROGlhFKPrGuE K6URak28vmAQ8+5iRbsmmbRRfvZgaxMkJn1tpbHPRU+BxEb3znFVwV8DV97x8UC3 i//j4EkGuuTLRoCMTetWt+9AkIQVmEHG/2A== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdehgeekfecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdp uffrtefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecunecujfgurhepfffhvf evuffkfhggtggujgesmhdtreertddtvdenucfhrhhomhepnfgvohcuhfgrmhhulhgrrhhi uceolhgvohesfhgrmhhulhgrrhhirdhnrghmvgeqnecuggftrfgrthhtvghrnheptddvgf ffleefjedvteekffduvdeftddtteeggeehgfdtvdehtefghfekfeeuveeinecuvehluhhs thgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomheplhgvohesfhgrmhhulh grrhhirdhnrghmvgdpnhgspghrtghpthhtohepfedpmhhouggvpehsmhhtphhouhhtpdhr tghpthhtohepvghikhgtrgiiseiirggttghhrggvrdhushdprhgtphhtthhopehmihhrrg hisehmrghkihhnrghtrgdrvghupdhrtghpthhtohepjeehleehleesuggvsggsuhhgshdr ghhnuhdrohhrgh X-ME-Proxy: Feedback-ID: i819c4023:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 16 Feb 2025 02:13:43 -0500 (EST) Date: Sun, 16 Feb 2025 02:13:41 -0500 From: Leo Famulari Message-ID: References: <871pvyg0kd.fsf@zacchae.us> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="vD/voWQk6N3gaabX" Content-Disposition: inline In-Reply-To: <871pvyg0kd.fsf@zacchae.us> X-Spam-Score: -0.7 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) --vD/voWQk6N3gaabX Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Sat, Feb 15, 2025 at 08:06:42PM -0500, Zacchaeus Scheffer wrote: > Subject: [PATCH v9] services: syncthing: Add support for config file > generation. Thanks! > + (start #~(lambda _ > + ;; If we are managing the config, and it's not a home > + ;; service, then exepect the config file at > + ;; /var/lib/syncthing-. This makes sure the ownership > + ;; is correct > + (unless (or #$(not config-file) #$home-service?) > + (chown (string-append "/var/lib/syncthing-" #$user) > + (passwd:uid #$user) > + (passwd:gid #$user)) > + (chmod (string-append "/var/lib/syncthing-" #$user) #o700)) This is making the service crash, not sure why: ------ # herd start syncthing-leo Service user-homes has been started. herd: error: exception caught while executing 'start' on service 'syncthing-leo': In procedure vector-ref: Wrong argument in position 1 (expecting vector): "leo" ------ Of course my user's name is leo in the test VM. I added some print-style tracing (attached diff) and it crashes in chown. --vD/voWQk6N3gaabX Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="trace.diff" diff --git a/gnu/services/syncthing.scm b/gnu/services/syncthing.scm index cc88bf7925..9fbcf2c4de 100644 --- a/gnu/services/syncthing.scm +++ b/gnu/services/syncthing.scm @@ -492,10 +492,14 @@ (define syncthing-shepherd-service ;; /var/lib/syncthing-. This makes sure the ownership ;; is correct (unless (or #$(not config-file) #$home-service?) + (display "1 before chown") (newline) (chown (string-append "/var/lib/syncthing-" #$user) (passwd:uid #$user) (passwd:gid #$user)) - (chmod (string-append "/var/lib/syncthing-" #$user) #o700)) + (display "2 before chmod") (newline) + (chmod (string-append "/var/lib/syncthing-" #$user) #o700) + (display "3 after chmod") (newline) +) (make-forkexec-constructor (append (list (string-append #$syncthing "/bin/syncthing") ;; Do not try to try to lauch a browser on startup. --vD/voWQk6N3gaabX-- From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v10] services: syncthing: Add support for config file generation. Resent-From: Zacchaeus Scheffer Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sun, 16 Feb 2025 09:36:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Leo Famulari Cc: Bruno Victal , 75959@debbugs.gnu.org Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.173969853313758 (code B ref 75959); Sun, 16 Feb 2025 09:36:02 +0000 Received: (at 75959) by debbugs.gnu.org; 16 Feb 2025 09:35:33 +0000 Received: from localhost ([127.0.0.1]:60193 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tjb3j-0003Zn-Gg for submit@debbugs.gnu.org; Sun, 16 Feb 2025 04:35:33 -0500 Received: from [47.204.136.169] (port=48066 helo=hun.zacchae.us) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tjb3e-0003ZX-Mb for 75959@debbugs.gnu.org; Sun, 16 Feb 2025 04:35:29 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Transfer-Encoding:Content-Type: MIME-Version:Message-ID:Date:References:In-Reply-To:Subject:Cc:To:From:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=DveX72Na6jX8Yp2sZ0Dfklg77k/q82XvlEbAqXO3iL4=; i=zacchae.us; b=ssrqvILndeaz JazkKkn4fSSbKg3r1HSsSvkAQQREJKamcG4ivhcRnndouzknJijJ87o6WOHgBuERT39VjFmBAQ==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Transfer-Encoding:Content-Type:MIME-Version: Message-ID:Date:References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=DveX72Na6jX8Yp2sZ0Dfklg77k/q82XvlEbAqXO3iL4=; i=zacchae.us; b=a1J9QxFhvWo6 iKZRIHdG58emMzI3pFvYN2JUV/X8htp80by7MVhtCA5A6JVOdNnjKK6GVy2HnyNwNFY6YNl/2ImZ3 X0/wgaKHuwq5BtXUPvchKt5pBwQCfhtGmO/nO6asmz78Y9ZRafV7SkONa9hnX2dlpn1y8TyNFORwA 4lJ2sPhwZKuEpVzIrzRweVIkhDLFpB/FXUUHKit0MkzNAqadM9cbD1oDkNuiT/0PwWVB1NGcq1QYq i2VPVg5o2pS/t/URPPNo0rdqZXfOztjxvPYbDbxxkPdHEdFbKZqEQ05XvpAspOy/tsqO9OL3iLmTR 5WbwDaQs/QjeHR08Deab7A==; Received: from localhost.home ([127.0.0.1]:37756 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1tjb3X-000000008Fc-3MOZ; Sun, 16 Feb 2025 04:35:20 -0500 From: Zacchaeus Scheffer In-Reply-To: (Leo Famulari's message of "Sun, 16 Feb 2025 02:13:41 -0500") References: <871pvyg0kd.fsf@zacchae.us> Date: Sun, 16 Feb 2025 04:35:20 -0500 Message-ID: <87tt8udyg7.fsf_-_@zacchae.us> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From a573fd78e6b8d10b32eb10a753423073c7bbaeef Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH v10] services: syncthing: Add support f [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in sa-accredit.habeas.com] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in bl.score.senderscore.com] 0.1 URIBL_SBL_A Contains URL's A record listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 0.6 URIBL_SBL Contains an URL's NS IP listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS 0.0 T_FILL_THIS_FORM_SHORT Fill in a short form with personal information X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 1.0 (+) >From a573fd78e6b8d10b32eb10a753423073c7bbaeef Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH v10] services: syncthing: Add support for config file generation. * gnu/services/syncthing.scm: (syncthing-config-file, syncthing-folder, syncthing-device, syncthing-folder-device): New records; (syncthing-service-type): Add special-files-service-type extension for the config file; (syncthing-files-service): Add service to create config file. * gnu/home/services/syncthing.scm: (home-syncthing-service-type): Extend home-files-services-type and re-exported more things from gnu/services/syncthing.scm. * doc/guix.texi: (syncthing-service-type): Document changes. Change-Id: I87eeba1ee1fdada8f29c2ee881fbc6bc4113dde9 --- Last time I forgot to test the system service. Chowning/chmodding now works. (Needed to add a getpw instead of passing string of user name.) doc/guix.texi | 334 ++++++++++++++++++++- gnu/home/services/syncthing.scm | 17 +- gnu/services/syncthing.scm | 516 ++++++++++++++++++++++++++++++-- 3 files changed, 834 insertions(+), 33 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index b1b6d98e74..d1fbe5ffd3 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -136,6 +136,7 @@ Copyright @copyright{} 2024 Troy Figiel@* Copyright @copyright{} 2024 Sharlatan Hellseher@* Copyright @copyright{} 2024 45mg@* Copyright @copyright{} 2025 S=C3=B6ren Tempel@* +Copyright @copyright{} 2025 Zacchaeus@* =20 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -22620,7 +22621,7 @@ client. The @code{(gnu services syncthing)} module provides the following services: @cindex syncthing =20 -You might want a syncthing daemon if you have files between two or more +You might want a Syncthing daemon if you have files between two or more computers and want to sync them in real time, safely protected from prying eyes. =20 @@ -22666,12 +22667,339 @@ The group as which the Syncthing service is to b= e run. This assumes that the specified group exists. =20 @item @code{home} (default: @var{#f}) -Common configuration and data directory. The default configuration -directory is @file{$HOME} of the specified Syncthing @code{user}. +Sets the @code{HOME} variable for the Syncthing daemon. The default is +@file{$HOME} of the specified Syncthing @code{user}. + +@item @code{config-file} (default: @var{#f}) +Either a file-like object that resolves to a Syncthing configuration XML +file, or a @code{syncthing-config-file} record (see below). If set to +@code{#f}, Guix will not try to generate a config file, and Syncthing +will generate a default configuration which will not be touched on +reconfigure. Specifying this in a system service moves Syncthing's +common configuration and data directory (@code{--home} in +@uref{https://docs.syncthing.net/users/syncthing.html}) to +@file{/var/lib/syncthing-}. + +@end table +@end deftp + +This section documents a subset of the Syncthing configuration +options=E2=80=94specifically those related to Guix or those affecting how = your +computer will connect to other computers over the network (such as +Syncthing relays or discovery servers). The configuration is fully +documented in the upstream +@uref{https://docs.syncthing.net/users/config.html, Syncthing config +documentation}; camelCase there is converted to kebab-case here. If you +are migrating from a Syncthing-managed configuration to one managed by +Guix, you can check what changes were introduced by @code{diff}ing the +respective @file{config.xml} files. Note that you will need to add +whitespace with 4-space indentation to the file generated by Guix, using +the @code{xmllint} program from the @code{libxml2} package like so: + +@example +XMLLINT_INDENT=3D" " xmllint --format /path/to/new/config.xml | diff /p= ath/to/old/config.xml - +@end example + +When generating a configuration file through Guix, you can still +temporarily modify Syncthing from the GUI or through @code{introducer} +and @code{autoAcceptFolders} mechanisms, but such changes will be reset +on reconfigure. + +@deftp {Data Type} syncthing-config-file +Data type representing the configuration file read by the Syncthing +daemon. + +@table @asis +@item @code{folders} (default: @var{(list (syncthing-folder (id "default")= (label "Default Folder") (path "~/Sync")))} +The default here is the same as Syncthing's default. The value should +be a list of @code{syncthing-folder}s. + +@item @code{devices} (default: @var{'()} +This should be a list of @code{syncthing-device}s. Guix will +automatically add any devices specified in any `folders' to this list. +There are instances when you want to connect to a device despite not +(initially) sharing any folders (such as a device with +autoAcceptFolders). In such instances, you should specify those devices +here. If multiple versions of the same device (as determined by +comparing device ID) are discovered, the one in this list is +prioritized. Otherwise, the first instance in the first folder is used. + +@item @code{gui-enabled} (default: @var{"true"}) +By default, any user on the computer can access the GUI and make changes +to Syncthing. If you leave this enabled, you should probably set +@code{gui-user} and @code{gui-password} (see below). + +@item @code{gui-tls} (default: @var{"false"}) +@item @code{gui-debugging} (default: @var{"false"}) +@item @code{gui-send-basic-auth-prompt} (default: @var{"false"}) +@item @code{gui-address} (default: @var{"127.0.0.1:8384"}) +@item @code{gui-user} (default: @var{#f}) +@item @code{gui-password} (default: @var{#f}) +A bcrypt hash of the GUI password. Remember that this will be globally +exposed in @file{/gnu/store}. + +@item @code{gui-apikey} (default: @var{#f}) +You must specify this to use the Syncthing REST interface. This key is +kept in @file{/gnu/store} and is accessible to all users of the system. + +@item @code{gui-theme} (default: @var{"default"}) +@item @code{ldap-enabled} (default: @var{#f}) +@item @code{ldap-address} (default: @var{""}) +@item @code{ldap-bind-dn} (default: @var{""}) +@item @code{ldap-transport} (default: @var{""}) +@item @code{ldap-insecure-skip-verify} (default: @var{""}) +@item @code{ldap-search-base-dn} (default: @var{""}) +@item @code{ldap-search-filter} (default: @var{""}) +@item @code{listen-address} (default: @var{"default"}) +@item @code{global-announce-server} (default: @var{"default"}) +@item @code{global-announce-enabled} (default: @var{"true"}) +Global discovery servers can be used to help connect devices at unknown +IP addresses by storing the last known IP address. + +@item @code{local-announce-enabled} (default: @var{"true"}) +This makes devices find each other very easily on the same LAN. Often, +this will allow you to just plug an Ethernet between two devices, or +connect one device to the other's hotspot and start syncing. + +@item @code{local-announce-port} (default: @var{"21027"}) +@item @code{local-announce-mcaddr} (default: @var{"[ff12::8384]:21027"}) +@item @code{max-send-kbps} (default: @var{"0"}) +@item @code{max-recv-kbps} (default: @var{"0"}) +@item @code{reconnection-interval-s} (default: @var{"60"}) +@item @code{relays-enabled} (default: @var{"true"}) +This option allows your Syncthing instance to use a global network of +@uref{https://docs.syncthing.net/users/relaying.html, relays} to enable +syncing between devices when all other methods fail. As always, +Syncthing traffic is encrypted in transport and the relays are unable to +decrypt it. + +@item @code{relay-reconnect-interval-m} (default: @var{"10"}) +@item @code{start-browser} (default: @var{"true"}) +@item @code{nat-enabled} (default: @var{"true"}) +@item @code{nat-lease-minutes} (default: @var{"60"}) +@item @code{nat-renewal-minutes} (default: @var{"30"}) +@item @code{nat-timeout-seconds} (default: @var{"10"}) +@item @code{ur-accepted} (default: @var{"0"}) +Options whose names begin with `ur-' control usage reporting. Set to -1 +to disable, or to a positive value to enable. The default (0) disables +reporting, but causes a usage reporting consent prompt to be displayed +in the Syncthing GUI. + +@item @code{ur-seen} (default: @var{"0"}) +@item @code{ur-unique-id} (default: @var{""}) +@item @code{ur-url} (default: @var{"https://data.syncthing.net/newdata"}) +@item @code{ur-post-insecurely} (default: @var{"false"}) +@item @code{ur-initial-delay-s} (default: @var{"1800"}) +@item @code{auto-upgrade-interval-h} (default: @var{"12"}) +@item @code{upgrade-to-pre-releases} (default: @var{"false"}) +@item @code{keep-temporaries-h} (default: @var{"24"}) +@item @code{cache-ignored-files} (default: @var{"false"}) +@item @code{progress-update-interval-s} (default: @var{"5"}) +@item @code{limit-bandwidth-in-lan} (default: @var{"false"}) +@item @code{min-home-disk-free-unit} (default: @var{"%"}) +@item @code{min-home-disk-free} (default: @var{"1"}) +@item @code{releases-url} (default: @var{"https://upgrades.syncthing.net/m= eta.json"}) +@item @code{overwrite-remote-device-names-on-connect} (default: @var{"fals= e"}) +@item @code{temp-index-min-blocks} (default: @var{"10"}) +@item @code{unacked-notification-id} (default: @var{"authenticationUserAnd= Password"}) +@item @code{traffic-class} (default: @var{"0"}) +@item @code{set-low-priority} (default: @var{"true"}) +@item @code{max-folder-concurrency} (default: @var{"0"}) +@item @code{crash-reporting-url} (default: @var{"https://crash.syncthing.n= et/newcrash"}) +@item @code{crash-reporting-enabled} (default: @var{"true"}) +@item @code{stun-keepalive-start-s} (default: @var{"180"}) +@item @code{stun-keepalive-min-s} (default: @var{"20"}) +@item @code{stun-server} (default: @var{"default"}) +@item @code{database-tuning} (default: @var{"auto"}) +@item @code{max-concurrent-incoming-request-kib} (default: @var{"0"}) +@item @code{announce-lan-addresses} (default: @var{"true"}) +@item @code{send-full-index-on-upgrade} (default: @var{"false"}) +@item @code{connection-limit-enough} (default: @var{"0"}) +@item @code{connection-limit-max} (default: @var{"0"}) +@item @code{insecure-allow-old-tls-versions} (default: @var{"false"}) +@item @code{connection-priority-tcp-lan} (default: @var{"10"}) +@item @code{connection-priority-quic-lan} (default: @var{"20"}) +@item @code{connection-priority-tcp-wan} (default: @var{"30"}) +@item @code{connection-priority-quic-wan} (default: @var{"40"}) +@item @code{connection-priority-relay} (default: @var{"50"}) +@item @code{connection-priority-upgrade-threshold} (default: @var{"0"}) +@item @code{default-folder} (default: @var{(syncthing-folder (label ""))}) +@item @code{default-device} (default: @var{(syncthing-device (id ""))}) +@item @code{default-ignores} (default: @var{"")}) +Options whose names begin with `default-' above do not affect folders +and devices added through the Guix configuration interface. They will, +however, affect folders and devices that are added through the Syncthing +GUI, by an @code{introducer}, or a device with +@code{auto-accept-folders}. +@end table +@end deftp + +@deftp {Data Type} syncthing-folder +Data type representing a folder to be synchronized. + +@table @asis +@item @code{id} (default: @var{#f}) +This ID cannot match the ID of any other folder on this device. If left +unspecified, it will default to the label (see below). + +@item @code{label} +A human readable label for the folder. + +@item @code{path} +The path at which to store this folder. + +@item @code{type} (default: @var{"sendreceive"}) +@item @code{rescan-interval-s} (default: @var{"3600"}) +@item @code{fs-watcher-enabled} (default: @var{"true"}) +@item @code{fs-watcher-delay-s} (default: @var{"10"}) +@item @code{ignore-perms} (default: @var{"false"}) +@item @code{auto-normalize} (default: @var{"true"}) +@item @code{devices} (default: @var{'()}) +This should be a list of other Syncthing devices. You do not need to +specify the current device. Each device can be listed as a a +@code{syncthing-device} record or a @code{syncthing-folder-device} +record if you want files to be encrypted on disk. See below. + +@item @code{filesystem-type} (default: @var{"basic"}) +@item @code{min-disk-free-unit} (default: @var{"%"}) +@item @code{min-disk-free} (default: @var{"1"}) +@item @code{versioning-type} (default: @var{#f}) +@item @code{versioning-fs-path} (default: @var{""}) +@item @code{versioning-fs-type} (default: @var{"basic"}) +@item @code{versioning-cleanup-interval-s} (default: @var{"3600"}) +@item @code{versioning-cleanout-days} (default: @var{#f}) +@item @code{versioning-keep} (default: @var{#f}) +@item @code{versioning-max-age} (default: @var{#f}) +@item @code{versioning-command} (default: @var{#f}) +@item @code{copiers} (default: @var{"0"}) +@item @code{puller-max-pending-kib} (default: @var{"0"}) +@item @code{hashers} (default: @var{"0"}) +@item @code{order} (default: @var{"random"}) +@item @code{ignore-delete} (default: @var{"false"}) +@item @code{scan-progress-interval-s} (default: @var{"0"}) +@item @code{puller-pause-s} (default: @var{"0"}) +@item @code{max-conflicts} (default: @var{"10"}) +@item @code{disable-sparse-files} (default: @var{"false"}) +@item @code{disable-temp-indexes} (default: @var{"false"}) +@item @code{paused} (default: @var{"false"}) +@item @code{weak-hash-threshold-pct} (default: @var{"25"}) +@item @code{marker-name} (default: @var{".stfolder"}) +@item @code{copy-ownership-from-parent} (default: @var{"false"}) +@item @code{mod-time-window-s} (default: @var{"0"}) +@item @code{max-concurrent-writes} (default: @var{"2"}) +@item @code{disable-fsync} (default: @var{"false"}) +@item @code{block-pull-order} (default: @var{"standard"}) +@item @code{copy-range-method} (default: @var{"standard"}) +@item @code{case-sensitive-fs} (default: @var{"false"}) +@item @code{junctions-as-dirs} (default: @var{"false"}) +@item @code{sync-ownership} (default: @var{"false"}) +@item @code{send-ownership} (default: @var{"false"}) +@item @code{sync-xattrs} (default: @var{"false"}) +@item @code{send-xattrs} (default: @var{"false"}) +@item @code{xattr-filter-max-single-entry-size} (default: @var{"1024"}) +@item @code{xattr-filter-max-total-size} (default: @var{"4096")}) +@end table +@end deftp + +@deftp {Data Type} syncthing-device +Data type representing a device to synchronize folders with. + +@table @asis +@item @code{id} +A long hash representing the keys generated by Syncthing on the first +launch. You can obtain this from the Syncthing GUI or by inspecting an +existing Syncthing configuration file. + +@item @code{name} (default: @var{""}) +A human readable device name for viewing in the GUI or in Scheme. + +@item @code{compression} (default: @var{"metadata"}) +@item @code{introducer} (default: @var{"false"}) +@item @code{skip-introduction-removals} (default: @var{"false"}) +@item @code{introduced-by} (default: @var{""}) +@item @code{addresses} (default: @var{'("dynamic")}) +List of addresses at which to search for this device. When the special +value ``dynamic'' is included, Syncthing will search for the device +locally as well as via the Syncthing project's +@uref{https://docs.syncthing.net/users/security.html#global-discovery, +global discovery} servers. + +@item @code{paused} (default: @var{"false"}) +@item @code{auto-accept-folders} (default: @var{"false"}) +@item @code{max-send-kbps} (default: @var{"0"}) +@item @code{max-recv-kbps} (default: @var{"0"}) +@item @code{max-request-kib} (default: @var{"0"}) +@item @code{untrusted} (default: @var{"false"}) +@item @code{remote-gui-port} (default: @var{"0"}) +@item @code{num-connections} (default: @var{"0")}) + +@end table +@end deftp + +@deftp {Data Type} syncthing-folder-device +This data type offers two folder-specific device options. First, it +offers @code{introduced-by}, which is a record of Syncthing +@uref{https://docs.syncthing.net/users/introducer.html, introductions}. +Second, it offers @code{encryption-password}, by which you can set the +password used to encrypt data that is synced with +@uref{https://docs.syncthing.net/users/untrusted.html, untrusted +devices}. + +@code{syncthing-folder-device} corresponds to the +@uref{https://docs.syncthing.net/users/config.html#config-option-folder.de= vice, +`device'} option in the upstream `folder' element. + +If you don't need to use these options, then you can just specify +@code{syncthing-device}s instead of @code{syncthing-folder-device}s in a +@code{syncthing-folder}'s @code{devices} field. + +@table @asis +@item @code{device} +The @code{syncthing-device} for which this configuration applies. + +@item @code{introduced-by} (default: @var{""}) +@item @code{encryption-password} (default: @var{""}) +Beware: specifying this field will include this password as plain text +(not encrypted) and globally visible in @file{/gnu/store/}. If the +encryption-password is non-empty, then it will be used as a password to +encrypt file chunks as they are synchronized to untrusted devices. For +more information on syncing to devices you don't totally trust, see +Syncthing's documentation on +@uref{https://docs.syncthing.net/users/untrusted.html, Untrusted +(Encrypted) Devices}. Note that data transfer is always encrypted while +in transport ("end-to-end encryption"), regardless of this setting. =20 @end table @end deftp =20 +Here is a more complex example configuration for illustrative purposes: + +@lisp +(service syncthing-service-type + (let ((laptop (syncthing-device (id "VHOD2D6-...-7XRMDEN"))) + (desktop (syncthing-device (id "64SAZ37-...-FZJ5GUA") + (addresses '("tcp://example.com"= )))) + (bob-desktop (syncthing-device (id "KYIMEGO-...-FT77EAO")))) + (syncthing-configuration + (user "alice") + (config-file + (syncthing-config-file + (folders (list (syncthing-folder + (label "some-files") + (path "~/data") + (devices (list desktop laptop))) + (syncthing-folder + (label "critical-files") + (path "~/secrets") + (devices + (list desktop + laptop + (syncthing-folder-device + (device bob-desktop) + (encryption-password "mypassword"))= )))))))))) +@end lisp + + Furthermore, @code{(gnu services ssh)} provides the following services. @cindex SSH @cindex SSH server diff --git a/gnu/home/services/syncthing.scm b/gnu/home/services/syncthing.= scm index 8d66a167ce..dd6c752ee4 100644 --- a/gnu/home/services/syncthing.scm +++ b/gnu/home/services/syncthing.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2023 Ludovic Court=C3=A8s +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -24,9 +25,23 @@ (define-module (gnu home services syncthing) #:use-module (gnu home services shepherd) #:export (home-syncthing-service-type) #:re-export (syncthing-configuration - syncthing-configuration?)) + syncthing-configuration? + syncthing-config-file + syncthing-config-file? + syncthing-device + syncthing-device? + syncthing-folder + syncthing-folder? + syncthing-folder-device + syncthing-folder-device?)) =20 (define home-syncthing-service-type (service-type (inherit (system->home-service-type syncthing-service-type)) + ;; system->home-service-type does not convert special-files-service-typ= e to + ;; home-files-service-type, so redefine extensios + (extensions (list (service-extension home-files-service-type + syncthing-files-service) + (service-extension home-shepherd-service-type + syncthing-shepherd-service))) (default-value (for-home (syncthing-configuration))))) diff --git a/gnu/services/syncthing.scm b/gnu/services/syncthing.scm index a7a9c6aadd..5cc7eadd57 100644 --- a/gnu/services/syncthing.scm +++ b/gnu/services/syncthing.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2021 Oleg Pykhalov ;;; Copyright =C2=A9 2023 Justin Veilleux +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -25,9 +26,20 @@ (define-module (gnu services syncthing) #:use-module (guix records) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (sxml simple) #:export (syncthing-configuration syncthing-configuration? - syncthing-service-type)) + syncthing-device + syncthing-device? + syncthing-config-file + syncthing-config-file? + syncthing-folder-device + syncthing-folder-device? + syncthing-folder + syncthing-folder? + syncthing-service-type + syncthing-shepherd-service + syncthing-files-service)) =20 ;;; Commentary: ;;; @@ -35,6 +47,414 @@ (define-module (gnu services syncthing) ;;; ;;; Code: =20 +(define-record-type* + syncthing-device make-syncthing-device + syncthing-device? + (id syncthing-device-id) + (name syncthing-device-name (default "")) + (compression syncthing-device-compression (default "metadata")) + (introducer syncthing-device-introducer (default "false")) + (skip-introduction-removals syncthing-device-skip-introduction-removals = (default "false")) + (introduced-by syncthing-device-introduced-by (default "")) + (addresses syncthing-device-addresses (default '("dynamic"))) + (paused syncthing-device-paused (default "false")) + (auto-accept-folders syncthing-device-auto-accept-folders (default "fals= e")) + (max-send-kbps syncthing-device-max-send-kbps (default "0")) + (max-recv-kbps syncthing-device-max-recv-kbps (default "0")) + (max-request-kib syncthing-device-max-request-kib (default "0")) + (untrusted syncthing-device-untrusted (default "false")) + (remote-gui-port syncthing-device-remote-gui-port (default "0")) + (num-connections syncthing-device-num-connections (default "0"))) + +(define syncthing-device->sxml + (match-record-lambda + (id + name compression introducer skip-introduction-removals introduced-by + addresses paused auto-accept-folders max-send-kbps max-recv-kbps + max-request-kib untrusted remote-gui-port num-connections) + `(device (@ (id ,id) + (name ,name) + (compression ,compression) + (introducer ,introducer) + (skipIntroductionRemovals ,skip-introduction-removals) + (introducedBy ,introduced-by)) + ,@(map (lambda (address) `(address ,address)) addresses) + (paused ,paused) + (autoAcceptFolders ,auto-accept-folders) + (maxSendKbps ,max-send-kbps) + (maxRecvKbps ,max-recv-kbps) + (maxRequestKiB ,max-request-kib) + (untrusted ,untrusted) + (remoteGUIPort ,remote-gui-port) + (numConnections ,num-connections)))) + +(define-record-type* + syncthing-folder-device make-syncthing-folder-device + syncthing-folder-device? + (device syncthing-folder-device-device) + (introduced-by syncthing-folder-device-introduced-by (default (syncthing= -device (id "")))) + (encryption-password syncthing-folder-device-encryption-password (defaul= t ""))) + +(define syncthing-folder-device->sxml + (match-record-lambda + (device introduced-by encryption-password) + `(device (@ (id ,(syncthing-device-id device)) + (introducedBy ,(syncthing-device-id introduced-by))) + (encryptionPassword ,encryption-password)))) + +(define-record-type* + syncthing-folder make-syncthing-folder + syncthing-folder? + (id syncthing-folder-id (default #f)) + (label syncthing-folder-label) + (path syncthing-folder-path) + (type syncthing-folder-type (default "sendreceive")) + (rescan-interval-s syncthing-folder-rescan-interval-s (default "3600")) + (fs-watcher-enabled syncthing-folder-fs-watcher-enabled (default "true")) + (fs-watcher-delay-s syncthing-folder-fs-watcher-delay-s (default "10")) + (fs-watcher-timeout-s syncthing-folder-fs-watcher-timeout-s (default "0"= )) + (ignore-perms syncthing-folder-ignore-perms (default "false")) + (auto-normalize syncthing-folder-auto-normalize (default "true")) + (devices syncthing-folder-devices (default '()) + (sanitize (lambda (folder-device-list) + (map (lambda (device) + (if (syncthing-folder-device? device) + device + (syncthing-folder-device (device device)= ))) + folder-device-list)))) + (filesystem-type syncthing-folder-filesystem-type (default "basic")) + (min-disk-free-unit syncthing-folder-min-disk-free-unit (default "%")) + (min-disk-free syncthing-folder-min-disk-free (default "1")) + (versioning-type syncthing-folder-versioning-type (default #f)) + (versioning-fs-path syncthing-folder-versioning-fs-path (default "")) + (versioning-fs-type syncthing-folder-versioning-fs-type (default "basic"= )) + (versioning-cleanup-interval-s syncthing-folder-versioning-cleanup-inter= val-s (default "3600")) + (versioning-cleanout-days syncthing-folder-versioning-cleanout-days (def= ault #f)) + (versioning-keep syncthing-folder-versioning-keep (default #f)) + (versioning-max-age syncthing-folder-versioning-max-age (default #f)) + (versioning-command syncthing-folder-versioning-command (default #f)) + (copiers syncthing-folder-copiers (default "0")) + (puller-max-pending-kib syncthing-folder-puller-max-pending-kib (default= "0")) + (hashers syncthing-folder-hashers (default "0")) + (order syncthing-folder-order (default "random")) + (ignore-delete syncthing-folder-ignore-delete (default "false")) + (scan-progress-interval-s syncthing-folder-scan-progress-interval-s (def= ault "0")) + (puller-pause-s syncthing-folder-puller-pause-s (default "0")) + (max-conflicts syncthing-folder-max-conflicts (default "10")) + (disable-sparse-files syncthing-folder-disable-sparse-files (default "fa= lse")) + (disable-temp-indexes syncthing-folder-disable-temp-indexes (default "fa= lse")) + (paused syncthing-folder-paused (default "false")) + (weak-hash-threshold-pct syncthing-folder-weak-hash-threshold-pct (defau= lt "25")) + (marker-name syncthing-folder-marker-name (default ".stfolder")) + (copy-ownership-from-parent syncthing-folder-copy-ownership-from-parent = (default "false")) + (mod-time-window-s syncthing-folder-mod-time-window-s (default "0")) + (max-concurrent-writes syncthing-folder-max-concurrent-writes (default "= 2")) + (disable-fsync syncthing-folder-disable-fsync (default "false")) + (block-pull-order syncthing-folder-block-pull-order (default "standard")) + (copy-range-method syncthing-folder-copy-range-method (default "standard= ")) + (case-sensitive-fs syncthing-folder-case-sensitive-fs (default "false")) + (junctions-as-dirs syncthing-folder-junctions-as-dirs (default "false")) + (sync-ownership syncthing-folder-sync-ownership (default "false")) + (send-ownership syncthing-folder-send-ownership (default "false")) + (sync-xattrs syncthing-folder-sync-xattrs (default "false")) + (send-xattrs syncthing-folder-send-xattrs (default "false")) + (xattr-filter-max-single-entry-size syncthing-folder-xattr-filter-max-si= ngle-entry-size (default "1024")) + (xattr-filter-max-total-size syncthing-folder-xattr-filter-max-total-siz= e (default "4096"))) + +;; Some parameters, when empty, are fully omitted from the config file. I= t is +;; unknown if this causes a functional difference, but stick to the normal +;; program's behavior to be safe. +(define (maybe-param symbol value) + (if value `((param (@ (key ,(symbol->string symbol)) (val ,value)) "")) = '())) + +(define syncthing-folder->sxml + (match-record-lambda + (id + label path type rescan-interval-s fs-watcher-enabled fs-watcher-del= ay-s + fs-watcher-timeout-s ignore-perms auto-normalize devices filesystem= -type + min-disk-free-unit min-disk-free versioning-type versioning-fs-path + versioning-fs-type versioning-cleanup-interval-s versioning-cleanou= t-days + versioning-keep versioning-max-age versioning-command copiers + puller-max-pending-kib hashers order ignore-delete scan-progress-in= terval-s + puller-pause-s max-conflicts disable-sparse-files disable-temp-inde= xes paused + weak-hash-threshold-pct marker-name copy-ownership-from-parent mod-= time-window-s + max-concurrent-writes disable-fsync block-pull-order copy-range-met= hod + case-sensitive-fs junctions-as-dirs sync-ownership send-ownership s= ync-xattrs + send-xattrs xattr-filter-max-single-entry-size xattr-filter-max-tot= al-size) + `(folder (@ (id ,(if id id label)) + (label ,label) + (path ,path) + (type ,type) + (rescanIntervalS ,rescan-interval-s) + (fsWatcherEnabled ,fs-watcher-enabled) + (fsWatcherDelayS ,fs-watcher-delay-s) + (fsWatcherTimeoutS ,fs-watcher-timeout-s) + (ignorePerms ,ignore-perms) + (autoNormalize ,auto-normalize)) + (filesystemType ,filesystem-type) + ,@(map syncthing-folder-device->sxml + devices) + (minDiskFree (@ (unit ,min-disk-free-unit)) + ,min-disk-free) + (versioning ,@(if versioning-type + `((@ (type ,versioning-type))) + '()) + ,@(maybe-param 'cleanoutDays versioning-cleanout-= days) + ,@(maybe-param 'keep versioning-keep) + ,@(maybe-param 'maxAge versioning-max-age) + ,@(maybe-param 'command versioning-command) + (cleanupIntervalS ,versioning-cleanup-interval-s) + (fsPath ,versioning-fs-path) + (fsType ,versioning-fs-type)) + (copiers ,copiers) + (pullerMaxPendingKiB ,puller-max-pending-kib) + (hashers ,hashers) + (order ,order) + (ignoreDelete ,ignore-delete) + (scanProgressIntervalS ,scan-progress-interval-s) + (pullerPauseS ,puller-pause-s) + (maxConflicts ,max-conflicts) + (disableSparseFiles ,disable-sparse-files) + (disableTempIndexes ,disable-temp-indexes) + (paused ,paused) + (weakHashThresholdPct ,weak-hash-threshold-pct) + (markerName ,marker-name) + (copyOwnershipFromParent ,copy-ownership-from-parent) + (modTimeWindowS ,mod-time-window-s) + (maxConcurrentWrites ,max-concurrent-writes) + (disableFsync ,disable-fsync) + (blockPullOrder ,block-pull-order) + (copyRangeMethod ,copy-range-method) + (caseSensitiveFS ,case-sensitive-fs) + (junctionsAsDirs ,junctions-as-dirs) + (syncOwnership ,sync-ownership) + (sendOwnership ,send-ownership) + (syncXattrs ,sync-xattrs) + (sendXattrs ,send-xattrs) + (xattrFilter (maxSingleEntrySize ,xattr-filter-max-single-ent= ry-size) + (maxTotalSize ,xattr-filter-max-total-size))))) + +(define-record-type* + syncthing-config-file make-syncthing-config-file + syncthing-config-file? + (folders syncthing-config-folders + ; this matches syncthing's default + (default (list (syncthing-folder (id "default") + (label "Default Folder") + (path "~/Sync"))))) + (devices syncthing-config-devices + (default '())) + (gui-enabled syncthing-config-gui-enabled (default "true")) + (gui-tls syncthing-config-gui-tls (default "false")) + (gui-debugging syncthing-config-gui-debugging (default "false")) + (gui-send-basic-auth-prompt syncthing-config-gui-send-basic-auth-prompt = (default "false")) + (gui-address syncthing-config-gui-address (default "127.0.0.1:8384")) + (gui-user syncthing-config-gui-user (default #f)) + (gui-password syncthing-config-gui-password (default #f)) + (gui-apikey syncthing-config-gui-apikey (default #f)) + (gui-theme syncthing-config-gui-theme (default "default")) + (ldap-enabled syncthing-config-ldap-enabled (default #f)) + (ldap-address syncthing-config-ldap-address (default "")) + (ldap-bind-dn syncthing-config-ldap-bind-dn (default "")) + (ldap-transport syncthing-config-ldap-transport (default "")) + (ldap-insecure-skip-verify syncthing-config-ldap-insecure-skip-verify (d= efault "")) + (ldap-search-base-dn syncthing-config-ldap-search-base-dn (default "")) + (ldap-search-filter syncthing-config-ldap-search-filter (default "")) + (listen-address syncthing-config-listen-address (default "default")) + (global-announce-server syncthing-config-global-announce-server (default= "default")) + (global-announce-enabled syncthing-config-global-announce-enabled (defau= lt "true")) + (local-announce-enabled syncthing-config-local-announce-enabled (default= "true")) + (local-announce-port syncthing-config-local-announce-port (default "2102= 7")) + (local-announce-mcaddr syncthing-config-local-announce-mcaddr (default "= [ff12::8384]:21027")) + (max-send-kbps syncthing-config-max-send-kbps (default "0")) + (max-recv-kbps syncthing-config-max-recv-kbps (default "0")) + (reconnection-interval-s syncthing-config-reconnection-interval-s (defau= lt "60")) + (relays-enabled syncthing-config-relays-enabled (default "true")) + (relay-reconnect-interval-m syncthing-config-relay-reconnect-interval-m = (default "10")) + (start-browser syncthing-config-start-browser (default "true")) + (nat-enabled syncthing-config-nat-enabled (default "true")) + (nat-lease-minutes syncthing-config-nat-lease-minutes (default "60")) + (nat-renewal-minutes syncthing-config-nat-renewal-minutes (default "30")) + (nat-timeout-seconds syncthing-config-nat-timeout-seconds (default "10")) + (ur-accepted syncthing-config-ur-accepted (default "0")) + (ur-seen syncthing-config-ur-seen (default "0")) + (ur-unique-id syncthing-config-ur-unique-id (default "")) + (ur-url syncthing-config-ur-url (default "https://data.syncthing.net/new= data")) + (ur-post-insecurely syncthing-config-ur-post-insecurely (default "false"= )) + (ur-initial-delay-s syncthing-config-ur-initial-delay-s (default "1800")) + (auto-upgrade-interval-h syncthing-config-auto-upgrade-interval-h (defau= lt "12")) + (upgrade-to-pre-releases syncthing-config-upgrade-to-pre-releases (defau= lt "false")) + (keep-temporaries-h syncthing-config-keep-temporaries-h (default "24")) + (cache-ignored-files syncthing-config-cache-ignored-files (default "fals= e")) + (progress-update-interval-s syncthing-config-progress-update-interval-s = (default "5")) + (limit-bandwidth-in-lan syncthing-config-limit-bandwidth-in-lan (default= "false")) + (min-home-disk-free-unit syncthing-config-min-home-disk-free-unit (defau= lt "%")) + (min-home-disk-free syncthing-config-min-home-disk-free (default "1")) + (releases-url syncthing-config-releases-url (default "https://upgrades.s= yncthing.net/meta.json")) + (overwrite-remote-device-names-on-connect syncthing-config-overwrite-rem= ote-device-names-on-connect (default "false")) + (temp-index-min-blocks syncthing-config-temp-index-min-blocks (default "= 10")) + (unacked-notification-id syncthing-config-unacked-notification-id (defau= lt "authenticationUserAndPassword")) + (traffic-class syncthing-config-traffic-class (default "0")) + (set-low-priority syncthing-config-set-low-priority (default "true")) + (max-folder-concurrency syncthing-config-max-folder-concurrency (default= "0")) + (crash-reporting-url syncthing-config-crash-reporting-url (default "http= s://crash.syncthing.net/newcrash")) + (crash-reporting-enabled syncthing-config-crash-reporting-enabled (defau= lt "true")) + (stun-keepalive-start-s syncthing-config-stun-keepalive-start-s (default= "180")) + (stun-keepalive-min-s syncthing-config-stun-keepalive-min-s (default "20= ")) + (stun-server syncthing-config-stun-server (default "default")) + (database-tuning syncthing-config-database-tuning (default "auto")) + (max-concurrent-incoming-request-kib syncthing-config-max-concurrent-inc= oming-request-kib (default "0")) + (announce-lan-addresses syncthing-config-announce-lan-addresses (default= "true")) + (send-full-index-on-upgrade syncthing-config-send-full-index-on-upgrade = (default "false")) + (connection-limit-enough syncthing-config-connection-limit-enough (defau= lt "0")) + (connection-limit-max syncthing-config-connection-limit-max (default "0"= )) + (insecure-allow-old-tlsVersions syncthing-config-insecure-allow-old-tlsV= ersions (default "false")) + (connection-priority-tcp-lan syncthing-config-connection-priority-tcp-la= n (default "10")) + (connection-priority-quic-lan syncthing-config-connection-priority-quic-= lan (default "20")) + (connection-priority-tcp-wan syncthing-config-connection-priority-tcp-wa= n (default "30")) + (connection-priority-quic-wan syncthing-config-connection-priority-quic-= wan (default "40")) + (connection-priority-relay syncthing-config-connection-priority-relay (d= efault "50")) + (connection-priority-upgrade-threshold syncthing-config-connection-prior= ity-upgrade-threshold (default "0")) + (default-folder syncthing-config-default-folder + (default (syncthing-folder (label "") (path "~")))) + (default-device syncthing-config-default-device + (default (syncthing-device (id "")))) + (default-ignores syncthing-config-default-ignores (default ""))) + +(define syncthing-config-file->sxml + (match-record-lambda + (folders + devices gui-enabled gui-tls gui-debugging gui-send-basic-auth-prompt + gui-address gui-user gui-password gui-apikey gui-theme ldap-enabled + ldap-address ldap-bind-dn ldap-transport ldap-insecure-skip-verify + ldap-search-base-dn ldap-search-filter listen-address global-announ= ce-server + global-announce-enabled local-announce-enabled local-announce-port + local-announce-mcaddr max-send-kbps max-recv-kbps reconnection-inte= rval-s + relays-enabled relay-reconnect-interval-m start-browser nat-enabled + nat-lease-minutes nat-renewal-minutes nat-timeout-seconds ur-accept= ed + ur-seen ur-unique-id ur-url ur-post-insecurely ur-initial-delay-s + auto-upgrade-interval-h upgrade-to-pre-releases keep-temporaries-h + cache-ignored-files progress-update-interval-s limit-bandwidth-in-l= an + min-home-disk-free-unit min-home-disk-free releases-url + overwrite-remote-device-names-on-connect temp-index-min-blocks + unacked-notification-id traffic-class set-low-priority max-folder-c= oncurrency + crash-reporting-url crash-reporting-enabled stun-keepalive-start-s + stun-keepalive-min-s stun-server database-tuning + max-concurrent-incoming-request-kib announce-lan-addresses + send-full-index-on-upgrade connection-limit-enough connection-limit= -max + insecure-allow-old-tlsVersions connection-priority-tcp-lan + connection-priority-quic-lan connection-priority-tcp-wan + connection-priority-quic-wan connection-priority-relay + connection-priority-upgrade-threshold default-folder default-device + default-ignores) + `(configuration (@ (version "37")) + ,@(map syncthing-folder->sxml + folders) + ;; collect any devices in any folders, as well as any + ;; devices explicitly added. + ,@(map syncthing-device->sxml + (delete-duplicates + (append devices + (apply append + (map (lambda (folder) + (map syncthing-folder-de= vice-device + (syncthing-folder-d= evices folder))) + folders))) + ;; devices are the same if their id's are equal + (lambda (device1 device2) + (string=3D (syncthing-device-id device1) + (syncthing-device-id device2))))) + (gui (@ (enabled ,gui-enabled) + (tls ,gui-tls) + (debugging ,gui-debugging) + (sendBasicAuthPrompt ,gui-send-basic-auth-prom= pt)) + (address ,gui-address) + ,@(if gui-user `((user ,gui-user)) '()) + ,@(if gui-password `((password ,gui-password)) '(= )) + ,@(if gui-apikey `((apikey ,gui-apikey)) '()) + (theme ,gui-theme)) + (ldap ,(if ldap-enabled + `((address ,ldap-address) + (bindDN ,ldap-bind-dn) + ,@(if ldap-transport + `((transport ,ldap-transport)) + '()) + ,@(if ldap-insecure-skip-verify + `((insecureSkipVerify ,ldap-insecur= e-skip-verify)) + '()) + ,@(if ldap-search-base-dn + `((searchBaseDN ,ldap-search-base-d= n)) + '()) + ,@(if ldap-search-filter + `((searchFilter ,ldap-search-filter= )) + '())) + "")) + (options (listenAddress ,listen-address) + (globalAnnounceServer ,global-announce-server) + (globalAnnounceEnabled ,global-announce-enabl= ed) + (localAnnounceEnabled ,local-announce-enabled) + (localAnnouncePort ,local-announce-port) + (localAnnounceMCAddr ,local-announce-mcaddr) + (maxSendKbps ,max-send-kbps) + (maxRecvKbps ,max-recv-kbps) + (reconnectionIntervalS ,reconnection-interval= -s) + (relaysEnabled ,relays-enabled) + (relayReconnectIntervalM ,relay-reconnect-int= erval-m) + (startBrowser ,start-browser) + (natEnabled ,nat-enabled) + (natLeaseMinutes ,nat-lease-minutes) + (natRenewalMinutes ,nat-renewal-minutes) + (natTimeoutSeconds ,nat-timeout-seconds) + (urAccepted ,ur-accepted) + (urSeen ,ur-seen) + (urUniqueID ,ur-unique-id) + (urURL ,ur-url) + (urPostInsecurely ,ur-post-insecurely) + (urInitialDelayS ,ur-initial-delay-s) + (autoUpgradeIntervalH ,auto-upgrade-interval-= h) + (upgradeToPreReleases ,upgrade-to-pre-release= s) + (keepTemporariesH ,keep-temporaries-h) + (cacheIgnoredFiles ,cache-ignored-files) + (progressUpdateIntervalS ,progress-update-int= erval-s) + (limitBandwidthInLan ,limit-bandwidth-in-lan) + (minHomeDiskFree (@ (unit ,min-home-disk-free= -unit)) + ,min-home-disk-free) + (releasesURL ,releases-url) + (overwriteRemoteDeviceNamesOnConnect ,overwri= te-remote-device-names-on-connect) + (tempIndexMinBlocks ,temp-index-min-blocks) + (unackedNotificationID ,unacked-notification-= id) + (trafficClass ,traffic-class) + (setLowPriority ,set-low-priority) + (maxFolderConcurrency ,max-folder-concurrency) + (crashReportingURL ,crash-reporting-url) + (crashReportingEnabled ,crash-reporting-enabl= ed) + (stunKeepaliveStartS ,stun-keepalive-start-s) + (stunKeepaliveMinS ,stun-keepalive-min-s) + (stunServer ,stun-server) + (databaseTuning ,database-tuning) + (maxConcurrentIncomingRequestKiB ,max-concurr= ent-incoming-request-kib) + (announceLANAddresses ,announce-lan-addresses) + (sendFullIndexOnUpgrade ,send-full-index-on-u= pgrade) + (connectionLimitEnough ,connection-limit-enou= gh) + (connectionLimitMax ,connection-limit-max) + (insecureAllowOldTLSVersions ,insecure-allow-= old-tlsVersions) + (connectionPriorityTcpLan ,connection-priorit= y-tcp-lan) + (connectionPriorityQuicLan ,connection-priori= ty-quic-lan) + (connectionPriorityTcpWan ,connection-priorit= y-tcp-wan) + (connectionPriorityQuicWan ,connection-priori= ty-quic-wan) + (connectionPriorityRelay ,connection-priority= -relay) + (connectionPriorityUpgradeThreshold ,connecti= on-priority-upgrade-threshold)) + (defaults + ,(syncthing-folder->sxml default-folder) + ,(syncthing-device->sxml default-device) + (ignores ,default-ignores))))) + + +(define (serialize-syncthing-config-file config) + (with-output-to-string + (lambda () + (sxml->xml (cons '*TOP* (list (syncthing-config-file->sxml config)))= )))) + (define-record-type* syncthing-configuration make-syncthing-configuration syncthing-configuration? @@ -50,12 +470,14 @@ (define-record-type* (default "users")) (home syncthing-configuration-home ;string (default #f)) + (config-file syncthing-configuration-config-file + (default #f)) ; syncthing-config-file or = file-like (home-service? syncthing-configuration-home-service? (default for-home?) (innate))) =20 (define syncthing-shepherd-service (match-record-lambda - (syncthing arguments logflags user group home home-service?) + (syncthing arguments logflags user group home home-service? config-f= ile) (list (shepherd-service (provision (if home-service? @@ -64,39 +486,75 @@ (define syncthing-shepherd-service (string-append "syncthing-" user))))) (documentation "Run syncthing.") (requirement (if home-service? '() '(loopback user-processes))) - (start #~(make-forkexec-constructor - (append (list (string-append #$syncthing "/bin/syncthing") - "--no-browser" - "--no-restart" - (string-append "--logflags=3D" (number->stri= ng #$logflags))) - '#$arguments) - #:user #$(and (not home-service?) user) - #:group #$(and (not home-service?) group) - #:environment-variables - (append - (list - (string-append "HOME=3D" - (or #$home - (passwd:dir - (getpw (if (and #$home-service? - (not #$user)) - (getuid) - #$user))))) - "SSL_CERT_DIR=3D/etc/ssl/certs" - "SSL_CERT_FILE=3D/etc/ssl/certs/ca-certifica= tes.crt") - (filter (negate ;XXX: 'remove' is not in (gu= ile) - (lambda (str) - (or (string-prefix? "HOME=3D" str) - (string-prefix? "SSL_CERT_DIR=3D" s= tr) - (string-prefix? "SSL_CERT_FILE=3D" = str)))) - (environ))))) + (start #~(lambda _ + ;; If we are managing the config, and it's not a home + ;; service, then exepect the config file at + ;; /var/lib/syncthing-. This makes sure the owners= hip + ;; is correct + (unless (or #$(not config-file) #$home-service?) + (let ((user-pw (getpw #$user))) + (chown (string-append "/var/lib/syncthing-" #$user) + (passwd:uid user-pw) + (passwd:gid user-pw))) + (chmod (string-append "/var/lib/syncthing-" #$user) #o7= 00)) + (make-forkexec-constructor + (append (list (string-append #$syncthing "/bin/syncthing= ") + ;; Do not try to try to lauch a browser on= startup. + "--no-browser" + ;; If syncthing crashes, let the service f= ail. + "--no-restart" + (string-append "--logflags=3D" (number->st= ring #$logflags))) + ;; Optionally move data and configuration home to + ;; /var/lib/syncthing-. + (if (or #$(not config-file) #$home-service?) '() + (list (string-append "--home=3D/var/lib/sync= thing-" #$user))) + '#$arguments) + #:user #$(and (not home-service?) user) + #:group #$(and (not home-service?) group) + #:environment-variables + (append + (list + (string-append "HOME=3D" + (or #$home + (passwd:dir + (getpw (if (and #$home-service? + (not #$user)) + (getuid) + #$user))))) + "SSL_CERT_DIR=3D/etc/ssl/certs" + "SSL_CERT_FILE=3D/etc/ssl/certs/ca-certificates.crt") + (filter (negate ;XXX: 'remove' is not in (guile) + (lambda (str) + (or (string-prefix? "HOME=3D" str) + (string-prefix? "SSL_CERT_DIR=3D" str) + (string-prefix? "SSL_CERT_FILE=3D" str))= )) + (environ)))))) (respawn? #f) (stop #~(make-kill-destructor)))))) =20 + +(define syncthing-files-service + (match-record-lambda (config-file user home ho= me-service?) + (if config-file + ;; When used as a system service, this service might be executed + ;; before a user's home even exists, causing it to be owned by roo= t, + ;; and the skeletons to never be applied to that user's home. In = such + ;; cases, put the config at /var/lib/syncthnig-/config.xml + `((,(if home-service? + ".config/syncthing/config.xml" + (string-append "/var/lib/syncthing-" user "/config.xml")) + ,(if (file-like? config-file) + config-file + (plain-file "syncthin-config.xml" (serialize-syncthing-con= fig-file + config-file))))) + '()))) + (define syncthing-service-type (service-type (name 'syncthing) (extensions (list (service-extension shepherd-root-service= -type - syncthing-shepherd-se= rvice))) + syncthing-shepherd-se= rvice) + (service-extension special-files-service= -type + syncthing-files-servi= ce))) (description "Run @uref{https://github.com/syncthing/syncthing, Syncth= ing} decentralized continuous file system synchronization."))) --=20 2.48.1 From unknown Mon Aug 18 09:05:05 2025 MIME-Version: 1.0 X-Mailer: MIME-tools 5.505 (Entity 5.505) X-Loop: help-debbugs@gnu.org From: help-debbugs@gnu.org (GNU bug Tracking System) To: Zacchaeus Subject: bug#75959: closed (Re: [PATCH v10] services: syncthing: Add support for config file generation.) Message-ID: References: <20250130215954.9394-1-eikcaz@zacchae.us> X-Gnu-PR-Message: they-closed 75959 X-Gnu-PR-Package: guix-patches X-Gnu-PR-Keywords: patch Reply-To: 75959@debbugs.gnu.org Date: Mon, 17 Feb 2025 06:16:02 +0000 Content-Type: multipart/mixed; boundary="----------=_1739772962-9282-1" This is a multi-part message in MIME format... ------------=_1739772962-9282-1 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Your bug report #75959: [PATCH] (home-)syncthing-service: added support for config serializ= ation which was filed against the guix-patches package, has been closed. The explanation is attached below, along with your original report. If you require more details, please reply to 75959@debbugs.gnu.org. --=20 75959: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=3D75959 GNU Bug Tracking System Contact help-debbugs@gnu.org with problems ------------=_1739772962-9282-1 Content-Type: message/rfc822 Content-Disposition: inline Content-Transfer-Encoding: 7bit Received: (at 75959-done) by debbugs.gnu.org; 17 Feb 2025 06:15:06 +0000 Received: from localhost ([127.0.0.1]:41435 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tjuPJ-0002GK-OK for submit@debbugs.gnu.org; Mon, 17 Feb 2025 01:15:06 -0500 Received: from fout-b3-smtp.messagingengine.com ([202.12.124.146]:53711) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tjuPF-0002DS-03 for 75959-done@debbugs.gnu.org; Mon, 17 Feb 2025 01:15:03 -0500 Received: from phl-compute-01.internal (phl-compute-01.phl.internal [10.202.2.41]) by mailfout.stl.internal (Postfix) with ESMTP id B741A114014B; Mon, 17 Feb 2025 01:14:54 -0500 (EST) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-01.internal (MEProxy); Mon, 17 Feb 2025 01:14:54 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=famulari.name; h=cc:cc:content-type:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=mesmtp; t=1739772894; x= 1739859294; bh=xU/h2JEAUueLcTkTQBggsC5772Ehc9M/XJGwnX+fuOU=; b=m p39N/DxTdWKthU2Wds1SCi05kpb4QVXtfO7iz/aWxLACd4kNYEd3fjB76Ro+gewT IKRqh7LnDFCaFswVam/oVnyuDXNXl2eWBk+/gxX+SYFOjbB22GqsUJZkRqmKnBsG /9yHvwj6+Al0Sz4VWp2XsvGmS05VxJW6H33u2NQZs4= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t= 1739772894; x=1739859294; bh=xU/h2JEAUueLcTkTQBggsC5772Ehc9M/XJG wnX+fuOU=; b=E1Js3mJNojXr/tvCs21XVEK0fy9IxpLbUpjocwzZSNfl+E6lfd/ QMV4AbG3O3vCodSPsh9sVfLB4bYVKh3zoaMMnKwxqRBf5OYsiEtv3dZ+6ahfWHts w3VUItumhaogpoT/QQmfYSlRIA9L36iN7FO71teJszDZtro01QiAegNLQ63QZ+C6 IHif1C/OBHuocWnjXc3R0VsaYSNjt+EYykUgA6FEDGe8kuUTLk91ry8Zy0lLQSe0 6i1hS50KyCUAwpn0KQ0mEbg0vCelifcNoU0Nefcb1N113G3Uh14Vw3V2Oz7TkC3D KHvUoJcLXYjfU49EJKHZfDrMV9IrXf5yt6A== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdehjeeifecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdp uffrtefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecunecujfgurhepfffhvf evuffkfhggtggujgesthdtredttddtvdenucfhrhhomhepnfgvohcuhfgrmhhulhgrrhhi uceolhgvohesfhgrmhhulhgrrhhirdhnrghmvgeqnecuggftrfgrthhtvghrnhepieetud ehfeekueefleegudfhjefgleehfeeluefhfeffgfeuudelhedvjeelieetnecuvehluhhs thgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomheplhgvohesfhgrmhhulh grrhhirdhnrghmvgdpnhgspghrtghpthhtohepfedpmhhouggvpehsmhhtphhouhhtpdhr tghpthhtohepvghikhgtrgiiseiirggttghhrggvrdhushdprhgtphhtthhopehmihhrrg hisehmrghkihhnrghtrgdrvghupdhrtghpthhtohepjeehleehledqughonhgvseguvggs sghughhsrdhgnhhurdhorhhg X-ME-Proxy: Feedback-ID: i819c4023:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 17 Feb 2025 01:14:53 -0500 (EST) Date: Mon, 17 Feb 2025 01:14:51 -0500 From: Leo Famulari To: Zacchaeus Scheffer Subject: Re: [PATCH v10] services: syncthing: Add support for config file generation. Message-ID: References: <871pvyg0kd.fsf@zacchae.us> <87tt8udyg7.fsf_-_@zacchae.us> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <87tt8udyg7.fsf_-_@zacchae.us> X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 75959-done Cc: Bruno Victal , 75959-done@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) On Sun, Feb 16, 2025 at 04:35:20AM -0500, Zacchaeus Scheffer wrote: > From a573fd78e6b8d10b32eb10a753423073c7bbaeef Mon Sep 17 00:00:00 2001 > From: Zacchaeus > Date: Sun, 21 Jul 2024 00:54:25 -0700 > Subject: [PATCH v10] services: syncthing: Add support for config file > generation. > > * gnu/services/syncthing.scm: (syncthing-config-file, > syncthing-folder, syncthing-device, syncthing-folder-device): New > records; (syncthing-service-type): Add special-files-service-type > extension for the config file; (syncthing-files-service): Add service > to create config file. > * gnu/home/services/syncthing.scm: (home-syncthing-service-type): > Extend home-files-services-type and re-exported more things from > gnu/services/syncthing.scm. > * doc/guix.texi: (syncthing-service-type): Document changes. Pushed as 651f8765b657e35baf85ac74a1f6b09ff71691cb Thank you for your contribution to Guix! ------------=_1739772962-9282-1 Content-Type: message/rfc822 Content-Disposition: inline Content-Transfer-Encoding: 7bit Received: (at submit) by debbugs.gnu.org; 31 Jan 2025 04:17:38 +0000 Received: from localhost ([127.0.0.1]:48851 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tdiTH-0001pQ-Vs for submit@debbugs.gnu.org; Thu, 30 Jan 2025 23:17:38 -0500 Received: from lists.gnu.org ([2001:470:142::17]:54118) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tdccl-0007O5-Vc for submit@debbugs.gnu.org; Thu, 30 Jan 2025 17:03:02 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tdccc-0006O8-CK for guix-patches@gnu.org; Thu, 30 Jan 2025 17:02:50 -0500 Received: from [47.204.136.169] (helo=hun.zacchae.us) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tdccY-0003xA-Id for guix-patches@gnu.org; Thu, 30 Jan 2025 17:02:50 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Transfer-Encoding:Content-Type: MIME-Version:Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=R5kdJCRRt3O/oAWwGScGfxmSrZTOLpVp23UzckEGeco=; i=zacchae.us; b=+TEHxkxlELoD FMDhHTEZhtLqqYixJBK42lS0KbPCaDoUOexuiSXTnxl181x9QpS5hqo0M+Zug63TLYzFCrHWDQ==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Transfer-Encoding:Content-Type:MIME-Version: Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=R5kdJCRRt3O/oAWwGScGfxmSrZTOLpVp23UzckEGeco=; i=zacchae.us; b=UbnHx/F1vj9z lOmioXoACwf0AhMrId+nBe5d542p+0nAO+G3i3zWdUrHT4g5NLPoYS3GEufGVQwp4Ay2ggz6RQ6O7 vOY3VoGr5mFJU3QRgut7WuGZYTkhH9/So6kn1oYBj5FbvbGYvmQHRe8vX1FPE85H+Q2LAxD8zgtjV ozRFE/QdY8h7dbZuVFpttZcKYPCBtHqrebd+CKfAzQfjcIVz3Ie7hQrVy664ftsAxdrB8iZvgfhnQ GCadIVV+eZrW6jtcleCeJS7YZPhvTWRY7V+gZbj0SmN1VFQQZAF4eeHTZfeUivBRazNeG8N9lHc5t kVKs260Q2bfDMr02NhUChg==; Received: from localhost.home ([127.0.0.1]:43730 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1tdccV-000000000Iw-2hrB; Thu, 30 Jan 2025 17:02:44 -0500 From: Zacchaeus To: guix-patches@gnu.org Subject: [PATCH] (home-)syncthing-service: added support for config serialization Date: Thu, 30 Jan 2025 13:59:12 -0800 Message-ID: <20250130215954.9394-1-eikcaz@zacchae.us> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Host-Lookup-Failed: Reverse DNS lookup failed for 47.204.136.169 (failed) Received-SPF: pass client-ip=47.204.136.169; envelope-from=eikcaz@zacchae.us; helo=hun.zacchae.us X-Spam_score_int: -7 X-Spam_score: -0.8 X-Spam_bar: / X-Spam_report: (-0.8 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_FILL_THIS_FORM_SHORT=0.01, URIBL_SBL_A=0.1 autolearn=no autolearn_force=no X-Spam_action: no action X-Spam-Score: 1.7 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From 48c227546ea15aadbd5f5832d8cd30887f65ace9 Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH] (home-)syncthing-service: added suppor [...] Content analysis details: (1.7 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.1 URIBL_SBL_A Contains URL's A record listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 0.6 URIBL_SBL Contains an URL's NS IP listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2001:470:142:0:0:0:0:17 listed in] [list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record 0.9 SPF_FAIL SPF: sender does not match SPF record (fail) [SPF failed: Please see http://www.openspf.org/Why?s=mfrom; id=eikcaz%40zacchae.us; ip=2001%3A470%3A142%3A%3A17; r=debbugs.gnu.org] 0.0 T_FILL_THIS_FORM_SHORT Fill in a short form with personal information X-Debbugs-Envelope-To: submit X-Mailman-Approved-At: Thu, 30 Jan 2025 23:17:30 -0500 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 0.7 (/) >From 48c227546ea15aadbd5f5832d8cd30887f65ace9 Mon Sep 17 00:00:00 2001 From: Zacchaeus Date: Sun, 21 Jul 2024 00:54:25 -0700 Subject: [PATCH] (home-)syncthing-service: added support for config serialization Change-Id: I87eeba1ee1fdada8f29c2ee881fbc6bc4113dde9 --- doc/guix.texi | 281 ++++++++++++++++++- gnu/home/services/syncthing.scm | 17 +- gnu/services/syncthing.scm | 459 +++++++++++++++++++++++++++++++- 3 files changed, 752 insertions(+), 5 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index b1b6d98e74..966fe852a4 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -136,6 +136,7 @@ Copyright @copyright{} 2024 Troy Figiel@* Copyright @copyright{} 2024 Sharlatan Hellseher@* Copyright @copyright{} 2024 45mg@* Copyright @copyright{} 2025 S=C3=B6ren Tempel@* +Copyright @copyright{} 2025 Zacchaeus@* =20 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -22669,8 +22670,284 @@ This assumes that the specified group exists. Common configuration and data directory. The default configuration directory is @file{$HOME} of the specified Syncthing @code{user}. =20 -@end table -@end deftp +@item @code{syncthing-config-file} (default: @var{#f}) +Either a file-like object that resolves to a syncthing configuraton xml +file, or a syncthing-config-file record (see below). + +@end table +@end deftp + +In the below, only details specific to Guix, or related to how your +device will ``ping'' others, are presented. Otherwise, you should +consult @uref{https://docs.syncthing.net/users/config.html, Syncthing +config documentation}. Camelcase is preserved below only as to be +consistent with its appearance in Syncthing code/documentation. If you +would like to migrate to Guix-powerd Syncthing configuration, the +generated config adds newlines/whitespace to the produced config such +that your old config can be diff'ed with the new one. + +@deftp {Data Type} syncthing-config-file +Data type representing the configuration file read by the syncthing +daemon. + +@table @asis +@item @code{folders} (default: @var{(list (syncthing-folder (id "default")= (label "Default Folder") (path "~/Sync")))} +The default here is the same as Syncthing's default. The value should +be a list of @code{syncthing-folder}s. + +@item @code{devices} (default: @var{'()} +This should be a list of @code{syncthing-device}s, or strings correspondin= g to +the device ids. A device entry corresponding to the current device is +silently ignored by Syncthing. + +@item @code{gui-enabled} (default: @var{"true"}) +By default, any user on the computer can access the GUI and make changes +to Syncthing. If you leave this enabled, you should probably set +gui-user and gui-password (see belowe). + +@item @code{gui-tls} (default: @var{"false"}) +@item @code{gui-debugging} (default: @var{"false"}) +@item @code{gui-sendBasicAuthPrompt} (default: @var{"false"}) +@item @code{gui-address} (default: @var{"127.0.0.1:8384"}) +@item @code{gui-user} (default: @var{#f}) +@item @code{gui-password} (default: @var{#f}) +@item @code{gui-apikey} (default: @var{"Vuky3VHVseQEoSk9YgxhSkNTnjQmqYK9"}) +@item @code{gui-theme} (default: @var{"default"}) +@item @code{ldap-enabled} (default: @var{#f}) +@item @code{ldap-address} (default: @var{""}) +@item @code{ldap-bindDN} (default: @var{""}) +@item @code{ldap-transport} (default: @var{""}) +@item @code{ldap-insecureSkipVerify} (default: @var{""}) +@item @code{ldap-searchBaseDN} (default: @var{""}) +@item @code{ldap-searchFilter} (default: @var{""}) +@item @code{listenAddress} (default: @var{"default"}) +@item @code{globalAnnounceServer} (default: @var{"default"}) +@item @code{globalAnnounceEnabled} (default: @var{"true"}) +Global discovery servers can be used to help connect devices at unknown +IP addresses by storing the last known IP address. + +@item @code{localAnnounceEnabled} (default: @var{"true"}) +This makes devices find eachother very easily on the same LAN. Often, +this will allow you to just plug an ethernet between two devices, or +connect one device to the other's hotspot and start syncing. + +@item @code{localAnnouncePort} (default: @var{"21027"}) +@item @code{localAnnounceMCAddr} (default: @var{"[ff12::8384]:21027"}) +@item @code{maxSendKbps} (default: @var{"0"}) +@item @code{maxRecvKbps} (default: @var{"0"}) +@item @code{reconnectionIntervalS} (default: @var{"60"}) +@item @code{relaysEnabled} (default: @var{"true"}) +This option allows your Syncthing instance to coordinate with a global +network of relays to enable syncing between devices when all other +methods fail. + +@item @code{relayReconnectIntervalM} (default: @var{"10"}) +@item @code{startBrowser} (default: @var{"true"}) +@item @code{natEnabled} (default: @var{"true"}) +@item @code{natLeaseMinutes} (default: @var{"60"}) +@item @code{natRenewalMinutes} (default: @var{"30"}) +@item @code{natTimeoutSeconds} (default: @var{"10"}) +@item @code{urAccepted} (default: @var{"0"}) +ur* options control usage reporting. Set to -1 to disable, or positive +to enable. The default (0) has reporting disabled, but you will be +asked to decide in the GUI. + +@item @code{urSeen} (default: @var{"0"}) +@item @code{urUniqueID} (default: @var{""}) +@item @code{urURL} (default: @var{"https://data.syncthing.net/newdata"}) +@item @code{urPostInsecurely} (default: @var{"false"}) +@item @code{urInitialDelayS} (default: @var{"1800"}) +@item @code{autoUpgradeIntervalH} (default: @var{"12"}) +@item @code{upgradeToPreReleases} (default: @var{"false"}) +@item @code{keepTemporariesH} (default: @var{"24"}) +@item @code{cacheIgnoredFiles} (default: @var{"false"}) +@item @code{progressUpdateIntervalS} (default: @var{"5"}) +@item @code{limitBandwidthInLan} (default: @var{"false"}) +@item @code{minHomeDiskFree-unit} (default: @var{"%"}) +@item @code{minHomeDiskFree} (default: @var{"1"}) +@item @code{releasesURL} (default: @var{"https://upgrades.syncthing.net/me= ta.json"}) +@item @code{overwriteRemoteDeviceNamesOnConnect} (default: @var{"false"}) +@item @code{tempIndexMinBlocks} (default: @var{"10"}) +@item @code{unackedNotificationID} (default: @var{"authenticationUserAndPa= ssword"}) +@item @code{trafficClass} (default: @var{"0"}) +@item @code{setLowPriority} (default: @var{"true"}) +@item @code{maxFolderConcurrency} (default: @var{"0"}) +@item @code{crashReportingURL} (default: @var{"https://crash.syncthing.net= /newcrash"}) +@item @code{crashReportingEnabled} (default: @var{"true"}) +@item @code{stunKeepaliveStartS} (default: @var{"180"}) +@item @code{stunKeepaliveMinS} (default: @var{"20"}) +@item @code{stunServer} (default: @var{"default"}) +@item @code{databaseTuning} (default: @var{"auto"}) +@item @code{maxConcurrentIncomingRequestKiB} (default: @var{"0"}) +@item @code{announceLANAddresses} (default: @var{"true"}) +@item @code{sendFullIndexOnUpgrade} (default: @var{"false"}) +@item @code{connectionLimitEnough} (default: @var{"0"}) +@item @code{connectionLimitMax} (default: @var{"0"}) +@item @code{insecureAllowOldTLSVersions} (default: @var{"false"}) +@item @code{connectionPriorityTcpLan} (default: @var{"10"}) +@item @code{connectionPriorityQuicLan} (default: @var{"20"}) +@item @code{connectionPriorityTcpWan} (default: @var{"30"}) +@item @code{connectionPriorityQuicWan} (default: @var{"40"}) +@item @code{connectionPriorityRelay} (default: @var{"50"}) +@item @code{connectionPriorityUpgradeThreshold} (default: @var{"0"}) +@item @code{default-folder} (default: @var{(syncthing-folder (label ""))}) +@item @code{default-device} (default: @var{(syncthing-device (id ""))}) +@item @code{default-ignores} (default: @var{"")}) +The default-* above do not affect folders and devices added by the Guix +interface. They will, however, affect folders and devices that are +added through the GUI, or by an ``introducer''. +@end table +@end deftp + +@deftp {Data Type} syncthing-device +Data type representing a device to sync with. + +@table @asis +@item @code{id} +A long hash tied to the keys generated by Syncthing on the first launch. +You can obtain this from the Syncthing GUI or by inpsecting an existing +Syncthing configuration file. + +@item @code{name} (default: @var{""}) +Human readable device name for viewing in the GUI or in scheme. + +@item @code{compression} (default: @var{"metadata"}) +@item @code{introducer} (default: @var{"false"}) +@item @code{skipIntroductionRemovals} (default: @var{"false"}) +@item @code{introducedBy} (default: @var{""}) +@item @code{addresses} (default: @var{'("dynamic")}) +List of addresses at which to search for this device. The special value +``dynamic'' will have syncthing use several means to find the device. + +@item @code{paused} (default: @var{"false"}) +@item @code{autoAcceptFolders} (default: @var{"false"}) +@item @code{maxSendKbps} (default: @var{"0"}) +@item @code{maxRecvKbps} (default: @var{"0"}) +@item @code{maxRequestKiB} (default: @var{"0"}) +@item @code{untrusted} (default: @var{"false"}) +@item @code{remoteGUIPort} (default: @var{"0"}) +@item @code{numConnections} (default: @var{"0")}) + +@end table +@end deftp + +@deftp {Data Type} syncthing-folder +Data type representing a folder to be synced. + +@table @asis +@item @code{id} (default: @var{#f}) +This id cannot match the id of any other folder on this device. If left +unspecified, it will default to the label (see below). + +@item @code{label} +Human readable label for the folder. + +@item @code{path} +The path at which to store this folder. + +@item @code{type} (default: @var{"sendreceive"}) +@item @code{rescanIntervalS} (default: @var{"3600"}) +@item @code{fsWatcherEnabled} (default: @var{"true"}) +@item @code{fsWatcherDelayS} (default: @var{"10"}) +@item @code{ignorePerms} (default: @var{"false"}) +@item @code{autoNormalize} (default: @var{"true"}) +@item @code{devices} (default: @var{'()}) +Devices should be a list of other Syncthing devices. If the current +device is included, it is silently ignored by syncthing (which makes for +lazier scheme code). Each device can be listed as a string representing +the device id, a @code{syncthing-device} object, or a +@code{syncthing-folder-device} object. + +@item @code{filesystemType} (default: @var{"basic"}) +@item @code{minDiskFree-unit} (default: @var{"%"}) +@item @code{minDiskFree} (default: @var{"1"}) +@item @code{versioning-type} (default: @var{#f}) +@item @code{versioning-fsPath} (default: @var{""}) +@item @code{versioning-fsType} (default: @var{"basic"}) +@item @code{versioning-cleanupIntervalS} (default: @var{"3600"}) +@item @code{versioning-cleanoutDays} (default: @var{#f}) +@item @code{versioning-keep} (default: @var{#f}) +@item @code{versioning-maxAge} (default: @var{#f}) +@item @code{versioning-command} (default: @var{#f}) +@item @code{copiers} (default: @var{"0"}) +@item @code{pullerMaxPendingKiB} (default: @var{"0"}) +@item @code{hashers} (default: @var{"0"}) +@item @code{order} (default: @var{"random"}) +@item @code{ignoreDelete} (default: @var{"false"}) +@item @code{scanProgressIntervalS} (default: @var{"0"}) +@item @code{pullerPauseS} (default: @var{"0"}) +@item @code{maxConflicts} (default: @var{"10"}) +@item @code{disableSparseFiles} (default: @var{"false"}) +@item @code{disableTempIndexes} (default: @var{"false"}) +@item @code{paused} (default: @var{"false"}) +@item @code{weakHashThresholdPct} (default: @var{"25"}) +@item @code{markerName} (default: @var{".stfolder"}) +@item @code{copyOwnershipFromParent} (default: @var{"false"}) +@item @code{modTimeWindowS} (default: @var{"0"}) +@item @code{maxConcurrentWrites} (default: @var{"2"}) +@item @code{disableFsync} (default: @var{"false"}) +@item @code{blockPullOrder} (default: @var{"standard"}) +@item @code{copyRangeMethod} (default: @var{"standard"}) +@item @code{caseSensitiveFS} (default: @var{"false"}) +@item @code{junctionsAsDirs} (default: @var{"false"}) +@item @code{syncOwnership} (default: @var{"false"}) +@item @code{sendOwnership} (default: @var{"false"}) +@item @code{syncXattrs} (default: @var{"false"}) +@item @code{sendXattrs} (default: @var{"false"}) +@item @code{xattrFilter-maxSingleEntrySize} (default: @var{"1024"}) +@item @code{xattrFilter-maxTotalSize} (default: @var{"4096")}) +@end table +@end deftp + +@deftp {Data Type} syncthing-folder-device +There is some configuration which is specific to the relationship +between a specific folder and a specific device. If you are fine +leaving these as their default, then you can simply specify a +syncthing-device instead of a syncthing-folder-device. + +@table @asis +@item @code{id} (default: @var{""}) +id can be provided as a string of the id, or a @code{syncthing-device}. + +@item @code{introducedBy} (default: @var{""}) +@item @code{encryptionPassword} (default: @var{""}) +if encryptionPassword is non-empty, then it will be used as a password +to encrypt file chunks as they are synced to that device. For more info +on syncing to devices you don't totally trust, see +@uref{https://docs.syncthing.net/users/untrusted.html, Syncthing Documenta= tion Untrusted}. +Note that file transfers are always end-to-end encrypted, regardless of +this setting. + +@end table +@end deftp + +Here is a more complex example configuration for illustrative purposes: +@lisp +(service syncthing-service-type + (let ((laptop (syncthing-device (id "VHOD2D6-...-7XRMDEN"))) + (desktop (syncthing-device (id "64SAZ37-...-FZJ5GUA") + (addresses '("mydomain.com")))) + (bob-desktop "KYIMEGO-...-FT77EAO")) + (syncthing-configuration + (user "alice") + (syncthing-config-file + (folders (list (syncthing-folder + (label "some-files") + (path "~/data") + (devices (list desktop laptop))) + (syncthing-folder + (label "critical-files") + (path "~/secrets") + (devices + (list desktop + laptop + (syncthing-folder-device + (id bob-desktop) + (encryptionPassword "mypassword")))))= )) + ;; any device used above should be in this list + (devices (list laptop desktop bob-desktop)))) +@end lisp + =20 Furthermore, @code{(gnu services ssh)} provides the following services. @cindex SSH diff --git a/gnu/home/services/syncthing.scm b/gnu/home/services/syncthing.= scm index 8d66a167ce..dd6c752ee4 100644 --- a/gnu/home/services/syncthing.scm +++ b/gnu/home/services/syncthing.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2023 Ludovic Court=C3=A8s +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -24,9 +25,23 @@ (define-module (gnu home services syncthing) #:use-module (gnu home services shepherd) #:export (home-syncthing-service-type) #:re-export (syncthing-configuration - syncthing-configuration?)) + syncthing-configuration? + syncthing-config-file + syncthing-config-file? + syncthing-device + syncthing-device? + syncthing-folder + syncthing-folder? + syncthing-folder-device + syncthing-folder-device?)) =20 (define home-syncthing-service-type (service-type (inherit (system->home-service-type syncthing-service-type)) + ;; system->home-service-type does not convert special-files-service-typ= e to + ;; home-files-service-type, so redefine extensios + (extensions (list (service-extension home-files-service-type + syncthing-files-service) + (service-extension home-shepherd-service-type + syncthing-shepherd-service))) (default-value (for-home (syncthing-configuration))))) diff --git a/gnu/services/syncthing.scm b/gnu/services/syncthing.scm index a7a9c6aadd..4f0d4c1082 100644 --- a/gnu/services/syncthing.scm +++ b/gnu/services/syncthing.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2021 Oleg Pykhalov ;;; Copyright =C2=A9 2023 Justin Veilleux +;;; Copyright =C2=A9 2025 Zacchaeus ;;; ;;; This file is part of GNU Guix. ;;; @@ -25,9 +26,20 @@ (define-module (gnu services syncthing) #:use-module (guix records) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (sxml simple) #:export (syncthing-configuration syncthing-configuration? - syncthing-service-type)) + syncthing-device + syncthing-device? + syncthing-config-file + syncthing-config-file? + syncthing-folder-device + syncthing-folder-device? + syncthing-folder + syncthing-folder? + syncthing-service-type + syncthing-shepherd-service + syncthing-files-service)) =20 ;;; Commentary: ;;; @@ -35,6 +47,431 @@ (define-module (gnu services syncthing) ;;; ;;; Code: =20 +(define-record-type* + syncthing-device make-syncthing-device + syncthing-device? + (id syncthing-device-id) + (name syncthing-device-name (default "")) + (compression syncthing-device-compression (default "metadata")) + (introducer syncthing-device-introducer (default "false")) + (skipIntroductionRemovals syncthing-device-skipIntroductionRemovals (def= ault "false")) + (introducedBy syncthing-device-introducedBy (default "")) + (addresses syncthing-device-addresses (default '("dynamic"))) + (paused syncthing-device-paused (default "false")) + (autoAcceptFolders syncthing-device-autoAcceptFolders (default "false")) + (maxSendKbps syncthing-device-maxSendKbps (default "0")) + (maxRecvKbps syncthing-device-maxRecvKbps (default "0")) + (maxRequestKiB syncthing-device-maxRequestKiB (default "0")) + (untrusted syncthing-device-untrusted (default "false")) + (remoteGUIPort syncthing-device-remoteGUIPort (default "0")) + (numConnections syncthing-device-numConnections (default "0"))) + +(define syncthing-device->sxml + (match-record-lambda + (id name compression introducer skipIntroductionRemovals introducedB= y addresses paused autoAcceptFolders maxSendKbps maxRecvKbps maxRequestKiB = untrusted remoteGUIPort numConnections) + `(device (@ (id ,id) + (name ,name) + (compression ,compression) + (introducer ,introducer) + (skipIntroductionRemovals ,skipIntroductionRemovals) + (introducedBy ,introducedBy)) + ,@(map (lambda (address) `(address ,address)) addresses) + (paused ,paused) + (autoAcceptFolders ,autoAcceptFolders) + (maxSendKbps ,maxSendKbps) + (maxRecvKbps ,maxRecvKbps) + (maxRequestKiB ,maxRequestKiB) + (untrusted ,untrusted) + (remoteGUIPort ,remoteGUIPort) + (numConnections ,numConnections)))) + +(define (id-or-device->id id-or-device) + (if (syncthing-device? id-or-device) + (syncthing-device-id id-or-device) + id-or-device)) + +(define-record-type* + syncthing-folder-device make-syncthing-folder-device + syncthing-folder-device? + (id syncthing-folder-device-id + (sanitize id-or-device->id)) + (introducedBy syncthing-folder-device-introducedBy (default "") + (sanitize id-or-device->id)) + (encryptionPassword syncthing-folder-device-encryptionPassword (default = ""))) + +(define syncthing-folder-device->sxml + (match-record-lambda + (id introducedBy encryptionPassword) + `(device (@ (id ,id) + (introducedBy ,introducedBy)) + (encryptionPassword ,encryptionPassword)))) + +(define-record-type* + syncthing-folder make-syncthing-folder + syncthing-folder? + (id syncthing-folder-id (default #f)) + (label syncthing-folder-label) + (path syncthing-folder-path) + (type syncthing-folder-type (default "sendreceive")) + (rescanIntervalS syncthing-folder-rescanIntervalS (default "3600")) + (fsWatcherEnabled syncthing-folder-fsWatcherEnabled (default "true")) + (fsWatcherDelayS syncthing-folder-fsWatcherDelayS (default "10")) + (ignorePerms syncthing-folder-ignorePerms (default "false")) + (autoNormalize syncthing-folder-autoNormalize (default "true")) + (devices syncthing-folder-devices (default '()) + (sanitize (lambda (folder-device-list) + (map (lambda (device) + (if (syncthing-folder-device? device) + device + (syncthing-folder-device (id device)))) + folder-device-list)))) + (filesystemType syncthing-folder-filesystemType (default "basic")) + (minDiskFree-unit syncthing-folder-minDiskFree-unit (default "%")) + (minDiskFree syncthing-folder-minDiskFree (default "1")) + (versioning-type syncthing-folder-versioning-type (default #f)) + (versioning-fsPath syncthing-folder-versioning-fsPath (default "")) + (versioning-fsType syncthing-folder-versioning-fsType (default "basic")) + (versioning-cleanupIntervalS syncthing-folder-versioning-cleanupInterval= S (default "3600")) + (versioning-cleanoutDays syncthing-folder-versioning-cleanoutDays (defau= lt #f)) + (versioning-keep syncthing-folder-versioning-keep (default #f)) + (versioning-maxAge syncthing-folder-versioning-maxAge (default #f)) + (versioning-command syncthing-folder-versioning-command (default #f)) + (copiers syncthing-folder-copiers (default "0")) + (pullerMaxPendingKiB syncthing-folder-pullerMaxPendingKiB (default "0")) + (hashers syncthing-folder-hashers (default "0")) + (order syncthing-folder-order (default "random")) + (ignoreDelete syncthing-folder-ignoreDelete (default "false")) + (scanProgressIntervalS syncthing-folder-scanProgressIntervalS (default "= 0")) + (pullerPauseS syncthing-folder-pullerPauseS (default "0")) + (maxConflicts syncthing-folder-maxConflicts (default "10")) + (disableSparseFiles syncthing-folder-disableSparseFiles (default "false"= )) + (disableTempIndexes syncthing-folder-disableTempIndexes (default "false"= )) + (paused syncthing-folder-paused (default "false")) + (weakHashThresholdPct syncthing-folder-weakHashThresholdPct (default "25= ")) + (markerName syncthing-folder-markerName (default ".stfolder")) + (copyOwnershipFromParent syncthing-folder-copyOwnershipFromParent (defau= lt "false")) + (modTimeWindowS syncthing-folder-modTimeWindowS (default "0")) + (maxConcurrentWrites syncthing-folder-maxConcurrentWrites (default "2")) + (disableFsync syncthing-folder-disableFsync (default "false")) + (blockPullOrder syncthing-folder-blockPullOrder (default "standard")) + (copyRangeMethod syncthing-folder-copyRangeMethod (default "standard")) + (caseSensitiveFS syncthing-folder-caseSensitiveFS (default "false")) + (junctionsAsDirs syncthing-folder-junctionsAsDirs (default "false")) + (syncOwnership syncthing-folder-syncOwnership (default "false")) + (sendOwnership syncthing-folder-sendOwnership (default "false")) + (syncXattrs syncthing-folder-syncXattrs (default "false")) + (sendXattrs syncthing-folder-sendXattrs (default "false")) + (xattrFilter-maxSingleEntrySize syncthing-folder-xattrFilter-maxSingleEn= trySize (default "1024")) + (xattrFilter-maxTotalSize syncthing-folder-xattrFilter-maxTotalSize (def= ault "4096"))) + +;; Some parameters, when empty, are fully omitted from the config file. I= t is +;; unknown if this causes a functional difference, but stick to the normal +;; program's behavior to be safe. +(define (maybe-param symbol value) + (if value `((param (@ (key ,(symbol->string symbol)) (val ,value)) "")) = '())) + +(define syncthing-folder->sxml + (match-record-lambda + (id + label path type rescanIntervalS fsWatcherEnabled fsWatcherDelayS + ignorePerms autoNormalize devices filesystemType minDiskFree-unit + minDiskFree versioning-type versioning-fsPath versioning-fsType + versioning-cleanupIntervalS versioning-cleanoutDays versioning-keep + versioning-maxAge versioning-command copiers pullerMaxPendingKiB + hashers order ignoreDelete scanProgressIntervalS pullerPauseS + maxConflicts disableSparseFiles disableTempIndexes paused + weakHashThresholdPct markerName copyOwnershipFromParent modTimeWind= owS + maxConcurrentWrites disableFsync blockPullOrder copyRangeMethod + caseSensitiveFS junctionsAsDirs syncOwnership sendOwnership syncXat= trs + sendXattrs xattrFilter-maxSingleEntrySize xattrFilter-maxTotalSize) + `(folder (@ (id ,(if id id label)) + (label ,label) + (path ,path) + (type ,type) + (rescanIntervalS ,rescanIntervalS) + (fsWatcherEnabled ,fsWatcherEnabled) + (fsWatcherDelayS ,fsWatcherDelayS) + (ignorePerms ,ignorePerms) + (autoNormalize ,autoNormalize)) + (filesystemType ,filesystemType) + ,@(map syncthing-folder-device->sxml + devices) + (minDiskFree (@ (unit ,minDiskFree-unit)) + ,minDiskFree) + (versioning ,@(if versioning-type + `((@ (type ,versioning-type))) + '()) + ,@(maybe-param 'cleanoutDays versioning-cleanoutD= ays) + ,@(maybe-param 'keep versioning-keep) + ,@(maybe-param 'maxAge versioning-maxAge) + ,@(maybe-param 'command versioning-command) + (cleanupIntervalS ,versioning-cleanupIntervalS) + (fsPath ,versioning-fsPath) + (fsType ,versioning-fsType)) + (copiers ,copiers) + (pullerMaxPendingKiB ,pullerMaxPendingKiB) + (hashers ,hashers) + (order ,order) + (ignoreDelete ,ignoreDelete) + (scanProgressIntervalS ,scanProgressIntervalS) + (pullerPauseS ,pullerPauseS) + (maxConflicts ,maxConflicts) + (disableSparseFiles ,disableSparseFiles) + (disableTempIndexes ,disableTempIndexes) + (paused ,paused) + (weakHashThresholdPct ,weakHashThresholdPct) + (markerName ,markerName) + (copyOwnershipFromParent ,copyOwnershipFromParent) + (modTimeWindowS ,modTimeWindowS) + (maxConcurrentWrites ,maxConcurrentWrites) + (disableFsync ,disableFsync) + (blockPullOrder ,blockPullOrder) + (copyRangeMethod ,copyRangeMethod) + (caseSensitiveFS ,caseSensitiveFS) + (junctionsAsDirs ,junctionsAsDirs) + (syncOwnership ,syncOwnership) + (sendOwnership ,sendOwnership) + (syncXattrs ,syncXattrs) + (sendXattrs ,sendXattrs) + (xattrFilter (maxSingleEntrySize ,xattrFilter-maxSingleEntryS= ize) + (maxTotalSize ,xattrFilter-maxTotalSize))))) + +(define-record-type* + syncthing-config-file make-syncthing-config-file + syncthing-config-file? + (folders syncthing-config-folders + ; this matches syncthing's default + (default (list (syncthing-folder (id "default") + (label "Default Folder") + (path "~/Sync"))))) + (devices syncthing-config-devices + (default '())) + (gui-enabled syncthing-config-gui-enabled (default "true")) + (gui-tls syncthing-config-gui-tls (default "false")) + (gui-debugging syncthing-config-gui-debugging (default "false")) + (gui-sendBasicAuthPrompt syncthing-config-gui-sendBasicAuthPrompt (defau= lt "false")) + (gui-address syncthing-config-gui-address (default "127.0.0.1:8384")) + (gui-user syncthing-config-gui-user (default #f)) + (gui-password syncthing-config-gui-password (default #f)) + (gui-apikey syncthing-config-gui-apikey (default "Vuky3VHVseQEoSk9YgxhSk= NTnjQmqYK9")) + (gui-theme syncthing-config-gui-theme (default "default")) + (ldap-enabled syncthing-config-ldap-enabled (default #f)) + (ldap-address syncthing-config-ldap-address (default "")) + (ldap-bindDN syncthing-config-ldap-bindDN (default "")) + (ldap-transport syncthing-config-ldap-transport (default "")) + (ldap-insecureSkipVerify syncthing-config-ldap-insecureSkipVerify (defau= lt "")) + (ldap-searchBaseDN syncthing-config-ldap-searchBaseDN (default "")) + (ldap-searchFilter syncthing-config-ldap-searchFilter (default "")) + (listenAddress syncthing-config-listenAddress (default "default")) + (globalAnnounceServer syncthing-config-globalAnnounceServer (default "de= fault")) + (globalAnnounceEnabled syncthing-config-globalAnnounceEnabled (default "= true")) + (localAnnounceEnabled syncthing-config-localAnnounceEnabled (default "tr= ue")) + (localAnnouncePort syncthing-config-localAnnouncePort (default "21027")) + (localAnnounceMCAddr syncthing-config-localAnnounceMCAddr (default "[ff1= 2::8384]:21027")) + (maxSendKbps syncthing-config-maxSendKbps (default "0")) + (maxRecvKbps syncthing-config-maxRecvKbps (default "0")) + (reconnectionIntervalS syncthing-config-reconnectionIntervalS (default "= 60")) + (relaysEnabled syncthing-config-relaysEnabled (default "true")) + (relayReconnectIntervalM syncthing-config-relayReconnectIntervalM (defau= lt "10")) + (startBrowser syncthing-config-startBrowser (default "true")) + (natEnabled syncthing-config-natEnabled (default "true")) + (natLeaseMinutes syncthing-config-natLeaseMinutes (default "60")) + (natRenewalMinutes syncthing-config-natRenewalMinutes (default "30")) + (natTimeoutSeconds syncthing-config-natTimeoutSeconds (default "10")) + (urAccepted syncthing-config-urAccepted (default "0")) + (urSeen syncthing-config-urSeen (default "0")) + (urUniqueID syncthing-config-urUniqueID (default "")) + (urURL syncthing-config-urURL (default "https://data.syncthing.net/newda= ta")) + (urPostInsecurely syncthing-config-urPostInsecurely (default "false")) + (urInitialDelayS syncthing-config-urInitialDelayS (default "1800")) + (autoUpgradeIntervalH syncthing-config-autoUpgradeIntervalH (default "12= ")) + (upgradeToPreReleases syncthing-config-upgradeToPreReleases (default "fa= lse")) + (keepTemporariesH syncthing-config-keepTemporariesH (default "24")) + (cacheIgnoredFiles syncthing-config-cacheIgnoredFiles (default "false")) + (progressUpdateIntervalS syncthing-config-progressUpdateIntervalS (defau= lt "5")) + (limitBandwidthInLan syncthing-config-limitBandwidthInLan (default "fals= e")) + (minHomeDiskFree-unit syncthing-config-minHomeDiskFree-unit (default "%"= )) + (minHomeDiskFree syncthing-config-minHomeDiskFree (default "1")) + (releasesURL syncthing-config-releasesURL (default "https://upgrades.syn= cthing.net/meta.json")) + (overwriteRemoteDeviceNamesOnConnect syncthing-config-overwriteRemoteDev= iceNamesOnConnect (default "false")) + (tempIndexMinBlocks syncthing-config-tempIndexMinBlocks (default "10")) + (unackedNotificationID syncthing-config-unackedNotificationID (default "= authenticationUserAndPassword")) + (trafficClass syncthing-config-trafficClass (default "0")) + (setLowPriority syncthing-config-setLowPriority (default "true")) + (maxFolderConcurrency syncthing-config-maxFolderConcurrency (default "0"= )) + (crashReportingURL syncthing-config-crashReportingURL (default "https://= crash.syncthing.net/newcrash")) + (crashReportingEnabled syncthing-config-crashReportingEnabled (default "= true")) + (stunKeepaliveStartS syncthing-config-stunKeepaliveStartS (default "180"= )) + (stunKeepaliveMinS syncthing-config-stunKeepaliveMinS (default "20")) + (stunServer syncthing-config-stunServer (default "default")) + (databaseTuning syncthing-config-databaseTuning (default "auto")) + (maxConcurrentIncomingRequestKiB syncthing-config-maxConcurrentIncomingR= equestKiB (default "0")) + (announceLANAddresses syncthing-config-announceLANAddresses (default "tr= ue")) + (sendFullIndexOnUpgrade syncthing-config-sendFullIndexOnUpgrade (default= "false")) + (connectionLimitEnough syncthing-config-connectionLimitEnough (default "= 0")) + (connectionLimitMax syncthing-config-connectionLimitMax (default "0")) + (insecureAllowOldTLSVersions syncthing-config-insecureAllowOldTLSVersion= s (default "false")) + (connectionPriorityTcpLan syncthing-config-connectionPriorityTcpLan (def= ault "10")) + (connectionPriorityQuicLan syncthing-config-connectionPriorityQuicLan (d= efault "20")) + (connectionPriorityTcpWan syncthing-config-connectionPriorityTcpWan (def= ault "30")) + (connectionPriorityQuicWan syncthing-config-connectionPriorityQuicWan (d= efault "40")) + (connectionPriorityRelay syncthing-config-connectionPriorityRelay (defau= lt "50")) + (connectionPriorityUpgradeThreshold syncthing-config-connectionPriorityU= pgradeThreshold (default "0")) + (default-folder syncthing-config-defaultFolder + (default (syncthing-folder (label "") (path "~")))) + (default-device syncthing-config-defaultDevice + (default (syncthing-device (id "")))) + (default-ignores syncthing-config-defaultIgnores (default ""))) + +(define syncthing-config-file->sxml + (match-record-lambda + (folders + devices gui-enabled gui-tls gui-debugging gui-sendBasicAuthPrompt + gui-address gui-user gui-password gui-apikey gui-theme ldap-enabled + ldap-address ldap-bindDN ldap-transport ldap-insecureSkipVerify + ldap-searchBaseDN ldap-searchFilter listenAddress globalAnnounceSer= ver + globalAnnounceEnabled localAnnounceEnabled localAnnouncePort + localAnnounceMCAddr maxSendKbps maxRecvKbps reconnectionIntervalS + relaysEnabled relayReconnectIntervalM startBrowser natEnabled + natLeaseMinutes natRenewalMinutes natTimeoutSeconds urAccepted + urSeen urUniqueID urURL urPostInsecurely urInitialDelayS + autoUpgradeIntervalH upgradeToPreReleases keepTemporariesH + cacheIgnoredFiles progressUpdateIntervalS limitBandwidthInLan + minHomeDiskFree-unit minHomeDiskFree releasesURL + overwriteRemoteDeviceNamesOnConnect tempIndexMinBlocks + unackedNotificationID trafficClass setLowPriority maxFolderConcurre= ncy + crashReportingURL crashReportingEnabled stunKeepaliveStartS + stunKeepaliveMinS stunServer databaseTuning + maxConcurrentIncomingRequestKiB announceLANAddresses + sendFullIndexOnUpgrade connectionLimitEnough connectionLimitMax + insecureAllowOldTLSVersions connectionPriorityTcpLan + connectionPriorityQuicLan connectionPriorityTcpWan + connectionPriorityQuicWan connectionPriorityRelay + connectionPriorityUpgradeThreshold default-folder default-device + default-ignores) + `(configuration (@ (version "37")) + ,@(map syncthing-folder->sxml + folders) + ,@(map syncthing-device->sxml + devices) + (gui (@ (enabled ,gui-enabled) + (tls ,gui-tls) + (debugging ,gui-debugging) + (sendBasicAuthPrompt ,gui-sendBasicAuthPrompt)) + (address ,gui-address) + ,@(if gui-user `((user ,gui-user)) '()) + ,@(if gui-password `((password ,gui-password)) '(= )) + (apikey ,gui-apikey) + (theme ,gui-theme)) + (ldap ,(if ldap-enabled + `((address ,ldap-address) + (bindDN ,ldap-bindDN) + ,@(if ldap-transport + `((transport ,ldap-transport)) + '()) + ,@(if ldap-insecureSkipVerify + `((insecureSkipVerify ,ldap-insecur= eSkipVerify)) + '()) + ,@(if ldap-searchBaseDN + `((searchBaseDN ,ldap-searchBaseDN)) + '()) + ,@(if ldap-searchFilter + `((searchFilter ,ldap-searchFilter)) + '())) + "")) + (options (listenAddress ,listenAddress) + (globalAnnounceServer ,globalAnnounceServer) + (globalAnnounceEnabled ,globalAnnounceEnabled) + (localAnnounceEnabled ,localAnnounceEnabled) + (localAnnouncePort ,localAnnouncePort) + (localAnnounceMCAddr ,localAnnounceMCAddr) + (maxSendKbps ,maxSendKbps) + (maxRecvKbps ,maxRecvKbps) + (reconnectionIntervalS ,reconnectionIntervalS) + (relaysEnabled ,relaysEnabled) + (relayReconnectIntervalM ,relayReconnectInter= valM) + (startBrowser ,startBrowser) + (natEnabled ,natEnabled) + (natLeaseMinutes ,natLeaseMinutes) + (natRenewalMinutes ,natRenewalMinutes) + (natTimeoutSeconds ,natTimeoutSeconds) + (urAccepted ,urAccepted) + (urSeen ,urSeen) + (urUniqueID ,urUniqueID) + (urURL ,urURL) + (urPostInsecurely ,urPostInsecurely) + (urInitialDelayS ,urInitialDelayS) + (autoUpgradeIntervalH ,autoUpgradeIntervalH) + (upgradeToPreReleases ,upgradeToPreReleases) + (keepTemporariesH ,keepTemporariesH) + (cacheIgnoredFiles ,cacheIgnoredFiles) + (progressUpdateIntervalS ,progressUpdateInter= valS) + (limitBandwidthInLan ,limitBandwidthInLan) + (minHomeDiskFree (@ (unit ,minHomeDiskFree-un= it)) + ,minHomeDiskFree) + (releasesURL ,releasesURL) + (overwriteRemoteDeviceNamesOnConnect ,overwri= teRemoteDeviceNamesOnConnect) + (tempIndexMinBlocks ,tempIndexMinBlocks) + (unackedNotificationID ,unackedNotificationID) + (trafficClass ,trafficClass) + (setLowPriority ,setLowPriority) + (maxFolderConcurrency ,maxFolderConcurrency) + (crashReportingURL ,crashReportingURL) + (crashReportingEnabled ,crashReportingEnabled) + (stunKeepaliveStartS ,stunKeepaliveStartS) + (stunKeepaliveMinS ,stunKeepaliveMinS) + (stunServer ,stunServer) + (databaseTuning ,databaseTuning) + (maxConcurrentIncomingRequestKiB ,maxConcurre= ntIncomingRequestKiB) + (announceLANAddresses ,announceLANAddresses) + (sendFullIndexOnUpgrade ,sendFullIndexOnUpgra= de) + (connectionLimitEnough ,connectionLimitEnough) + (connectionLimitMax ,connectionLimitMax) + (insecureAllowOldTLSVersions ,insecureAllowOl= dTLSVersions) + (connectionPriorityTcpLan ,connectionPriority= TcpLan) + (connectionPriorityQuicLan ,connectionPriorit= yQuicLan) + (connectionPriorityTcpWan ,connectionPriority= TcpWan) + (connectionPriorityQuicWan ,connectionPriorit= yQuicWan) + (connectionPriorityRelay ,connectionPriorityR= elay) + (connectionPriorityUpgradeThreshold ,connecti= onPriorityUpgradeThreshold)) + (defaults + ,(syncthing-folder->sxml default-folder) + ,(syncthing-device->sxml default-device) + (ignores ,default-ignores))))) + +;; It is useful to be able to view the xml output by Guix, and to be able = to +;; diff it with a users previous config, especially when migrating one's +;; config to Guix. This function adds whitespace that matches the whitesp= ace +;; of config files managed by syncthing for easy diffing +(define (indent-sxml sxml indent-increment current-indent) + (match sxml + (((tag ('@ properties ...) (subtags ..1) ..1) sibling-tags ...) + `(,current-indent (,tag (@ ,@properties) "\n" + ,@(indent-sxml subtags indent-increment + (string-append indent-incremen= t current-indent)) + ,current-indent) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag ('@ properties ...) primitive ...) sibling-tags ...) + `(,current-indent (,tag (@ ,@properties) ,@primitive) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag (subtags ..1) ..1) sibling-tags ...) + `(,current-indent (,tag "\n" + ,@(indent-sxml subtags indent-increment + (string-append indent-incremen= t current-indent)) + ,current-indent) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (((tag primitive ...) sibling-tags ...) + `(,current-indent (,tag ,@primitive) "\n" + ,@(indent-sxml sibling-tags indent-increment curren= t-indent))) + (() '()))) + +(define (serialize-syncthing-config-file config) + (with-output-to-string + (lambda () + (sxml->xml (cons '*TOP* (indent-sxml (list (syncthing-config-file->s= xml config)) + " " + "")))))) + (define-record-type* syncthing-configuration make-syncthing-configuration syncthing-configuration? @@ -50,6 +487,8 @@ (define-record-type* (default "users")) (home syncthing-configuration-home ;string (default #f)) + (syncthing-config-file syncthing-configuration-syncthing-config-file + (default #f)) ; syncthing-config-file or = file-like (home-service? syncthing-configuration-home-service? (default for-home?) (innate))) =20 @@ -93,10 +532,26 @@ (define syncthing-shepherd-service (respawn? #f) (stop #~(make-kill-destructor)))))) =20 + +(define syncthing-files-service + (match-record-lambda (syncthing-config-file us= er home home-service?) + (if syncthing-config-file + `((,(if home-service? + ".config/syncthing/config.xml" + (string-join (or home (passwd:dir (getpw user))) + "/.config/syncthing/config.xml")) + ,(if (file-like? syncthing-config-file) + syncthing-config-file + (plain-file "syncthin-config.xml" (serialize-syncthing-con= fig-file + syncthing-config-file))= ))) + '()))) + (define syncthing-service-type (service-type (name 'syncthing) (extensions (list (service-extension shepherd-root-service= -type - syncthing-shepherd-se= rvice))) + syncthing-shepherd-se= rvice) + (service-extension special-files-service= -type + syncthing-files-servi= ce))) (description "Run @uref{https://github.com/syncthing/syncthing, Syncth= ing} decentralized continuous file system synchronization."))) --=20 2.45.2 ------------=_1739772962-9282-1-- From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v10] services: syncthing: Add support for config file generation. Resent-From: Ludovic =?UTF-8?Q?Court=C3=A8s?= Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Mon, 17 Feb 2025 10:27:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Zacchaeus Scheffer Cc: Bruno Victal , 75959@debbugs.gnu.org, Leo Famulari Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.17397879741006 (code B ref 75959); Mon, 17 Feb 2025 10:27:02 +0000 Received: (at 75959) by debbugs.gnu.org; 17 Feb 2025 10:26:14 +0000 Received: from localhost ([127.0.0.1]:43359 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tjyKL-0000G5-JI for submit@debbugs.gnu.org; Mon, 17 Feb 2025 05:26:14 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:37196) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tjyKI-0000FJ-GG for 75959@debbugs.gnu.org; Mon, 17 Feb 2025 05:26:12 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tjyKC-0007ZB-9o; Mon, 17 Feb 2025 05:26:04 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:References:In-Reply-To:Subject:To: From; bh=rlc2AYCOy+P7Zos+Uf6dicRSjTWCHrPAWPuWebdT9LA=; b=NJ7lHfNSTD83r9a9911q YJDIzzSCk6u4iXYMLZ4AP77L2UcjgaXkuhrPmDhAygq0tclEfi0GKaDV3MU8dh6wOroKha4JxuWZa jmhIB8GDe9UKA5nO0WtjQgLU3ADBF/oqH7PVz0c1iDT2FN8OY/u/JISVAvXO233mqCDRJ1LjEjumb s3LEs8kRJUYz11AQccVYzZrPg3RDCW5IL+viEohpz1CgkbLFKu3EXTAzy/aUghNaYZejaq9r+ruEC +mv/CEVHLZjrGV713cVQuBk4WOiNCBZxBsv1NfhDIEaU/XZLEHT1UMRQSsvAOWIvTpWhOIRPaHwnf BC0/lzUSoFrdBA==; From: Ludovic =?UTF-8?Q?Court=C3=A8s?= In-Reply-To: <87tt8udyg7.fsf_-_@zacchae.us> (Zacchaeus Scheffer's message of "Sun, 16 Feb 2025 04:35:20 -0500") References: <871pvyg0kd.fsf@zacchae.us> <87tt8udyg7.fsf_-_@zacchae.us> Date: Mon, 17 Feb 2025 11:26:00 +0100 Message-ID: <87bjv0n9zb.fsf@gnu.org> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -1.6 (-) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -2.6 (--) Hi, Zacchaeus Scheffer skribis: >>>From a573fd78e6b8d10b32eb10a753423073c7bbaeef Mon Sep 17 00:00:00 2001 > From: Zacchaeus > Date: Sun, 21 Jul 2024 00:54:25 -0700 > Subject: [PATCH v10] services: syncthing: Add support for config file > generation. > > * gnu/services/syncthing.scm: (syncthing-config-file, > syncthing-folder, syncthing-device, syncthing-folder-device): New > records; (syncthing-service-type): Add special-files-service-type > extension for the config file; (syncthing-files-service): Add service > to create config file. > * gnu/home/services/syncthing.scm: (home-syncthing-service-type): > Extend home-files-services-type and re-exported more things from > gnu/services/syncthing.scm. > * doc/guix.texi: (syncthing-service-type): Document changes. > > Change-Id: I87eeba1ee1fdada8f29c2ee881fbc6bc4113dde9 This is a nice improvement! Much better than fiddling with the GUI. :-) Sorry for not chiming in earlier; I just noticed a couple of stylistic issues: > +This section documents a subset of the Syncthing configuration > +options=E2=80=94specifically those related to Guix or those affecting ho= w your > +computer will connect to other computers over the network (such as > +Syncthing relays or discovery servers). The configuration is fully > +documented in the upstream > +@uref{https://docs.syncthing.net/users/config.html, Syncthing config > +documentation}; camelCase there is converted to kebab-case here. If you =E2=80=9CKebab-case=E2=80=9D, really? :-) > +@table @asis > +@item @code{folders} (default: @var{(list (syncthing-folder (id "default= ") (label "Default Folder") (path "~/Sync")))} Should be @code, not @var (throughout this table). Could you send a patch fixing this? BTW, =E2=80=98define-configuration=E2=80=99 would make it easier to generat= e this doc. > +@item @code{gui-enabled} (default: @var{"true"}) The naming convention used in all of Guix is to add a final question mark for Boolean values; this would be =E2=80=98gui-enabled?=E2=80=99. As for the value itself, it would help a lot to use #t and #f instead of the strings "true" and "false" (both of which have truth value in Scheme). It leads to a bit of extra work in the serializer, but I think it=E2=80=99s worth it. Because then we can also have type-checking of fiel= ds. > +@item @code{gui-tls} (default: @var{"false"}) > +@item @code{gui-debugging} (default: @var{"false"}) > +@item @code{gui-send-basic-auth-prompt} (default: @var{"false"}) > +@item @code{gui-address} (default: @var{"127.0.0.1:8384"}) > +@item @code{gui-user} (default: @var{#f}) > +@item @code{gui-password} (default: @var{#f}) > +A bcrypt hash of the GUI password. Remember that this will be globally > +exposed in @file{/gnu/store}. I believe you want @itemx for all but the first item. > +@item @code{local-announce-port} (default: @var{"21027"}) > +@item @code{local-announce-mcaddr} (default: @var{"[ff12::8384]:21027"}) > +@item @code{max-send-kbps} (default: @var{"0"}) > +@item @code{max-recv-kbps} (default: @var{"0"}) > +@item @code{reconnection-interval-s} (default: @var{"60"}) Similar to what I wrote above: numbers should be numbers, not strings. Last note: the convention throughout Guix it to avoid abbreviations. I=E2=80=99m not sure about the way forward; maybe we can make those typing changes (and perhaps some naming changes) and afford some incompatibility because the service is young? WDYT? Ludo=E2=80=99. From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v10] services: syncthing: Add support for config file generation. Resent-From: Zacchaeus Scheffer Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Mon, 17 Feb 2025 20:33:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Ludovic =?UTF-8?Q?Court=C3=A8s?= Cc: Bruno Victal , 75959@debbugs.gnu.org, Leo Famulari Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.173982433122872 (code B ref 75959); Mon, 17 Feb 2025 20:33:01 +0000 Received: (at 75959) by debbugs.gnu.org; 17 Feb 2025 20:32:11 +0000 Received: from localhost ([127.0.0.1]:49842 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tk7mk-0005wi-OQ for submit@debbugs.gnu.org; Mon, 17 Feb 2025 15:32:11 -0500 Received: from [47.204.136.169] (port=58326 helo=hun.zacchae.us) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tk7mi-0005wB-5w for 75959@debbugs.gnu.org; Mon, 17 Feb 2025 15:32:09 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Transfer-Encoding:Content-Type: MIME-Version:Message-ID:Date:References:In-Reply-To:Subject:Cc:To:From:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=IsWJllygZKEJd61QiW005pn6tbZGoAcX00gBOoy9NDM=; i=zacchae.us; b=XuBc5igTY85s si5apuL0Z1VVe+O6Mnsu0zhMIqCSYWhyT2HrLtujCq9DrKOfbqbI0UvM6K1YnK4WJlS+KrbHCw==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Transfer-Encoding:Content-Type:MIME-Version: Message-ID:Date:References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=IsWJllygZKEJd61QiW005pn6tbZGoAcX00gBOoy9NDM=; i=zacchae.us; b=Drn7CnSZmJE4 IdEetqLA3inynSKmDDCAl5lvyyef1wpLtUJfrb/m79BZ8eDILMLW5M4DDUKuEJ1vsGD5wlWkWieuE 0Mg/1Ewgk8KyAJxWqlZxRwW8Z5xrXdoce4z3w8oY0kny64zFwQjljd9zIohR+m/KF/ZHyR86A/u/Q Ar/bnuUYTB12AhZlc89tiOvBKhCAlou6zc7EglOeEt/3+bWwm2wyxjjyQwF7b6jl+7lB8wqnqi0yh TwM+8D8L7ZdvbNJWqxEI1wlQZ84hdWOcZLcKDHwlenmN1B3ABZWcJ9OxFJ0pVoWmg27THt3JglzTa pPSGjyN5dmbojLWQp/LNDg==; Received: from localhost.home ([127.0.0.1]:45860 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1tk7mb-000000000gp-2SdY; Mon, 17 Feb 2025 15:32:01 -0500 From: Zacchaeus Scheffer In-Reply-To: <87bjv0n9zb.fsf@gnu.org> ("Ludovic =?UTF-8?Q?Court=C3=A8s?="'s message of "Mon, 17 Feb 2025 11:26:00 +0100") References: <871pvyg0kd.fsf@zacchae.us> <87tt8udyg7.fsf_-_@zacchae.us> <87bjv0n9zb.fsf@gnu.org> Date: Mon, 17 Feb 2025 15:32:01 -0500 Message-ID: <87frkc8g8u.fsf@zacchae.us> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic =?UTF-8?Q?Court=C3=A8s?= writes: > Hi, > > Zacchaeus Scheffer skribis: > >>>From a573fd78e6b8d10b32eb10a753423073c7bbaeef Mon Sep 17 00:00:00 2001 >> From: Zacchaeus >> Date: Sun, 21 Jul 2024 0 [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in sa-trusted.bondedsender.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in bl.score.senderscore.com] 0.1 URIBL_SBL_A Contains URL's A record listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 0.6 URIBL_SBL Contains an URL's NS IP listed in the Spamhaus SBL blocklist [URIs: docs.syncthing.net] 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 1.0 (+) Ludovic Court=C3=A8s writes: > Hi, > > Zacchaeus Scheffer skribis: > >>>>From a573fd78e6b8d10b32eb10a753423073c7bbaeef Mon Sep 17 00:00:00 2001 >> From: Zacchaeus >> Date: Sun, 21 Jul 2024 00:54:25 -0700 >> Subject: [PATCH v10] services: syncthing: Add support for config file >> generation. >> >> * gnu/services/syncthing.scm: (syncthing-config-file, >> syncthing-folder, syncthing-device, syncthing-folder-device): New >> records; (syncthing-service-type): Add special-files-service-type >> extension for the config file; (syncthing-files-service): Add service >> to create config file. >> * gnu/home/services/syncthing.scm: (home-syncthing-service-type): >> Extend home-files-services-type and re-exported more things from >> gnu/services/syncthing.scm. >> * doc/guix.texi: (syncthing-service-type): Document changes. >> >> Change-Id: I87eeba1ee1fdada8f29c2ee881fbc6bc4113dde9 > > This is a nice improvement! Much better than fiddling with the GUI. > :-) Thanks. I'm glad you agree. Great for managing swarms of devices > Sorry for not chiming in earlier; I just noticed a couple of stylistic > issues: > >> +This section documents a subset of the Syncthing configuration >> +options=E2=80=94specifically those related to Guix or those affecting h= ow your >> +computer will connect to other computers over the network (such as >> +Syncthing relays or discovery servers). The configuration is fully >> +documented in the upstream >> +@uref{https://docs.syncthing.net/users/config.html, Syncthing config >> +documentation}; camelCase there is converted to kebab-case here. If you > > =E2=80=9CKebab-case=E2=80=9D, really? :-) I believe that is an accurate term: https://en.wikipedia.org/wiki/Naming_convention_(programming)#Delimiter-sep= arated_words >> +@table @asis >> +@item @code{folders} (default: @var{(list (syncthing-folder (id "defaul= t") (label "Default Folder") (path "~/Sync")))} > > Should be @code, not @var (throughout this table). > > Could you send a patch fixing this? Sure thing. I assume I can send it to the same issue even though it is closed? > BTW, =E2=80=98define-configuration=E2=80=99 would make it easier to gener= ate this doc. I originally used define-record because that is what the original syncthing service implementation used. If there are reasons to change this I could update this as well, but it seems fine. >> +@item @code{gui-enabled} (default: @var{"true"}) > > The naming convention used in all of Guix is to add a final question > mark for Boolean values; this would be =E2=80=98gui-enabled?=E2=80=99. > > As for the value itself, it would help a lot to use #t and #f instead of > the strings "true" and "false" (both of which have truth value in > Scheme). It leads to a bit of extra work in the serializer, but I think > it=E2=80=99s worth it. Because then we can also have type-checking of fi= elds. This would be easiest to implement as a sanitizer as in: (define (bool-string bool) (if bool "true" "false")) (define-record-type* ... (gui-enabled (default "true") (sanitizer bool-string)) ... But then the guix docs would technically be wrong reporting a default value of #t instead of the actual default value of "true". I think this would yield a more helpful type-checking error though, so I'll go this direction unless you think otherwise. >> +@item @code{gui-tls} (default: @var{"false"}) >> +@item @code{gui-debugging} (default: @var{"false"}) >> +@item @code{gui-send-basic-auth-prompt} (default: @var{"false"}) >> +@item @code{gui-address} (default: @var{"127.0.0.1:8384"}) >> +@item @code{gui-user} (default: @var{#f}) >> +@item @code{gui-password} (default: @var{#f}) >> +A bcrypt hash of the GUI password. Remember that this will be globally >> +exposed in @file{/gnu/store}. > > I believe you want @itemx for all but the first item. Does it matter that the describing text only applies to gui-password, not to the whole block? For now, I'll assume not and change all the consecutive items with no specific documentation throughout to itemx. >> +@item @code{local-announce-port} (default: @var{"21027"}) >> +@item @code{local-announce-mcaddr} (default: @var{"[ff12::8384]:21027"}) >> +@item @code{max-send-kbps} (default: @var{"0"}) >> +@item @code{max-recv-kbps} (default: @var{"0"}) >> +@item @code{reconnection-interval-s} (default: @var{"60"}) > > Similar to what I wrote above: numbers should be numbers, not strings. I'll figure this out as well, using sanitizers (or leaving it as numbers. It seems sxml allows the body of a tag to be a number, but not values of parameters of tags, so most the time it just works.) > Last note: the convention throughout Guix it to avoid abbreviations. My goal was to, as much as possible, avoid needing to maintain Syncthing documentation in Guix. My original patch even had camelcase for record names so the user could easily search the Syncthing documentation knowing what keyword to search. Since you can't directly search anymore anyway, maybe it does make sense to expand out some names. I'll do that for these: auth - authorization s - seconds m - minutes h - hours fs - file-system pct - percentage mcaddr - mac-address recv - recieve ur - usage-reporting > I=E2=80=99m not sure about the way forward; maybe we can make those typing > changes (and perhaps some naming changes) and afford some > incompatibility because the service is young? WDYT? > > Ludo=E2=80=99. I think it's unlikely that the service update will have major adoption in the couple days between patches, so I think a bit of incompatibility is fine. eikcaz- From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v10] services: syncthing: Add support for config file generation. Resent-From: Ludovic =?UTF-8?Q?Court=C3=A8s?= Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Fri, 21 Feb 2025 11:07:04 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Zacchaeus Scheffer Cc: Bruno Victal , 75959@debbugs.gnu.org, Leo Famulari Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.174013599414258 (code B ref 75959); Fri, 21 Feb 2025 11:07:04 +0000 Received: (at 75959) by debbugs.gnu.org; 21 Feb 2025 11:06:34 +0000 Received: from localhost ([127.0.0.1]:54878 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tlQrZ-0003hs-VQ for submit@debbugs.gnu.org; Fri, 21 Feb 2025 06:06:34 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:59384) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tlQrX-0003gq-9E for 75959@debbugs.gnu.org; Fri, 21 Feb 2025 06:06:32 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tlQrO-0004rT-1e; Fri, 21 Feb 2025 06:06:22 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:References:In-Reply-To:Subject:To: From; bh=EY7El7Xxo4M4Gx1w/17MsEaGoDlK3Csnz5wn+KNifmo=; b=GhImZA+Nd98fULDaLeOr WJAqEcth5jTxMk6W3fhNjUyU8x4H1vV4kogQearPMgaRWxa0vSwTJnw8OFO51oLMU5m0mOzgM53lJ zav+UbUJGMpm389rercghmFsFQf6RNRwAPndCYyXqgb8wcjss+QneqEEMImeRN9VJd00n7mQ4vFRH pIKCN+YrOueC0kse4iU8RSE7l18RUltGt6s7VTlglhv1U1YN3dCO26MPCYf9N/EOF3pmhbXOiWTuV 5FvVGreuh7RnEJvhVED0h5FF/EB2C8SRW67vin+BzkEfTas3hLIljzgMd3XjZ970bC0EuEG3H4QkG YO1lI+4QBT73Eg==; From: Ludovic =?UTF-8?Q?Court=C3=A8s?= In-Reply-To: <87frkc8g8u.fsf@zacchae.us> (Zacchaeus Scheffer's message of "Mon, 17 Feb 2025 15:32:01 -0500") References: <871pvyg0kd.fsf@zacchae.us> <87tt8udyg7.fsf_-_@zacchae.us> <87bjv0n9zb.fsf@gnu.org> <87frkc8g8u.fsf@zacchae.us> X-URL: http://www.fdn.fr/~lcourtes/ X-Revolutionary-Date: Tridi 3 =?UTF-8?Q?Vent=C3=B4se?= an 233 de la =?UTF-8?Q?R=C3=A9volution,?= jour du Violier X-PGP-Key-ID: 0x090B11993D9AEBB5 X-PGP-Key: http://www.fdn.fr/~lcourtes/ludovic.asc X-PGP-Fingerprint: 3CE4 6455 8A84 FDC6 9DB4 0CFB 090B 1199 3D9A EBB5 X-OS: x86_64-pc-linux-gnu Date: Fri, 21 Feb 2025 12:05:58 +0100 Message-ID: <87h64na76x.fsf@gnu.org> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) Hi, Zacchaeus Scheffer skribis: > I believe that is an accurate term: > https://en.wikipedia.org/wiki/Naming_convention_(programming)#Delimiter-s= eparated_words Woow, TIL. :-) > Sure thing. I assume I can send it to the same issue even though it is > closed? Yes, but maybe open a new issue, for clarity. >> As for the value itself, it would help a lot to use #t and #f instead of >> the strings "true" and "false" (both of which have truth value in >> Scheme). It leads to a bit of extra work in the serializer, but I think >> it=E2=80=99s worth it. Because then we can also have type-checking of f= ields. > > This would be easiest to implement as a sanitizer as in: > > (define (bool-string bool) > (if bool "true" "false")) > (define-record-type* > ... > (gui-enabled (default "true") > (sanitizer bool-string)) > ... > > But then the guix docs would technically be wrong reporting a default > value of #t instead of the actual default value of "true". I think this > would yield a more helpful type-checking error though, so I'll go this > direction unless you think otherwise. I would advise against using sanitizer in this way because it would lead to inconsistencies: users would provide a boolean, but they=E2=80=99d get a string when calling the accessor. Instead the record should contain records of the =E2=80=9Cright=E2=80=9D ty= pe; converting to the relevant string should be left to whatever serializes the record to the config file. (This is something =E2=80=98define-configuration=E2=80=99 really helps with= ; I think it=E2=80=99s worth looking into it!) >>> +@item @code{gui-tls} (default: @var{"false"}) >>> +@item @code{gui-debugging} (default: @var{"false"}) >>> +@item @code{gui-send-basic-auth-prompt} (default: @var{"false"}) >>> +@item @code{gui-address} (default: @var{"127.0.0.1:8384"}) >>> +@item @code{gui-user} (default: @var{#f}) >>> +@item @code{gui-password} (default: @var{#f}) >>> +A bcrypt hash of the GUI password. Remember that this will be globally >>> +exposed in @file{/gnu/store}. >> >> I believe you want @itemx for all but the first item. > > Does it matter that the describing text only applies to gui-password, > not to the whole block? It does yes, so my suggestion is actually bogus, sorry! Normally each field would be documented, not just =E2=80=98gui-password=E2= =80=99. > My goal was to, as much as possible, avoid needing to maintain Syncthing > documentation in Guix. My original patch even had camelcase for record > names so the user could easily search the Syncthing documentation > knowing what keyword to search. Since you can't directly search anymore > anyway, maybe it does make sense to expand out some names. I'll do that > for these: > > auth - authorization > s - seconds > m - minutes > h - hours > fs - file-system > pct - percentage > mcaddr - mac-address > recv - recieve > ur - usage-reporting Sounds good to me. Thanks! Ludo=E2=80=99. From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v10] services: syncthing: Add support for config file generation. Resent-From: Zacchaeus Scheffer Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Fri, 21 Feb 2025 20:27:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Ludovic =?UTF-8?Q?Court=C3=A8s?= Cc: Bruno Victal , 75959@debbugs.gnu.org, Leo Famulari Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.17401696113712 (code B ref 75959); Fri, 21 Feb 2025 20:27:02 +0000 Received: (at 75959) by debbugs.gnu.org; 21 Feb 2025 20:26:51 +0000 Received: from localhost ([127.0.0.1]:37266 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tlZbm-0000xi-BL for submit@debbugs.gnu.org; Fri, 21 Feb 2025 15:26:51 -0500 Received: from [47.204.136.169] (port=54476 helo=hun.zacchae.us) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tlZbi-0000x1-Tb for 75959@debbugs.gnu.org; Fri, 21 Feb 2025 15:26:48 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Transfer-Encoding:Content-Type: MIME-Version:Message-ID:Date:References:In-Reply-To:Subject:Cc:To:From:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=lSfYxSC9PawvAptfPkkJmZAVRyEkLad63Al3vSNrpzw=; i=zacchae.us; b=N4sn4izTJIHv TuW52V4PXh76qtM70742+uESGySbWzTGHJ5kklPAZjA6C8VJdtGjFugXkjkxpzWd9CoQkHFdBQ==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Transfer-Encoding:Content-Type:MIME-Version: Message-ID:Date:References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=lSfYxSC9PawvAptfPkkJmZAVRyEkLad63Al3vSNrpzw=; i=zacchae.us; b=MZlFt/GR4yVs ta8ErRSjbI1yZ0Jp8Lse6uG8p54cnz6N5tyy9A0VwwUZF0TPb0It64nBM5GlYK24vLcCgPZpF2iMM lzm6lJs+gHIE1F3eJK5I1Gs+WGRLgjTTADnMTR++5y9jdmPFenA18jX6p30RceBPcordcpefBVcal 2et25rMrcK6NnpQ2Pq0XLPhR+OTZkgqkMtGN7+7d/5ALgMXbvCsC7f00xlPK7vB9iUvPda7E3VKYH KYbbSNZFYp4xHYUt6eie6bwKhlu25fLBvOHd1ACZTmB5eOWGmYgRUiQAqIgZJN7F6m8z3xfeEnP6f hKPsbIRcqcdAFXGh/BJnmA==; Received: from localhost.home ([127.0.0.1]:45782 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1tlZbc-000000006Js-1TFz; Fri, 21 Feb 2025 15:26:40 -0500 From: Zacchaeus Scheffer In-Reply-To: <87h64na76x.fsf@gnu.org> ("Ludovic =?UTF-8?Q?Court=C3=A8s?="'s message of "Fri, 21 Feb 2025 12:05:58 +0100") References: <871pvyg0kd.fsf@zacchae.us> <87tt8udyg7.fsf_-_@zacchae.us> <87bjv0n9zb.fsf@gnu.org> <87frkc8g8u.fsf@zacchae.us> <87h64na76x.fsf@gnu.org> Date: Fri, 21 Feb 2025 15:26:40 -0500 Message-ID: <87o6yv6o3j.fsf@zacchae.us> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 1.3 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Hi all, Ludovic =?UTF-8?Q?Court=C3=A8s?= writes: > Hi, > > Zacchaeus Scheffer skribis: >> Sure thing. I assume I can send it to the same issue even though it is >> closed? > > Yes, but maybe open a new issue, for clarity. Content analysis details: (1.3 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in bl.score.senderscore.com] 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in sa-trusted.bondedsender.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 0.3 (/) Hi all, Ludovic Court=C3=A8s writes: > Hi, > > Zacchaeus Scheffer skribis: >> Sure thing. I assume I can send it to the same issue even though it is >> closed? > > Yes, but maybe open a new issue, for clarity. I have opened a new issue at #76379 >>> As for the value itself, it would help a lot to use #t and #f instead of >>> the strings "true" and "false" (both of which have truth value in >>> Scheme). It leads to a bit of extra work in the serializer, but I think >>> it=E2=80=99s worth it. Because then we can also have type-checking of = fields. >> >> This would be easiest to implement as a sanitizer as in: >> >> (define (bool-string bool) >> (if bool "true" "false")) >> (define-record-type* >> ... >> (gui-enabled (default "true") >> (sanitizer bool-string)) >> ... >> >> But then the guix docs would technically be wrong reporting a default >> value of #t instead of the actual default value of "true". I think this >> would yield a more helpful type-checking error though, so I'll go this >> direction unless you think otherwise. > > I would advise against using sanitizer in this way because it would lead > to inconsistencies: users would provide a boolean, but they=E2=80=99d get= a > string when calling the accessor. > > Instead the record should contain records of the =E2=80=9Cright=E2=80=9D = type; > converting to the relevant string should be left to whatever serializes > the record to the config file. > > (This is something =E2=80=98define-configuration=E2=80=99 really helps wi= th; I think > it=E2=80=99s worth looking into it!) Alright, a suggestion from the Ludo made twice should not be so easily dismissed. I should mention my original assertion here is slightly wrong; to work, I should set (default #t), but, as you mention, the accessor will still retrieve a string instead of a bool. I originally tried to do my serialization through 'define-configuration', but most of that work evaporated when I discovered sxml (which is the right way to do it). Still, there may be some room for improvment translating to 'define-configuration'. I will investigate how to best translate 'define-record-type*' to 'define-configuration', but in the meantime I think we should prioritize getting my new patch (#76379) through. I renamed fields and changed data types per your suggestions, so my new patch is backwards incompatible with the first. >>>> +@item @code{gui-tls} (default: @var{"false"}) >>>> +@item @code{gui-debugging} (default: @var{"false"}) >>>> +@item @code{gui-send-basic-auth-prompt} (default: @var{"false"}) >>>> +@item @code{gui-address} (default: @var{"127.0.0.1:8384"}) >>>> +@item @code{gui-user} (default: @var{#f}) >>>> +@item @code{gui-password} (default: @var{#f}) >>>> +A bcrypt hash of the GUI password. Remember that this will be global= ly >>>> +exposed in @file{/gnu/store}. >>> >>> I believe you want @itemx for all but the first item. >> >> Does it matter that the describing text only applies to gui-password, >> not to the whole block? > > It does yes, so my suggestion is actually bogus, sorry! Alright, I reverted (most of) my itemx changes in the v2 patch submitted at #76379. > Normally each field would be documented, not just =E2=80=98gui-password= =E2=80=99. So here's the problem: Syncthing has a LOT of documentation for a LOT of fields. Do we really want to maintain all that documentation in Guix? I omitted documenting the majority of fields, pointing to Syncthing documentation instead, out of caution for future Guix maintainers, not laziness. I opted for just documenting (1) any feature that is specific to Guix configuration and (2) anything that controls to which other devices your device connects. For anything else, the user should consult Syncthing documentation. Is my premise flawed, and I should document everything? Maybe a one-liner for each is unlikely to be invalidated by future Syncthing updates. WDYT? eikcaz- From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v10] services: syncthing: Add support for config file generation. Resent-From: Gabriel Santos Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sat, 22 Feb 2025 11:17:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 75959@debbugs.gnu.org, eikcaz@zacchae.us, ludo@gnu.org Cc: mirai@makinata.eu, leo@famulari.name X-Debbugs-Original-To: guix-patches@gnu.org, Zacchaeus Scheffer , Ludovic =?UTF-8?Q?Court=C3=A8s?= X-Debbugs-Original-Cc: Bruno Victal , 75959@debbugs.gnu.org, Leo Famulari Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.174022301615461 (code B ref 75959); Sat, 22 Feb 2025 11:17:02 +0000 Received: (at 75959) by debbugs.gnu.org; 22 Feb 2025 11:16:56 +0000 Received: from localhost ([127.0.0.1]:49233 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tlnVA-00041H-5F for submit@debbugs.gnu.org; Sat, 22 Feb 2025 06:16:56 -0500 Received: from layka.disroot.org ([178.21.23.139]:58460) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1tlnV7-00040R-2n for 75959@debbugs.gnu.org; Sat, 22 Feb 2025 06:16:54 -0500 Received: from mail01.disroot.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id 1985825FFA; Sat, 22 Feb 2025 12:16:51 +0100 (CET) X-Virus-Scanned: SPAM Filter at disroot.org Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id FA8RI_LK7Z4y; Sat, 22 Feb 2025 12:16:46 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1740223003; bh=ow93HYzzsG7x4msW7OhJvkYeeMxBntJqeVoI4VXLbOg=; h=Date:From:To:CC:Subject:In-Reply-To:References; b=A9/9t5wjHKRKyAyCBox6F6G8lTR3cfuUi10Nr9VJpgqIYA5AJY8PIDZeM3Ve6a1g4 JljYOLs4m62axcSOnO5enDa8vIW4rQhfq9dZj3Ytmuai4qTfMuWgYGr9zr1DVYgLqL hVWsQTCaj+V1N4g6JkCZvtaot2h7pWbdsZlx6YgzR1wS0/vsOwI7OQUbHE0xoD6iBW cgv9NU0f7czJTMIjj0qVL5F0d9Fn/f1cRB081ZajP+aT3UBJiZSE6Onrmi5JiOAHk5 q2jBeR9PTgD8t5m8+av5VT9ingxG3BA3muXW+rbBuEkk4AX3I8eCBJs8N3P7wv/uif +EtaMt7fnerCQ== Date: Sat, 22 Feb 2025 08:16:36 -0300 From: Gabriel Santos User-Agent: Thunderbird for Android In-Reply-To: <87o6yv6o3j.fsf@zacchae.us> References: <871pvyg0kd.fsf@zacchae.us> <87tt8udyg7.fsf_-_@zacchae.us> <87bjv0n9zb.fsf@gnu.org> <87frkc8g8u.fsf@zacchae.us> <87h64na76x.fsf@gnu.org> <87o6yv6o3j.fsf@zacchae.us> Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Greetings, I appreciate your efforts on this, but this completly broke home-syncthing-service-type for me, as it's resetting my configuration, giving my device another ID=2E -- Gabriel Santos From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v10] services: syncthing: Add support for config file generation. Resent-From: Zacchaeus Scheffer Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sat, 22 Feb 2025 20:50:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Gabriel Santos Cc: ludo@gnu.org, mirai@makinata.eu, 75959@debbugs.gnu.org, leo@famulari.name X-Debbugs-Original-Cc: Ludovic =?UTF-8?Q?Court=C3=A8s?= , Bruno Victal , 75959@debbugs.gnu.org, guix-patches@gnu.org, Leo Famulari Received: via spool by submit@debbugs.gnu.org id=B.174025736926862 (code B ref -1); Sat, 22 Feb 2025 20:50:01 +0000 Received: (at submit) by debbugs.gnu.org; 22 Feb 2025 20:49:29 +0000 Received: from localhost ([127.0.0.1]:57377 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tlwRF-0006zB-Af for submit@debbugs.gnu.org; Sat, 22 Feb 2025 15:49:29 -0500 Received: from lists.gnu.org ([2001:470:142::17]:42000) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tlwR3-0006yT-LG for submit@debbugs.gnu.org; Sat, 22 Feb 2025 15:49:18 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tlwQx-0003Pn-OP for guix-patches@gnu.org; Sat, 22 Feb 2025 15:49:11 -0500 Received: from [47.204.136.169] (helo=hun.zacchae.us) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tlwQw-0002zV-Bx; Sat, 22 Feb 2025 15:49:11 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=n0a+kTivEf0x+z12GrWSS4Zoskmr7I/SjwCt7uMNzts=; i=zacchae.us; b=vlao3KdOwfis 2tnug4wq4bJaifQHa77T/n+UxJ8Du/zfINEONShPGOgfAc9E8kyCESFKWzbydss3eDB5N5q0BQ==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Type:MIME-Version:Message-ID:Date:References: In-Reply-To:Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=n0a+kTivEf0x+z12GrWSS4Zoskmr7I/SjwCt7uMNzts=; i=zacchae.us; b=gtGtj3abdrYh 6te3BF3YdkAcCBVE1v9GDRHpekW59MsgjigBpaf0hFims2UmC2wCVvkdWKtGQJRf7TvmnuaWWyTWq k1smkqTOfTh5ynCbd8fwngDuS6f9tXYaRcFVDl5S8pJBjeF2nWE+wXqK5y+LLoMB3rLLarxxIQpZp HNdT8J7S52SvH+uh3uWju7z9xtETYcuF6MB/CD9QFebDkAr6Vk3jFW5S4saKNzL5LJvgllBr++g/C e/MWD1XQ0/QPmZH8AvPHwmrlg1hbZFQZ8L516zpLRGsNuAxhj3x1QgopQDU8Nxg0CYWVsRiW+Qv3C Zyya/Uze9YbO0S6eUP/X8w==; Received: from localhost.home ([127.0.0.1]:37544 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1tlwQq-000000001T9-1sMJ; Sat, 22 Feb 2025 15:49:04 -0500 From: Zacchaeus Scheffer In-Reply-To: (Gabriel Santos's message of "Sat, 22 Feb 2025 08:16:36 -0300") References: <871pvyg0kd.fsf@zacchae.us> <87tt8udyg7.fsf_-_@zacchae.us> <87bjv0n9zb.fsf@gnu.org> <87frkc8g8u.fsf@zacchae.us> <87h64na76x.fsf@gnu.org> <87o6yv6o3j.fsf@zacchae.us> Date: Sat, 22 Feb 2025 15:49:04 -0500 Message-ID: <87eczp7lj3.fsf@zacchae.us> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain X-Host-Lookup-Failed: Reverse DNS lookup failed for 47.204.136.169 (failed) Received-SPF: pass client-ip=47.204.136.169; envelope-from=eikcaz@zacchae.us; helo=hun.zacchae.us X-Spam_score_int: -8 X-Spam_score: -0.9 X-Spam_bar: / X-Spam_report: (-0.9 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-Spam-Score: 0.9 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.1 (/) Hi, Gabriel Santos writes: > Greetings, > > I appreciate your efforts on this, but this completly broke > home-syncthing-service-type for me, as it's resetting my configuration, > giving my device another ID. > > -- > Gabriel Santos I think I know why this is. At some point Syncthing changed the default config directory from ~/.config/syncthing to ~/.local/state/syncthing. If you move your syncthing .pem files from ~/.local/state/syncthing to ~/.config/syncthing, it will work. Since it seems Syncthing has changed the default, this service should really do so as well. I'll update it on the other patch that I'm submitting. -Zacchae From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v10] services: syncthing: Add support for config file generation. Resent-From: Rodion Goritskov Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sat, 22 Feb 2025 23:30:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Zacchaeus Scheffer Cc: ludo@gnu.org, mirai@makinata.eu, 75959@debbugs.gnu.org, Gabriel Santos , leo@famulari.name Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.174026697715092 (code B ref 75959); Sat, 22 Feb 2025 23:30:02 +0000 Received: (at 75959) by debbugs.gnu.org; 22 Feb 2025 23:29:37 +0000 Received: from localhost ([127.0.0.1]:57751 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tlywC-0003vL-MH for submit@debbugs.gnu.org; Sat, 22 Feb 2025 18:29:37 -0500 Received: from mail.goritskov.com ([65.108.121.176]:59720) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tlyw8-0003v7-By for 75959@debbugs.gnu.org; Sat, 22 Feb 2025 18:29:34 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=goritskov.com; s=04012025; t=1740266784; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=RNqv2S9c0HRjbI3nMHy9iquw3tXxeoav9c/1h9YEUEs=; b=IytUYMd8JJwlKrj8nBdDiXg3FfuY8KqEQn5p3rMHEtXGAJQhEE8ZB896xyhWew935j8AxW ZQ8+8jS4mu3eCGbHqRmW11E/1oJkBmYiXDoDeowVbpKVBfO7wWzlbNiFZ3ukt2UyMkMp5m AYosERXK8eakjZukGlQi/ov83LNzwcA= Received: from bumblebee-old (port-83-236-30-155.dynamic.as20676.net [83.236.30.155]) by mail.goritskov.com (OpenSMTPD) with ESMTPSA id 4c9ca564 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Sat, 22 Feb 2025 23:26:23 +0000 (UTC) From: Rodion Goritskov In-Reply-To: <87eczp7lj3.fsf@zacchae.us> (Zacchaeus Scheffer's message of "Sat, 22 Feb 2025 15:49:04 -0500") References: <871pvyg0kd.fsf@zacchae.us> <87tt8udyg7.fsf_-_@zacchae.us> <87bjv0n9zb.fsf@gnu.org> <87frkc8g8u.fsf@zacchae.us> <87h64na76x.fsf@gnu.org> <87o6yv6o3j.fsf@zacchae.us> <87eczp7lj3.fsf@zacchae.us> Date: Sun, 23 Feb 2025 00:29:25 +0100 Message-ID: <87cyf9tv6y.fsf@goritskov.com> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Zacchaeus Scheffer writes: > Hi, > > Gabriel Santos writes: > >> Greetings, >> >> I appreciate your efforts on this, but this completly broke >> home-syncthing-service-type for me, as it's resetting my configuration, >> giving my device another ID. >> >> -- >> Gabriel Santos > > I think I know why this is. At some point Syncthing changed the default > config directory from ~/.config/syncthing to ~/.local/state/syncthing. > If you move your syncthing .pem files from ~/.local/state/syncthing to > ~/.config/syncthing, it will work. Since it seems Syncthing has changed > the default, this service should really do so as well. I'll update it > on the other patch that I'm submitting. > > -Zacchae Hi! I also have a problem (cannot say if it the same as Gabriel's) - after upgrade my Syncthing instances stopped working with the odd error "remote device missing in cluster config". Moving config didn't work - and, as far as I understand, Syncthing still read the config in .config if it is present. However, it looks like it is not because the service itself, but because of the syncthing upgrade to 1.29.2 in commit 06d37f38606fabbace21e55ec7f2546b3ae5214f. I checked it by inheriting the Syncthing with the older version: > (define-public syncthing-old > (package > (inherit syncthing) > (name "syncthing-old") > (version "1.28.1") > (source (origin > (method url-fetch) > (uri (string-append "https://github.com/syncthing/syncthing" > "/releases/download/v" version > "/syncthing-source-v" version ".tar.gz")) > (sha256 > (base32 > "16j5w6hdr1x2231hw0zsxm53sw34wxcs4ijjjcnzcg1vz9drjrg9")))))) And passing it to the server: > (service syncthing-with-vpn-service-type > (syncthing-configuration > (syncthing syncthing-old) > (user "rodion"))) After that everything started working as before. Will try to investigate the issue further - couldn't find anything related neither in Syncthing form nor in the Github issues. From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v10] services: syncthing: Add support for config file generation. Resent-From: Zacchaeus Scheffer Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sat, 22 Feb 2025 23:57:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Rodion Goritskov Cc: ludo@gnu.org, mirai@makinata.eu, 75959@debbugs.gnu.org, Gabriel Santos , leo@famulari.name Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.174026858620313 (code B ref 75959); Sat, 22 Feb 2025 23:57:02 +0000 Received: (at 75959) by debbugs.gnu.org; 22 Feb 2025 23:56:26 +0000 Received: from localhost ([127.0.0.1]:57804 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tlzMA-0005HZ-1p for submit@debbugs.gnu.org; Sat, 22 Feb 2025 18:56:26 -0500 Received: from [47.204.136.169] (port=40586 helo=hun.zacchae.us) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tlzM6-0005HG-NL for 75959@debbugs.gnu.org; Sat, 22 Feb 2025 18:56:24 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_ed_sel; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=0br2Rv/ZEP258Stkt0Qc034LB13lJ/lHemNU+kenBR8=; i=zacchae.us; b=VPUj9V2N+GbH qZO+zzJ87UMSQD5YIsQ84AutygvmbzF1zny+DvgMSni2uFM0a2jPJkYaL5fFJUHRU9mBuxFTCQ==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zacchae.us; s=my_rsa_sel; h=Content-Type:MIME-Version:Message-ID:Date:References: In-Reply-To:Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=0br2Rv/ZEP258Stkt0Qc034LB13lJ/lHemNU+kenBR8=; i=zacchae.us; b=NNSKZVZf5zK2 TQw7dq3RAAMX9KL1geUeNcyme+i2CBSUvKlid2XNTqA8tmpSuALXHUGfmIfv9Bvdmgg8SgbaLEuVm W8OcW8zmGM7CISM0u8sLBLdbn1/P4niIs425oz2AvIYohXPjf4x2dBVEbzC5xy448gMvmzQ687iIm epX57E3dJutOLelo6egVZxdCN8/2JqMOv4lGVvN9ngtvt30WtbEDRPKC7gMwy2DzojSE/vh95dq/H ikVtImIN9L5tc0uweGCTQKYAUsoxtDfQRzQz/dKIzCaFnM4CDkYceK4DcytzAI7WaakRcfprylCyH b/f5Z1vFzjd9rFbICoiVxA==; Received: from localhost.home ([127.0.0.1]:52194 helo=hun) by hun.zacchae.us with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1tlzM0-000000001ib-1hsU; Sat, 22 Feb 2025 18:56:16 -0500 From: Zacchaeus Scheffer In-Reply-To: <87cyf9tv6y.fsf@goritskov.com> (Rodion Goritskov's message of "Sun, 23 Feb 2025 00:29:25 +0100") References: <871pvyg0kd.fsf@zacchae.us> <87tt8udyg7.fsf_-_@zacchae.us> <87bjv0n9zb.fsf@gnu.org> <87frkc8g8u.fsf@zacchae.us> <87h64na76x.fsf@gnu.org> <87o6yv6o3j.fsf@zacchae.us> <87eczp7lj3.fsf@zacchae.us> <87cyf9tv6y.fsf@goritskov.com> Date: Sat, 22 Feb 2025 18:56:16 -0500 Message-ID: <871pvp7cv3.fsf@zacchae.us> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: 1.3 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Rodion Goritskov writes: >> (service syncthing-with-vpn-service-type >> (syncthing-configuration >> (syncthing syncthing-old) >> (user "rodion"))) > > After that everything started working as before. > Will try to investigate [...] Content analysis details: (1.3 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in sa-accredit.habeas.com] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [47.204.136.169 listed in bl.score.senderscore.com] 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 0.3 (/) Rodion Goritskov writes: >> (service syncthing-with-vpn-service-type >> (syncthing-configuration >> (syncthing syncthing-old) >> (user "rodion"))) > > After that everything started working as before. > Will try to investigate the issue further - couldn't find anything > related neither in Syncthing form nor in the Github issues. If you aren't passing a non-#f value for config-file in syncthing-configuration, then my update should have no affect on your system, so the issue should be somewhere else, probably in the syncthing version update you mentioned. Still, the other issue of syncthing configuration directory location is one I will address. -Zacchae From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v10] services: syncthing: Add support for config file generation. Resent-From: Leo Famulari Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Tue, 25 Feb 2025 02:21:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Rodion Goritskov Cc: ludo@gnu.org, Zacchaeus Scheffer , 75959@debbugs.gnu.org, Gabriel Santos , mirai@makinata.eu Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.17404500462249 (code B ref 75959); Tue, 25 Feb 2025 02:21:02 +0000 Received: (at 75959) by debbugs.gnu.org; 25 Feb 2025 02:20:46 +0000 Received: from localhost ([127.0.0.1]:43828 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tmkYw-0000aB-4L for submit@debbugs.gnu.org; Mon, 24 Feb 2025 21:20:46 -0500 Received: from fout-a4-smtp.messagingengine.com ([103.168.172.147]:32799) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tmkYu-0000Zw-5K for 75959@debbugs.gnu.org; Mon, 24 Feb 2025 21:20:44 -0500 Received: from phl-compute-13.internal (phl-compute-13.phl.internal [10.202.2.53]) by mailfout.phl.internal (Postfix) with ESMTP id 0B07F13817C3; Mon, 24 Feb 2025 21:20:38 -0500 (EST) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-13.internal (MEProxy); Mon, 24 Feb 2025 21:20:38 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=famulari.name; h=cc:cc:content-type:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=mesmtp; t=1740450038; x= 1740536438; bh=RjsBFZmDWd3V5C9bhk6oSszubhrPVRsl9nAbBsoxMnk=; b=A Qaj7oiINzhK7qYWxXiqvxYpsIqbNdk+CgQh5FiVCGXp9pp2/4qaCXzEZEiM9dnwC fS+Rqw3q/XF7Xtir8ryPJpMo1IBXv9wWsLsXEwoBMgwPW6OUtLxtZZ9PQ7F4HKoU 4wF1SVhgyCdiPEWegzbfnZes23J5bMgruu5HTcF7uM= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t= 1740450038; x=1740536438; bh=RjsBFZmDWd3V5C9bhk6oSszubhrPVRsl9nA bBsoxMnk=; b=fXSccdYX9vGwU3UwfRRycGn/68yM5l2vFOddgrDti3fc9z6HCzc FrI5/pK8E7aUWQtHRXHenil3kc0nYdGtRg3YktV9yBxVYfMD+yUhkmadl5PBG+bS uIaltT0pMXl3In6dKGMCOMSS82AovMGSqxD5BTf5G7yz8hC70pJQPJzsePoEU7Tv 0XhcUGof4Ogv6AqqxF3jbSQbSO6PQiamRV2ux6+En0IlUIYM9H/eYtuOoUCMMrbz A9e310wF813uA8YtcVdTpHt0McvT/l4EAPOGDqV4jPSHXfRLETwY9kB7Pe90vdZU /IebAskrXD0IQMjYQcxbCoB9BlRrPPWPk6w== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdektdeghecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdp uffrtefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivg hnthhsucdlqddutddtmdenucfjughrpeffhffvvefukfhfgggtuggjsehttdertddttddv necuhfhrohhmpefnvghoucfhrghmuhhlrghrihcuoehlvghosehfrghmuhhlrghrihdrnh grmhgvqeenucggtffrrghtthgvrhhnpeeiteduheefkeeufeelgeduhfejgfelheefleeu hfeffffgueduleehvdejleeiteenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmh epmhgrihhlfhhrohhmpehlvghosehfrghmuhhlrghrihdrnhgrmhgvpdhnsggprhgtphht thhopeeipdhmohguvgepshhmthhpohhuthdprhgtphhtthhopehrohguihhonhesghhorh hithhskhhovhdrtghomhdprhgtphhtthhopegvihhktggriiesiigrtggthhgrvgdruhhs pdhrtghpthhtohepghgrsghrihgvlhhsrghnthhoshguvghsohhuiigrseguihhsrhhooh htrdhorhhgpdhrtghpthhtoheplhhuughosehgnhhurdhorhhgpdhrtghpthhtohepmhhi rhgrihesmhgrkhhinhgrthgrrdgvuhdprhgtphhtthhopeejheelheelseguvggssghugh hsrdhgnhhurdhorhhg X-ME-Proxy: Feedback-ID: i819c4023:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 24 Feb 2025 21:20:37 -0500 (EST) Date: Mon, 24 Feb 2025 21:20:15 -0500 From: Leo Famulari Message-ID: References: <871pvyg0kd.fsf@zacchae.us> <87tt8udyg7.fsf_-_@zacchae.us> <87bjv0n9zb.fsf@gnu.org> <87frkc8g8u.fsf@zacchae.us> <87h64na76x.fsf@gnu.org> <87o6yv6o3j.fsf@zacchae.us> <87eczp7lj3.fsf@zacchae.us> <87cyf9tv6y.fsf@goritskov.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <87cyf9tv6y.fsf@goritskov.com> X-Spam-Score: -0.7 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) On Sun, Feb 23, 2025 at 12:29:25AM +0100, Rodion Goritskov wrote: > I also have a problem (cannot say if it the same as Gabriel's) - after upgrade my Syncthing > instances stopped working with the odd error "remote device missing in > cluster config". I see this too. I don't use the Guix service for Syncthing so it has nothing to do with that. > However, it looks like it is not because the service itself, but because > of the syncthing upgrade to 1.29.2 in commit > 06d37f38606fabbace21e55ec7f2546b3ae5214f. Yes, seems that way. > After that everything started working as before. > Will try to investigate the issue further - couldn't find anything > related neither in Syncthing form nor in the Github issues. Let's try to debug a bit before reporting this upstream. From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v10] services: syncthing: Add support for config file generation. Resent-From: Leo Famulari Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Tue, 25 Feb 2025 03:10:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Rodion Goritskov Cc: ludo@gnu.org, Zacchaeus Scheffer , 75959@debbugs.gnu.org, Gabriel Santos , mirai@makinata.eu Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.174045294811195 (code B ref 75959); Tue, 25 Feb 2025 03:10:02 +0000 Received: (at 75959) by debbugs.gnu.org; 25 Feb 2025 03:09:08 +0000 Received: from localhost ([127.0.0.1]:43890 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tmlJj-0002uU-JX for submit@debbugs.gnu.org; Mon, 24 Feb 2025 22:09:07 -0500 Received: from fhigh-a7-smtp.messagingengine.com ([103.168.172.158]:36221) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tmlJh-0002tx-Ek for 75959@debbugs.gnu.org; Mon, 24 Feb 2025 22:09:06 -0500 Received: from phl-compute-10.internal (phl-compute-10.phl.internal [10.202.2.50]) by mailfhigh.phl.internal (Postfix) with ESMTP id 03E381140169; Mon, 24 Feb 2025 22:09:00 -0500 (EST) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-10.internal (MEProxy); Mon, 24 Feb 2025 22:09:00 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=famulari.name; h=cc:cc:content-type:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=mesmtp; t=1740452939; x= 1740539339; bh=cCPebk4Djjlgogsy+l7vMuiTt1KOSWxau0Rpc2csP+k=; b=f bizS5HBTQ73zpgEHT/0YFBH7Rwez8ba0rxzcI1wz4XIdmo/q6KcPIQBg+tzPh06F 1yf0JEd+Vp5rUB6jCNaBJDp6em4pbaJWe5HSPj1LdlxKadrKGiHv6hR4vf/sPNFM s7gdgMaqYLSglMZemgiui8x1JWdyl6lSsIjGM6GEx4= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t= 1740452939; x=1740539339; bh=cCPebk4Djjlgogsy+l7vMuiTt1KOSWxau0R pc2csP+k=; b=qttXtTlqwGjzNatVH+KaSo5EitAZusFfY0TDDY0ORYdQUT5ySg1 lN6oxGeDrux6Njz6TI/ricFGAqvY1x1WfhhpymLr0bZJ2/hCUDwPZ2CrT7sGCMxz l9oHUrqVJHFjwQLiGbyu8jbK/NqN1SDy8uCDkjjXbFhsP4vJ0s1mi1JwJ56L6Hbq M/2TeVc3+FMg4UnS0EjC7tQG+QU4zRw5kzrMpkN/aHHN6r5Fhm/HUAXWazG724Dt O+cu66zP+RceMB2MZXHC1JZHm9/HzpXVnadK1VZmzbJTygG6EMr0ts04ucJQ1rVy YfWFTG1DArqhKS6MauQ/ix/Hv1KFcYIyGpw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdektdehiecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdp uffrtefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivg hnthhsucdlqddutddtmdenucfjughrpeffhffvvefukfhfgggtuggjsehttdertddttddv necuhfhrohhmpefnvghoucfhrghmuhhlrghrihcuoehlvghosehfrghmuhhlrghrihdrnh grmhgvqeenucggtffrrghtthgvrhhnpeetgeffgfeihfevgfevhedtgeejgfefhffhveff feeuffehvedtffdtgfegveeltdenucffohhmrghinhepghhithhhuhgsrdgtohhmpdhgnh hurdhorhhgnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhho mheplhgvohesfhgrmhhulhgrrhhirdhnrghmvgdpnhgspghrtghpthhtohepiedpmhhoug gvpehsmhhtphhouhhtpdhrtghpthhtoheprhhoughiohhnsehgohhrihhtshhkohhvrdgt ohhmpdhrtghpthhtohepvghikhgtrgiiseiirggttghhrggvrdhushdprhgtphhtthhope hgrggsrhhivghlshgrnhhtohhsuggvshhouhiirgesughishhrohhothdrohhrghdprhgt phhtthhopehluhguohesghhnuhdrohhrghdprhgtphhtthhopehmihhrrghisehmrghkih hnrghtrgdrvghupdhrtghpthhtohepjeehleehleesuggvsggsuhhgshdrghhnuhdrohhr gh X-ME-Proxy: Feedback-ID: i819c4023:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 24 Feb 2025 22:08:59 -0500 (EST) Date: Mon, 24 Feb 2025 22:08:47 -0500 From: Leo Famulari Message-ID: References: <871pvyg0kd.fsf@zacchae.us> <87tt8udyg7.fsf_-_@zacchae.us> <87bjv0n9zb.fsf@gnu.org> <87frkc8g8u.fsf@zacchae.us> <87h64na76x.fsf@gnu.org> <87o6yv6o3j.fsf@zacchae.us> <87eczp7lj3.fsf@zacchae.us> <87cyf9tv6y.fsf@goritskov.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <87cyf9tv6y.fsf@goritskov.com> X-Spam-Score: -0.7 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) On Sun, Feb 23, 2025 at 12:29:25AM +0100, Rodion Goritskov wrote: > However, it looks like it is not because the service itself, but because > of the syncthing upgrade to 1.29.2 in commit > 06d37f38606fabbace21e55ec7f2546b3ae5214f. We can see here that Syncthing v1.29 requires Go 1.22 or newer: https://github.com/syncthing/syncthing/blob/v1.29.2/go.mod#L3 However, the default Go version in Guix is 1.21: https://git.savannah.gnu.org/cgit/guix.git/tree/gnu/packages/golang.scm?id=68cd38756b51d4abd8c796a5bcbbb9ea053eafde#n1045 I fixed the bug on our end by building Syncthing with Go 1.23: https://git.savannah.gnu.org/cgit/guix.git/commit/?id=68cd38756b51d4abd8c796a5bcbbb9ea053eafde Please let me know if you still experience this problem. From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v10] services: syncthing: Add support for config file generation. Resent-From: Gabriel Santos Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Tue, 25 Feb 2025 09:27:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Leo Famulari , Rodion Goritskov Cc: ludo@gnu.org, Zacchaeus Scheffer , 75959@debbugs.gnu.org, mirai@makinata.eu Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.174047560610165 (code B ref 75959); Tue, 25 Feb 2025 09:27:02 +0000 Received: (at 75959) by debbugs.gnu.org; 25 Feb 2025 09:26:46 +0000 Received: from localhost ([127.0.0.1]:44738 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tmrDB-0002dt-Ry for submit@debbugs.gnu.org; Tue, 25 Feb 2025 04:26:46 -0500 Received: from layka.disroot.org ([178.21.23.139]:38710) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1tmrCt-0002dJ-FI for 75959@debbugs.gnu.org; Tue, 25 Feb 2025 04:26:28 -0500 Received: from mail01.disroot.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id BD6C925C3B; Tue, 25 Feb 2025 10:26:25 +0100 (CET) X-Virus-Scanned: SPAM Filter at disroot.org Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id X-_S_SJkuFmq; Tue, 25 Feb 2025 10:26:25 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1740475584; bh=m1Rh+TCcdMWHepv1T7GwXjrseTkw045XHavg9u+ZFoA=; h=Date:From:To:CC:Subject:In-Reply-To:References; b=QzW8jWhnAhSMOHxociS7Jl2viFIL7r/kNgZApqLXrP4mn8j6cuGC1O9OJVgnNNfmK s7TenslVQbMWAK0ClIspRZVL9dAtm3OxkV/YYchsxQSVMDBNOFgBanMbavj/uc2Aal NR3gPaq3pfF2xqq/aOeGlxvHVkler00Va/v3kidajjZkemJWp3h+4oJqa08KD5bGYM nhBCp9cTMvALUIgh6X3uYONA9B/80Lk/4wwOsFElgvpqFbTak/cu3BjE2e4IsVTS++ e9Ft4BJTQYPRoupCTPgg/HFkUft/vO42OqTn+tbDAW2FG5xvodQfdLOcEgQCfvnDud 4PeDrS9eUQa5w== Date: Tue, 25 Feb 2025 00:14:12 -0300 From: Gabriel Santos User-Agent: Thunderbird for Android In-Reply-To: References: <871pvyg0kd.fsf@zacchae.us> <87tt8udyg7.fsf_-_@zacchae.us> <87bjv0n9zb.fsf@gnu.org> <87frkc8g8u.fsf@zacchae.us> <87h64na76x.fsf@gnu.org> <87o6yv6o3j.fsf@zacchae.us> <87eczp7lj3.fsf@zacchae.us> <87cyf9tv6y.fsf@goritskov.com> Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 1.1 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: >I see this too. I don't use the Guix service for Syncthing so it has >nothing to do with that. > >> However, it looks like it is not because the service itself, but because >> of the syncthing upgrad [...] Content analysis details: (1.1 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [178.21.23.139 listed in bl.score.senderscore.com] 0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [178.21.23.139 listed in sa-accredit.habeas.com] 1.1 DATE_IN_PAST_06_12 Date: is 6 to 12 hours before Received: date -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 0.1 (/) >I see this too=2E I don't use the Guix service for Syncthing so it has >nothing to do with that=2E > >> However, it looks like it is not because the service itself, but becaus= e >> of the syncthing upgrade to 1=2E29=2E2 in commit >> 06d37f38606fabbace21e55ec7f2546b3ae5214f=2E > >Yes, seems that way=2E Since this isn't related to the service, but rather the version, I think it would be best to look at the diff between the tags: -- Gabriel Santos From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v10] services: syncthing: Add support for config file generation. Resent-From: Gabriel Santos Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Tue, 25 Feb 2025 12:37:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Leo Famulari , Rodion Goritskov Cc: ludo@gnu.org, Zacchaeus Scheffer , 75959@debbugs.gnu.org, mirai@makinata.eu Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.17404870125208 (code B ref 75959); Tue, 25 Feb 2025 12:37:02 +0000 Received: (at 75959) by debbugs.gnu.org; 25 Feb 2025 12:36:52 +0000 Received: from localhost ([127.0.0.1]:45192 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tmuB9-0001Lv-Ll for submit@debbugs.gnu.org; Tue, 25 Feb 2025 07:36:52 -0500 Received: from layka.disroot.org ([178.21.23.139]:37446) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1tmuB5-0001Lk-8G for 75959@debbugs.gnu.org; Tue, 25 Feb 2025 07:36:49 -0500 Received: from mail01.disroot.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id 5471B257BE; Tue, 25 Feb 2025 13:36:45 +0100 (CET) X-Virus-Scanned: SPAM Filter at disroot.org Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id bf4IRKyrGRrZ; Tue, 25 Feb 2025 13:36:41 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1740487001; bh=H4CQCS2059B2nxz60PTekY33Aoh8fDg+H3bzh9i1kU4=; h=Date:From:To:CC:Subject:In-Reply-To:References; b=UzZEVxRfhH9HbnkpcZM16nhXZ3tnJq3BMDquf1wIjKdjvC4EEPeBnF/NdUc6eJi1g /341Rbqiqd7TPwKdHg6X1r2+9Lg9V0pFLfpBMnR7wdo23BA6lz00UTcmZiWvU0Tqs7 xWBCTwl6ZUP9K+xj6QaIVeDuXfWvunic6zQdlhgUl+boAI9OvBPXZGVptkwWCrPIIf 2JPYNfGPdPLMUKCayMxnKMFIic/8KuYi35Tf7lIDHTH2Wh9ga7f8DzHA0mvGEB50Zi LfDrqux79V3J2jJSkReFvdANhpHRqvLGvuHDSvd/Wr8gmqj7mKIYeBciP2sedo/Kb7 ZqzJmgL28Dd1A== Date: Tue, 25 Feb 2025 08:37:43 -0300 From: Gabriel Santos User-Agent: Thunderbird for Android In-Reply-To: References: <871pvyg0kd.fsf@zacchae.us> <87tt8udyg7.fsf_-_@zacchae.us> <87bjv0n9zb.fsf@gnu.org> <87frkc8g8u.fsf@zacchae.us> <87h64na76x.fsf@gnu.org> <87o6yv6o3j.fsf@zacchae.us> <87eczp7lj3.fsf@zacchae.us> <87cyf9tv6y.fsf@goritskov.com> Message-ID: <2B64F5FA-305B-48C6-85CF-85DC333CDCAE@disroot.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) >I fixed the bug on our end by building Syncthing with Go 1=2E23: > >https://git=2Esavannah=2Egnu=2Eorg/cgit/guix=2Egit/commit/?id=3D68cd38756= b51d4abd8c796a5bcbbb9ea053eafde > >Please let me know if you still experience this problem=2E Thank you, that was it=2E Updating solved the issue for me=2E -- Gabriel Santos From unknown Mon Aug 18 09:05:05 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#75959] [PATCH v10] services: syncthing: Add support for config file generation. Resent-From: Rodion Goritskov Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Tue, 25 Feb 2025 23:15:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 75959 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Leo Famulari Cc: 75959@debbugs.gnu.org, Rodion Goritskov Received: via spool by 75959-submit@debbugs.gnu.org id=B75959.17405252721067 (code B ref 75959); Tue, 25 Feb 2025 23:15:01 +0000 Received: (at 75959) by debbugs.gnu.org; 25 Feb 2025 23:14:32 +0000 Received: from localhost ([127.0.0.1]:48962 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tn48G-0000H9-AR for submit@debbugs.gnu.org; Tue, 25 Feb 2025 18:14:32 -0500 Received: from mail.goritskov.com ([65.108.121.176]:58448) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tn48E-0000Gu-65 for 75959@debbugs.gnu.org; Tue, 25 Feb 2025 18:14:31 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=goritskov.com; s=04012025; t=1740525078; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=x1qA2NCA8/b3eX23cG/jFQNZPjJok9h2FS0y5yY48nA=; b=GWsWV+WeaSYNmll/5mCZxIMzfU7iX4uYvSjHRrDGtqMldTPCVA20IVYH+1Jfc773gc/W6l YcbtQWoLdXiOnb1kjzXxoo2dzBm31DnBHJhDNORixQZ6hBL+3LEux6zWp8vqF//ieaUkR6 4JUBiP9Rn0uWR480COyjDd97FIiFjLE= Received: from bumblebee-old (port-92-196-15-22.dynamic.as20676.net [92.196.15.22]) by mail.goritskov.com (OpenSMTPD) with ESMTPSA id 832b4344 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Tue, 25 Feb 2025 23:11:17 +0000 (UTC) From: Rodion Goritskov In-Reply-To: (Leo Famulari's message of "Mon, 24 Feb 2025 22:08:47 -0500") References: <871pvyg0kd.fsf@zacchae.us> <87tt8udyg7.fsf_-_@zacchae.us> <87bjv0n9zb.fsf@gnu.org> <87frkc8g8u.fsf@zacchae.us> <87h64na76x.fsf@gnu.org> <87o6yv6o3j.fsf@zacchae.us> <87eczp7lj3.fsf@zacchae.us> <87cyf9tv6y.fsf@goritskov.com> Date: Wed, 26 Feb 2025 00:14:20 +0100 Message-ID: <87tt8haa7n.fsf@goritskov.com> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Hi! Syncthing 1.29.2 works great now! Thank you for the fix, Leo.