mirror of
https://github.com/syncthing/syncthing.git
synced 2026-09-08 12:13:23 -04:00
Compare commits
5
Commits
v2.1.4-rc.2
...
release
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ca95cf149 | ||
|
|
62f6060ceb | ||
|
|
c10408263e | ||
|
|
6c25cdebf6 | ||
|
|
ed8d87f251 |
No files matched your search
@@ -445,7 +445,7 @@ jobs:
|
||||
CERTIFICATE_PATH=$RUNNER_TEMP/codesign.p12
|
||||
echo "$DEVELOPER_ID_CERTIFICATE_BASE64" | base64 -d -o "$CERTIFICATE_PATH"
|
||||
security import "$CERTIFICATE_PATH" -k "$KEYCHAIN_PATH" -P "$DEVELOPER_ID_CERTIFICATE_PASSWORD" -T /usr/bin/codesign -T /usr/bin/productsign
|
||||
security set-key-partition-list -S apple-tool:,apple: -s -k actions "$KEYCHAIN_PATH"
|
||||
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
||||
|
||||
# Set the codesign identity for following steps
|
||||
echo "CODESIGN_IDENTITY=$CODESIGN_IDENTITY" >> $GITHUB_ENV
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -20,6 +21,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/alecthomas/kong"
|
||||
@@ -31,11 +33,12 @@ import (
|
||||
)
|
||||
|
||||
type cli struct {
|
||||
Listen string `default:":8080" help:"Listen address"`
|
||||
MetricsListen string `default:":8082" help:"Listen address for metrics"`
|
||||
URL string `short:"u" default:"https://api.github.com/repos/syncthing/syncthing/releases?per_page=25" help:"GitHub releases url"`
|
||||
Forward []string `short:"f" help:"Forwarded pages, format: /path->https://example/com/url"`
|
||||
CacheTime time.Duration `default:"15m" help:"Cache time"`
|
||||
Listen string `default:":8080" help:"Listen address"`
|
||||
MetricsListen string `default:":8082" help:"Listen address for metrics"`
|
||||
URL string `short:"u" default:"https://api.github.com/repos/syncthing/syncthing/releases?per_page=25" help:"GitHub releases url"`
|
||||
Forward []string `short:"f" help:"Forwarded pages, format: /path->https://example/com/url"`
|
||||
CacheTime time.Duration `default:"15m" help:"Cache time"`
|
||||
AssetURLTemplate string `help:"Template for asset URLs, blank to use GitHub default" env:"ASSET_URL_TEMPLATE"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -69,7 +72,7 @@ func server(params *cli) error {
|
||||
}()
|
||||
}
|
||||
|
||||
cache := &cachedReleases{url: params.URL}
|
||||
cache := &cachedReleases{url: params.URL, assetURLTemplate: params.AssetURLTemplate}
|
||||
if err := cache.Update(context.Background()); err != nil {
|
||||
return fmt.Errorf("initial cache update: %w", err)
|
||||
} else {
|
||||
@@ -266,6 +269,7 @@ func filterForCompatibility(rels []upgrade.Release, ua, osv string) []upgrade.Re
|
||||
|
||||
type cachedReleases struct {
|
||||
url string
|
||||
assetURLTemplate string
|
||||
mut sync.RWMutex
|
||||
current []upgrade.Release
|
||||
latestRel, latestPre string
|
||||
@@ -278,7 +282,7 @@ func (c *cachedReleases) Releases() []upgrade.Release {
|
||||
}
|
||||
|
||||
func (c *cachedReleases) Update(ctx context.Context) error {
|
||||
rels, err := fetchGithubReleases(ctx, c.url)
|
||||
rels, err := fetchGithubReleases(ctx, c.url, c.assetURLTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -306,7 +310,7 @@ func (c *cachedReleases) Update(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func fetchGithubReleases(ctx context.Context, url string) ([]upgrade.Release, error) {
|
||||
func fetchGithubReleases(ctx context.Context, url, assetURLTemplate string) ([]upgrade.Release, error) {
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
metricHTTPRequests.WithLabelValues("github-releases", "error").Inc()
|
||||
@@ -325,12 +329,25 @@ func fetchGithubReleases(ctx context.Context, url string) ([]upgrade.Release, er
|
||||
}
|
||||
metricHTTPRequests.WithLabelValues("github-releases", "success").Inc()
|
||||
|
||||
tpl, err := template.New("asset").Parse(assetURLTemplate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Move the URL used for browser downloads to the URL field, and remove
|
||||
// the browser URL field. This avoids going via the GitHub API for
|
||||
// downloads, since Syncthing uses the URL field.
|
||||
for _, rel := range rels {
|
||||
for j, asset := range rel.Assets {
|
||||
rel.Assets[j].URL = asset.BrowserURL
|
||||
if assetURLTemplate != "" {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := tpl.Execute(buf, map[string]any{"Release": rel, "Asset": asset}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rel.Assets[j].URL = buf.String()
|
||||
} else {
|
||||
rel.Assets[j].URL = asset.BrowserURL
|
||||
}
|
||||
rel.Assets[j].BrowserURL = ""
|
||||
}
|
||||
}
|
||||
|
||||
+23
-14
@@ -23,6 +23,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -154,21 +155,10 @@ func (s *apiSrv) handler(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
slog.Debug("Handling request", "id", reqID, "method", req.Method, "url", req.URL, "proto", req.Proto)
|
||||
|
||||
remoteAddr := &net.TCPAddr{
|
||||
IP: nil,
|
||||
Port: -1,
|
||||
}
|
||||
|
||||
var remoteAddr *net.TCPAddr
|
||||
if s.useHTTP {
|
||||
// X-Forwarded-For can have multiple client IPs; split using the comma separator
|
||||
forwardIP, _, _ := strings.Cut(req.Header.Get("X-Forwarded-For"), ",")
|
||||
|
||||
// net.ParseIP will return nil if leading/trailing whitespace exists; use strings.TrimSpace()
|
||||
remoteAddr.IP = net.ParseIP(strings.TrimSpace(forwardIP))
|
||||
|
||||
if parsedPort, err := strconv.ParseInt(req.Header.Get("X-Client-Port"), 10, 0); err == nil {
|
||||
remoteAddr.Port = int(parsedPort)
|
||||
}
|
||||
remoteAddr = forwardedRemoteAddr(req)
|
||||
} else {
|
||||
var err error
|
||||
remoteAddr, err = net.ResolveTCPAddr("tcp", req.RemoteAddr)
|
||||
@@ -191,6 +181,21 @@ func (s *apiSrv) handler(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func forwardedRemoteAddr(req *http.Request) *net.TCPAddr {
|
||||
forwardIP, _, _ := strings.Cut(req.Header.Get("X-Forwarded-For"), ",")
|
||||
|
||||
remoteAddr := &net.TCPAddr{
|
||||
IP: net.ParseIP(strings.TrimSpace(forwardIP)),
|
||||
Port: -1,
|
||||
}
|
||||
|
||||
if parsedPort, err := strconv.ParseInt(req.Header.Get("X-Client-Port"), 10, 0); err == nil {
|
||||
remoteAddr.Port = int(parsedPort)
|
||||
}
|
||||
|
||||
return remoteAddr
|
||||
}
|
||||
|
||||
func (s *apiSrv) handleGET(w http.ResponseWriter, req *http.Request) {
|
||||
reqID := req.Context().Value(idKey).(requestID)
|
||||
|
||||
@@ -327,7 +332,11 @@ func (s *apiSrv) handleAnnounce(deviceID protocol.DeviceID, addresses []string)
|
||||
return s.db.merge(&deviceID, dbAddrs, seen)
|
||||
}
|
||||
|
||||
func handlePing(w http.ResponseWriter, _ *http.Request) {
|
||||
func handlePing(w http.ResponseWriter, req *http.Request) {
|
||||
hostname, _ := os.Hostname()
|
||||
w.Header().Set("Discovery-Server-Instance", hostname)
|
||||
w.Header().Set("Discovery-Client-Address", req.RemoteAddr)
|
||||
w.Header().Set("Discovery-Client-Remote", forwardedRemoteAddr(req).String())
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Le système de mise à jour automatique propose le choix entre versions stables et versions préliminaires.",
|
||||
"Automatic upgrades": "Mises à jour automatiques",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "Les mises à jour automatiques sont toujours activées pour les versions mineures.",
|
||||
"Automatically create or share folders that this device advertises at the default path.": "Automatiquement créer dans le chemin par défaut les partages auxquels cet appareil vous propose de participer, ou accepter leur partage s'ils pré-existent.",
|
||||
"Automatically create or share folders that this device advertises at the default path.": "Accepter automatiquement ses propositions de partage. Si le partage n'existe pas déjà ici, le répertoire correspondant sera créé dans le chemin par défaut.",
|
||||
"Available debug logging facilities:": "Outils de débogage disponibles :",
|
||||
"Be careful!": "Faites attention !",
|
||||
"Block Indexing": "Indexation des blocs",
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "STDISCOSRV" "1" "Aug 12, 2026" "v2.1.0" "Syncthing"
|
||||
.TH "STDISCOSRV" "1" "Sep 06, 2026" "v2.1.0" "Syncthing"
|
||||
.SH NAME
|
||||
stdiscosrv \- Syncthing Discovery Server
|
||||
.SH SYNOPSIS
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "STRELAYSRV" "1" "Aug 12, 2026" "v2.1.0" "Syncthing"
|
||||
.TH "STRELAYSRV" "1" "Sep 06, 2026" "v2.1.0" "Syncthing"
|
||||
.SH NAME
|
||||
strelaysrv \- Syncthing Relay Server
|
||||
.SH SYNOPSIS
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SYNCTHING-BEP" "7" "Aug 12, 2026" "v2.1.0" "Syncthing"
|
||||
.TH "SYNCTHING-BEP" "7" "Sep 06, 2026" "v2.1.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-bep \- Block Exchange Protocol v1
|
||||
.SH INTRODUCTION AND DEFINITIONS
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SYNCTHING-CONFIG" "5" "Aug 12, 2026" "v2.1.0" "Syncthing"
|
||||
.TH "SYNCTHING-CONFIG" "5" "Sep 06, 2026" "v2.1.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-config \- Syncthing Configuration
|
||||
.SH OVERVIEW
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SYNCTHING-DEVICE-IDS" "7" "Aug 12, 2026" "v2.1.0" "Syncthing"
|
||||
.TH "SYNCTHING-DEVICE-IDS" "7" "Sep 06, 2026" "v2.1.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-device-ids \- Understanding Device IDs
|
||||
.sp
|
||||
@@ -40,12 +40,12 @@ the public key in use.
|
||||
To understand device IDs we need to look at the underlying mechanisms. At first
|
||||
startup, Syncthing will create a public/private keypair.
|
||||
.sp
|
||||
Currently this is a 384 bit ECDSA key (3072 bit RSA prior to v0.12.5,
|
||||
which is what is used as an example in this article). The keys are saved in
|
||||
the form of the private key (\fBkey.pem\fP) and a self signed certificate
|
||||
(\fBcert.pem\fP). The self signing part doesn’t actually add any security or
|
||||
functionality as far as Syncthing is concerned but it enables the use of the
|
||||
keys in a standard TLS exchange.
|
||||
Currently this is a 256 bit Ed25519 key (384 bit ECDSA prior to v2.0.0 and
|
||||
3072 bit RSA prior to v0.12.5, which is what is used as an example in this
|
||||
article). The keys are saved in the form of the private key (\fBkey.pem\fP) and a
|
||||
self signed certificate (\fBcert.pem\fP). The self signing part doesn’t actually
|
||||
add any security or functionality as far as Syncthing is concerned but it enables
|
||||
the use of the keys in a standard TLS exchange.
|
||||
.sp
|
||||
The typical certificate will look something like this, inspected with
|
||||
\fBopenssl x509\fP:
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SYNCTHING-EVENT-API" "7" "Aug 12, 2026" "v2.1.0" "Syncthing"
|
||||
.TH "SYNCTHING-EVENT-API" "7" "Sep 06, 2026" "v2.1.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-event-api \- Event API
|
||||
.SH DESCRIPTION
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SYNCTHING-FAQ" "7" "Aug 12, 2026" "v2.1.0" "Syncthing"
|
||||
.TH "SYNCTHING-FAQ" "7" "Sep 06, 2026" "v2.1.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-faq \- Frequently Asked Questions
|
||||
.INDENT 0.0
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SYNCTHING-GLOBALDISCO" "7" "Aug 12, 2026" "v2.1.0" "Syncthing"
|
||||
.TH "SYNCTHING-GLOBALDISCO" "7" "Sep 06, 2026" "v2.1.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-globaldisco \- Global Discovery Protocol v3
|
||||
.SH ANNOUNCEMENTS
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SYNCTHING-LOCALDISCO" "7" "Aug 12, 2026" "v2.1.0" "Syncthing"
|
||||
.TH "SYNCTHING-LOCALDISCO" "7" "Sep 06, 2026" "v2.1.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-localdisco \- Local Discovery Protocol v4
|
||||
.SH MODE OF OPERATION
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SYNCTHING-NETWORKING" "7" "Aug 12, 2026" "v2.1.0" "Syncthing"
|
||||
.TH "SYNCTHING-NETWORKING" "7" "Sep 06, 2026" "v2.1.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-networking \- Firewall Setup
|
||||
.SH ROUTER SETUP
|
||||
|
||||
@@ -28,7 +28,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SYNCTHING-RELAY" "7" "Aug 12, 2026" "v2.1.0" "Syncthing"
|
||||
.TH "SYNCTHING-RELAY" "7" "Sep 06, 2026" "v2.1.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-relay \- Relay Protocol v1
|
||||
.SH WHAT IS A RELAY?
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SYNCTHING-REST-API" "7" "Aug 12, 2026" "v2.1.0" "Syncthing"
|
||||
.TH "SYNCTHING-REST-API" "7" "Sep 06, 2026" "v2.1.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-rest-api \- REST API
|
||||
.sp
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SYNCTHING-SECURITY" "7" "Aug 12, 2026" "v2.1.0" "Syncthing"
|
||||
.TH "SYNCTHING-SECURITY" "7" "Sep 06, 2026" "v2.1.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-security \- Security Principles
|
||||
.sp
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SYNCTHING-STIGNORE" "5" "Aug 12, 2026" "v2.1.0" "Syncthing"
|
||||
.TH "SYNCTHING-STIGNORE" "5" "Sep 06, 2026" "v2.1.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-stignore \- Prevent files from being synchronized to other nodes
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SYNCTHING-VERSIONING" "7" "Aug 12, 2026" "v2.1.0" "Syncthing"
|
||||
.TH "SYNCTHING-VERSIONING" "7" "Sep 06, 2026" "v2.1.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-versioning \- Keep automatic backups of deleted files by other nodes
|
||||
.sp
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SYNCTHING" "1" "Aug 12, 2026" "v2.1.0" "Syncthing"
|
||||
.TH "SYNCTHING" "1" "Sep 06, 2026" "v2.1.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing \- Syncthing
|
||||
.SH SYNOPSIS
|
||||
|
||||
Reference in new issue
Block a user