Installation¶
Timing¶
A complete installation of woohoo pDNS GUI will require about 30 minutes to complete for an experienced admin.
This does not include installing woohoo pDNS itself.
Requirements¶
woohoo pDNS GUI is a Python 3 project, therefore you need Python 3 to run it.
Also, (access to) a pDNS database that ouptuts data in Passive DNS - Common Output Format is required. Currently only databases offering API token authentication are supported (not for example the ones _guiusing basic authentication). One option is to use woohoo pDNS.
The Flask webapp is served by Gunicorn. It is strongly suggested to have a reverse proxy (like Nginx, lighttpd, Apache, …) in front of it.
Overview¶
The installation will consist of the following steps:
create a virtual environment (Python 3)
install woohoo pDNS GUI and dependencies
configure access to the pDNS database
set up the configuration in the reverse proxy
configure Gunicorn to serve the GUI
Installing¶
The virtual environment¶
Any way of virtualising the Python environment can be used to run woohoo pDNS
GUI. For this guide we use Python’s integrated venv method.
Caution
woohoo pDNS has pinned it’s dependencies! This means that the exact version
is noted in requirements.txt for all dependencies.
This might have undesired side effects when installing in a non-empty
environment where one of the packages woohoo pDNS depends on is already
installed.
So, go ahead and choose a suitable home for your installation of woohoo pDNS
GUI. For Linux/*BSD systems, something under /usr/local might make sense
(e.g. /usr/local/opt/woohoo-pdns).
Once you have decided on the location and created a folder for woohoo pDNS GUI, create a new virtual environment like this:
$ python -m venv .pdns_gui
This will create a folder named .pdns_gui in the current directory and this
folder will hold your virtual environment of the same name.
Note: on a Mac of mine, creating the virtual environment like this failed with an error like:
Error: Command '['/Users/<username>/tmp/.pdns/bin/python', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1.
which can be fixed by following advice found on Stackoverflow:
$ python -m venv --without-pip .pdns
$ source .pdns_gui/bin/activate
$ curl https://bootstrap.pypa.io/get-pip.py | python
$ deactivate
$ source .pdns_gui/bin/activate
Install woohoo pDNS GUI and dependencies¶
Go ahead and activate the new environment if not already done (your shell prompt should change):
$ source .pdns_gui/bin/activate
You should now populate this new virtual environment with woohoo pDNS GUI and the required dependencies:
(.pdns_gui)$ pip install woohoo-pdns-gui
or install it from source:
(.pdns_gui)$ git clone https://gitlab.com/scherand/woohoo-pdns-gui
(.pdns_gui)$ cd woohoo-pdns-gui
(.pdns_gui)$ python setup.py install
(.pdns_gui)$ pip install -r requirements.txt
Configure access to the pDNS database¶
To properly run the woohoo pDNS GUI, you will have to provide a config file
(python file, i.e. ending in .py) with the following information/format:
TIMEZONE="UTC" # "Europe/Zurich" or "America/New_York"
WOOHOO_APPLICATION_ROOT = ""
SECRET_KEY = "snakeoil"
API_KEY = "MsfPfDqYMQGDc4nVcGTMS8UA"
API_ENTRYPOINT = "http://localhost:5000/api"
The values shown here are the default values that will be used if you do not provide a config file.
A list of all known timezones can be found via pytz.all_timezones.
You can use whatever you like for the SECRET_KEY; it is a Flask thing, see
woohoo_pdns_gui.config.DefaultSettings.SECRET_KEY.
Use the WOOHOO_APPLICATION_ROOT variable if you are running woohoo pDNS
from a subfolder of the vHost.
If you have for example configured your reverse proxy to forward requests for
www.example.com/pdns/ to gunicorn, you should set
WOOHOO_APPLICATION_ROOT to /pdns. This is required that woohoo pDNS GUI
can construct the correct hyperlinks.
Set up the configuration in the reverse proxy¶
Again, the exact steps depend on the reverse proxy software you use and the administrative processes around it. Assuming you have all the required permissions and want to use lighttpd, the configuration should look about as follows:
$HTTP["host"] =~ "^pdns.example.com$" {
$HTTP["url"] =~ "^/" {
proxy.server = ( "" => ( (
"host" => "localhost",
"port" => 5000
) ) )
}
}
Configure Gunicorn to serve the GUI¶
The GUI is served by a Flask application (WSGI application) that lives in
woohoo_pdns_gui.app.py and is served by Gunicorn. To fire it up, you can
use many different ways. For example, a startup script.
Consider using a dedicated user for Gunicorn.
You must provide the name of a config file via an environment variable
called WOOHOO_PDNS_GUI_SETTINGS. This should be the python config file
mentioned earlier. If only a filename is specified, the file is expected to be
in a folder called instance in the directory you are starting flask from.
In general, the path to the config file is interpreted as relative to the
mentioned instance folder.
The following outlines the FreeBSD rc.d script (/usr/local/etc/rc.d/pdns-api-gunicorn)
I use for this purpose (inspired by a thread in the FreeBSD forums):
#! /bin/sh
# PROVIDE: pdns_gui_gunicorn
# REQUIRE: DAEMON
# KEYWORD: shutdown
#
# Add the following lines to /etc/rc.conf to enable the woohoo pDNS GUI:
#
#pdns_gui_gunicorn_enable="YES"
. /etc/rc.subr
name="pdns_gui_gunicorn"
rcvar="${name}_enable"
start_cmd="${name}_start"
stop_cmd="${name}_stop"
pidfile="/var/run/${name}.pid"
procname="daemon:"
gip="localhost"
gport="5000"
pdns_gui_gunicorn_start(){
chdir /usr/local/opt/woohoo-pdns-gui
. /root/.virtualenvs/pdns_gui/bin/activate
LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 FLASK_ENV=production WOOHOO_PDNS_GUI_SETTINGS="pdns_gui_conf.py" daemon -r -S -P ${pidfile} -T pdns-gui-gunicorn -u root /root/.virtualenvs/pdns_gui/bin/gunicorn --workers 3 --bind ${gip}:${gport} "woohoo_pdns.gui:create_app()"
}
pdns_gui_gunicorn_stop(){
if [ -f ${pidfile} ]; then
echo -n "Stopping services: ${name}"
# MUST send TERM signal (not e.g. INT) to work properly with '-P' switch
# check daemon(8) for details
kill -s TERM $(cat ${pidfile})
if [ -f ${gsocket} ]; then
rm -f ${gsocket}
fi
echo "."
else
echo "It appears ${name} is not running."
fi
}
load_rc_config ${name}
# this sets the default 'enable' (to no)
: ${pdns_gui_gunicorn_enable:="no"}
run_rc_command "$1"