syncthing
syncthing copied to clipboard
Manually add or override addresses announced to Discovery Server
Background: We use Syncthing (extremely satisfied, btw!) in a small team of staff members within the organisation's local network & VPN. Each staff member runs one instance on their laptop, and two instances run on our servers (one on-premise, one cloud/VPS).
To have all instances mutually discover each over smoothly and yet to keep everything within our network/VPN, we also started running a discovery server a while ago. Since then, everything works very smoothly and reliably.
Now I just migrated one of the server instances into a Docker container and face one issue: that Syncthing instance only announces its internal container IP (when NAT disabled), plus the VPS' external/public IP (when NAT enabled). Both aren't the IPs under which other instances can reach it (this would be one of the VPS internal IPs). And it's of course clear that Syncthing couldn't possibly know/find out the other IP.
Feature needed/suggested: It would be a useful feature if one could manually specify IP addresses that the Syncthing instance announces to the Discovery Server (in addition or instead of the local interface IPs).
I guess this could be useful for others running Syncthing in a dockerized setup. Or in any other setup where the instance is actually reachable on a fixed/known IP address that is, however, not one of it's own/visible interfaces.
Workaround used for now: I added the internally-reachable IP as listen address together with wildcard listen addresses. This seems to make Syncthing announce it to the Discovery Server regardless of the fact it can't bind the address.
The downsides are that this does not look very elegant, might not actually be the desired/expected behaviour and pollutes the log with periodic failure messages (rightly so, about not being able to bind those IPs).
Other alternatives considered:
- Running the Syncthing container with host networking mode: doesn't really seem more elegant to me. This would be the only service running in host networking mode.
- Using a local Relay Server: I did not pursue this too far, but it seems overkill somehow and I am not sure again if that would be any more elegant.
- Running a local STUN server: seems overkill, too.
At least for docker you could switch to the host network mode.
Since it's a server, letting the clients connect to it via hostname or (static) IP might also be an option.
In general, the tool is aimed at individuals, that are unlikely to ever need to run their own discovery servers.
If you do choose to run it, then there are certain requirements for that, which doesn't look like your setup meets, I don't think we should add any band-aids for that.
For your specific setup, you can always pre-configure the network topology, or use some sort of dynamic dns based approach.
@calmh thanks, that's a good point and a possible alternative (better?) workaround.
We actually used that approach prior to running a discovery server. The only downside I could see is that we'd have two server names statically configured in each instance, as opposed to one discovery server, but that's a small trade-off. And if we use server names pointing to a CNAME record we could quite flexibly change a server IP if ever needed without reconfiguring the client.
@AudriusButkevicius fully understand that our use case goes beyond what Syncthing actually aims at.
When you suggest "pre-configure the network topology", do you mean the same as @calmh effectively - configure static IPs/host names for some devices in the config - or something else?
OK, I will add my 2 cents here.
I agree that it would really be nice to have a way to override the announcement address when running in a Docker container. Here is a syncthing
instance I just provisioned and connected it to the central syncthing
instance that does the majority of syncing.
The addresses that get announced are the internal IP for the Docker container and the public facing IP on the firewall. I don't do any port forwarding on the firewall for syncthing
.
The instance I just created sits inside the firewall and can talk directly to the central syncthing
. In my case discovery will not happen because the two instances sit on different VLANs and different subnets.
So If I could configure syncthing
to allow me to specify what address(es) it uses to announce how to be contacted, that would be absolutely great. As it is right now, I have to rely on the relays and that can sometimes take quite a while to see each other.
Please, please syncthing
maintainers add the option to allow the announcement address(es) to be specified.
There already exists a way, it's just not what addresses get announced, but which addresses get tried when connecting. Use that.
That and we should improve the discovery section in our docker documentation:
https://github.com/syncthing/syncthing/blob/main/README-Docker.md#discovery
Interface IP discovery is also solved by switching to host network mode. I'll create a PR later.
Are we planning to do something about this? To me it seems all the required facilities (i.e. configuring device addresses) are already there, so I don't think there is anything to be done here.
I am very against allowing spoofing of addresses to be provided to discovery.
I guess we somewhat inadvertently already allow that by advertising addresses we can't bind to, and I guess we should fix that?
Maybe we should discuss this in the forum. There's also https://github.com/syncthing/syncthing/issues/8453 which also hits the same note of "what do we want to publish".
Looking back at my comment from yesterday, I realized that I probably should have also stated that the address that the needed to be announced was 172.19.150.21. That is the IP on the box where the docker container is running. There is no way to determine the IP address within the container and running with --network host
is not a preferable option.
Actually in several environments I am not able/allowed to run with --network host
, so having a way to manually specify the announcement address is sort of necessary.
+1
I'm running Syncthing in a container behind NGINX, which has all neccessary port forwards set. --network host
isn't an option with my setup and entering the IP/hostname of the container-host on every device doesn't seem like a good/sustainable solution. Announcing the container IP (whether global or local) is useless and just wastes time as the clients try to connect to the non-existing IP.
Also found this forum post of someone also requesting this feature.
I'd be happy implementing this feature, if someone could point me in the right direction, where to look in the code as I haven't yet contributed.
There already exists a way, it's just not what addresses get announced, but which addresses get tried when connecting. Use that.
Not sure If I understand this. Can't find such a setting anywhere either. Could you be so kind and elaborate a bit?
There already exists a way, it's just not what addresses get announced, but which addresses get tried when connecting. Use that.
Not sure If I understand this. Can't find such a setting anywhere either. Could you be so kind and elaborate a bit?
How do I do X, where do I find Y is best handled on the forums, so we don't pollute github issues with random support questions. Please use that.
I second this. Being able to specify an IP that the instance is running on is a very basic feature and simply telling everyone to run in host mode isn't necessarily a good alternative.
I have a similar need. I tried to set this up in my private cloud I run in a Colo, I have a dns name that resolves to an internal ip when on my home network or VPN, and a public ip when on the raw internet. I was hoping to find a setting where I could set the announce address to docker-dmz.domain.com. which would make the dockers sync thing reachable from anywhere.
But currently everything is connecting thru the Wan relay
Why not just point the other side towards the name directly, skipping the round trip via discovery?
Because some devices are portable and are not always on the same network. So when they are not on the internal network they will not be able to sync.
I for the life of me can not understand why there is such opposition to what seems like a pretty simple request. Is it not a matter of adding a new switch to specify the announce address and a little bit of code around the existing code that is used to determine (wrongfully) what the announce address should be?
So "tcp://whatever.example.com, dynamic" to first try your host name and then use discovery if it doesn't work.
I don't see opposition, really. I see people thinking they need this when they really don't, and I see an absence of anyone actually stepping up to implement something reasonable.
Generally most of the "I want to publish this specific hard coded address" wishes can always be solved by just entering that one address as an alternative on the other side.
(I'm not sure this is related but I think it is.)
I have syncthing running in a FreeBSD jail so actually the server il listening to some 10.0.0.1:22000 but it is statically mapped from globalAddress:22000
.
Yet, it gets "discovered" as NAT and it publishes globalAddress:randomPort
.
Which is working, but changes on each restart and seems like a waste to me to not use the "real" 22000 port which is working.
Is it possible to change config.xml
so that Syncthing knows of my manual port mapping and uses the default 22000 port?
That already happens by default. globalAddress:localListeningPort
is announced and tried because that's where any manual port forward would be.