My site uses two app server, namely app1 and app2, so in the configuration I have something like this:
upstream cluster {
server app1:8080;
server app2:8080;
}
Since every time I update the code I need to restart both server processes and I want the service undisturbed, I will follow these steps manually:
Comment app1
within upstream block so to modify it into:
upstream cluster {
#server app1:8080;
server app2:8080;
}
Run nginx -s reload
Update code at app1
and restart the server program, and then uncomment app1
in upstream block
Do steps 1-3 for app2
I wish to write a script to spare this tedious work, so what I hope to do is this:
Have a folder named "available" which contains app1.conf
and app2.conf
in form as
server app1:8080;
Have another folder named "enabled" to contain the soft links of app1.conf
and app2.conf
Modify the upstream cluster into
upstream cluster {
include /usr/local/nginx/conf/enabled/*;
}
So every time I need to disable any app server I can just remove the corresponding soft link from the "enabled" folder, and later can restore it by running ln -s
However this approach didn't work well as I got an error message from nginx saying:
[emerg]: "include" directive is not allowed here in ....
Is that so include
cannot not be put into the upstream block? and I'd imagine I'm not alone in this kind of scenario, disabling and enabling server at times, how other folks normally deal with it?
Unfortunately, nginx can't handle include directive inside upstream,.
But you can use this script to manage your upstream servers:
somewhere in http section of nginx.conf:
include /usr/local/nginx/conf/upstream.conf
create empty file:
touch /usr/local/nginx/conf/upstream.conf
use this script to manage upstream servers(upstreamctl.sh):
#!/bin/bash
if [ -n "$1" -a -n "$2" ]; then
action="$1";
target="$2";
else
echo "Usage: $0 (add|rm) server:port"
exit 0;
fi;
# Path to nginx binary
BIN="/usr/local/nginx/sbin/nginx"
# Path to upstream config file
CONF="/usr/local/nginx/conf/upstream.conf"
SERVERS=`cat $CONF | grep server`
output="upstream cluster {"
if [ $action == "add" ]; then
echo -e "$output" > $CONF
if $( echo $SERVERS | grep --quiet $target ); then
echo "Warning: Server is already enabled."
else
SERVERS="$SERVERS\n\tserver $target;"
fi
echo -e "$SERVERS" >> $CONF
echo "}" >> $CONF
elif [ $action == "rm" ]; then
sed -i "/$target/d" $CONF
else
echo "Unknown action"
fi
# Check changes:
$BIN -t
In your case you may run:
./upstreamctl.sh add app1:8080
and
./upstreamctl.sh rm app2:8080
Just putting this here in case we can help others:
Include directive can be used in upstream block in later versions of nginx.
Example:
/etc/nginx/upstream.conf
server ip:port;
server ip:port;
/etc/nginx/conf.d/default.conf
upstream cluster {
include /etc/nginx/upstream.conf;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://cluster;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}