Open atfrase opened 2 years ago
I tinkered with this today and hacked together something that seems to work for me so far. Rather than fork and rebuild the entire image I just added an entrypoint
to a custom script (below), so that on container startup it patches parts of the autopause setup and then calls the original /start
entrypoint. Consequently I can't offer you a proper PR for this, but at least the changes are relatively small. :)
First, the script scans any (space-delimited) port numbers in the AUTOPAUSE_TCP_PORTS
and AUTOPAUSE_UDP_PORTS
env vars, and for each one, appends a new section to /autopause/knockd-config.cfg
; that lets me set AUTOPAUSE_TCP_PORTS=8123
so that queries to the Dynmap web server port will wake the java server process.
Next, the script appends /autopause/autopause-fcns.sh
to redefine java_clients_connected()
such that any ESTABLISHED tcp connections on any AUTOPAUSE_TCP_PORTS
as shown in netstat
will be counted as active clients; that prevents the server from pausing so long as someone is actively watching the Dynmap (but if I even switch to another browser tab, those connections promptly disappear and the server starts counting down to pause again). This piece is less important for my use case since even if the server paused while someone was watching Dynmap, the javascript polling in the client's browser would just hit that port and resume the server again right away anyway, but in general there may be use cases that react more poorly to interruptions and would care more about making sure not to pause at all so long as a tcp connection remained established.
#!/bin/bash
: "${AUTOPAUSE_TCP_PORTS:=}"
: "${AUTOPAUSE_UDP_PORTS:=}"
export AUTOPAUSE_TCP_PORTS
export AUTOPAUSE_UDP_PORTS
# add listening ports to the template knockd config
AUTOPAUSE_TCP_PORTS_RE=""
for P in $AUTOPAUSE_TCP_PORTS ; do
if ! [[ $P =~ ^[0-9]+$ ]]; then
log "Warning: ignoring invalid port '$P' in AUTOPAUSE_TCP_PORTS"
else
AUTOPAUSE_TCP_PORTS_RE="$AUTOPAUSE_TCP_PORTS_RE|$P"
cat >> /autopause/knockd-config.cfg <<- EOF
[unpauseMCServer-tcp$P]
sequence = $P:tcp
seq_timeout = 1
command = /autopause/resume.sh
tcpflags = syn
EOF
fi
done
for P in $AUTOPAUSE_UDP_PORTS ; do
if ! [[ $P =~ ^[0-9]+$ ]]; then
log "Warning: ignoring invalid port '$P' in AUTOPAUSE_UDP_PORTS"
else
cat >> /autopause/knockd-config.cfg <<- EOF
[unpauseMCServer-udp$P]
sequence = $P:udp
seq_timeout = 1
command = /autopause/resume.sh
EOF
fi
done
export AUTOPAUSE_TCP_PORTS_RE
# patch the autopause functions to check for additional TCP port connections
cat >> /autopause/autopause-fcns.sh <<- EOF
tcp_clients_connections() {
netstat --numeric --all --tcp | awk '(\$6=="ESTABLISHED" && \$4~":(${AUTOPAUSE_TCP_PORTS_RE:1})\$")' | wc -l
}
java_clients_connected() {
(( \$(java_clients_connections) + \$(tcp_clients_connections) > 0 ))
}
EOF
# call the original container entrypoint
/start $*
Great idea on allowing for runtime building of the config file. I will definitely "borrow" some of the logic you provided 😉
Maybe this helps solve #1630 as well?
Would definitely solve my issue (i opened 1630) with port scanners waking up a paused server that I host for some friends since I could just set AUTOPAUSE_TCP_PORTS=25565,25565,25565,25565
and along with #2003, a custom sequence timeout
Actually, rereading the code block, the above would just create 4 [unpauseMCServer-tcp25565]
blocks
Enhancement Type
Improve an existing feature
Describe the enhancement
Currently, autopause starts with a template
/autopause/knockd-config.cfg
file and then substitutes SERVER_PORT and RCON_PORT in case they've been changed. The config also includes port 19132/udp (the default Bedrock port) just in case someone installs GeyserMC, but if they were to run that on a different port, there's no way for them to make that port change in the knockd config.Some other plugins also add server ports that ought to prevent or resume from pause, such as the Dynmap plugin with its built-in web server, and there's similarly no easy way to add those ports to the
knockd
config so that connections to the map port (8123 by default) wake up the server.To handle both of these cases, I wonder if it would be worth just generating the entire
knockd-config.cfg
file dynamically on startup, by having the container ask docker which ports have been mapped into it and addingknockd
listeners for each one. Anyone who changes a port (such as for GeyserMC), or adds a plugin that needs a new port (such as Dynmap) must necessarily add that port mapping to theirdocker-compose.yml
, so it should suffice forknockd
to just listen on all of those ports (plus RCON).Ideally (but maybe optionally) it would be great to somehow also detect activity on any such additional ports (such as someone watching Dynmap) to prevent server pause even if no players are connected any more. I'm not sure how best to do that, though, and that maybe should have to be explicitly set (i.e. env
AUTOPAUSE_TCP_PORTS
) rather than being automatic for every port mapped to the container.