I often wondered, whilst typing the full phrase, ln -s /etc/nginx/sites… to enable a site and undoubtedly getting them the wrong way around, “Surely there must be a better way?”

Of course, Apache has a2ensite, which can be quite easily replicated in a bash script.

After a quick Google to a Server Fault question (like Stack Overflow, but for server-peeps), I stumbled across a script that goes one better.

Called nginx-modsite, it provides a full suite of tools to list enabled sites, available sites, and enable/disable those sites.

Installation

First, download the version you need from GitHub:

  • ubuntu is for Ubuntu and Debian-based distros.
  • homebrew is for macOS pros.
  • main is for everything else (based on Linux) that might work.

Installation is fairly straightforward on *nix (Linux and Unix-type, including macOS) machines. The bash script simply needs to be saved in /usr/local/bin, as nginx-modsite, or anything easier for you to remember (provided the name doesn’t clash with an existing command).

The file then needs to be made executable, with sudo chmod +=x.

Usage

Using the command nginx-modsite, or whatever you named the script file on install, you have a few options:

  • -l lists all available and enabled sites.
  • -e SITE enables the site SITE.
  • -d SITE disables the site SITE
  • -r reloads the Nginx server, for when you have manually edited config files.
  • -h displays help.

If you miss out the SITE, you will be presented with a number of options:

root@ajsalkeld:/etc/nginx# nginx-modsite -e
SELECT A WEBSITE:
0:	example
1:	another-example
Enter number for website:

Then, just hit the number of the one you want, and enter.

After enabling/disabling a site, the script will ask you if you want to reload Nginx now, or you fancy doing it manually later.

Quite simple, really, and far more powerful and feature filled than a2ensite.

How does it work, then?

Again, quite simple, really.

The bash file is simply a list of functions, which can read the sites-available and sites-enabled folders, make links from sites-available to sites-enabled with ln -sf, and remove them.

You can, of course, read the latest script on the repo at GitHub, but I have included the script below, though this may become out of date:

##
# Default Settings
##

NGINX_CONF_FILE="$(awk -F= -v RS=' ' '/conf-path/ {print $2}' <<< $(nginx -V 2>&1))"
NGINX_CONF_DIR="${NGINX_CONF_FILE%/*}"
NGINX_SITES_AVAILABLE="$NGINX_CONF_DIR/sites-available"
NGINX_SITES_ENABLED="$NGINX_CONF_DIR/sites-enabled"
SELECTED_SITE="$2"

##
# Script Functions
##

ngx_enable_site() {
	[[ ! "$SELECTED_SITE" ]] &&
		ngx_select_site "not_enabled"

	[[ ! -e "$NGINX_SITES_AVAILABLE/$SELECTED_SITE" ]] &&
		ngx_error "Site does not appear to exist."
	[[ -e "$NGINX_SITES_ENABLED/$SELECTED_SITE" ]] &&
		ngx_error "Site appears to already be enabled"

	ln -sf "$NGINX_SITES_AVAILABLE/$SELECTED_SITE" "$NGINX_SITES_ENABLED/$SELECTED_SITE"
	ngx_reload
}

ngx_disable_site() {
	[[ ! "$SELECTED_SITE" ]] &&
		ngx_select_site "is_enabled"

	[[ ! -e "$NGINX_SITES_AVAILABLE/$SELECTED_SITE" ]] &&
		ngx_error "Site does not appear to be \'available\'. - Not Removing"
	[[ ! -e "$NGINX_SITES_ENABLED/$SELECTED_SITE" ]] &&
		ngx_error "Site does not appear to be enabled."

	rm -f "$NGINX_SITES_ENABLED/$SELECTED_SITE"
	ngx_reload
}

ngx_list_site() {
	echo "Available sites:"
	ngx_sites "available"
	echo "Enabled Sites"
	ngx_sites "enabled"
}

##
# Helper Functions
##

ngx_select_site() {
	sites_avail=($NGINX_SITES_AVAILABLE/*)
	sa="${sites_avail[@]##*/}"
	sites_en=($NGINX_SITES_ENABLED/*)
	se="${sites_en[@]##*/}"

	case "$1" in
		not_enabled) sites=$(comm -13 <(printf "%s\n" $se) <(printf "%s\n" $sa));;
		is_enabled) sites=$(comm -12 <(printf "%s\n" $se) <(printf "%s\n" $sa));;
	esac

	ngx_prompt "$sites"
}

ngx_prompt() {
	sites=($1)
	i=0

	echo "SELECT A WEBSITE:"
	for site in ${sites[@]}; do
		echo -e "$i:\t${sites[$i]}"
		((i++))
	done

	read -p "Enter number for website: " i
	SELECTED_SITE="${sites[$i]}"
}

ngx_sites() {
	case "$1" in
		available) dir="$NGINX_SITES_AVAILABLE";;
		enabled) dir="$NGINX_SITES_ENABLED";;
	esac

	for file in $dir/*; do
		echo -e "\t${file#*$dir/}"
	done
}

ngx_reload() {
	read -p "Would you like to reload the Nginx configuration now? (Y/n) " reload
    [[ "$reload" != "n" && "$reload" != "N" ]] && invoke-rc.d nginx reload
}

ngx_reload_now() {
	invoke-rc.d nginx reload
}

ngx_error() {
	echo -e "${0##*/}: ERROR: $1"
	[[ "$2" ]] && ngx_help
	exit 1
}

ngx_help() {
	echo "Usage: ${0##*/} [options]"
	echo "Options:"
	echo -e "\t<-e|--enable> <site>\tEnable site"
	echo -e "\t<-d|--disable> <site>\tDisable site"
	echo -e "\t<-l|--list>\t\tList sites"
	echo -e "\t<-h|--help>\t\tDisplay help"
	echo -e "\n\tIf <site> is left out a selection of options will be presented."
	echo -e "\tIt is assumed you are using the default sites-enabled and"
	echo -e "\tsites-disabled located at $NGINX_CONF_DIR."
}

##
# Core Piece
##

case "$1" in
	-e|--enable)	ngx_enable_site;;
	-d|--disable)	ngx_disable_site;;
	-r|--reload) ngx_reload_now;;
	-l|--list)	ngx_list_site;;
	-h|--help)	ngx_help;;
	*)		ngx_error "No Options Selected" 1; ngx_help;;
esac

Cool! Who wrote it?

Not me. A guy called “Michael Lustfield” is named in the confusing copyright bit, but pyghassen is the original GitHubber.

Then, gabrielwolf ported it for Homebrew on macOS, and made a few improvements.

What I’ve done is add the option -r (about 2 lines’ work), ported the code back to Linux (about one line’s work), changed the name from nginx_modsite to nginx-modsite because I think it works better, and provided branches for Ubuntu and Homebrew.

View on GitHub!