Syncthing 2.1.7
Overview
Syncthing is an open-source continuous file synchronisation program. Devices that you pair keep shared folders identical, directly between themselves, over an encrypted and mutually authenticated connection. There is no central server and no cloud account.
This SecureAnyCloud image runs Syncthing 2.1.7 on Ubuntu 24.04 on Amazon EC2, as one version of the SecureAnyCloud file sharing and sync listing on the AWS Marketplace. Pick it as the software version when you subscribe and launch. The instance is an always-on device. Your laptops, desktops, servers and phones sync with it whenever they are online, so changes reach your other devices even when those devices are never online at the same time. The instance keeps a copy of every shared folder on its own EBS volume.
What you get:
- Nothing shared ships in the image. The AMI contains no device identity, certificate, API key or password. On your instance's first boot, Syncthing generates its own device ID and API key, and the web GUI user
admingets a password unique to your instance. All of them are written to/root/syncthing-credentials.txt(root only). - HTTPS from the first boot. The web GUI listens on
127.0.0.1only. nginx serves it on port 443 with a certificate generated on your instance's first boot. Port 80 redirects to HTTPS, and requests for a host name the instance does not serve are dropped. - Sign-in through the GUI or the API key. The GUI uses Syncthing's own sign-in page and session cookie. Every REST call needs Syncthing's per-session token or the API key, so another website cannot drive your Syncthing through your browser. nginx does not accept HTTP Basic authentication (see Step 7).
- Private by default. Usage reporting, crash reporting, automatic upgrades, global discovery, relaying, local discovery and NAT traversal are all off, so the instance tells no outside service where it is. Your devices connect to it directly at
tcp://<your-host>:22000. You can switch global discovery and relays on deliberately (Step 8). - Confined service. Syncthing runs as the unprivileged
syncthingaccount. It can write only its own configuration, index and folders on the data volume, it cannot replace its own program, and, like nginx, it is blocked from the EC2 instance metadata service. - Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
- Components: Syncthing 2.1.7 (MPL-2.0; the project's own signed release build for Linux amd64, verified against the release signature), nginx, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent. The licence, authors and build provenance are in
/usr/share/doc/sac/syncthing/.
Default user: ubuntu. Architecture: x86_64. Recommended instance type: m5.large.
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet
- A security group that allows the following, from your own networks only:
- TCP 22 (SSH)
- TCP 443 (the web GUI) and TCP 80 (redirects to HTTPS)
- TCP 22000 and UDP 22000 (the Syncthing sync protocol; UDP carries QUIC), from the public addresses of the devices that sync with this one, or from your VPC range for devices inside AWS
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Pick Syncthing 2.1.7 on Ubuntu 24.04 as the software version, choose your Region, then choose Launch through EC2. Choose m5.large, your key pair, a security group as described above, and a subnet.
The AMI includes an 8 GiB root volume and a separate 20 GiB data volume that holds Syncthing's state and your synced folders. If you will sync more than 20 GiB, raise the data volume under Configure storage. You can also grow it later (see Step 10).
To launch with the AWS CLI instead, replace the values in angle brackets. This command sets the data volume to 200 GiB:
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--block-device-mappings 'DeviceName=/dev/sdf,Ebs={VolumeSize=200,VolumeType=gp3}' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=syncthing}]'Your devices reach the instance by its address, so give it a stable one. Allocate an Elastic IP and associate it with the instance. A plain public IP changes when the instance is stopped and started.
Connect to your instance
Version SSH user
Syncthing 2.1.7 on Ubuntu 24.04 ubuntu
ssh -i <your-key.pem> ubuntu@<public-ip>Check the services
First boot sets the host name and certificate, generates the device identity, API key and password, verifies them, and only then opens the site. This takes a few seconds. Check the services:
systemctl is-active syncthing-set-host syncthing-firstboot syncthing nginxactive active active activeOn the network, Syncthing listens only on port 22000 (TCP, and UDP for QUIC) for other devices. Its web GUI is on 127.0.0.1:8384 behind nginx (80 and 443). The remaining entries are SSH, Ubuntu's local DNS resolver, the time service and DHCP:
sudo ss -lntup | awk 'NR>1 {print $1, $5}' | sort -utcp *:22000 tcp 0.0.0.0:22 tcp 0.0.0.0:443 tcp 0.0.0.0:80 tcp 127.0.0.1:8384 tcp 127.0.0.53%lo:53 tcp 127.0.0.54:53 tcp [::]:22 tcp [::]:443 tcp [::]:80 udp *:22000 udp 127.0.0.1:323 udp 127.0.0.53%lo:53 udp 127.0.0.54:53 udp 172.31.85.189%ens5:68 udp [::1]:323There is no listener on 21027/udp (local discovery), because a VPC carries no broadcast or multicast traffic.
If nginx is not running, first boot has not finished, or it failed. In either case the GUI is never served. Check systemctl status syncthing-firstboot and journalctl -u syncthing-firstboot.
Get your password, API key and device ID
sudo cat /root/syncthing-credentials.txtOnly root can read the file. It holds the GUI address, this instance's sync address, the GUI sign-in, the REST API key and the device ID:
# Syncthing on Ubuntu 24.04 (sac AWS Marketplace image) - this instance's web GUI sign-in, REST API key and # device ID. Generated on this instance at first boot; unique to it and not known to sac or the Syncthing project. ... SYNCTHING_URL=https://ec2-203-0-113-10.compute-1.amazonaws.com/ SYNCTHING_SYNC_ADDRESS=tcp://ec2-203-0-113-10.compute-1.amazonaws.com:22000 syncthing.admin.user=admin syncthing.admin.pass=<SYNCTHING_ADMIN_PASSWORD> syncthing.apikey=<SYNCTHING_API_KEY> syncthing.device_id=<DEVICE-ID>Keep the password and the API key secret. Either one gives full control of Syncthing, including which folders on the instance are shared with which devices.
You can verify the sign-in from the instance itself. The helper goes through nginx on 443, the way a browser does. It checks that an anonymous call and a wrong password are refused, that the password signs in, that the signed-in session still needs Syncthing's per-session token, and that the API key works:
sudo /usr/local/sbin/syncthing-verify.shSYNCTHING_ROUNDTRIP_OK (https://ec2-203-0-113-10.compute-1.amazonaws.com/ via 127.0.0.1: 403 anonymous, 403 wrong password, 204 sign-in, CSRF enforced, API key v2.1.7)Sign in to the web GUI
Open the SYNCTHING_URL address in your browser. The certificate is self-signed until you install your own (Step 9), so the browser warns you once. Before you continue, compare the fingerprint it shows with the one on the instance:
sudo openssl x509 -in /etc/ssl/syncthing/syncthing.crt -noout -fingerprint -sha256Sign in as admin with the password from Step 4:
The GUI opens on the dashboard. Folders is on the left, and a new instance has none. This Device is on the right, with its listeners (2/2: TCP and QUIC on 22000), its short device ID and its version. Remote Devices is below. In this example, a second device has already dialled the instance and asks to be added:
Change the GUI password to one of your own under Actions -> Settings -> GUI, then select Save. The credentials file is not updated when you do, so store the new password safely. That tab shows the API key, which you can also regenerate there, so keep it closed when someone could see your screen.
Pair your devices and share a folder
Syncthing devices talk only to devices they have been told about, and they identify each other by device ID. Show this instance's ID:
sudo grep '^syncthing.device_id=' /root/syncthing-credentials.txtIn the GUI, choose Actions -> Show ID. It also shows the ID as a QR code for the Syncthing apps on phones.
Global discovery is off, so tell your other devices where the instance is:
- On your laptop, desktop or server, install Syncthing from syncthing.net, open its GUI and choose Add Remote Device. Paste the instance's device ID. On the Advanced tab, set Addresses to the
SYNCTHING_SYNC_ADDRESSfrom the credentials file, for exampletcp://ec2-203-0-113-10.compute-1.amazonaws.com:22000, or your own name and Elastic IP. Select Save. - Your device connects to the instance on port 22000, and the instance shows New Device ... wants to connect. Choose Add Device, give the device a name and select Save:
- Share a folder from your device with the instance. On the folder's Sharing tab, tick the instance. The instance shows New Folder ... wants to share folder. Choose Add. The folder path defaults to
/var/lib/syncthing/folders/<label>on the data volume. Select Save:
You can also start on the instance. Choose Add Folder there, tick your device on its Sharing tab, and accept the folder on your device.
The instance then pulls the folder's files and keeps them in sync. When the folder and the device both show Up to Date, the instance holds a full copy:
The instance never needs to reach your devices. As long as they can reach it on 22000, they connect to it, so devices behind a home router, or a laptop on the move, work without port forwarding on their side. Two devices that cannot reach each other directly still stay in sync through the instance when both share the folder with it.
Use the REST API
Scripts use Syncthing's REST API at https://<your-host>/rest/... with the API key in an X-API-Key header. The stnoupgrade tag shows that upgrades are disabled.
On the instance, this command reads the key from the credentials file into curl's configuration on standard input, so the key never appears on a command line or in your shell history:
sudo sed -n 's/^syncthing\.apikey=\(.*\)$/header = "X-API-Key: \1"/p' /root/syncthing-credentials.txt \
| curl -s --cacert /etc/ssl/syncthing/syncthing.crt -K - https://127.0.0.1/rest/system/version \
| jq '{version, codename, date, isRelease, tags}'{ "version": "v2.1.7", "codename": "Hafnium Hornet", "date": "2026-10-20T19:54:38Z", "isRelease": true, "tags": [ "stnoupgrade" ] }When a device is connected, /rest/system/connections lists it. Here, the second device from Step 6 dialled the instance on 22000:
{ "EASV76M-PVPKKQY-OZMTYK4-PWH3E7A-TRPD32I-O72IS6C-6BLVKXE-BFUW3AQ": { "connected": true, "address": "172.31.83.184:22000", "type": "tcp-server", "clientVersion": "v2.1.7" } }nginx does not accept HTTP Basic authentication. Syncthing itself would accept the GUI user name and password as Basic authentication on every REST route. That would let a password-guessing tool bypass the limits on the sign-in page, so nginx removes the Authorization header before the request reaches Syncthing. A Basic authentication request is therefore treated like an anonymous one and refused:
curl -s -o /dev/null -w '%{http_code}\n' --cacert /etc/ssl/syncthing/syncthing.crt -u admin:not-the-password https://127.0.0.1/rest/system/version403People should use the GUI sign-in. Scripts and tools should use the API key.
Discovery, relays and the sync port
The instance starts with every outside service off. Confirm this through the API:
sudo sed -n 's/^syncthing\.apikey=\(.*\)$/header = "X-API-Key: \1"/p' /root/syncthing-credentials.txt \
| curl -s --cacert /etc/ssl/syncthing/syncthing.crt -K - https://127.0.0.1/rest/config/options \
| jq '{listenAddresses, globalAnnounceEnabled, localAnnounceEnabled, relaysEnabled, natEnabled, urAccepted, autoUpgradeIntervalH, crashReportingEnabled}'{ "listenAddresses": [ "tcp://0.0.0.0:22000", "quic://0.0.0.0:22000" ], "globalAnnounceEnabled": false, "localAnnounceEnabled": false, "relaysEnabled": false, "natEnabled": false, "urAccepted": -1, "autoUpgradeIntervalH": 0, "crashReportingEnabled": false }The same settings are on the Connections tab of Actions -> Settings:
- Sync port. Other devices connect to the instance on TCP 22000 and UDP 22000 (QUIC). Allow both in the security group from the networks your devices use. Nothing else needs to reach Syncthing. If you change the listen address, change the security group to match.
- Global discovery lets your devices find the instance by device ID alone, without an address. Syncthing then announces this instance's device ID and addresses to the global discovery servers run by the Syncthing project, and asks them for your other devices' addresses. Switch it on only if you want that. Tick Global Discovery on the Connections tab and select Save, or use the API:
sudo sed -n 's/^syncthing\.apikey=\(.*\)$/header = "X-API-Key: \1"/p' /root/syncthing-credentials.txt \
| curl -s --cacert /etc/ssl/syncthing/syncthing.crt -K - -X PATCH -H 'Content-Type: application/json' \
-d '{"globalAnnounceEnabled": true}' https://127.0.0.1/rest/config/options- Relaying lets two devices that cannot connect directly exchange data through the public Syncthing relays. The data stays end-to-end encrypted, but it passes through a third party's server, and relays are slower. The instance has a public sync port, so devices that can reach it never need a relay. To allow relays, tick Enable Relaying or send
{"relaysEnabled": true}in the same way. Your devices learn each other's relay addresses through global discovery, so enable both. - Usage reporting, crash reporting and automatic upgrades stay off. The Syncthing program on the image cannot replace itself. SecureAnyCloud publishes a new version of the image for each new Syncthing release (see Step 10).
Use your own host name and certificate
Point a DNS record at the instance's Elastic IP, then tell the instance its name. The command creates a new self-signed certificate for that name, updates the nginx host rule and the GUI and sync addresses in the credentials file, and keeps the name across reboots:
sudo syncthing-set-hostname sync.example.comThe command prints the new certificate's SHA-256 fingerprint, which your browser shows when you next connect. On your other devices, update the address of the instance to tcp://sync.example.com:22000 under Edit Device -> Advanced -> Addresses.
To use a certificate from a public authority for the GUI instead, replace /etc/ssl/syncthing/syncthing.crt (full chain) and /etc/ssl/syncthing/syncthing.key (mode 0600, owned by root) with your own, then run sudo systemctl reload nginx. If you run syncthing-set-hostname again later, it replaces them with a new self-signed pair.
The sync protocol on 22000 does not use this certificate. Devices authenticate each other by device ID, whatever the name.
Storage, persistence and updates
Syncthing's configuration, its index database and your synced folders live on the data volume at /var/lib/syncthing. The volume is mounted by file system UUID with noexec, nosuid and nodev:
findmnt -no SOURCE,FSTYPE,OPTIONS /var/lib/syncthing/dev/nvme1n1 ext4 rw,nosuid,nodev,noexec,relatimesudo ls -la /var/lib/syncthingtotal 36 drwxr-xr-x 6 root root 4096 Oct 30 22:07 . drwxr-xr-x 49 root root 4096 Oct 30 22:05 .. drwx------ 2 syncthing syncthing 4096 Oct 30 22:23 config drwx------ 3 syncthing syncthing 4096 Oct 30 22:17 folders drwx------ 3 syncthing syncthing 4096 Oct 30 22:06 index drwx------ 2 root root 16384 Oct 30 22:04 lost+foundShared folders are created under folders/ and owned by the syncthing account, the only account Syncthing can write as. To place files into a synced folder from the instance's shell, write them as that account, for example:
sudo -u syncthing cp /home/ubuntu/report.pdf /var/lib/syncthing/folders/Documents/Every service is enabled, so Syncthing returns after a reboot or a stop and start, with the same device ID, folders and password. Unattended security upgrades keep the operating system and nginx patched. Check them:
systemctl is-enabled syncthing nginx unattended-upgradesenabled enabled enabledTo grow the data volume, enlarge the EBS volume in the EC2 console, then extend the file system online:
sudo resize2fs $(findmnt -no SOURCE /var/lib/syncthing)Syncthing is a sync tool, not a backup. A file deleted or overwritten on one device is deleted or overwritten on the others. Turn on File Versioning for a folder, in its Edit dialog, to keep old versions on the instance. For real backups, take EBS snapshots of the data volume or use AWS Backup.
To move to a newer Syncthing release, launch the new version of the image, pair it with your devices and share the folders with it. Syncthing fills it from your other devices.
Security notes
- No shared secret ships in the image. The device certificate and key, the GUI's own certificate, the API key, the GUI password (stored by Syncthing as a bcrypt hash), the nginx certificate and the credentials file are all generated on your instance's first boot. nginx does not serve the GUI until first boot has generated them and verified that the password and the API key work.
- Fail closed. If first boot cannot complete, the GUI is never served and Syncthing does not start with a default configuration.
- Confined service. Syncthing runs as the
syncthingaccount with no login shell, no capabilities and no core dumps. The operating system is read-only to it, except itsconfig,indexandfoldersdirectories. It runs with--no-upgrade, so its upgrade check answers 501 and the program is owned by root. Syncthing, nginx and the first-boot step that generates the identity and password cannot reach the EC2 instance metadata service (IPAddressDeny). Only the step that looks up the instance's public name uses it, with IMDSv2. - Web GUI behind nginx. Syncthing's own check that the GUI is addressed as
localhoststays on. nginx passes the real client address, taken from the connection and never from a request header, so failed sign-ins are logged against the right address. Sign-ins are rate limited. Syncthing's debugging and upgrade routes also refuse requests that do not come from the GUI's own page. - Web GUI libraries. The Syncthing 2.1.7 web GUI bundles AngularJS 1.3.20 and moment 2.19.4, and Bootstrap 3.4.1. Both AngularJS and moment have published advisories rated HIGH for which no fixed release exists on those lines: AngularJS CVE-2026-11998, CVE-2024-21490 and CVE-2019-10768, and moment CVE-2022-31129 and CVE-2022-24785. SecureAnyCloud reviewed each against this GUI and found none reachable. The GUI defines no resource URL policy with regular expressions and loads only fixed templates, uses no ng-srcset, never calls angular.merge, and gives moment only timestamps produced by Syncthing itself. The moment locale issue affects Node.js only. The libraries run in your browser after you sign in. They are shipped unchanged from the Syncthing release, and SecureAnyCloud will publish a new version of the image when Syncthing updates them.
- Syncthing itself (the Go program) has no known vulnerability reachable in this release. The Syncthing project builds it with Go 1.27.3, and every published Syncthing advisory was fixed in earlier releases.
- Restrict access. Allow 22/tcp only from your management network, 80/443 only from the networks that use the GUI, and 22000 TCP/UDP only from the networks of your devices. A device ID alone does not let anyone sync with the instance, because you must accept each device and each folder.
Architecture summary
Component Detail
Sync engine Syncthing 2.1.7 (MPL-2.0), /usr/local/bin/syncthing, account syncthing, syncthing.service
Sync protocol 22000/tcp (TLS) and 22000/udp (QUIC), device to device authentication by device ID
Web GUI and REST API Syncthing on 127.0.0.1:8384, served by nginx on 443 (HTTPS, per instance certificate in /etc/ssl/syncthing); 80 redirects to HTTPS
Sign in GUI user admin (session cookie), REST API key in the X-API-Key header; Basic auth not accepted through nginx
Discovery Global and local discovery, relays, NAT traversal off; devices connect to tcp://<host>:22000
Your files /var/lib/syncthing/folders on the 20 GiB data volume (resizable, mounted noexec)
State /var/lib/syncthing/config (configuration, device key), /var/lib/syncthing/index (index database)
Credentials /root/syncthing-credentials.txt, mode 0600, root only
First boot syncthing-set-host.service (host name and certificate), syncthing-firstboot.service (device identity, API key, password)
Tools syncthing-set-hostname, syncthing-verify.sh
Ports 22 SSH, 80 redirect, 443 web GUI, 22000 TCP/UDP sync
Base image Ubuntu 24.04 LTS, fully patched, unattended security upgrades enabled, IMDSv2 required
Support
SecureAnyCloud images come with 24/7 support. Email sales@secureanycloud.com and include your AWS account ID and the instance ID. For questions about Syncthing itself, see the Syncthing documentation and the Syncthing forum.
Syncthing is a trademark of the Syncthing Foundation. SecureAnyCloud is not affiliated with, endorsed by or sponsored by the Syncthing Foundation or the Syncthing project.
Deploy on AWS
Launch Syncthing 2.1.7 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com