We are using letsencrypt to get our certificates for the SSL connections. As letsencrypt wants us to renew the certificate at least every 90 days, it would be nice to have a solution for doing that without closing the listener (and dropping all active connections) every time.
I looked at esockd as well as mochiweb if there is any solution for this but didn't found anything.
Any suggestions to make that possible?
Thank you in advance
Just tried a few possible ways to achieve this without touching the code. The most promising and easiest solution I came up with is:
Childs = supervisor:which_children(esockd:listener({'mqtt:ssl',8883})),
[Listener] = lists:filtermap(fun(E) -> case E of {listener,P,_,_} -> {true, P}; _ -> false end end, Childs),
exit(Listener, kill).
Existing connections will not be terminated and all new connections use the new certificate.
However, if I use this solution in a one liner it often crashes the system - not sure whats the problem here but I assume that it could be the asynchronous exit?
It's not the cleanest solution but it works- still hope that it will be implemented a better way where the 'listener' process will be terminated and restarted cleanly.
Best,
baer
After some further investigations I found a pretty simple solution but it needs some additional code in the source. Adding the following code to 'emqttd_app':
restart_listener(ssl, ListenOn) ->
restart_listener({'mqtt:ssl', ListenOn});
restart_listener(wss, ListenOn) ->
restart_listener({'mqtt:wss', ListenOn});
restart_listener(Proto, ListenOn) ->
restart_listener({Proto, ListenOn}).
restart_listener({Protocol, ListenOn}) ->
% get supervisor pid & child specs
ListenerSup = esockd:listener({Protocol, ListenOn}),
{ok, Map} = supervisor:get_childspec(ListenerSup, listener),
% stop and delete old child (cant be simply restart if transient)
supervisor:terminate_child(ListenerSup, listener),
supervisor:delete_child(ListenerSup, listener),
% start child again
supervisor:start_child(ListenerSup, {listener,
maps:get(start, Map),
maps:get(restart, Map), maps:get(shutdown, Map), maps:get(type, Map), maps:get(modules, Map)}).
As well as change the exported functions to:
-export([start_listener/1, stop_listener/1, restart_listener/2]).
This will work on both SSL connections (MQTT and WSS)! 馃
I hope it will find the way into the next release.
Cheers,
baer
@ baer Thanks for your contributions. I will review and merge the fix in next release if it works fine:)
@baer-devl restart_listener working in v2.2-rc.2