If you don't mind a few small advices:
don't use global variables that you mutate, prefer structs with methods.
Add a main context with signal.NotifyContext to globally handle sigkill/sigterm and have a gracefull shutdown. Also use DialContext when available instead of Dial.
You could use errGroup to handle multiple goroutines that return errors (rather than iterating on a channel).
Otherwise it looks good, great job !