← Back to team overview

nagios-charmers team mailing list archive

[Merge] ~woutervb/nagios-charm:master into nagios-charm:master

 

Wouter van Bommel has proposed merging ~woutervb/nagios-charm:master into nagios-charm:master.

Requested reviews:
  Nagios Charm developers (nagios-charmers)

For more details, see:
https://code.launchpad.net/~woutervb/nagios-charm/+git/nagios-charm/+merge/364255
-- 
Your team Nagios Charm developers is requested to review the proposed merge of ~woutervb/nagios-charm:master into nagios-charm:master.
diff --git a/.gitignore b/.gitignore
index e650362..bc3c250 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+<<<<<<< .gitignore
 *.pyc
 *.swp
 *~
@@ -6,3 +7,24 @@ data/*.pem
 data/*.key
 data/*.crt
 data/*.csr
+=======
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# Log files
+*.log
+
+.tox/
+.coverage
+
+# vi
+.*.swp
+
+# pycharm
+.idea/
+
+# version data
+src/repo-info
+>>>>>>> .gitignore
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..55d5325
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,15 @@
+[submodule "layers/layer-basic"]
+    path = layers/layer-basic
+    url = https://github.com/juju-solutions/layer-basic.git
+[submodule "layers/layer-options"]
+    path = layers/layer-options
+    url = https://github.com/juju-solutions/layer-options.git
+[submodule "layers/juju-info"]
+    path = layers/juju-info
+    url = https://github.com/juju-solutions/interface-juju-info.git
+[submodule "layers/http"]
+    path = layers/http
+    url = https://github.com/juju-solutions/interface-http.git
+[submodule "src/lib/pynag"]
+    path = src/lib/pynag
+    url = https://github.com/netmarkjp/pynag.git
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..af325b6
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,49 @@
+repos:
+-   repo: git://github.com/pre-commit/pre-commit-hooks
+    rev: v2.1.0
+    hooks:
+    -   id: trailing-whitespace
+        exclude: cherrypy/test/static/index.html
+    -   id: flake8
+        args:
+        # W503 ignored for https://github.com/PyCQA/pycodestyle/issues/498
+        - --ignore=W503
+        # E126 ignored, as yapf will give better identation
+        - --ignore=E126
+    -   id: check-merge-conflict
+    -   id: double-quote-string-fixer
+    -   id: end-of-file-fixer
+    -   id: name-tests-test
+    -   id: check-ast
+    -   id: check-added-large-files
+    -   id: check-byte-order-marker
+    -   id: check-case-conflict
+    -   id: check-json
+#        include: .mention-bot
+    -   id: pretty-format-json
+    -   id: check-symlinks
+    -   id: check-yaml
+    -   id: detect-private-key
+#        exclude: cherrypy/test/test.pem
+    - id: requirements-txt-fixer
+
+
+-   repo: git://github.com/Lucas-C/pre-commit-hooks
+    rev: v1.1.6
+    hooks:
+    - id: remove-tabs
+
+- repo: https://github.com/pre-commit/mirrors-yapf
+  rev: v0.26.0  # Use the sha / tag you want to point at
+  hooks:
+    - id: yapf
+
+- repo: https://github.com/pre-commit/mirrors-isort
+  rev: v4.3.12  # Use the sha / tag you want to point at
+  hooks:
+    - id: isort
+
+- repo: git://github.com/FalconSocial/pre-commit-mirrors-pep257
+  rev: v0.3.3
+  hooks:
+    - id: pep257
diff --git a/Makefile b/Makefile
index 9d48829..8ff24e5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,4 @@
+<<<<<<< Makefile
 #!/usr/bin/make
 PYTHON := /usr/bin/python3
 export PYTHONPATH := hooks
@@ -26,3 +27,55 @@ sync: bin/charm_helpers_sync.py
 	@$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers.yaml
 
 
+=======
+ifndef JUJU_REPOSITORY
+    JUJU_REPOSITORY := $(shell pwd)
+    $(warning Warning JUJU_REPOSITORY was not set, defaulting to $(JUJU_REPOSITORY))
+endif
+
+help:
+	@echo "This project supports the following targets"
+	@echo ""
+	@echo " make help - show this text"
+	@echo " make submodules - make sure that the submodules are up-to-date"
+	@echo " make lint - run flake8"
+	@echo " make test - run the unittests and lint"
+	@echo " make unittest - run the tests defined in the unittest subdirectory"
+	@echo " make functional - run the tests defined in the functional subdirectory"
+	@echo " make release - build the charm"
+	@echo " make clean - remove unneeded files"
+	@echo ""
+
+submodules:
+	@echo "Cloning submodules"
+	@git submodule update --init --recursive
+
+lint:
+	@echo "Running flake8"
+	@cd src && tox -e lint
+
+test: unittest functional lint
+
+unittest:
+	@cd src && tox -e unit
+
+functional: build
+	@cd src && tox -e functional
+
+build:
+	@echo "Building charm to base directory $(JUJU_REPOSITORY)"
+	@-git describe --tags > ./src/repo-info
+	@CHARM_LAYERS_DIR=./layers CHARM_INTERFACES_DIR=./interfaces TERM=linux\
+		JUJU_REPOSITORY=$(JUJU_REPOSITORY) charm build ./src --force
+
+release: clean build
+	@echo "Charm is built at $(JUJU_REPOSITORY)/builds"
+
+clean:
+	@echo "Cleaning files"
+	@if [ -d src/.tox ] ; then rm -r src/.tox ; fi
+	@if [ -d src/.pytest_cache ] ; then rm -r src/.pytest_cache ; fi
+
+# The targets below don't depend on a file
+.PHONY: lint test unittest functional build release clean help submodules
+>>>>>>> Makefile
diff --git a/interfaces/.empty b/interfaces/.empty
new file mode 100644
index 0000000..792d600
--- /dev/null
+++ b/interfaces/.empty
@@ -0,0 +1 @@
+#
diff --git a/interfaces/monitors/interface.yaml b/interfaces/monitors/interface.yaml
new file mode 100644
index 0000000..01e3d25
--- /dev/null
+++ b/interfaces/monitors/interface.yaml
@@ -0,0 +1,3 @@
+name: monitors
+summary: Monitoring link
+version: 1
diff --git a/interfaces/monitors/requires.py b/interfaces/monitors/requires.py
new file mode 100644
index 0000000..807d9b3
--- /dev/null
+++ b/interfaces/monitors/requires.py
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import yaml
+from charmhelpers.core import hookenv
+from charms.reactive import RelationBase, hook, scopes
+
+
+class MonitorsClient(RelationBase):
+    scope = scopes.GLOBAL
+
+    auto_accessors = ['private_address']
+
+    @hook('{requires:monitors}-relation-{joined,changed}')
+    def changed(self):
+        self.set_state('{relation_name}.connected')
+        if self.private_address():
+            self.set_state('{relation_name}.available')
+
+    @hook('{requires:monitors}-relation-{broken, departed}')
+    def broken(self):
+        self.remove_state('{relation_name}.available')
+        self.remove_state('{relation_name}.connected')
+
+    def monitors(self):
+        """
+        Returns dict containing the information about the host to monitor, the how and the what parts.
+
+        {
+            'monitors':
+                {
+                    'remote': {}
+                }
+        }
+
+        """
+        monitors = self.get_remote('monitors')
+        if monitors is not type(dict):
+            monitors = yaml.safe_load(monitors)
+
+        return monitors
diff --git a/layers/.empty b/layers/.empty
new file mode 100644
index 0000000..792d600
--- /dev/null
+++ b/layers/.empty
@@ -0,0 +1 @@
+#
diff --git a/layers/http b/layers/http
new file mode 160000
index 0000000..0614445
--- /dev/null
+++ b/layers/http
@@ -0,0 +1 @@
+Subproject commit 0614445f60f11422cc1bb36bdb2f4a87d2c3d0bc
diff --git a/layers/juju-info b/layers/juju-info
new file mode 160000
index 0000000..8495c8d
--- /dev/null
+++ b/layers/juju-info
@@ -0,0 +1 @@
+Subproject commit 8495c8d5e183ee57dffee939aefe92e246d5186b
diff --git a/layers/layer-basic b/layers/layer-basic
new file mode 160000
index 0000000..871cdfa
--- /dev/null
+++ b/layers/layer-basic
@@ -0,0 +1 @@
+Subproject commit 871cdfa33f120181f6267be2db5712984c760721
diff --git a/layers/layer-options b/layers/layer-options
new file mode 160000
index 0000000..fcdcea4
--- /dev/null
+++ b/layers/layer-options
@@ -0,0 +1 @@
+Subproject commit fcdcea4e5de3e1556c24e6704607862d0ba00a56
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..cbd8b5c
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,30 @@
+help:
+	@echo "This project supports the following targets"
+	@echo ""
+	@echo " make help - show this text"
+	@echo " make lint - run flake8"
+	@echo " make test - run the functional test and unittests"
+	@echo " make unittest - run the the unittest"
+	@echo " make functionaltest - run the functional tests"
+	@echo " make clean - remove unneeded files"
+	@echo ""
+
+lint:
+	@echo "Running flake8"
+	@tox -e lint
+
+test: unittest functionaltest lint
+
+unittest:
+	@tox -e unit
+
+functionaltest:
+	@tox -e functional
+
+clean:
+	@echo "Cleaning files"
+	@if [ -d ./.tox ] ; then rm -r ./.tox ; fi
+	@if [ -d ./.pytest_cache ] ; then rm -r ./.pytest_cache ; fi
+
+# The targets below don't depend on a file
+.PHONY: lint test unittest functionaltest clean help
diff --git a/src/actions.yaml b/src/actions.yaml
new file mode 100644
index 0000000..f1b2535
--- /dev/null
+++ b/src/actions.yaml
@@ -0,0 +1,2 @@
+example-action:
+  description: "This is just a test"
diff --git a/src/actions/example-action b/src/actions/example-action
new file mode 100755
index 0000000..459e59e
--- /dev/null
+++ b/src/actions/example-action
@@ -0,0 +1,6 @@
+#!/usr/local/sbin/charm-env python3
+
+from lib_nagios_charm import NagioscharmHelper
+
+helper = NagioscharmHelper()
+helper.action_function()
diff --git a/src/config.yaml b/src/config.yaml
new file mode 100644
index 0000000..23f0a59
--- /dev/null
+++ b/src/config.yaml
@@ -0,0 +1,186 @@
+options:
+    extraconfig:
+        type: string
+        default: ""
+        description: |
+            Any additional nagios configuration you would like to
+            add can be set into this element. It will be placed in
+            /etc/nagios3/conf.d/extra.cfg
+    ssl:
+        type: string
+        default: "off"
+        description: |
+            Enable SSL communication for Nagios. Possible values are
+            "on", "off", or "only". The "only" option disables
+            All HTTP communication in favor of HTTPS - may play havok with
+            existing nagios deployments.
+    ssl_cert:
+        type: string
+        default: None
+        description: |
+            base64 encoded server certificate.  If left blank, the certificate
+            and key will be autogenerated as self-signed.
+        default: ''
+    ssl_key:
+        type: string
+        default: None
+        description: |
+            base64 encoded server certificate key.  If ssl_cert is
+            blank, this is ignored.
+        default: ''
+    ssl_chain:
+        type: string
+        default: ''
+        description: |
+            base64 encoded chain certificates file.  If ssl_cert is
+            blank, this will be ignored.
+    enable_livestatus:
+        type: boolean
+        default: false
+        description: |
+            Config variable to enable livestatus module or not.
+    livestatus_path:
+        type: string
+        default: "/var/lib/nagios3/livestatus/socket"
+        description: |
+            Default path to livestatus socket, if enabled via enable_livestatus
+    livestatus_args:
+        type: string
+        default: ""
+        description: |
+            Arguments to be passed to the livestatus module, defaults to empty.
+    nagios_user:
+        type: string
+        default: nagios
+        description: |
+            The effective user that nagios will run as.
+    nagios_group:
+        type: string
+        default: nagios
+        description: |
+            The effective group that nagios will run as.
+    check_external_commands:
+        type: int
+        default: 1
+        description: |
+            Config variable to enable checking external commands - 0 is disable, 1 is enable.
+    command_check_interval:
+        type: string
+        default: "-1"
+        description: |
+            How often to check for external commands.
+    command_file:
+        type: string
+        default: /var/lib/nagios3/rw/nagios.cmd
+        description: |
+            File that Nagios checks for external command requests.
+    debug_level:
+        type: int
+        default: 0
+        description: |
+            Specify the debug level for nagios.  See the docs for more details.
+    debug_verbosity:
+        type: int
+        default: 1
+        description: |
+            How verbose will the debug logs be - 0 is brief, 1 is more detailed
+            and 2 is very detailed.
+    debug_file:
+        type: string
+        default: "/var/log/nagios3/nagios.debug"
+        description: |
+            Path for the debug file.
+    daemon_dumps_core:
+        type: int
+        default: 0
+        description:
+            Option to determine if Nagios is allowed to create a core dump.
+    admin_email:
+        type: string
+        default: root@localhost
+        description: |
+            Email address used for the admin, used by $ADMINEMAIL$ in notification
+            commands.
+    admin_pager:
+        type: string
+        default: pageroot@localhost
+        description: |
+            Email address used for the admin pager, used by $ADMINPAGER$ in
+            notification commands.
+    enable_pagerduty:
+        type: boolean
+        default: false
+        description: |
+            Config variable to enable pagerduty notifications or not.
+    pagerduty_key:
+        type: string
+        default: ""
+        description: |
+            Pagerduty API key to use for notifications
+    pagerduty_path:
+        type: string
+        default: "/var/lib/nagios3/pagerduty"
+        description: |
+            Path for Pagerduty notifications to be queued.
+    log_rotation_method:
+        type: string
+        default: "d"
+        description: |
+            Log rotation method that Nagios should use to rotate the main logfile.
+    log_archive_path:
+        type: string
+        default: "/var/log/nagios3/archives"
+        description: |
+            Path for archived log files
+    use_syslog:
+        type: int
+        default: 1
+        description: |
+            Log messages to syslog as well as main file.
+    password:
+        type: string
+        default: '/var/lib/juju/nagios.passwd'
+        description: |
+            Password to use for Nagios administrative access.  If not
+            provided, a password will be generated (see documentation for
+            instructions on retrieving the generated password.)
+    ro-password:
+        type: string
+        default: ''
+        description: |
+            Password to use for read-only Nagios access.  If left blank, the nagiosro account will not be created.
+    monitor_self:
+        type: boolean
+        default: true
+        description: |
+            If true, enable monitoring of the nagios unit itself.
+    nagios_host_context:
+        default: "juju"
+        type: string
+        description: |
+            a string that will be prepended to instance name to set the host name
+            in nagios. So for instance the hostname would be something like:
+                juju-postgresql-0
+            If you're running multiple environments with the same services in them
+            this allows you to differentiate between them.
+    load_monitor:
+        default: '5.0!4.0!3.0!10.0!6.0!4.0'
+        type: string
+        description: |
+            A string to pass to the Nagios load monitoring command.  Default is
+            to report warning at 5.0, 4.0 and 3.0 averages, critical at 10.0,
+            6.0 and 4.0.
+    pagerduty_notification_levels:
+        default: w,u,c,r
+        type: string
+        description: |
+            A string to use for the service_notification_options in the
+            pagerduty contact configuration.  Remove w to avoid paging for
+            warning events.
+    check_timeout:
+        default: 10
+        type: int
+        description: |
+            A number of seconds before nrpe checks timeout from not being able
+            to connect to the client or finish execution of the command.
+            Raise this value to combat 'CHECK_NRPE Socket timeout alerts'
diff --git a/src/files/pagerduty_nagios.pl b/src/files/pagerduty_nagios.pl
new file mode 100755
index 0000000..afd18be
--- /dev/null
+++ b/src/files/pagerduty_nagios.pl
@@ -0,0 +1,289 @@
+#!/usr/bin/env perl
+
+
+# Nagios plugin that sends Nagios events to PagerDuty.
+#
+# Copyright (c) 2011, PagerDuty, Inc. <info@xxxxxxxxxxxxx>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in the
+#       documentation and/or other materials provided with the distribution.
+#     * Neither the name of PagerDuty Inc nor the
+#       names of its contributors may be used to endorse or promote products
+#       derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL PAGERDUTY INC BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+use Pod::Usage;
+use Getopt::Long;
+use Sys::Syslog;
+use HTTP::Request::Common qw(POST);
+use HTTP::Status qw(is_client_error);
+use LWP::UserAgent;
+use File::Path;
+use Fcntl qw(:flock);
+
+
+=head1 NAME
+
+pagerduty_nagios -- Send Nagios events to the PagerDuty alert system
+
+=head1 SYNOPSIS
+
+pagerduty_nagios enqueue [options]
+
+pagerduty_nagios flush [options]
+
+=head1 DESCRIPTION
+
+  This script passes events from Nagios to the PagerDuty alert system. It's
+  meant to be run as a Nagios notification plugin. For more details, please see
+  the PagerDuty Nagios integration docs at:
+  http://www.pagerduty.com/docs/nagios-integration.
+
+  When called in the "enqueue" mode, the script loads a Nagios notification out
+  of the environment and into the event queue.  It then tries to flush the
+  queue by sending any enqueued events to the PagerDuty server.  The script is
+  typically invoked in this mode from a Nagios notification handler.
+
+  When called in the "flush" mode, the script simply tries to send any enqueued
+  events to the PagerDuty server.  This mode is typically invoked by cron.  The
+  purpose of this mode is to retry any events that couldn't be sent to the
+  PagerDuty server for whatever reason when they were initially enqueued.
+
+=head1 OPTIONS
+
+  --api-base URL
+    The base URL used to communicate with PagerDuty.  The default option here
+    should be fine, but adjusting it may make sense if your firewall doesn't
+    pass HTTPS traffic for some reason.  See the PagerDuty Nagios integration
+    docs for details.
+
+  --field KEY=VALUE
+    Add this key-value pair to the event being passed to PagerDuty.  The script
+    automatically gathers Nagios macros out of the environment, so there's no
+    need to specify these explicitly.  This option can be repeated as many
+    times as necessary to pass multiple key-value pairs.  This option is only
+    useful when an event is being enqueued.0
+
+  --help
+    Display documentation for the script.
+
+  --queue-dir DIR
+    Path to the directory to use to store the event queue.  By default, we use
+    /tmp/pagerduty_nagios.
+
+  --verbose
+    Turn on extra debugging information.  Useful for debugging.
+
+  --proxy
+    Use a proxy for the connections like "--proxy http://127.0.0.1:8888/";
+
+=cut
+
+# This release tested on:
+# Debian Sarge (Perl 5.8.4)
+# Ubuntu 9.04  (Perl 5.10.0)
+
+my $opt_api_base = "https://events.pagerduty.com/nagios/2010-04-15";;
+my %opt_fields;
+my $opt_help;
+my $opt_queue_dir = "/tmp/pagerduty_nagios";
+my $opt_verbose;
+my $opt_proxy;
+
+
+sub get_queue_from_dir {
+    my $dh;
+
+    unless (opendir($dh, $opt_queue_dir)) {
+        syslog(LOG_ERR, "opendir %s failed: %s", $opt_queue_dir, $!);
+        die $!;
+    }
+
+    my @files;
+    while (my $f = readdir($dh)) {
+        next unless $f =~ /^pd_(\d+)_\d+\.txt$/;
+        push @files, [int($1), $f];
+    }
+
+    closedir($dh);
+
+    @files = sort { @{$a}[0] <=> @{$b}[0] } @files;
+    return map { @{$_}[1] } @files;
+}
+
+
+sub flush_queue {
+    my @files = get_queue_from_dir();
+    my $ua = LWP::UserAgent->new;
+
+    # It's not a big deal if we don't get the message through the first time.
+    # It will get sent the next time cron fires.
+    $ua->timeout(15);
+
+    if ($opt_proxy) {
+        $ua->proxy (['http', 'https'], $opt_proxy);
+    }
+
+    foreach (@files) {
+        my $filename = "$opt_queue_dir/$_";
+        my $fd;
+        my %event;
+
+        print STDERR "==== Now processing: $filename\n" if $opt_verbose;
+
+        unless (open($fd, "<", $filename)) {
+            syslog(LOG_ERR, "open %s for read failed: %s", $filename, $!);
+            die $!;
+        }
+
+        while (<$fd>) {
+            chomp;
+            my @fields = split("=", $_, 2);
+            $event{$fields[0]} = $fields[1];
+        }
+
+        close($fd);
+
+        my $req = POST("$opt_api_base/create_event", \%event);
+
+        if ($opt_verbose) {
+            my $s = $req->as_string;
+            print STDERR "Request:\n$s\n";
+        }
+
+        my $resp = $ua->request($req);
+
+        if ($opt_verbose) {
+            my $s = $resp->as_string;
+            print STDERR "Response:\n$s\n";
+        }
+
+        if ($resp->is_success) {
+            syslog(LOG_INFO, "Nagios event in file %s ACCEPTED by the PagerDuty server.", $filename);
+            unlink($filename);
+        }
+        elsif (is_client_error($resp->code)) {
+            syslog(LOG_WARNING, "Nagios event in file %s REJECTED by the PagerDuty server.  Server says: %s", $filename, $resp->content);
+            unlink($filename) if ($resp->content !~ /retry later/);
+        }
+        else {
+            # Something else went wrong.
+            syslog(LOG_WARNING, "Nagios event in file %s DEFERRED due to network/server problems.", $filename);
+            return 0;
+        }
+    }
+
+    # Everything that needed to be sent was sent.
+    return 1;
+}
+
+
+sub lock_and_flush_queue {
+    # Serialize access to the queue directory while we flush.
+    # (We don't want more than one flush at once.)
+
+    my $lock_filename = "$opt_queue_dir/lockfile";
+    my $lock_fd;
+
+    unless (open($lock_fd, ">", $lock_filename)) {
+        syslog(LOG_ERR, "open %s for write failed: %s", $lock_filename, $!);
+        die $!;
+    }
+
+    unless (flock($lock_fd, LOCK_EX)) {
+        syslog(LOG_ERR, "flock %s failed: %s", $lock_filename, $!);
+        die $!;
+    }
+
+    my $ret = flush_queue();
+
+    close($lock_fd);
+
+    return $ret;
+}
+
+
+sub enqueue_event {
+    my %event;
+
+    # Scoop all the Nagios related stuff out of the environment.
+    while ((my $k, my $v) = each %ENV) {
+        next unless $k =~ /^(ICINGA|NAGIOS)_(.*)$/;
+        $event{$2} = $v;
+    }
+
+    # Apply any other variables that were passed in.
+    %event = (%event, %opt_fields);
+
+    $event{"pd_version"} = "1.0";
+
+    # Right off the bat, enqueue the event.  Nothing tiem consuming should come
+    # before here (i.e. no locks or remote connections), because we want to
+    # make sure we get the event written out within the Nagios notification
+    # timeout.  If we get killed off after that, it isn't a big deal.
+
+    my $filename = sprintf("$opt_queue_dir/pd_%u_%u.txt", time(), $$);
+    my $fd;
+
+    unless (open($fd, ">", $filename)) {
+        syslog(LOG_ERR, "open %s for write failed: %s", $filename, $!);
+        die $!;
+    }
+
+    while ((my $k, my $v) = each %event) {
+        # "=" can't occur in the keyname, and "\n" can't occur anywhere.
+        # (Nagios follows this already, so I think we're safe)
+        print $fd "$k=$v\n";
+    }
+
+    close($fd);
+}
+
+###########
+
+GetOptions("api-base=s" => \$opt_api_base,
+           "field=s%" => \%opt_fields,
+           "help" => \$opt_help,
+           "queue-dir=s" => \$opt_queue_dir,
+           "verbose" => \$opt_verbose,
+           "proxy=s" => \$opt_proxy
+          ) || pod2usage(2);
+
+pod2usage(2) if @ARGV < 1 ||
+     (($ARGV[0] ne "enqueue") && ($ARGV[0] ne "flush"));
+
+pod2usage(-verbose => 3) if $opt_help;
+
+my @log_mode = ("nofatal", "pid");
+push(@log_mode, "perror") if $opt_verbose;
+
+openlog("pagerduty_nagios", join(",", @log_mode), LOG_LOCAL0);
+
+# This function automatically terminates the program on things like permission
+# errors.
+mkpath($opt_queue_dir);
+
+if ($ARGV[0] eq "enqueue") {
+    enqueue_event();
+    lock_and_flush_queue();
+}
+elsif ($ARGV[0] eq "flush") {
+    lock_and_flush_queue();
+}
diff --git a/src/icon.svg b/src/icon.svg
new file mode 100644
index 0000000..bcf3595
--- /dev/null
+++ b/src/icon.svg
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg xmlns:dc="http://purl.org/dc/elements/1.1/"; xmlns:cc="http://creativecommons.org/ns#"; xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"; xmlns:svg="http://www.w3.org/2000/svg"; xmlns="http://www.w3.org/2000/svg"; xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"; xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"; width="96" height="96" id="svg6517" version="1.1" inkscape:version="0.91+devel r" sodipodi:docname="nagios01.svg" viewBox="0 0 96 96">
+  <defs id="defs6519">
+    <filter style="color-interpolation-filters:sRGB" inkscape:label="Inner Shadow" id="filter1121">
+      <feFlood flood-opacity="0.59999999999999998" flood-color="rgb(0,0,0)" result="flood" id="feFlood1123"/>
+      <feComposite in="flood" in2="SourceGraphic" operator="out" result="composite1" id="feComposite1125"/>
+      <feGaussianBlur in="composite1" stdDeviation="1" result="blur" id="feGaussianBlur1127"/>
+      <feOffset dx="0" dy="2" result="offset" id="feOffset1129"/>
+      <feComposite in="offset" in2="SourceGraphic" operator="atop" result="composite2" id="feComposite1131"/>
+    </filter>
+    <filter style="color-interpolation-filters:sRGB" inkscape:label="Drop Shadow" id="filter950">
+      <feFlood flood-opacity="0.25" flood-color="rgb(0,0,0)" result="flood" id="feFlood952"/>
+      <feComposite in="flood" in2="SourceGraphic" operator="in" result="composite1" id="feComposite954"/>
+      <feGaussianBlur in="composite1" stdDeviation="1" result="blur" id="feGaussianBlur956"/>
+      <feOffset dx="0" dy="1" result="offset" id="feOffset958"/>
+      <feComposite in="SourceGraphic" in2="offset" operator="over" result="composite2" id="feComposite960"/>
+    </filter>
+    <linearGradient id="Background">
+      <stop id="stop4178" offset="0" style="stop-color:#22779e;stop-opacity:1"/>
+      <stop id="stop4180" offset="1" style="stop-color:#2991c0;stop-opacity:1"/>
+    </linearGradient>
+    <clipPath clipPathUnits="userSpaceOnUse" id="clipPath873">
+      <g transform="matrix(0,-0.66666667,0.66604479,0,-258.25992,677.00001)" id="g875" inkscape:label="Layer 1" style="display:inline;fill:#ff00ff;fill-opacity:1;stroke:none">
+        <path style="display:inline;fill:#ff00ff;fill-opacity:1;stroke:none" d="M 46.702703,898.22775 H 97.297297 C 138.16216,898.22775 144,904.06497 144,944.92583 v 50.73846 c 0,40.86071 -5.83784,46.69791 -46.702703,46.69791 H 46.702703 C 5.8378378,1042.3622 0,1036.525 0,995.66429 v -50.73846 c 0,-40.86086 5.8378378,-46.69808 46.702703,-46.69808 z" id="path877" inkscape:connector-curvature="0" sodipodi:nodetypes="sssssssss"/>
+      </g>
+    </clipPath>
+    <style id="style867" type="text/css"><![CDATA[
+    .fil0 {fill:#1F1A17}
+   ]]></style>
+  </defs>
+  <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="5.0931702" inkscape:cx="51.311597" inkscape:cy="9.1743059" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" fit-margin-top="0" fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0" inkscape:window-width="1920" inkscape:window-height="1029" inkscape:window-x="0" inkscape:window-y="24" inkscape:window-maximized="1" showborder="true" showguides="true" inkscape:guide-bbox="true" inkscape:showpageshadow="false" inkscape:snap-global="false" inkscape:snap-bbox="true" inkscape:bbox-paths="true" inkscape:bbox-nodes="true" inkscape:snap-bbox-edge-midpoints="true" inkscape:snap-bbox-midpoints="true" inkscape:object-paths="true" inkscape:snap-intersection-paths="true" inkscape:object-nodes="true" inkscape:snap-smooth-nodes="true" inkscape:snap-midpoints="true" inkscape:snap-object-midpoints="true" inkscape:snap-center="true" inkscape:snap-text-baseline="true">
+    <inkscape:grid type="xygrid" id="grid821"/>
+    <sodipodi:guide orientation="1,0" position="16,48" id="guide823" inkscape:locked="false"/>
+    <sodipodi:guide orientation="0,1" position="64,80" id="guide825" inkscape:locked="false"/>
+    <sodipodi:guide orientation="1,0" position="80,40" id="guide827" inkscape:locked="false"/>
+    <sodipodi:guide orientation="0,1" position="64,16" id="guide829" inkscape:locked="false"/>
+  </sodipodi:namedview>
+  <metadata id="metadata6522">
+    <rdf:RDF>
+      <cc:Work rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+        <dc:title/>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g inkscape:label="BACKGROUND" inkscape:groupmode="layer" id="layer1" transform="translate(268,-635.29076)" style="display:inline">
+    <path style="display:inline;fill:#383838;fill-opacity:1;stroke:none" d="M 48 0 A 48 48 0 0 0 0 48 A 48 48 0 0 0 48 96 A 48 48 0 0 0 96 48 A 48 48 0 0 0 48 0 z " transform="translate(-268,635.29076)" id="path6455"/>
+    <path style="opacity:1;fill:#ffffff;stroke-width:0.49836424" d="m -245.09662,711.72332 c 0.11462,-2.99034 3.05007,-3.91613 4.84239,-4.18797 1.71688,-0.26041 5.37891,0.68965 12.09436,0.58011 6.71546,-0.10955 12.86651,-0.84046 13.96291,-0.88947 1.9861,-0.0888 5.3861,0.76742 8.80105,1.10369 4.31039,0.42444 6.80977,-0.52091 9.2513,0.84518 1.61577,0.90407 1.08624,3.01777 -0.74659,4.38113 -1.33442,0.99261 -1.63017,1.00618 -10.21647,0.46871 -5.17466,-0.32392 -9.97919,-0.38052 -11.58328,-0.13645 -1.35912,0.2068 -6.41923,0.46913 -11.10369,0.29831 -2.63405,-0.096 -4.79303,-0.60312 -6.97952,-0.66401 -2.52649,-0.0704 -3.8034,0.41679 -4.70411,0.38205 -2.3943,-0.0924 -3.67838,-0.61513 -3.61835,-2.18128 z m 5.08818,-11.30155 c -2.22213,-1.35482 -2.60399,-2.66785 -2.60399,-8.95375 0,-1.80081 -0.61411,-3.70956 0,-5.40241 0.30925,-0.85248 1.16285,-1.39184 1.74428,-2.08776 1.99091,-2.38297 2.18499,-3.96166 0.73705,-5.99511 -2.15336,-3.02411 -2.55856,-5.26728 -2.5057,-13.87166 0.0276,-4.48536 0.36374,-8.50768 0.51938,-9.03208 0.39979,-1.34711 1.27377,-1.54835 3.07627,-1.29531 1.70445,0.23927 3.95595,-0.20898 5.39827,-0.90867 2.60236,-1.26243 3.2066,-0.51959 4.20906,0.37736 0.59637,0.5336 1.3041,1.99758 1.7922,3.12788 0.56626,1.31131 1.45544,2.99812 3.01987,3.48855 2.97891,0.93386 3.54465,3.48769 6.64802,8.00186 2.48359,3.61262 5.05929,7.14477 5.7238,7.84924 2.77866,2.94574 3.73548,0.83339 3.37029,-7.44054 -0.10452,-2.36805 -0.60796,-4.45632 -0.35748,-6.22263 0.44969,-3.17117 -0.064,-6.30696 1.06018,-8.13995 0.72523,-1.18253 2.25821,-0.84224 4.94907,-0.82731 5.87758,0.0326 7.51589,1.06692 8.04026,7.66048 0.17784,2.23625 -0.0448,5.06655 0.0935,8.77532 0.21258,5.69922 0.36565,9.89449 -0.19419,13.9542 -0.33257,2.4116 -0.23954,5.19203 0.11854,7.85689 0.65813,4.89781 0.10092,7.46463 -1.97891,9.11584 -1.22508,0.97261 -1.74021,1.04732 -5.2449,0.76061 -2.13752,-0.17486 -4.77629,-0.67399 -5.86393,-1.10918 -2.47417,-0.98996 -5.12777,-3.97168 -7.68278,-8.63275 -1.08686,-1.98272 -3.08563,-4.87223 -4.44173,-6.42113 -1.35609,-1.5489 -3.21923,-3.99357 -4.14032,-5.4326 -1.7631,-2.75454 -3.20325,-3.36232 -4.08098,-1.72228 -0.26319,0.49178 -0.61704,4.2482 -0.78633,8.3476 -0.0761,1.84209 0.29872,3.56974 0.0707,5.40334 -0.27023,2.17271 -1.51256,3.76156 -0.90944,4.81483 1.14113,1.99282 0.59074,2.41331 0.15055,3.26026 -0.85686,1.64863 -7.25181,2.33409 -9.93055,0.70086 z" id="path4279" inkscape:connector-curvature="0" sodipodi:nodetypes="sssssssssssssssssssssssssssssssssssssssssssssss"/>
+  </g>
+</svg>
diff --git a/src/layer.yaml b/src/layer.yaml
new file mode 100644
index 0000000..c680356
--- /dev/null
+++ b/src/layer.yaml
@@ -0,0 +1,11 @@
+includes:
+  - layer:basic
+  # Add additional layers and interfaces here
+  - interface:juju-info
+  - interface:monitors
+  - interface:http
+options:
+  basic:
+    use_venv: true
+    include_system_packages: true
+    packages: ['pwgen']
diff --git a/src/lib/lib_nagios_charm.py b/src/lib/lib_nagios_charm.py
new file mode 100644
index 0000000..3f57820
--- /dev/null
+++ b/src/lib/lib_nagios_charm.py
@@ -0,0 +1,493 @@
+import base64
+import datetime
+import grp
+import os
+import pwd
+import shutil
+import subprocess
+
+from charmhelpers.contrib import ssl
+from charmhelpers.core import hookenv, host, services, templating
+from charmhelpers.fetch import apt_install, apt_update
+
+
+def set_package_options(*args):
+    """This is a helper function that will use the parsed arguments, and feed them to debconf-set-selection."""
+
+    cmd = [
+        'echo',
+    ] + list(args) + ['|', '/usr/bin/debconf-set-selections']
+    # we need the shell as we are using the pipe option, might add some input validation later
+    output = subprocess.check_output(
+        cmd, shell=True, stderr=subprocess.PIPE).decode('utf-8')
+    hookenv.log(output, 'DEBUG')
+
+
+def set_package_stat_override(*args):
+    """A helper to set some package overrides using the dpkg-startoverride utility."""
+    cmd = [
+        '/usr/bin/dpkg-statoverride',
+    ] + list(args)
+    # we need the shell as we are using the pipe option, might add some input validation later, but we don't care
+    # about the exit status
+    output = subprocess.run(
+        cmd, stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE).stdout.decode('utf-8')
+    hookenv.log(output, 'DEBUG')
+
+
+class NagioscharmHelper:
+    """Helper class that does the basic heavy lifting of the charm."""
+
+    NAGIOS_CFG = '/etc/nagios3/nagios.cfg'
+    NAGIOS_CGI_CFG = '/etc/nagios3/cgi.cfg'
+    PAGERDUTY_CRON = '/etc/cron.d/nagios-pagerduty-flush'
+    PAGERDUTY_CFG = '/etc/nagios3/conf.d/pagerduty_nagios.cfg'
+    EXTRA_CFG = '/etc/nagios3/conf.d/extra.cfg'
+    PACKAGE_LIST = ['nagios3', 'nagios-plugins', 'nagios-nrpe-plugin']
+    ALLOWED_SSL_OPTIONS = ['on', 'only']
+
+    def __init__(self):
+        self.charm_config = hookenv.config()
+
+    @property
+    def password_file(self):
+        return self.charm_config['password']
+
+    @property
+    def cert_domain(self):
+        return hookenv.unit_get('public-address')
+
+    @property
+    def cert_file(self):
+        """This depends on some other charm parameters, so we can't make is static."""
+        return '/etc/ssl/certs/{}.pem'.format(self.cert_domain)
+
+    @property
+    def key_file(self):
+        """This depends on some other charm parameters, so we can't make is static."""
+        return '/etc/ssl/private/{}.key'.format(self.cert_domain)
+
+    @property
+    def chain_file(self):
+        """This depends on some other charm parameters, so we can't make is static."""
+        return '/etc/ssl/certs/{}.csr'.format(self.cert_domain)
+
+    def install_nagios(self):
+        """This function will install nagios3.
+
+        FUTURE: Make it an option to install nagios4, if the version changes via a config option, simply reset the
+        nagios.installed flag state.
+        """
+        hookenv.status_set('maintenance', 'Installing nagios')
+        apt_update()
+        self.check_handle_password()
+        apt_install(self.PACKAGE_LIST)
+
+    def check_handle_password(self):
+        """Make sure that the password file is written and used. This is a prerequisite to install nagios3 package.
+
+        :FUTURE: handle nagios4
+        """
+        hookenv.status_set('maintenance', 'Setting up password')
+
+        if not os.path.exists(self.password_file):
+            # The file does not exist, so we create it
+            cmd = 'pwgen 10 1'
+            hookenv.log('Command to execute [{}]'.format(cmd.split()), 'DEBUG')
+            output = subprocess.check_output(
+                cmd.split(), shell=True).decode('utf-8')
+            # change the file to read-only for the current user
+            with open(self.password_file, 'w') as fh:
+                fh.write(output)
+            os.chmod(self.password_file, 0o0400)
+
+        with open(self.password_file, 'r') as fh:
+            password = fh.read()
+
+        set_package_options('nagios3-cgi', 'nagios3/adminpassword password',
+                            password)
+        set_package_options('nagios3-cgi',
+                            'nagios3/adminpassword-repeat password', password)
+
+        self._update_password('nagiosadmin', password)
+
+    def setup_overrides(self):
+        """Set some variables other then the default for the nagios dpkgs.
+
+        :FUTURE: handle nagios4
+        """
+        self.stop_service_nagios()
+        set_package_stat_override('--update', '--add', 'nagios', 'www-data',
+                                  '2710', '/var/lib/nagios3/rw')
+        set_package_stat_override('--update', '--add', 'nagios', 'nagios',
+                                  '5751', '/var/lib/nagios3')
+        self.start_service_nagios()
+
+    @staticmethod
+    def stop_service_nagios():
+        """Stop the nagios service.
+
+        :FUTURE: handle nagios4
+        """
+        services.service_stop('nagios3')
+
+    def start_service_nagios(self):
+        """Currently an alias for restart as we lack the services option for a start."""
+        self.restart_service_nagios()
+
+    @staticmethod
+    def restart_service_nagios():
+        """Restart the nagios service.
+
+        :FUTURE: handle nagios4
+        """
+        services.service_restart('nagios3')
+
+    @staticmethod
+    def reload_service_nagios():
+        """Reload the nagios3 service."""
+        host.service_reload('nagios3', restart_on_failure=True)
+
+    @staticmethod
+    def reload_service_apache2():
+        """Reload the apache2 service."""
+        host.service_reload('apache2', restart_on_failure=True)
+
+    def setup_hostgroups(self):
+        """Make sure that the hostgroup is overwritten with our version, so we don't end up as being marked Debian."""
+        hookenv.status_set('maintenance', 'Setting up hostgroups')
+        context = {'today': datetime.datetime.now().isoformat()}
+        context.update(self.charm_config)
+        templating.render(
+            source='hostgroups_nagios2.cfg.j2',
+            target='/etc/nagios3/conf.d/hostgroups_nagios2.cfg',
+            owner='nagios',
+            perms=0o0644,
+            context=context,
+        )
+
+        remove_files = [
+            '/etc/nagios3/conf.d/services_nagios2.cfg',
+            '/etc/nagios3/conf.d/extinfo_nagios2.cfg'
+        ]
+        for filename in remove_files:
+            if os.path.exists(filename):
+                os.unlink(filename)
+
+    def install_livestatus(self):
+        """Install the livestatus additions for nagios."""
+        hookenv.status_set('maintenance', 'Installing livestatus')
+        apt_install(['check-mk-livestatus'])
+        self.configure_livestatus_dir()
+
+    def configure_livestatus_dir(self):
+        """
+        Configure the directory where the livestatus dir sockets lives, so it can be accessed.
+
+        Should be called if either the location (livestatus_path) changes or when livestatus is enabled.
+        """
+        livestatus_dir = os.path.dirname(self.charm_config['livestatus_path'])
+        if not os.path.exists(livestatus_dir):
+            os.mkdir(livestatus_dir)
+        os.chmod(livestatus_dir, 0o2775)
+        os.chown(livestatus_dir,
+                 pwd.getpwnam('nagios').pw_uid,
+                 grp.getgrnam('www-data').gr_gid)
+
+    def install_http_redirect(self):
+        """Install a redirect file for apache, so that it will redirect to /nagios3."""
+        hookenv.status_set('maintenance', 'Installing redirect')
+        context = {'today': datetime.datetime.now().isoformat()}
+        context.update(self.charm_config)
+        templating.render(
+            source='index.html.j2',
+            target='/var/www/html/index.html',
+            context=context,
+        )
+
+    def setup_pagerduty(self):
+        """
+        Install and configure the pagerduty configuration. Depends on the following config options:
+
+        enable_pagerduty
+        pagerduty_key
+        pagerduty_path
+        pagerduty_notification_levels
+        admin_email
+        nagios_user
+        nagios_group
+        """
+
+        hookenv.status_set('maintenance', 'Configuring pagerduty')
+
+        if self.charm_config['enable_pagerduty']:
+            hookenv.log('pagerduty is enabled')
+            apt_install([
+                'libhttp-parser-perl',
+            ])
+            env = os.environ
+            proxy = env.get('JUJU_CHARM_HTTPS_PROXY') or env.get(
+                'https_proxy') or env.get('HTTPS_PROXY')
+            proxy_switch = '--proxy {}'.format(proxy) if proxy else ''
+
+            template_values = {
+                'today':
+                datetime.datetime.now().isoformat(),
+                'pagerduty_key':
+                self.charm_config['pagerduty_key'],
+                'pagerduty_path':
+                self.charm_config['pagerduty_path'],
+                'proxy_switch':
+                proxy_switch,
+                'notification_levels':
+                self.charm_config['pagerduty_notification_levels']
+            }
+
+            # The nagios configuration
+            templating.render(
+                source='pagerduty_nagios.cfg.j2',
+                target=self.PAGERDUTY_CFG,
+                context=template_values,
+            )
+
+            # The crontab for the cleanup
+            templating.render(
+                source='nagios-pagerduty-flush-cron.j2',
+                target=self.PAGERDUTY_CRON,
+                context=template_values,
+            )
+
+            if not os.path.isfile('/usr/local/bin/pagerduty_nagios.pl'):
+                shutil.copy('files/pagerduty_nagios.pl',
+                            '/usr/local/bin/pagerduty_nagios.pl')
+
+            if not os.path.isdir(self.charm_config['pagerduty_path']):
+                os.makedirs(self.charm_config['pagerduty_path'])
+                os.chown(
+                    self.charm_config['pagerduty_path'],
+                    pwd.getpwnam(self.charm_config['nagios_user']).pw_uid,
+                    grp.getgrnam(self.charm_config['nagios_group']).gr_gid)
+
+        else:
+            # Remove the pagerduty file(s)
+            if os.path.isfile(self.PAGERDUTY_CFG):
+                os.remove(self.PAGERDUTY_CFG)
+            if os.path.isfile(self.PAGERDUTY_CRON):
+                os.remove(self.PAGERDUTY_CRON)
+
+        context = {
+            'today': datetime.datetime.now().isoformat(),
+            'enable_pagerduty': self.charm_config['enable_pagerduty'],
+            'admin_email': self.charm_config['admin_email']
+        }
+        templating.render(
+            source='contacts.cfg.j2',
+            target='/etc/nagios3/conf.d/contacts_nagios2.cfg',
+            context=context)
+
+        # let's restart after the update of the config
+        self.restart_service_nagios()
+
+    def setup_nagios_config(self):
+        """Setup the configuration of nagios.
+
+        As this is heavily templated we depend on most config options of the charm. So any change to the config would
+        be a valid reason to update the configs.
+        """
+
+        hookenv.status_set('maintenance', 'Writing nagios config')
+
+        host_context = self.charm_config['nagios_host_context']
+        principal_unitname = hookenv.principal_unit()
+
+        # Fallback to primary if it exists for the unitname
+        if principal_unitname:
+            local_host_name = principal_unitname
+        else:
+            local_host_name = hookenv.local_unit().replace('/', '-')
+
+        template_values = {'today': datetime.datetime.now().isoformat()}
+        for key in [
+                'nagios_user', 'nagios_group', 'enable_livestatus',
+                'livestatus_path', 'livestatus_args',
+                'check_external_commands', 'command_check_interval',
+                'command_file', 'debug_file', 'debug_verbosity', 'debug_level',
+                'daemon_dumps_core', 'admin_email', 'admin_pager',
+                'log_rotation_method', 'log_archive_path', 'use_syslog',
+                'monitor_self', 'load_monitor'
+        ]:
+            template_values.update({key: self.charm_config[key]})
+        template_values.update(
+            {'nagios_hostname': '{}-{}'.format(host_context, local_host_name)})
+
+        templating.render(
+            source='nagios.cfg.j2',
+            target=self.NAGIOS_CFG,
+            context=template_values)
+
+        templating.render(
+            source='localhost_nagios.cfg.j2',
+            target='/etc/nagios3/conf.d/localhost_nagios.cfg',
+            context=template_values)
+
+        self.restart_service_nagios()
+
+    def setup_cgi_config(self):
+        """
+        Configure the cgi configuration, using the configuration from juju.
+
+        This function should be triggered on changes on any of the following config option; ro-password
+        """
+
+        hookenv.status_set('maintenance', 'Writing nagios-cgi config')
+
+        template_value = {
+            'today': datetime.datetime.now().isoformat(),
+            'ro_password': self.charm_config['ro-password'],
+        }
+
+        templating.render(
+            source='nagios-cgi.cfg.j2',
+            target=self.NAGIOS_CGI_CFG,
+            context=template_value)
+
+        self.reload_service_nagios()
+        self.reload_service_apache2()
+
+    def setup_extra_config(self):
+        """Write the extra config attached to the charm to the nagios configuration directory."""
+
+        hookenv.status_set('maintenance', 'Writing extra configuration data.')
+
+        # Always remove the file, so we know that we end up in a state the user expects
+        if os.path.exists(self.EXTRA_CFG):
+            os.remove(self.EXTRA_CFG)
+
+        if self.charm_config['extraconfig'] is not None:
+            host.write_file(self.EXTRA_CFG, self.charm_config['extraconfig'])
+
+    def ssl_configured(self):
+        """Check if ssl is properly configured."""
+        return self.charm_config['ssl'].lower() in self.ALLOWED_SSL_OPTIONS
+
+    def enable_ssl(self):
+        """Setup apache to use ssl."""
+        if not self.charm_config['ssl_cert']:
+            # We are not given a certificate, see if we need to create one, or if we already did that
+            if os.path.exists(self.cert_file):
+                hookenv.log('Certificate key already exist at [{}], not creating new one'.format(self.cert_file),
+                            'WARNING')
+                return
+            hookenv.log('No Certificate currently exists at [{}], creating a self signed one'.format(self.cert_file),
+                        'WARNING')
+            # ssl is from charmhelpers
+            ssl.generate_selfsigned(self.key_file, self.cert_file, cn=self.cert_domain)
+        else:
+            hookenv.log('Decoding provided certificate files', 'INFO')
+            self.decode_cert_files()
+
+    def decode_cert_files(self):
+        """Get the certificate files from the charm config and write them to disk."""
+
+        hookenv.status_set('maintenance', 'Handling ssl files')
+
+        if self.charm_config['ssl_key']:
+            hookenv.log('Decoding and writing ssl_key to [{}]'.format(self.key_file))
+            with open(self.key_file, 'w') as fh:
+                fh.write(base64.b64decode(self.charm_config['ssl_key']))
+
+        if self.charm_config['ssl_cert']:
+            hookenv.log('Decoding and writing ssl_cert to [{}]'.format(self.cert_file))
+            with open(self.cert_file, 'w') as fh:
+                fh.write(base64.b64decode(self.charm_config['ssl_cert']))
+
+        if self.charm_config['ssl_chain']:
+            hookenv.log('Decoding and writing ssl_chain to [{}]'.format(self.chain_file))
+            with open(self.chain_file, 'w') as fh:
+                fh.write(base64.b64decode(self.charm_config['ssl_chain']))
+
+    def disable_ssl(self):
+        """Remove the ssl configuration parts from apache2."""
+        if os.path.exists(self.key_file):
+            os.remove(self.key_file)
+        if os.path.exists(self.cert_file):
+            os.remove(self.cert_file)
+        if os.path.exists(self.chain_file):
+            os.remove(self.chain_file)
+
+    def update_apache(self):
+        """Configure apache, based on the charm config."""
+
+        if os.path.exists(self.chain_file) and os.path.getsize(self.chain_file) > 0:
+            ssl_chain = self.chain_file
+        else:
+            ssl_chain = None
+
+        template_values = {
+            'today': datetime.datetime.now().isoformat(),
+            'ssl_chain': ssl_chain,
+            'ssl_key': self.key_file,
+            'ssl_cert': self.cert_file,
+        }
+
+        templating.render(
+            source='default-ssl.j2',
+            target='/etc/apache2/sites-available/default-ssl',
+            context=template_values,
+        )
+
+        # Process all the options we manipulate in every case to be sure we don't mis any if things are toggled
+        if self.charm_config['ssl'].lower() == 'on':
+            subprocess.call(['a2enmod', 'ssl'])
+            subprocess.call(['a2ensite', 'default-ssl'])
+            subprocess.call(['a2ensite', 'default'])
+            hookenv.open_port(80)
+            hookenv.open_port(443)
+        elif self.charm_config['ssl'].lower() == 'only':
+            subprocess.call(['a2enmod', 'ssl'])
+            subprocess.call(['a2ensite', 'default-ssl'])
+            subprocess.call(['a2dissite', 'default'])
+            hookenv.close_port(80)
+            hookenv.open_port(443)
+        else:
+            subprocess.call(['a2enmod', 'ssl'])
+            subprocess.call(['a2dissite', 'default-ssl'])
+            subprocess.call(['a2ensite', 'default'])
+            hookenv.open_port(80)
+            hookenv.close_port(443)
+
+        self.reload_service_apache2()
+
+    @staticmethod
+    def _update_password(account, password):
+        """The real code that changes the password(s)."""
+        account_file = os.path.join(['var', 'lib', 'juju','nagios.{}.passwd'.format(account)])
+
+        hookenv.log('Updating password for account [{}]',format(account), 'INFO')
+        if password:
+            with open(account_file, 'w') as fh:
+                fh.write(account_file)
+            subprocess.check_output(['htpasswd', '-b', '/etc/nagios3/htpasswd.users', account, password])
+        else:
+            if os.path.exists(account_file):
+                os.remove(account_file)
+            subprocess.check_output(['htpasswd', '-D', '/etc/nagios3/htpasswd.users', account])
+
+    def update_password(self):
+        """Figure out which password was changed and how, and act accordingly"""
+
+        hookenv.status_set('maintenance', 'Updating password(s)')
+
+        if self.charm_config['ro-password'] is not None:
+            self._update_password('nagiosro', self.charm_config['ro-password'])
+        else:
+            self._update_password('nagiosro', None)
+
+        # this is the same password as we set for the initial installation? Should that not mean we need to update
+        # the debian package installation defaults. While we could skip it, as it will prevent a prompt on
+        # (re)installtion
+        if self.charm_config['password'] is not None:
+            self._update_password('nagiosadmin', self.charm_config['nagiosadmin'])
+        else:
+            self._update_password('nagiosadmin', None)
diff --git a/src/lib/pynag b/src/lib/pynag
new file mode 160000
index 0000000..bcdbd43
--- /dev/null
+++ b/src/lib/pynag
@@ -0,0 +1 @@
+Subproject commit bcdbd435dd48f9bf791b5d41307da93683cb17b3
diff --git a/src/metadata.yaml b/src/metadata.yaml
new file mode 100644
index 0000000..537386f
--- /dev/null
+++ b/src/metadata.yaml
@@ -0,0 +1,23 @@
+name: nagios
+summary: Nagios Core 3 monitoring.
+maintainers:
+  - Marco Ceppi <marco@xxxxxxxxx>
+  - Nagios Charm Developers <nagios-charmers@xxxxxxxxxxxxxxxxxxx>
+description: |
+  Nagios is a monitoring and management system for hosts, services, and
+  networks.
+tags: ["monitoring"]
+series:
+  - xenial
+  - bionic
+  - trusty
+provides:
+  website:
+    interface: http
+requires:
+  nagios:
+    interface: juju-info
+  monitors:
+    interface: monitors
+extra-bindings:
+  public:
diff --git a/src/reactive/nagios_charm.py b/src/reactive/nagios_charm.py
new file mode 100644
index 0000000..09ee5d3
--- /dev/null
+++ b/src/reactive/nagios_charm.py
@@ -0,0 +1,163 @@
+from charmhelpers.core import hookenv
+from charms.reactive import (clear_flag, hook, register_trigger, set_flag,
+                             when, when_any, when_not)
+from lib_nagios_charm import NagioscharmHelper
+
+helper = NagioscharmHelper()
+
+# Make sure that we register changes in the livestatus
+register_trigger(
+    when='config.changed.enable_livestatus',
+    set_flag='nagios.livestatus.changed')
+
+
+@hook('upgrade-charm')
+def upgrade_charm():
+    """Make sure that the upgrade is handles as we expect it. We do this by basically resetting all the flags."""
+    install_flags = [
+        'nagios.installed',
+        'nagios.installed.hostgroup',
+        'nagios.installed.overrides',
+        'nagios.installed.redirect',
+        'nagios.installed.livestatus',
+    ]
+    for flag in install_flags:
+        clear_flag(flag)
+
+
+@when_not('nagios.installed')
+def install_nagios_charm():
+    # Do your setup here.
+    #
+    # If your charm has other dependencies before it can install,
+    # add those as @when() clauses above., or as additional @when()
+    # decorated handlers below
+    #
+    # See the following for information about reactive charms:
+    #
+    #  * https://jujucharms.com/docs/devel/developer-getting-started
+    #  * https://github.com/juju-solutions/layer-basic#overview
+    #
+    helper.install_nagios()
+    set_flag('nagios.installed')
+
+    # The config sets this to false by default, but we don't want to mis it, so this is here as a safety precaution
+    if hookenv.config('enable_livestatus'):
+        set_flag('nagios.livestatus.changed')
+
+    update_pagerduty()
+    update_nagios_config()
+    update_nagios_cgi_config()
+    update_ssl_flags()
+    unit_ready()
+
+
+def unit_ready():
+    hookenv.status_set('active', 'unit ready')
+
+
+@when('nagios.installed')
+@when_not('nagios.installed.hostgroup')
+def setup_nagios_hostgroups():
+    helper.setup_hostgroups()
+    set_flag('nagios.installed.hostgroup')
+    unit_ready()
+
+
+@when('nagios.installed')
+@when_not('nagios.installed.overrides')
+def setup_nagios_overrides():
+    """Override some dpkg settings."""
+    helper.setup_overrides()
+    set_flag('nagios.installed.overrides')
+    unit_ready()
+
+
+@when('nagios.installed')
+@when_not('nagios.installed.redirect')
+def handle_redirect():
+    """Install our index.html so we have an redirect."""
+    helper.install_http_redirect()
+    set_flag('nagios.installed.redirect')
+    unit_ready()
+
+
+@when('nagios.installed')
+@when_not('nagios.installed.livestatus')
+@when('nagios.livestatus.changed')
+def setup_livestatus():
+    """Setup livestatus as we want it installed."""
+    if hookenv.config('enable_livestatus'):
+        helper.install_livestatus()
+        set_flag('nagios.installed.livestatus')
+    else:
+        clear_flag('nagios.installed.livestatus')
+
+    clear_flag('nagios.livestatus.changed')
+    unit_ready()
+
+
+@when('nagios.installed.livestatus')
+@when('config.changed.livestatus_path')
+def update_livestatus_path():
+    helper.configure_livestatus_dir()
+    unit_ready()
+
+
+@when('nagios.installed')
+@when_any(
+    'config.changed.enable_pagerduty',
+    'config.changed.pagerduty_key',
+    'config.changed.pagerduty_path',
+    'config.changed.pagerduty_notification_levels',
+    'config.changed.admin_email',
+    'config.changes.nagios_user',
+    'config.changed.nagios_group',
+)
+def update_pagerduty():
+    helper.setup_pagerduty()
+    unit_ready()
+
+
+@when('nagios.installed')
+@when('config.changed')
+def update_nagios_config():
+    helper.setup_nagios_config()
+    unit_ready()
+
+
+@when('nagios.installed')
+@when('config.changed.ro-password')
+def update_nagios_cgi_config():
+    helper.setup_cgi_config()
+    unit_ready()
+
+
+@when('nagios.installed')
+@when('config.changed.extraconfig')
+def update_extra_config():
+    helper.setup_extra_config()
+    unit_ready()
+
+
+@when('nagios.installed')
+@when_any('config.changed.ssl_config',
+          'config.changed.ssl_cert',
+          'config.changed.ssl_chain',
+          'config.changed.ssl_key')
+def update_ssl_flags():
+    if helper.ssl_configured():
+        # We want to have ssl configured
+        helper.enable_ssl()
+    else:
+        helper.disable_ssl()
+
+    helper.update_apache()
+    unit_ready()
+
+@when('nagios.installed')
+@when_any('config.changed.ro-password',
+          'config.changed.password')
+def update_passwords():
+    helper.update_password()
+    unit_ready()
diff --git a/src/requirements.txt b/src/requirements.txt
new file mode 100644
index 0000000..8462291
--- /dev/null
+++ b/src/requirements.txt
@@ -0,0 +1 @@
+# Include python requirements here
diff --git a/src/templates/contacts.cfg.j2 b/src/templates/contacts.cfg.j2
new file mode 100644
index 0000000..9cdb64d
--- /dev/null
+++ b/src/templates/contacts.cfg.j2
@@ -0,0 +1,51 @@
+#------------------------------------------------
+# This file is juju managed
+# last update was on {{ today }}
+#------------------------------------------------
+
+###############################################################################
+# contacts.cfg
+###############################################################################
+
+
+
+###############################################################################
+###############################################################################
+#
+# CONTACTS
+#
+###############################################################################
+###############################################################################
+
+# In this simple config file, a single contact will receive all alerts.
+
+define contact{
+        contact_name                    root
+        alias                           Root
+        service_notification_period     24x7
+        host_notification_period        24x7
+        service_notification_options    w,u,c,r
+        host_notification_options       d,r
+        service_notification_commands   notify-service-by-email
+        host_notification_commands      notify-host-by-email
+        email                           {{ admin_email }}
+        }
+
+
+
+###############################################################################
+###############################################################################
+#
+# CONTACT GROUPS
+#
+###############################################################################
+###############################################################################
+
+# We only have one contact in this simple configuration file, so there is
+# no need to create more than one contact group.
+
+define contactgroup{
+        contactgroup_name       admins
+        alias                   Nagios Administrators
+        members                 root{% if enable_pagerduty -%}, pagerduty{% endif %}
+        }
diff --git a/src/templates/default-ssl.j2 b/src/templates/default-ssl.j2
new file mode 100644
index 0000000..53bade7
--- /dev/null
+++ b/src/templates/default-ssl.j2
@@ -0,0 +1,181 @@
+# Default Apache SSL configuration - with template bits for SSL keyfile updates
+#
+# This file is maintained by JUJU
+# Written on: {{ today }}
+#
+<IfModule mod_ssl.c>
+<VirtualHost _default_:443>
+	ServerAdmin webmaster@localhost
+
+	DocumentRoot /var/www
+	<Directory />
+		Options FollowSymLinks
+		AllowOverride None
+	</Directory>
+	<Directory /var/www/>
+		Options Indexes FollowSymLinks MultiViews
+		AllowOverride None
+		Order allow,deny
+		allow from all
+	</Directory>
+
+	ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
+	<Directory "/usr/lib/cgi-bin">
+		AllowOverride None
+		Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
+		Order allow,deny
+		Allow from all
+	</Directory>
+
+	ErrorLog ${APACHE_LOG_DIR}/error.log
+
+	# Possible values include: debug, info, notice, warn, error, crit,
+	# alert, emerg.
+	LogLevel warn
+
+	CustomLog ${APACHE_LOG_DIR}/ssl_access.log combined
+
+	Alias /doc/ "/usr/share/doc/"
+	<Directory "/usr/share/doc/">
+		Options Indexes MultiViews FollowSymLinks
+		AllowOverride None
+		Order deny,allow
+		Deny from all
+		Allow from 127.0.0.0/255.0.0.0 ::1/128
+	</Directory>
+
+	#   SSL Engine Switch:
+	#   Enable/Disable SSL for this virtual host.
+	SSLEngine on
+
+	#   A self-signed (snakeoil) certificate can be created by installing
+	#   the ssl-cert package. See
+	#   /usr/share/doc/apache2.2-common/README.Debian.gz for more info.
+	#   If both key and certificate are stored in the same file, only the
+	#   SSLCertificateFile directive is needed.
+	SSLCertificateFile    {{ssl_cert}}
+	SSLCertificateKeyFile {{ssl_key}}
+
+	#   Server Certificate Chain:
+	#   Point SSLCertificateChainFile at a file containing the
+	#   concatenation of PEM encoded CA certificates which form the
+	#   certificate chain for the server certificate. Alternatively
+	#   the referenced file can be the same as SSLCertificateFile
+	#   when the CA certificates are directly appended to the server
+	#   certificate for convinience.
+	#SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt
+{%if ssl_chain %}
+	SSLCertificateChainFile {{ssl_chain}}
+{% endif %}
+
+
+	#   Certificate Authority (CA):
+	#   Set the CA certificate verification path where to find CA
+	#   certificates for client authentication or alternatively one
+	#   huge file containing all of them (file must be PEM encoded)
+	#   Note: Inside SSLCACertificatePath you need hash symlinks
+	#         to point to the certificate files. Use the provided
+	#         Makefile to update the hash symlinks after changes.
+	#SSLCACertificatePath /etc/ssl/certs/
+	#SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt
+
+	#   Certificate Revocation Lists (CRL):
+	#   Set the CA revocation path where to find CA CRLs for client
+	#   authentication or alternatively one huge file containing all
+	#   of them (file must be PEM encoded)
+	#   Note: Inside SSLCARevocationPath you need hash symlinks
+	#         to point to the certificate files. Use the provided
+	#         Makefile to update the hash symlinks after changes.
+	#SSLCARevocationPath /etc/apache2/ssl.crl/
+	#SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl
+
+	#   Client Authentication (Type):
+	#   Client certificate verification type and depth.  Types are
+	#   none, optional, require and optional_no_ca.  Depth is a
+	#   number which specifies how deeply to verify the certificate
+	#   issuer chain before deciding the certificate is not valid.
+	#SSLVerifyClient require
+	#SSLVerifyDepth  10
+
+	#   Access Control:
+	#   With SSLRequire you can do per-directory access control based
+	#   on arbitrary complex boolean expressions containing server
+	#   variable checks and other lookup directives.  The syntax is a
+	#   mixture between C and Perl.  See the mod_ssl documentation
+	#   for more details.
+	#<Location />
+	#SSLRequire (    %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
+	#            and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
+	#            and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
+	#            and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
+	#            and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20       ) \
+	#           or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
+	#</Location>
+
+	#   SSL Engine Options:
+	#   Set various options for the SSL engine.
+	#   o FakeBasicAuth:
+	#     Translate the client X.509 into a Basic Authorisation.  This means that
+	#     the standard Auth/DBMAuth methods can be used for access control.  The
+	#     user name is the `one line' version of the client's X.509 certificate.
+	#     Note that no password is obtained from the user. Every entry in the user
+	#     file needs this password: `xxj31ZMTZzkVA'.
+	#   o ExportCertData:
+	#     This exports two additional environment variables: SSL_CLIENT_CERT and
+	#     SSL_SERVER_CERT. These contain the PEM-encoded certificates of the
+	#     server (always existing) and the client (only existing when client
+	#     authentication is used). This can be used to import the certificates
+	#     into CGI scripts.
+	#   o StdEnvVars:
+	#     This exports the standard SSL/TLS related `SSL_*' environment variables.
+	#     Per default this exportation is switched off for performance reasons,
+	#     because the extraction step is an expensive operation and is usually
+	#     useless for serving static content. So one usually enables the
+	#     exportation for CGI and SSI requests only.
+	#   o StrictRequire:
+	#     This denies access when "SSLRequireSSL" or "SSLRequire" applied even
+	#     under a "Satisfy any" situation, i.e. when it applies access is denied
+	#     and no other module can change it.
+	#   o OptRenegotiate:
+	#     This enables optimized SSL connection renegotiation handling when SSL
+	#     directives are used in per-directory context.
+	#SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
+	<FilesMatch "\.(cgi|shtml|phtml|php)$">
+		SSLOptions +StdEnvVars
+	</FilesMatch>
+	<Directory /usr/lib/cgi-bin>
+		SSLOptions +StdEnvVars
+	</Directory>
+
+	#   SSL Protocol Adjustments:
+	#   The safe and default but still SSL/TLS standard compliant shutdown
+	#   approach is that mod_ssl sends the close notify alert but doesn't wait for
+	#   the close notify alert from client. When you need a different shutdown
+	#   approach you can use one of the following variables:
+	#   o ssl-unclean-shutdown:
+	#     This forces an unclean shutdown when the connection is closed, i.e. no
+	#     SSL close notify alert is send or allowed to received.  This violates
+	#     the SSL/TLS standard but is needed for some brain-dead browsers. Use
+	#     this when you receive I/O errors because of the standard approach where
+	#     mod_ssl sends the close notify alert.
+	#   o ssl-accurate-shutdown:
+	#     This forces an accurate shutdown when the connection is closed, i.e. a
+	#     SSL close notify alert is send and mod_ssl waits for the close notify
+	#     alert of the client. This is 100% SSL/TLS standard compliant, but in
+	#     practice often causes hanging connections with brain-dead browsers. Use
+	#     this only for browsers where you know that their SSL implementation
+	#     works correctly.
+	#   Notice: Most problems of broken clients are also related to the HTTP
+	#   keep-alive facility, so you usually additionally want to disable
+	#   keep-alive for those clients, too. Use variable "nokeepalive" for this.
+	#   Similarly, one has to force some clients to use HTTP/1.0 to workaround
+	#   their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and
+	#   "force-response-1.0" for this.
+	BrowserMatch "MSIE [2-6]" \
+		nokeepalive ssl-unclean-shutdown \
+		downgrade-1.0 force-response-1.0
+	# MSIE 7 and newer should be able to use keepalive
+	BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
+
+</VirtualHost>
+</IfModule>
diff --git a/src/templates/hostgroups_nagios2.cfg.j2 b/src/templates/hostgroups_nagios2.cfg.j2
new file mode 100644
index 0000000..dc855e3
--- /dev/null
+++ b/src/templates/hostgroups_nagios2.cfg.j2
@@ -0,0 +1,9 @@
+# Written by juju on: {{ today }}
+# Some generic hostgroup definitions
+
+# A simple wildcard hostgroup
+define hostgroup {
+        hostgroup_name  all
+        alias           All Servers
+        members         *
+}
diff --git a/src/templates/index.html.j2 b/src/templates/index.html.j2
new file mode 100644
index 0000000..8828624
--- /dev/null
+++ b/src/templates/index.html.j2
@@ -0,0 +1,14 @@
+<!-- Written by juju on: {{ today }} -->
+<html lang="en-US">
+    <head>
+        <meta charset="UTF-8">
+        <meta http-equiv="refresh" content="1;url=nagios3/">
+        <script type="text/javascript">
+            window.location.href = "nagios3/"
+        </script>
+        <title>Nagios3</title>
+    </head>
+    <body>
+        If you are not redirected automatically, follow the <a href='nagios3/'>link to nagios3</a>.
+    </body>
+</html>
diff --git a/src/templates/localhost_nagios.cfg.j2 b/src/templates/localhost_nagios.cfg.j2
new file mode 100644
index 0000000..2d45c1c
--- /dev/null
+++ b/src/templates/localhost_nagios.cfg.j2
@@ -0,0 +1,70 @@
+#------------------------------------------------
+# This file is juju managed
+#------------------------------------------------
+{% if monitor_self -%}
+
+# A simple configuration file for monitoring the local host
+# This can serve as an example for configuring other servers;
+# Custom services specific to this host are added here, but services
+# defined in nagios2-common_services.cfg may also apply.
+#
+
+define host{
+        use                     generic-host            ; Name of host template to use
+        host_name               {{ nagios_hostname }}
+        alias                   {{ nagios_hostname }}
+        address                 127.0.0.1
+        icon_image_alt          Ubuntu Linux
+        statusmap_image         base/ubuntu.gd2
+        vrml_image              ubuntu.png
+        icon_image              base/ubuntu.png
+        }
+
+# Define a service to check the disk space of the root partition
+# on the local machine.  Warning if < 20% free, critical if
+# < 10% free space on partition.
+
+define service{
+        use                             generic-service         ; Name of service template to use
+        host_name                       {{ nagios_hostname }}
+        service_description             Disk Space
+        check_command                   check_all_disks!20%!10%
+        }
+
+
+
+# Define a service to check the number of currently logged in
+# users on the local machine.  Warning if > 20 users, critical
+# if > 50 users.
+
+define service{
+        use                             generic-service         ; Name of service template to use
+        host_name                       {{ nagios_hostname }}
+        service_description             Current Users
+        check_command                   check_users!20!50
+        }
+
+
+# Define a service to check the number of currently running procs
+# on the local machine.  Warning if > 250 processes, critical if
+# > 400 processes.
+
+define service{
+        use                             generic-service         ; Name of service template to use
+        host_name                       {{ nagios_hostname }}
+        service_description             Total Processes
+        check_command                   check_procs!250!400
+        }
+
+
+
+# Define a service to check the load on the local machine.
+
+define service{
+        use                             generic-service         ; Name of service template to use
+        host_name                       {{ nagios_hostname }}
+        service_description             Current Load
+        check_command                   check_load!{{ load_monitor }}
+        }
+
+{% endif %}
diff --git a/src/templates/nagios-cgi.cfg.j2 b/src/templates/nagios-cgi.cfg.j2
new file mode 100644
index 0000000..24410d5
--- /dev/null
+++ b/src/templates/nagios-cgi.cfg.j2
@@ -0,0 +1,380 @@
+#################################################################
+#
+# CGI.CFG - Sample CGI Configuration File for Nagios
+#
+#################################################################
+
+
+# MAIN CONFIGURATION FILE
+# This tells the CGIs where to find your main configuration file.
+# The CGIs will read the main and host config files for any other
+# data they might need.
+
+main_config_file=/etc/nagios3/nagios.cfg
+
+
+
+# PHYSICAL HTML PATH
+# This is the path where the HTML files for Nagios reside.  This
+# value is used to locate the logo images needed by the statusmap
+# and statuswrl CGIs.
+
+physical_html_path=/usr/share/nagios3/htdocs
+
+
+
+# URL HTML PATH
+# This is the path portion of the URL that corresponds to the
+# physical location of the Nagios HTML files (as defined above).
+# This value is used by the CGIs to locate the online documentation
+# and graphics.  If you access the Nagios pages with an URL like
+# http://www.myhost.com/nagios, this value should be '/nagios'
+# (without the quotes).
+
+url_html_path=/nagios3
+
+
+
+# CONTEXT-SENSITIVE HELP
+# This option determines whether or not a context-sensitive
+# help icon will be displayed for most of the CGIs.
+# Values: 0 = disables context-sensitive help
+#         1 = enables context-sensitive help
+
+show_context_help=1
+
+
+
+# PENDING STATES OPTION
+# This option determines what states should be displayed in the web
+# interface for hosts/services that have not yet been checked.
+# Values: 0 = leave hosts/services that have not been check yet in their original state
+#         1 = mark hosts/services that have not been checked yet as PENDING
+
+use_pending_states=1
+
+# NAGIOS PROCESS CHECK COMMAND
+# This is the full path and filename of the program used to check
+# the status of the Nagios process.  It is used only by the CGIs
+# and is completely optional.  However, if you don't use it, you'll
+# see warning messages in the CGIs about the Nagios process
+# not running and you won't be able to execute any commands from
+# the web interface.  The program should follow the same rules
+# as plugins; the return codes are the same as for the plugins,
+# it should have timeout protection, it should output something
+# to STDIO, etc.
+#
+# Note: The command line for the check_nagios plugin below may
+# have to be tweaked a bit, as different versions of the plugin
+# use different command line arguments/syntaxes.
+
+nagios_check_command=/usr/lib/nagios/plugins/check_nagios /var/cache/nagios3/status.dat 5 '/usr/sbin/nagios3'
+
+
+# AUTHENTICATION USAGE
+# This option controls whether or not the CGIs will use any
+# authentication when displaying host and service information, as
+# well as committing commands to Nagios for processing.
+#
+# Read the HTML documentation to learn how the authorization works!
+#
+# NOTE: It is a really *bad* idea to disable authorization, unless
+# you plan on removing the command CGI (cmd.cgi)!  Failure to do
+# so will leave you wide open to kiddies messing with Nagios and
+# possibly hitting you with a denial of service attack by filling up
+# your drive by continuously writing to your command file!
+#
+# Setting this value to 0 will cause the CGIs to *not* use
+# authentication (bad idea), while any other value will make them
+# use the authentication functions (the default).
+
+use_authentication=1
+
+
+
+
+# x509 CERT AUTHENTICATION
+# When enabled, this option allows you to use x509 cert (SSL)
+# authentication in the CGIs.  This is an advanced option and should
+# not be enabled unless you know what you're doing.
+
+use_ssl_authentication=0
+
+
+
+
+# DEFAULT USER
+# Setting this variable will define a default user name that can
+# access pages without authentication.  This allows people within a
+# secure domain (i.e., behind a firewall) to see the current status
+# without authenticating.  You may want to use this to avoid basic
+# authentication if you are not using a secure server since basic
+# authentication transmits passwords in the clear.
+#
+# Important:  Do not define a default username unless you are
+# running a secure web server and are sure that everyone who has
+# access to the CGIs has been authenticated in some manner!  If you
+# define this variable, anyone who has not authenticated to the web
+# server will inherit all rights you assign to this user!
+
+#default_user_name=guest
+
+
+
+# SYSTEM/PROCESS INFORMATION ACCESS
+# This option is a comma-delimited list of all usernames that
+# have access to viewing the Nagios process information as
+# provided by the Extended Information CGI (extinfo.cgi).  By
+# default, *no one* has access to this unless you choose to
+# not use authorization.  You may use an asterisk (*) to
+# authorize any user who has authenticated to the web server.
+
+authorized_for_system_information=nagiosadmin
+
+
+
+# CONFIGURATION INFORMATION ACCESS
+# This option is a comma-delimited list of all usernames that
+# can view ALL configuration information (hosts, commands, etc).
+# By default, users can only view configuration information
+# for the hosts and services they are contacts for. You may use
+# an asterisk (*) to authorize any user who has authenticated
+# to the web server.
+
+authorized_for_configuration_information=nagiosadmin
+
+
+
+# SYSTEM/PROCESS COMMAND ACCESS
+# This option is a comma-delimited list of all usernames that
+# can issue shutdown and restart commands to Nagios via the
+# command CGI (cmd.cgi).  Users in this list can also change
+# the program mode to active or standby. By default, *no one*
+# has access to this unless you choose to not use authorization.
+# You may use an asterisk (*) to authorize any user who has
+# authenticated to the web server.
+
+authorized_for_system_commands=nagiosadmin
+
+
+
+# GLOBAL HOST/SERVICE VIEW ACCESS
+# These two options are comma-delimited lists of all usernames that
+# can view information for all hosts and services that are being
+# monitored.  By default, users can only view information
+# for hosts or services that they are contacts for (unless you
+# you choose to not use authorization). You may use an asterisk (*)
+# to authorize any user who has authenticated to the web server.
+
+
+{%if ro_password%}
+authorized_for_read_only=nagiosro
+authorized_for_all_services=nagiosadmin,nagiosro
+authorized_for_all_hosts=nagiosadmin,nagiosro
+{% else %}
+authorized_for_all_services=nagiosadmin
+authorized_for_all_hosts=nagiosadmin
+{% endif %}
+
+
+
+# GLOBAL HOST/SERVICE COMMAND ACCESS
+# These two options are comma-delimited lists of all usernames that
+# can issue host or service related commands via the command
+# CGI (cmd.cgi) for all hosts and services that are being monitored.
+# By default, users can only issue commands for hosts or services
+# that they are contacts for (unless you you choose to not use
+# authorization).  You may use an asterisk (*) to authorize any
+# user who has authenticated to the web server.
+
+authorized_for_all_service_commands=nagiosadmin
+authorized_for_all_host_commands=nagiosadmin
+
+
+
+# READ-ONLY USERS
+# A comma-delimited list of usernames that have read-only rights in
+# the CGIs.  This will block any service or host commands normally shown
+# on the extinfo CGI pages.  It will also block comments from being shown
+# to read-only users.
+
+#authorized_for_read_only=user1,user2
+
+
+
+
+# STATUSMAP BACKGROUND IMAGE
+# This option allows you to specify an image to be used as a
+# background in the statusmap CGI.  It is assumed that the image
+# resides in the HTML images path (i.e. /usr/local/nagios/share/images).
+# This path is automatically determined by appending "/images"
+# to the path specified by the 'physical_html_path' directive.
+# Note:  The image file may be in GIF, PNG, JPEG, or GD2 format.
+# However, I recommend that you convert your image to GD2 format
+# (uncompressed), as this will cause less CPU load when the CGI
+# generates the image.
+
+#statusmap_background_image=smbackground.gd2
+
+
+
+
+# STATUSMAP TRANSPARENCY INDEX COLOR
+# These options set the r,g,b values of the background color used the statusmap CGI,
+# so normal browsers that can't show real png transparency set the desired color as
+# a background color instead (to make it look pretty).
+# Defaults to white: (R,G,B) = (255,255,255).
+
+#color_transparency_index_r=255
+#color_transparency_index_g=255
+#color_transparency_index_b=255
+
+
+
+
+# DEFAULT STATUSMAP LAYOUT METHOD
+# This option allows you to specify the default layout method
+# the statusmap CGI should use for drawing hosts.  If you do
+# not use this option, the default is to use user-defined
+# coordinates.  Valid options are as follows:
+#       0 = User-defined coordinates
+#       1 = Depth layers
+#       2 = Collapsed tree
+#       3 = Balanced tree
+#       4 = Circular
+#       5 = Circular (Marked Up)
+
+default_statusmap_layout=5
+
+
+
+# DEFAULT STATUSWRL LAYOUT METHOD
+# This option allows you to specify the default layout method
+# the statuswrl (VRML) CGI should use for drawing hosts.  If you
+# do not use this option, the default is to use user-defined
+# coordinates.  Valid options are as follows:
+#       0 = User-defined coordinates
+#       2 = Collapsed tree
+#       3 = Balanced tree
+#       4 = Circular
+
+default_statuswrl_layout=4
+
+
+
+# STATUSWRL INCLUDE
+# This option allows you to include your own objects in the
+# generated VRML world.  It is assumed that the file
+# resides in the HTML path (i.e. /usr/local/nagios/share).
+
+#statuswrl_include=myworld.wrl
+
+
+
+# PING SYNTAX
+# This option determines what syntax should be used when
+# attempting to ping a host from the WAP interface (using
+# the statuswml CGI.  You must include the full path to
+# the ping binary, along with all required options.  The
+# $HOSTADDRESS$ macro is substituted with the address of
+# the host before the command is executed.
+# Please note that the syntax for the ping binary is
+# notorious for being different on virtually ever *NIX
+# OS and distribution, so you may have to tweak this to
+# work on your system.
+
+ping_syntax=/bin/ping -n -U -c 5 $HOSTADDRESS$
+
+
+
+# REFRESH RATE
+# This option allows you to specify the refresh rate in seconds
+# of various CGIs (status, statusmap, extinfo, and outages).
+
+refresh_rate=90
+
+# DEFAULT PAGE LIMIT
+# This option allows you to specify the default number of results
+# displayed on the status.cgi.  This number can be adjusted from
+# within the UI after the initial page load. Setting this to 0
+# will show all results.
+
+result_limit=100
+
+
+# ESCAPE HTML TAGS
+# This option determines whether HTML tags in host and service
+# status output is escaped in the web interface.  If enabled,
+# your plugin output will not be able to contain clickable links.
+
+escape_html_tags=1
+
+
+
+
+# SOUND OPTIONS
+# These options allow you to specify an optional audio file
+# that should be played in your browser window when there are
+# problems on the network.  The audio files are used only in
+# the status CGI.  Only the sound for the most critical problem
+# will be played.  Order of importance (higher to lower) is as
+# follows: unreachable hosts, down hosts, critical services,
+# warning services, and unknown services. If there are no
+# visible problems, the sound file optionally specified by
+# 'normal_sound' variable will be played.
+#
+#
+# <varname>=<sound_file>
+#
+# Note: All audio files must be placed in the /media subdirectory
+# under the HTML path (i.e. /usr/local/nagios/share/media/).
+
+#host_unreachable_sound=hostdown.wav
+#host_down_sound=hostdown.wav
+#service_critical_sound=critical.wav
+#service_warning_sound=warning.wav
+#service_unknown_sound=warning.wav
+#normal_sound=noproblem.wav
+
+
+
+# URL TARGET FRAMES
+# These options determine the target frames in which notes and
+# action URLs will open.
+
+action_url_target=_blank
+notes_url_target=_blank
+
+
+
+
+# LOCK AUTHOR NAMES OPTION
+# This option determines whether users can change the author name
+# when submitting comments, scheduling downtime.  If disabled, the
+# author names will be locked into their contact name, as defined in Nagios.
+# Values: 0 = allow editing author names
+#         1 = lock author names (disallow editing)
+
+lock_author_names=1
+
+
+
+
+# SPLUNK INTEGRATION OPTIONS
+# These options allow you to enable integration with Splunk
+# in the web interface.  If enabled, you'll be presented with
+# "Splunk It" links in various places in the CGIs (log file,
+# alert history, host/service detail, etc).  Useful if you're
+# trying to research why a particular problem occurred.
+# For more information on Splunk, visit http://www.splunk.com/
+
+# This option determines whether the Splunk integration is enabled
+# Values: 0 = disable Splunk integration
+#         1 = enable Splunk integration
+
+#enable_splunk_integration=1
+
+
+# This option should be the URL used to access your instance of Splunk
+
+#splunk_url=http://127.0.0.1:8000/
diff --git a/src/templates/nagios-pagerduty-flush-cron.j2 b/src/templates/nagios-pagerduty-flush-cron.j2
new file mode 100644
index 0000000..9213e97
--- /dev/null
+++ b/src/templates/nagios-pagerduty-flush-cron.j2
@@ -0,0 +1,7 @@
+#------------------------------------------------
+# This file is juju managed
+#------------------------------------------------
+
+# Flush the nagios pagerduty alerts every minute as per
+# http://www.pagerduty.com/docs/guides/nagios-perl-integration-guide/
+* * * * *   nagios  /usr/local/bin/pagerduty_nagios.pl flush {{ proxy_switch }} --queue-dir {{ pagerduty_path }}
diff --git a/src/templates/nagios.cfg.j2 b/src/templates/nagios.cfg.j2
new file mode 100644
index 0000000..afd3455
--- /dev/null
+++ b/src/templates/nagios.cfg.j2
@@ -0,0 +1,1359 @@
+#------------------------------------------------
+# This file is juju managed
+# File is written on: {{ today }}
+#------------------------------------------------
+
+##############################################################################
+#
+# NAGIOS.CFG - Sample Main Config File for Nagios
+#
+#
+##############################################################################
+
+
+# LOG FILE
+# This is the main log file where service and host events are logged
+# for historical purposes.  This should be the first option specified
+# in the config file!!!
+
+log_file=/var/log/nagios3/nagios.log
+
+# Commands definitions
+cfg_file=/etc/nagios3/commands.cfg
+
+# Debian also defaults to using the check commands defined by the debian
+# nagios-plugins package
+cfg_dir=/etc/nagios-plugins/config
+
+# Debian uses by default a configuration directory where nagios3-common,
+# other packages and the local admin can dump or link configuration
+# files into.
+cfg_dir=/etc/nagios3/conf.d
+
+# OBJECT CONFIGURATION FILE(S)
+# These are the object configuration files in which you define hosts,
+# host groups, contacts, contact groups, services, etc.
+# You can split your object definitions across several config files
+# if you wish (as shown below), or keep them all in a single config file.
+
+# You can specify individual object config files as shown below:
+#cfg_file=/etc/nagios3/objects/commands.cfg
+#cfg_file=/etc/nagios3/objects/contacts.cfg
+#cfg_file=/etc/nagios3/objects/timeperiods.cfg
+#cfg_file=/etc/nagios3/objects/templates.cfg
+
+# Definitions for monitoring a Windows machine
+#cfg_file=/etc/nagios3/objects/windows.cfg
+
+# Definitions for monitoring a router/switch
+#cfg_file=/etc/nagios3/objects/switch.cfg
+
+# Definitions for monitoring a network printer
+#cfg_file=/etc/nagios3/objects/printer.cfg
+
+
+# You can also tell Nagios to process all config files (with a .cfg
+# extension) in a particular directory by using the cfg_dir
+# directive as shown below:
+
+#cfg_dir=/etc/nagios3/servers
+#cfg_dir=/etc/nagios3/printers
+#cfg_dir=/etc/nagios3/switches
+#cfg_dir=/etc/nagios3/routers
+
+
+
+
+# OBJECT CACHE FILE
+# This option determines where object definitions are cached when
+# Nagios starts/restarts.  The CGIs read object definitions from
+# this cache file (rather than looking at the object config files
+# directly) in order to prevent inconsistencies that can occur
+# when the config files are modified after Nagios starts.
+
+object_cache_file=/var/cache/nagios3/objects.cache
+
+
+
+# PRE-CACHED OBJECT FILE
+# This options determines the location of the precached object file.
+# If you run Nagios with the -p command line option, it will preprocess
+# your object configuration file(s) and write the cached config to this
+# file.  You can then start Nagios with the -u option to have it read
+# object definitions from this precached file, rather than the standard
+# object configuration files (see the cfg_file and cfg_dir options above).
+# Using a precached object file can speed up the time needed to (re)start
+# the Nagios process if you've got a large and/or complex configuration.
+# Read the documentation section on optimizing Nagios to find our more
+# about how this feature works.
+
+precached_object_file=/var/lib/nagios3/objects.precache
+
+
+
+# RESOURCE FILE
+# This is an optional resource file that contains $USERx$ macro
+# definitions. Multiple resource files can be specified by using
+# multiple resource_file definitions.  The CGIs will not attempt to
+# read the contents of resource files, so information that is
+# considered to be sensitive (usernames, passwords, etc) can be
+# defined as macros in this file and restrictive permissions (600)
+# can be placed on this file.
+
+resource_file=/etc/nagios3/resource.cfg
+
+
+
+# STATUS FILE
+# This is where the current status of all monitored services and
+# hosts is stored.  Its contents are read and processed by the CGIs.
+# The contents of the status file are deleted every time Nagios
+#  restarts.
+
+status_file=/var/cache/nagios3/status.dat
+
+
+
+# STATUS FILE UPDATE INTERVAL
+# This option determines the frequency (in seconds) that
+# Nagios will periodically dump program, host, and
+# service status data.
+
+status_update_interval=10
+
+
+
+# NAGIOS USER
+# This determines the effective user that Nagios should run as.
+# You can either supply a username or a UID.
+
+nagios_user={{ nagios_user }}
+
+
+
+# NAGIOS GROUP
+# This determines the effective group that Nagios should run as.
+# You can either supply a group name or a GID.
+
+nagios_group={{ nagios_group }}
+
+
+
+# EXTERNAL COMMAND OPTION
+# This option allows you to specify whether or not Nagios should check
+# for external commands (in the command file defined below).  By default
+# Nagios will *not* check for external commands, just to be on the
+# cautious side.  If you want to be able to use the CGI command interface
+# you will have to enable this.
+# Values: 0 = disable commands, 1 = enable commands
+
+check_external_commands={{ check_external_commands }}
+
+
+
+# EXTERNAL COMMAND CHECK INTERVAL
+# This is the interval at which Nagios should check for external commands.
+# This value works of the interval_length you specify later.  If you leave
+# that at its default value of 60 (seconds), a value of 1 here will cause
+# Nagios to check for external commands every minute.  If you specify a
+# number followed by an "s" (i.e. 15s), this will be interpreted to mean
+# actual seconds rather than a multiple of the interval_length variable.
+# Note: In addition to reading the external command file at regularly
+# scheduled intervals, Nagios will also check for external commands after
+# event handlers are executed.
+# NOTE: Setting this value to -1 causes Nagios to check the external
+# command file as often as possible.
+
+#command_check_interval=15s
+command_check_interval={{ command_check_interval }}
+
+
+
+# EXTERNAL COMMAND FILE
+# This is the file that Nagios checks for external command requests.
+# It is also where the command CGI will write commands that are submitted
+# by users, so it must be writeable by the user that the web server
+# is running as (usually 'nobody').  Permissions should be set at the
+# directory level instead of on the file, as the file is deleted every
+# time its contents are processed.
+# Debian Users: In case you didn't read README.Debian yet, _NOW_ is the
+# time to do it.
+
+command_file={{ command_file }}
+
+
+
+# EXTERNAL COMMAND BUFFER SLOTS
+# This settings is used to tweak the number of items or "slots" that
+# the Nagios daemon should allocate to the buffer that holds incoming
+# external commands before they are processed.  As external commands
+# are processed by the daemon, they are removed from the buffer.
+
+external_command_buffer_slots=4096
+
+
+
+# LOCK FILE
+# This is the lockfile that Nagios will use to store its PID number
+# in when it is running in daemon mode.
+
+lock_file=/var/run/nagios3/nagios3.pid
+
+
+
+# TEMP FILE
+# This is a temporary file that is used as scratch space when Nagios
+# updates the status log, cleans the comment file, etc.  This file
+# is created, used, and deleted throughout the time that Nagios is
+# running.
+
+temp_file=/var/cache/nagios3/nagios.tmp
+
+
+
+# TEMP PATH
+# This is path where Nagios can create temp files for service and
+# host check results, etc.
+
+temp_path=/tmp
+
+
+
+# EVENT BROKER OPTIONS
+# Controls what (if any) data gets sent to the event broker.
+# Values:  0      = Broker nothing
+#         -1      = Broker everything
+#         <other> = See documentation
+
+event_broker_options=-1
+
+
+
+# EVENT BROKER MODULE(S)
+# This directive is used to specify an event broker module that should
+# by loaded by Nagios at startup.  Use multiple directives if you want
+# to load more than one module.  Arguments that should be passed to
+# the module at startup are seperated from the module path by a space.
+#
+#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+# WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING
+#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+#
+# Do NOT overwrite modules while they are being used by Nagios or Nagios
+# will crash in a fiery display of SEGFAULT glory.  This is a bug/limitation
+# either in dlopen(), the kernel, and/or the filesystem.  And maybe Nagios...
+#
+# The correct/safe way of updating a module is by using one of these methods:
+#    1. Shutdown Nagios, replace the module file, restart Nagios
+#    2. Delete the original module file, move the new module file into place, restart Nagios
+#
+# Example:
+#
+#   broker_module=<modulepath> [moduleargs]
+
+#broker_module=/somewhere/module1.o
+#broker_module=/somewhere/module2.o arg1 arg2=3 debug=0
+{% if enable_livestatus -%}
+broker_module=/usr/lib/check_mk/livestatus.o {{ livestatus_path }} {{ livestatus_args }}
+{% endif %}
+
+
+# LOG ROTATION METHOD
+# This is the log rotation method that Nagios should use to rotate
+# the main log file. Values are as follows..
+#    n    = None - don't rotate the log
+#    h    = Hourly rotation (top of the hour)
+#    d    = Daily rotation (midnight every day)
+#    w    = Weekly rotation (midnight on Saturday evening)
+#    m    = Monthly rotation (midnight last day of month)
+
+log_rotation_method={{ log_rotation_method }}
+
+
+
+# LOG ARCHIVE PATH
+# This is the directory where archived (rotated) log files should be
+# placed (assuming you've chosen to do log rotation).
+
+log_archive_path={{ log_archive_path }}
+
+
+
+# LOGGING OPTIONS
+# If you want messages logged to the syslog facility, as well as the
+# Nagios log file set this option to 1.  If not, set it to 0.
+
+use_syslog={{ use_syslog }}
+
+
+
+# NOTIFICATION LOGGING OPTION
+# If you don't want notifications to be logged, set this value to 0.
+# If notifications should be logged, set the value to 1.
+
+log_notifications=1
+
+
+
+# SERVICE RETRY LOGGING OPTION
+# If you don't want service check retries to be logged, set this value
+# to 0.  If retries should be logged, set the value to 1.
+
+log_service_retries=1
+
+
+
+# HOST RETRY LOGGING OPTION
+# If you don't want host check retries to be logged, set this value to
+# 0.  If retries should be logged, set the value to 1.
+
+log_host_retries=1
+
+
+
+# EVENT HANDLER LOGGING OPTION
+# If you don't want host and service event handlers to be logged, set
+# this value to 0.  If event handlers should be logged, set the value
+# to 1.
+
+log_event_handlers=1
+
+
+
+# INITIAL STATES LOGGING OPTION
+# If you want Nagios to log all initial host and service states to
+# the main log file (the first time the service or host is checked)
+# you can enable this option by setting this value to 1.  If you
+# are not using an external application that does long term state
+# statistics reporting, you do not need to enable this option.  In
+# this case, set the value to 0.
+
+log_initial_states=0
+
+
+
+# EXTERNAL COMMANDS LOGGING OPTION
+# If you don't want Nagios to log external commands, set this value
+# to 0.  If external commands should be logged, set this value to 1.
+# Note: This option does not include logging of passive service
+# checks - see the option below for controlling whether or not
+# passive checks are logged.
+
+log_external_commands=1
+
+
+
+# PASSIVE CHECKS LOGGING OPTION
+# If you don't want Nagios to log passive host and service checks, set
+# this value to 0.  If passive checks should be logged, set
+# this value to 1.
+
+log_passive_checks=1
+
+
+
+# GLOBAL HOST AND SERVICE EVENT HANDLERS
+# These options allow you to specify a host and service event handler
+# command that is to be run for every host or service state change.
+# The global event handler is executed immediately prior to the event
+# handler that you have optionally specified in each host or
+# service definition. The command argument is the short name of a
+# command definition that you define in your host configuration file.
+# Read the HTML docs for more information.
+
+#global_host_event_handler=somecommand
+#global_service_event_handler=somecommand
+
+
+
+# SERVICE INTER-CHECK DELAY METHOD
+# This is the method that Nagios should use when initially
+# "spreading out" service checks when it starts monitoring.  The
+# default is to use smart delay calculation, which will try to
+# space all service checks out evenly to minimize CPU load.
+# Using the dumb setting will cause all checks to be scheduled
+# at the same time (with no delay between them)!  This is not a
+# good thing for production, but is useful when testing the
+# parallelization functionality.
+#    n    = None - don't use any delay between checks
+#    d    = Use a "dumb" delay of 1 second between checks
+#    s    = Use "smart" inter-check delay calculation
+#       x.xx    = Use an inter-check delay of x.xx seconds
+
+service_inter_check_delay_method=s
+
+
+
+# MAXIMUM SERVICE CHECK SPREAD
+# This variable determines the timeframe (in minutes) from the
+# program start time that an initial check of all services should
+# be completed.  Default is 30 minutes.
+
+max_service_check_spread=30
+
+
+
+# SERVICE CHECK INTERLEAVE FACTOR
+# This variable determines how service checks are interleaved.
+# Interleaving the service checks allows for a more even
+# distribution of service checks and reduced load on remote
+# hosts.  Setting this value to 1 is equivalent to how versions
+# of Nagios previous to 0.0.5 did service checks.  Set this
+# value to s (smart) for automatic calculation of the interleave
+# factor unless you have a specific reason to change it.
+#       s       = Use "smart" interleave factor calculation
+#       x       = Use an interleave factor of x, where x is a
+#                 number greater than or equal to 1.
+
+service_interleave_factor=s
+
+
+
+# HOST INTER-CHECK DELAY METHOD
+# This is the method that Nagios should use when initially
+# "spreading out" host checks when it starts monitoring.  The
+# default is to use smart delay calculation, which will try to
+# space all host checks out evenly to minimize CPU load.
+# Using the dumb setting will cause all checks to be scheduled
+# at the same time (with no delay between them)!
+#    n    = None - don't use any delay between checks
+#    d    = Use a "dumb" delay of 1 second between checks
+#    s    = Use "smart" inter-check delay calculation
+#       x.xx    = Use an inter-check delay of x.xx seconds
+
+host_inter_check_delay_method=s
+
+
+
+# MAXIMUM HOST CHECK SPREAD
+# This variable determines the timeframe (in minutes) from the
+# program start time that an initial check of all hosts should
+# be completed.  Default is 30 minutes.
+
+max_host_check_spread=30
+
+
+
+# MAXIMUM CONCURRENT SERVICE CHECKS
+# This option allows you to specify the maximum number of
+# service checks that can be run in parallel at any given time.
+# Specifying a value of 1 for this variable essentially prevents
+# any service checks from being parallelized.  A value of 0
+# will not restrict the number of concurrent checks that are
+# being executed.
+
+max_concurrent_checks=0
+
+
+
+# HOST AND SERVICE CHECK REAPER FREQUENCY
+# This is the frequency (in seconds!) that Nagios will process
+# the results of host and service checks.
+
+check_result_reaper_frequency=10
+
+
+
+
+# MAX CHECK RESULT REAPER TIME
+# This is the max amount of time (in seconds) that  a single
+# check result reaper event will be allowed to run before
+# returning control back to Nagios so it can perform other
+# duties.
+
+max_check_result_reaper_time=30
+
+
+
+
+# CHECK RESULT PATH
+# This is directory where Nagios stores the results of host and
+# service checks that have not yet been processed.
+#
+# Note: Make sure that only one instance of Nagios has access
+# to this directory!
+
+check_result_path=/var/lib/nagios3/spool/checkresults
+
+
+
+
+# MAX CHECK RESULT FILE AGE
+# This option determines the maximum age (in seconds) which check
+# result files are considered to be valid.  Files older than this
+# threshold will be mercilessly deleted without further processing.
+
+max_check_result_file_age=3600
+
+
+
+
+# CACHED HOST CHECK HORIZON
+# This option determines the maximum amount of time (in seconds)
+# that the state of a previous host check is considered current.
+# Cached host states (from host checks that were performed more
+# recently that the timeframe specified by this value) can immensely
+# improve performance in regards to the host check logic.
+# Too high of a value for this option may result in inaccurate host
+# states being used by Nagios, while a lower value may result in a
+# performance hit for host checks.  Use a value of 0 to disable host
+# check caching.
+
+cached_host_check_horizon=15
+
+
+
+# CACHED SERVICE CHECK HORIZON
+# This option determines the maximum amount of time (in seconds)
+# that the state of a previous service check is considered current.
+# Cached service states (from service checks that were performed more
+# recently that the timeframe specified by this value) can immensely
+# improve performance in regards to predictive dependency checks.
+# Use a value of 0 to disable service check caching.
+
+cached_service_check_horizon=15
+
+
+
+# ENABLE PREDICTIVE HOST DEPENDENCY CHECKS
+# This option determines whether or not Nagios will attempt to execute
+# checks of hosts when it predicts that future dependency logic test
+# may be needed.  These predictive checks can help ensure that your
+# host dependency logic works well.
+# Values:
+#  0 = Disable predictive checks
+#  1 = Enable predictive checks (default)
+
+enable_predictive_host_dependency_checks=1
+
+
+
+# ENABLE PREDICTIVE SERVICE DEPENDENCY CHECKS
+# This option determines whether or not Nagios will attempt to execute
+# checks of service when it predicts that future dependency logic test
+# may be needed.  These predictive checks can help ensure that your
+# service dependency logic works well.
+# Values:
+#  0 = Disable predictive checks
+#  1 = Enable predictive checks (default)
+
+enable_predictive_service_dependency_checks=1
+
+
+
+# SOFT STATE DEPENDENCIES
+# This option determines whether or not Nagios will use soft state
+# information when checking host and service dependencies. Normally
+# Nagios will only use the latest hard host or service state when
+# checking dependencies. If you want it to use the latest state (regardless
+# of whether its a soft or hard state type), enable this option.
+# Values:
+#  0 = Don't use soft state dependencies (default)
+#  1 = Use soft state dependencies
+
+soft_state_dependencies=0
+
+
+
+# TIME CHANGE ADJUSTMENT THRESHOLDS
+# These options determine when Nagios will react to detected changes
+# in system time (either forward or backwards).
+
+#time_change_threshold=900
+
+
+
+# AUTO-RESCHEDULING OPTION
+# This option determines whether or not Nagios will attempt to
+# automatically reschedule active host and service checks to
+# "smooth" them out over time.  This can help balance the load on
+# the monitoring server.
+# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE
+# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY
+
+auto_reschedule_checks=0
+
+
+
+# AUTO-RESCHEDULING INTERVAL
+# This option determines how often (in seconds) Nagios will
+# attempt to automatically reschedule checks.  This option only
+# has an effect if the auto_reschedule_checks option is enabled.
+# Default is 30 seconds.
+# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE
+# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY
+
+auto_rescheduling_interval=30
+
+
+
+# AUTO-RESCHEDULING WINDOW
+# This option determines the "window" of time (in seconds) that
+# Nagios will look at when automatically rescheduling checks.
+# Only host and service checks that occur in the next X seconds
+# (determined by this variable) will be rescheduled. This option
+# only has an effect if the auto_reschedule_checks option is
+# enabled.  Default is 180 seconds (3 minutes).
+# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE
+# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY
+
+auto_rescheduling_window=180
+
+
+
+# SLEEP TIME
+# This is the number of seconds to sleep between checking for system
+# events and service checks that need to be run.
+
+sleep_time=0.25
+
+
+
+# TIMEOUT VALUES
+# These options control how much time Nagios will allow various
+# types of commands to execute before killing them off.  Options
+# are available for controlling maximum time allotted for
+# service checks, host checks, event handlers, notifications, the
+# ocsp command, and performance data commands.  All values are in
+# seconds.
+
+service_check_timeout=60
+host_check_timeout=30
+event_handler_timeout=30
+notification_timeout=30
+ocsp_timeout=5
+perfdata_timeout=5
+
+
+
+# RETAIN STATE INFORMATION
+# This setting determines whether or not Nagios will save state
+# information for services and hosts before it shuts down.  Upon
+# startup Nagios will reload all saved service and host state
+# information before starting to monitor.  This is useful for
+# maintaining long-term data on state statistics, etc, but will
+# slow Nagios down a bit when it (re)starts.  Since its only
+# a one-time penalty, I think its well worth the additional
+# startup delay.
+
+retain_state_information=1
+
+
+
+# STATE RETENTION FILE
+# This is the file that Nagios should use to store host and
+# service state information before it shuts down.  The state
+# information in this file is also read immediately prior to
+# starting to monitor the network when Nagios is restarted.
+# This file is used only if the retain_state_information
+# variable is set to 1.
+
+state_retention_file=/var/lib/nagios3/retention.dat
+
+
+
+# RETENTION DATA UPDATE INTERVAL
+# This setting determines how often (in minutes) that Nagios
+# will automatically save retention data during normal operation.
+# If you set this value to 0, Nagios will not save retention
+# data at regular interval, but it will still save retention
+# data before shutting down or restarting.  If you have disabled
+# state retention, this option has no effect.
+
+retention_update_interval=60
+
+
+
+# USE RETAINED PROGRAM STATE
+# This setting determines whether or not Nagios will set
+# program status variables based on the values saved in the
+# retention file.  If you want to use retained program status
+# information, set this value to 1.  If not, set this value
+# to 0.
+
+use_retained_program_state=1
+
+
+
+# USE RETAINED SCHEDULING INFO
+# This setting determines whether or not Nagios will retain
+# the scheduling info (next check time) for hosts and services
+# based on the values saved in the retention file.  If you
+# If you want to use retained scheduling info, set this
+# value to 1.  If not, set this value to 0.
+
+use_retained_scheduling_info=1
+
+
+
+# RETAINED ATTRIBUTE MASKS (ADVANCED FEATURE)
+# The following variables are used to specify specific host and
+# service attributes that should *not* be retained by Nagios during
+# program restarts.
+#
+# The values of the masks are bitwise ANDs of values specified
+# by the "MODATTR_" definitions found in include/common.h.
+# For example, if you do not want the current enabled/disabled state
+# of flap detection and event handlers for hosts to be retained, you
+# would use a value of 24 for the host attribute mask...
+# MODATTR_EVENT_HANDLER_ENABLED (8) + MODATTR_FLAP_DETECTION_ENABLED (16) = 24
+
+# This mask determines what host attributes are not retained
+retained_host_attribute_mask=0
+
+# This mask determines what service attributes are not retained
+retained_service_attribute_mask=0
+
+# These two masks determine what process attributes are not retained.
+# There are two masks, because some process attributes have host and service
+# options.  For example, you can disable active host checks, but leave active
+# service checks enabled.
+retained_process_host_attribute_mask=0
+retained_process_service_attribute_mask=0
+
+# These two masks determine what contact attributes are not retained.
+# There are two masks, because some contact attributes have host and
+# service options.  For example, you can disable host notifications for
+# a contact, but leave service notifications enabled for them.
+retained_contact_host_attribute_mask=0
+retained_contact_service_attribute_mask=0
+
+
+
+# INTERVAL LENGTH
+# This is the seconds per unit interval as used in the
+# host/contact/service configuration files.  Setting this to 60 means
+# that each interval is one minute long (60 seconds).  Other settings
+# have not been tested much, so your mileage is likely to vary...
+
+interval_length=60
+
+
+
+# CHECK FOR UPDATES
+# This option determines whether Nagios will automatically check to
+# see if new updates (releases) are available.  It is recommend that you
+# enable this option to ensure that you stay on top of the latest critical
+# patches to Nagios.  Nagios is critical to you - make sure you keep it in
+# good shape.  Nagios will check once a day for new updates. Data collected
+# by Nagios Enterprises from the update check is processed in accordance
+# with our privacy policy - see http://api.nagios.org for details.
+
+check_for_updates=1
+
+
+
+# BARE UPDATE CHECK
+# This option deterines what data Nagios will send to api.nagios.org when
+# it checks for updates.  By default, Nagios will send information on the
+# current version of Nagios you have installed, as well as an indicator as
+# to whether this was a new installation or not.  Nagios Enterprises uses
+# this data to determine the number of users running specific version of
+# Nagios.  Enable this option if you do not want this information to be sent.
+
+bare_update_check=0
+
+
+
+# AGGRESSIVE HOST CHECKING OPTION
+# If you don't want to turn on aggressive host checking features, set
+# this value to 0 (the default).  Otherwise set this value to 1 to
+# enable the aggressive check option.  Read the docs for more info
+# on what aggressive host check is or check out the source code in
+# base/checks.c
+
+use_aggressive_host_checking=0
+
+
+
+# SERVICE CHECK EXECUTION OPTION
+# This determines whether or not Nagios will actively execute
+# service checks when it initially starts.  If this option is
+# disabled, checks are not actively made, but Nagios can still
+# receive and process passive check results that come in.  Unless
+# you're implementing redundant hosts or have a special need for
+# disabling the execution of service checks, leave this enabled!
+# Values: 1 = enable checks, 0 = disable checks
+
+execute_service_checks=1
+
+
+
+# PASSIVE SERVICE CHECK ACCEPTANCE OPTION
+# This determines whether or not Nagios will accept passive
+# service checks results when it initially (re)starts.
+# Values: 1 = accept passive checks, 0 = reject passive checks
+
+accept_passive_service_checks=1
+
+
+
+# HOST CHECK EXECUTION OPTION
+# This determines whether or not Nagios will actively execute
+# host checks when it initially starts.  If this option is
+# disabled, checks are not actively made, but Nagios can still
+# receive and process passive check results that come in.  Unless
+# you're implementing redundant hosts or have a special need for
+# disabling the execution of host checks, leave this enabled!
+# Values: 1 = enable checks, 0 = disable checks
+
+execute_host_checks=1
+
+
+
+# PASSIVE HOST CHECK ACCEPTANCE OPTION
+# This determines whether or not Nagios will accept passive
+# host checks results when it initially (re)starts.
+# Values: 1 = accept passive checks, 0 = reject passive checks
+
+accept_passive_host_checks=1
+
+
+
+# NOTIFICATIONS OPTION
+# This determines whether or not Nagios will sent out any host or
+# service notifications when it is initially (re)started.
+# Values: 1 = enable notifications, 0 = disable notifications
+
+enable_notifications=1
+
+
+
+# EVENT HANDLER USE OPTION
+# This determines whether or not Nagios will run any host or
+# service event handlers when it is initially (re)started.  Unless
+# you're implementing redundant hosts, leave this option enabled.
+# Values: 1 = enable event handlers, 0 = disable event handlers
+
+enable_event_handlers=1
+
+
+
+# PROCESS PERFORMANCE DATA OPTION
+# This determines whether or not Nagios will process performance
+# data returned from service and host checks.  If this option is
+# enabled, host performance data will be processed using the
+# host_perfdata_command (defined below) and service performance
+# data will be processed using the service_perfdata_command (also
+# defined below).  Read the HTML docs for more information on
+# performance data.
+# Values: 1 = process performance data, 0 = do not process performance data
+
+process_performance_data=0
+
+
+
+# HOST AND SERVICE PERFORMANCE DATA PROCESSING COMMANDS
+# These commands are run after every host and service check is
+# performed.  These commands are executed only if the
+# enable_performance_data option (above) is set to 1.  The command
+# argument is the short name of a command definition that you
+# define in your host configuration file.  Read the HTML docs for
+# more information on performance data.
+
+#host_perfdata_command=process-host-perfdata
+#service_perfdata_command=process-service-perfdata
+
+
+
+# HOST AND SERVICE PERFORMANCE DATA FILES
+# These files are used to store host and service performance data.
+# Performance data is only written to these files if the
+# enable_performance_data option (above) is set to 1.
+
+#host_perfdata_file=/tmp/host-perfdata
+#service_perfdata_file=/tmp/service-perfdata
+
+
+
+# HOST AND SERVICE PERFORMANCE DATA FILE TEMPLATES
+# These options determine what data is written (and how) to the
+# performance data files.  The templates may contain macros, special
+# characters (\t for tab, \r for carriage return, \n for newline)
+# and plain text.  A newline is automatically added after each write
+# to the performance data file.  Some examples of what you can do are
+# shown below.
+
+#host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\t$HOSTEXECUTIONTIME$\t$HOSTOUTPUT$\t$HOSTPERFDATA$
+#service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$
+
+
+
+# HOST AND SERVICE PERFORMANCE DATA FILE MODES
+# This option determines whether or not the host and service
+# performance data files are opened in write ("w") or append ("a")
+# mode. If you want to use named pipes, you should use the special
+# pipe ("p") mode which avoid blocking at startup, otherwise you will
+# likely want the defult append ("a") mode.
+
+#host_perfdata_file_mode=a
+#service_perfdata_file_mode=a
+
+
+
+# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING INTERVAL
+# These options determine how often (in seconds) the host and service
+# performance data files are processed using the commands defined
+# below.  A value of 0 indicates the files should not be periodically
+# processed.
+
+#host_perfdata_file_processing_interval=0
+#service_perfdata_file_processing_interval=0
+
+
+
+# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING COMMANDS
+# These commands are used to periodically process the host and
+# service performance data files.  The interval at which the
+# processing occurs is determined by the options above.
+
+#host_perfdata_file_processing_command=process-host-perfdata-file
+#service_perfdata_file_processing_command=process-service-perfdata-file
+
+
+
+# HOST AND SERVICE PERFORMANCE DATA PROCESS EMPTY RESULTS
+# THese options determine wether the core will process empty perfdata
+# results or not. This is needed for distributed monitoring, and intentionally
+# turned on by default.
+# If you don't require empty perfdata - saving some cpu cycles
+# on unwanted macro calculation - you can turn that off. Be careful!
+# Values: 1 = enable, 0 = disable
+
+#host_perfdata_process_empty_results=1
+#service_perfdata_process_empty_results=1
+
+
+# OBSESS OVER SERVICE CHECKS OPTION
+# This determines whether or not Nagios will obsess over service
+# checks and run the ocsp_command defined below.  Unless you're
+# planning on implementing distributed monitoring, do not enable
+# this option.  Read the HTML docs for more information on
+# implementing distributed monitoring.
+# Values: 1 = obsess over services, 0 = do not obsess (default)
+
+obsess_over_services=0
+
+
+
+# OBSESSIVE COMPULSIVE SERVICE PROCESSOR COMMAND
+# This is the command that is run for every service check that is
+# processed by Nagios.  This command is executed only if the
+# obsess_over_services option (above) is set to 1.  The command
+# argument is the short name of a command definition that you
+# define in your host configuration file. Read the HTML docs for
+# more information on implementing distributed monitoring.
+
+#ocsp_command=somecommand
+
+
+
+# OBSESS OVER HOST CHECKS OPTION
+# This determines whether or not Nagios will obsess over host
+# checks and run the ochp_command defined below.  Unless you're
+# planning on implementing distributed monitoring, do not enable
+# this option.  Read the HTML docs for more information on
+# implementing distributed monitoring.
+# Values: 1 = obsess over hosts, 0 = do not obsess (default)
+
+obsess_over_hosts=0
+
+
+
+# OBSESSIVE COMPULSIVE HOST PROCESSOR COMMAND
+# This is the command that is run for every host check that is
+# processed by Nagios.  This command is executed only if the
+# obsess_over_hosts option (above) is set to 1.  The command
+# argument is the short name of a command definition that you
+# define in your host configuration file. Read the HTML docs for
+# more information on implementing distributed monitoring.
+
+#ochp_command=somecommand
+
+
+
+# TRANSLATE PASSIVE HOST CHECKS OPTION
+# This determines whether or not Nagios will translate
+# DOWN/UNREACHABLE passive host check results into their proper
+# state for this instance of Nagios.  This option is useful
+# if you have distributed or failover monitoring setup.  In
+# these cases your other Nagios servers probably have a different
+# "view" of the network, with regards to the parent/child relationship
+# of hosts.  If a distributed monitoring server thinks a host
+# is DOWN, it may actually be UNREACHABLE from the point of
+# this Nagios instance.  Enabling this option will tell Nagios
+# to translate any DOWN or UNREACHABLE host states it receives
+# passively into the correct state from the view of this server.
+# Values: 1 = perform translation, 0 = do not translate (default)
+
+translate_passive_host_checks=0
+
+
+
+# PASSIVE HOST CHECKS ARE SOFT OPTION
+# This determines whether or not Nagios will treat passive host
+# checks as being HARD or SOFT.  By default, a passive host check
+# result will put a host into a HARD state type.  This can be changed
+# by enabling this option.
+# Values: 0 = passive checks are HARD, 1 = passive checks are SOFT
+
+passive_host_checks_are_soft=0
+
+
+
+# ORPHANED HOST/SERVICE CHECK OPTIONS
+# These options determine whether or not Nagios will periodically
+# check for orphaned host service checks.  Since service checks are
+# not rescheduled until the results of their previous execution
+# instance are processed, there exists a possibility that some
+# checks may never get rescheduled.  A similar situation exists for
+# host checks, although the exact scheduling details differ a bit
+# from service checks.  Orphaned checks seem to be a rare
+# problem and should not happen under normal circumstances.
+# If you have problems with service checks never getting
+# rescheduled, make sure you have orphaned service checks enabled.
+# Values: 1 = enable checks, 0 = disable checks
+
+check_for_orphaned_services=1
+check_for_orphaned_hosts=1
+
+
+
+# SERVICE FRESHNESS CHECK OPTION
+# This option determines whether or not Nagios will periodically
+# check the "freshness" of service results.  Enabling this option
+# is useful for ensuring passive checks are received in a timely
+# manner.
+# Values: 1 = enabled freshness checking, 0 = disable freshness checking
+
+check_service_freshness=1
+
+
+
+# SERVICE FRESHNESS CHECK INTERVAL
+# This setting determines how often (in seconds) Nagios will
+# check the "freshness" of service check results.  If you have
+# disabled service freshness checking, this option has no effect.
+
+service_freshness_check_interval=60
+
+
+
+# SERVICE CHECK TIMEOUT STATE
+# This setting determines the state Nagios will report when a
+# service check times out - that is does not respond within
+# service_check_timeout seconds.  This can be useful if a
+# machine is running at too high a load and you do not want
+# to consider a failed service check to be critical (the default).
+# Valid settings are:
+# c - Critical (default)
+# u - Unknown
+# w - Warning
+# o - OK
+
+service_check_timeout_state=c
+
+
+
+# HOST FRESHNESS CHECK OPTION
+# This option determines whether or not Nagios will periodically
+# check the "freshness" of host results.  Enabling this option
+# is useful for ensuring passive checks are received in a timely
+# manner.
+# Values: 1 = enabled freshness checking, 0 = disable freshness checking
+
+check_host_freshness=0
+
+
+
+# HOST FRESHNESS CHECK INTERVAL
+# This setting determines how often (in seconds) Nagios will
+# check the "freshness" of host check results.  If you have
+# disabled host freshness checking, this option has no effect.
+
+host_freshness_check_interval=60
+
+
+
+
+# ADDITIONAL FRESHNESS THRESHOLD LATENCY
+# This setting determines the number of seconds that Nagios
+# will add to any host and service freshness thresholds that
+# it calculates (those not explicitly specified by the user).
+
+additional_freshness_latency=15
+
+
+
+
+# FLAP DETECTION OPTION
+# This option determines whether or not Nagios will try
+# and detect hosts and services that are "flapping".
+# Flapping occurs when a host or service changes between
+# states too frequently.  When Nagios detects that a
+# host or service is flapping, it will temporarily suppress
+# notifications for that host/service until it stops
+# flapping.  Flap detection is very experimental, so read
+# the HTML documentation before enabling this feature!
+# Values: 1 = enable flap detection
+#         0 = disable flap detection (default)
+
+enable_flap_detection=1
+
+
+
+# FLAP DETECTION THRESHOLDS FOR HOSTS AND SERVICES
+# Read the HTML documentation on flap detection for
+# an explanation of what this option does.  This option
+# has no effect if flap detection is disabled.
+
+low_service_flap_threshold=5.0
+high_service_flap_threshold=20.0
+low_host_flap_threshold=5.0
+high_host_flap_threshold=20.0
+
+
+
+# DATE FORMAT OPTION
+# This option determines how short dates are displayed. Valid options
+# include:
+#    us        (MM-DD-YYYY HH:MM:SS)
+#    euro        (DD-MM-YYYY HH:MM:SS)
+#    iso8601        (YYYY-MM-DD HH:MM:SS)
+#    strict-iso8601    (YYYY-MM-DDTHH:MM:SS)
+#
+
+date_format=iso8601
+
+
+
+
+# TIMEZONE OFFSET
+# This option is used to override the default timezone that this
+# instance of Nagios runs in.  If not specified, Nagios will use
+# the system configured timezone.
+#
+# NOTE: In order to display the correct timezone in the CGIs, you
+# will also need to alter the Apache directives for the CGI path
+# to include your timezone.  Example:
+#
+#   <Directory "/usr/local/nagios/sbin/">
+#      SetEnv TZ "Australia/Brisbane"
+#      ...
+#   </Directory>
+
+#use_timezone=US/Mountain
+#use_timezone=Australia/Brisbane
+
+
+
+
+# P1.PL FILE LOCATION
+# This value determines where the p1.pl perl script (used by the
+# embedded Perl interpreter) is located.  If you didn't compile
+# Nagios with embedded Perl support, this option has no effect.
+
+p1_file=/usr/lib/nagios3/p1.pl
+
+
+
+# EMBEDDED PERL INTERPRETER OPTION
+# This option determines whether or not the embedded Perl interpreter
+# will be enabled during runtime.  This option has no effect if Nagios
+# has not been compiled with support for embedded Perl.
+# Values: 0 = disable interpreter, 1 = enable interpreter
+
+enable_embedded_perl=1
+
+
+
+# EMBEDDED PERL USAGE OPTION
+# This option determines whether or not Nagios will process Perl plugins
+# and scripts with the embedded Perl interpreter if the plugins/scripts
+# do not explicitly indicate whether or not it is okay to do so. Read
+# the HTML documentation on the embedded Perl interpreter for more
+# information on how this option works.
+
+use_embedded_perl_implicitly=1
+
+
+
+# ILLEGAL OBJECT NAME CHARACTERS
+# This option allows you to specify illegal characters that cannot
+# be used in host names, service descriptions, or names of other
+# object types.
+
+illegal_object_name_chars=`~!$%^&*|'"<>?,()=
+
+
+
+# ILLEGAL MACRO OUTPUT CHARACTERS
+# This option allows you to specify illegal characters that are
+# stripped from macros before being used in notifications, event
+# handlers, etc.  This DOES NOT affect macros used in service or
+# host check commands.
+# The following macros are stripped of the characters you specify:
+#    $HOSTOUTPUT$
+#    $HOSTPERFDATA$
+#    $HOSTACKAUTHOR$
+#    $HOSTACKCOMMENT$
+#    $SERVICEOUTPUT$
+#    $SERVICEPERFDATA$
+#    $SERVICEACKAUTHOR$
+#    $SERVICEACKCOMMENT$
+
+illegal_macro_output_chars=`~$&|'"<>
+
+
+
+# REGULAR EXPRESSION MATCHING
+# This option controls whether or not regular expression matching
+# takes place in the object config files.  Regular expression
+# matching is used to match host, hostgroup, service, and service
+# group names/descriptions in some fields of various object types.
+# Values: 1 = enable regexp matching, 0 = disable regexp matching
+
+use_regexp_matching=0
+
+
+
+# "TRUE" REGULAR EXPRESSION MATCHING
+# This option controls whether or not "true" regular expression
+# matching takes place in the object config files.  This option
+# only has an effect if regular expression matching is enabled
+# (see above).  If this option is DISABLED, regular expression
+# matching only occurs if a string contains wildcard characters
+# (* and ?).  If the option is ENABLED, regexp matching occurs
+# all the time (which can be annoying).
+# Values: 1 = enable true matching, 0 = disable true matching
+
+use_true_regexp_matching=0
+
+
+
+# ADMINISTRATOR EMAIL/PAGER ADDRESSES
+# The email and pager address of a global administrator (likely you).
+# Nagios never uses these values itself, but you can access them by
+# using the $ADMINEMAIL$ and $ADMINPAGER$ macros in your notification
+# commands.
+
+admin_email={{ admin_email }}
+admin_pager={{ admin_pager }}
+
+
+
+# DAEMON CORE DUMP OPTION
+# This option determines whether or not Nagios is allowed to create
+# a core dump when it runs as a daemon.  Note that it is generally
+# considered bad form to allow this, but it may be useful for
+# debugging purposes.  Enabling this option doesn't guarantee that
+# a core file will be produced, but that's just life...
+# Values: 1 - Allow core dumps
+#         0 - Do not allow core dumps (default)
+
+daemon_dumps_core={{ daemon_dumps_core }}
+
+
+
+# LARGE INSTALLATION TWEAKS OPTION
+# This option determines whether or not Nagios will take some shortcuts
+# which can save on memory and CPU usage in large Nagios installations.
+# Read the documentation for more information on the benefits/tradeoffs
+# of enabling this option.
+# Values: 1 - Enabled tweaks
+#         0 - Disable tweaks (default)
+
+use_large_installation_tweaks=0
+
+
+
+# ENABLE ENVIRONMENT MACROS
+# This option determines whether or not Nagios will make all standard
+# macros available as environment variables when host/service checks
+# and system commands (event handlers, notifications, etc.) are
+# executed.  Enabling this option can cause performance issues in
+# large installations, as it will consume a bit more memory and (more
+# importantly) consume more CPU.
+# Values: 1 - Enable environment variable macros (default)
+#         0 - Disable environment variable macros
+
+enable_environment_macros=1
+
+
+
+# CHILD PROCESS MEMORY OPTION
+# This option determines whether or not Nagios will free memory in
+# child processes (processed used to execute system commands and host/
+# service checks).  If you specify a value here, it will override
+# program defaults.
+# Value: 1 - Free memory in child processes
+#        0 - Do not free memory in child processes
+
+#free_child_process_memory=1
+
+
+
+# CHILD PROCESS FORKING BEHAVIOR
+# This option determines how Nagios will fork child processes
+# (used to execute system commands and host/service checks).  Normally
+# child processes are fork()ed twice, which provides a very high level
+# of isolation from problems.  Fork()ing once is probably enough and will
+# save a great deal on CPU usage (in large installs), so you might
+# want to consider using this.  If you specify a value here, it will
+# program defaults.
+# Value: 1 - Child processes fork() twice
+#        0 - Child processes fork() just once
+
+#child_processes_fork_twice=1
+
+
+
+# DEBUG LEVEL
+# This option determines how much (if any) debugging information will
+# be written to the debug file.  OR values together to log multiple
+# types of information.
+# Values:
+#          -1 = Everything
+#          0 = Nothing
+#       1 = Functions
+#          2 = Configuration
+#          4 = Process information
+#       8 = Scheduled events
+#          16 = Host/service checks
+#          32 = Notifications
+#          64 = Event broker
+#          128 = External commands
+#          256 = Commands
+#          512 = Scheduled downtime
+#          1024 = Comments
+#          2048 = Macros
+
+debug_level={{ debug_level }}
+
+
+
+# DEBUG VERBOSITY
+# This option determines how verbose the debug log out will be.
+# Values: 0 = Brief output
+#         1 = More detailed
+#         2 = Very detailed
+
+debug_verbosity={{ debug_verbosity }}
+
+
+
+# DEBUG FILE
+# This option determines where Nagios should write debugging information.
+
+debug_file={{ debug_file }}
+
+
+
+# MAX DEBUG FILE SIZE
+# This option determines the maximum size (in bytes) of the debug file.  If
+# the file grows larger than this size, it will be renamed with a .old
+# extension.  If a file already exists with a .old extension it will
+# automatically be deleted.  This helps ensure your disk space usage doesn't
+# get out of control when debugging Nagios.
+
+max_debug_file_size=1000000
diff --git a/src/templates/pagerduty_nagios.cfg.j2 b/src/templates/pagerduty_nagios.cfg.j2
new file mode 100644
index 0000000..3dfd0fe
--- /dev/null
+++ b/src/templates/pagerduty_nagios.cfg.j2
@@ -0,0 +1,26 @@
+#------------------------------------------------
+# This file is juju managed
+# File created on: {{ today }}
+#------------------------------------------------
+
+define contact {
+       contact_name                             pagerduty
+       alias                                    PagerDuty Pseudo-Contact
+       service_notification_period              24x7
+       host_notification_period                 24x7
+       service_notification_options             {{ notification_levels }}
+       host_notification_options                d,r
+       service_notification_commands            notify-service-by-pagerduty
+       host_notification_commands               notify-host-by-pagerduty
+       pager                                    {{ pagerduty_key }}
+}
+
+define command {
+       command_name     notify-service-by-pagerduty
+       command_line     /usr/local/bin/pagerduty_nagios.pl enqueue -f pd_nagios_object=service -q {{ pagerduty_path }}
+}
+
+define command {
+       command_name     notify-host-by-pagerduty
+       command_line     /usr/local/bin/pagerduty_nagios.pl enqueue -f pd_nagios_object=host -q {{ pagerduty_path }}
+}
diff --git a/src/tests/functional/requirements.txt b/src/tests/functional/requirements.txt
new file mode 100644
index 0000000..f76bfbb
--- /dev/null
+++ b/src/tests/functional/requirements.txt
@@ -0,0 +1,6 @@
+flake8
+juju
+mock
+pytest
+pytest-asyncio
+requests
diff --git a/src/tests/functional/test_deploy.py b/src/tests/functional/test_deploy.py
new file mode 100644
index 0000000..51b4f2e
--- /dev/null
+++ b/src/tests/functional/test_deploy.py
@@ -0,0 +1,59 @@
+import os
+
+import pytest
+from juju.model import Model
+
+# Treat tests as coroutines
+pytestmark = pytest.mark.asyncio
+
+series = ['xenial', 'bionic']
+juju_repository = os.getenv('JUJU_REPOSITORY', '.').rstrip('/')
+
+
+@pytest.fixture
+async def model():
+    model = Model()
+    await model.connect_current()
+    yield model
+    await model.disconnect()
+
+
+@pytest.fixture
+async def apps(model):
+    apps = []
+    for entry in series:
+        app = model.applications['nagios-charm-{}'.format(entry)]
+        apps.append(app)
+    return apps
+
+
+@pytest.fixture
+async def units(apps):
+    units = []
+    for app in apps:
+        units.extend(app.units)
+    return units
+
+
+@pytest.mark.parametrize('series', series)
+async def test_nagioscharm_deploy(model, series):
+    # Starts a deploy for each series
+    await model.deploy(
+        '{}/builds/nagios-charm'.format(juju_repository),
+        series=series,
+        application_name='nagios-charm-{}'.format(series))
+    assert True
+
+
+async def test_nagioscharm_status(apps, model):
+    # Verifies status for all deployed series of the charm
+    for app in apps:
+        await model.block_until(lambda: app.status == 'active')
+    assert True
+
+
+async def test_example_action(units):
+    for unit in units:
+        action = await unit.run_action('example-action')
+        action = await action.wait()
+        assert action.status == 'completed'
diff --git a/src/tests/unit/conftest.py b/src/tests/unit/conftest.py
new file mode 100644
index 0000000..f7caa95
--- /dev/null
+++ b/src/tests/unit/conftest.py
@@ -0,0 +1,72 @@
+#!/usr/bin/python3
+import mock
+import pytest
+
+
+# If layer options are used, add this to nagioscharm
+# and import layer in lib_nagios_charm
+@pytest.fixture
+def mock_layers(monkeypatch):
+    import sys
+    sys.modules['charms.layer'] = mock.Mock()
+    sys.modules['reactive'] = mock.Mock()
+
+    # Mock any functions in layers that need to be mocked here
+
+    def options(layer):
+        # mock options for layers here
+        if layer == 'example-layer':
+            options = {'port': 9999}
+            return options
+        else:
+            return None
+
+    monkeypatch.setattr('lib_nagios_charm.layer.options', options)
+
+
+@pytest.fixture
+def mock_hookenv_config(monkeypatch):
+    import yaml
+
+    def mock_config():
+        cfg = {}
+        yml = yaml.load(open('./config.yaml'))
+
+        # Load all defaults
+        for key, value in yml['options'].items():
+            cfg[key] = value['default']
+
+        # Manually add cfg from other layers
+        # cfg['my-other-layer'] = 'mock'
+        return cfg
+
+    monkeypatch.setattr('lib_nagios_charm.hookenv.config', mock_config)
+
+
+@pytest.fixture
+def mock_remote_unit(monkeypatch):
+    monkeypatch.setattr(
+        'lib_nagios_charm.hookenv.remote_unit', lambda: 'unit-mock/0')
+
+
+@pytest.fixture
+def mock_charm_dir(monkeypatch):
+    monkeypatch.setattr(
+        'lib_nagios_charm.hookenv.charm_dir', lambda: '/mock/charm/dir')
+
+
+@pytest.fixture
+def nagioscharm(tmpdir, mock_hookenv_config, mock_charm_dir, monkeypatch):
+    from lib_nagios_charm import NagioscharmHelper
+    helper = NagioscharmHelper()
+
+    # Example config file patching
+    cfg_file = tmpdir.join('example.cfg')
+    with open('./tests/unit/example.cfg', 'r') as src_file:
+        cfg_file.write(src_file.read())
+    helper.example_config_file = cfg_file.strpath
+
+    # Any other functions that load helper will get this version
+    monkeypatch.setattr('lib_nagios_charm.NagioscharmHelper', lambda: helper)
+
+    return helper
diff --git a/src/tests/unit/example.cfg b/src/tests/unit/example.cfg
new file mode 100644
index 0000000..81b1e94
--- /dev/null
+++ b/src/tests/unit/example.cfg
@@ -0,0 +1 @@
+This is an example config file included with the unit tests
diff --git a/src/tests/unit/requirements.txt b/src/tests/unit/requirements.txt
new file mode 100644
index 0000000..9c685e5
--- /dev/null
+++ b/src/tests/unit/requirements.txt
@@ -0,0 +1,5 @@
+charmhelpers
+charms.reactive
+mock
+pytest
+pytest-cov
diff --git a/src/tests/unit/test_actions.py b/src/tests/unit/test_actions.py
new file mode 100644
index 0000000..a181707
--- /dev/null
+++ b/src/tests/unit/test_actions.py
@@ -0,0 +1,12 @@
+import imp
+
+import mock
+
+
+class TestActions():
+    def test_example_action(self, nagioscharm, monkeypatch):
+        mock_function = mock.Mock()
+        monkeypatch.setattr(nagioscharm, 'action_function', mock_function)
+        assert mock_function.call_count == 0
+        imp.load_source('action_function', './actions/example-action')
+        assert mock_function.call_count == 1
diff --git a/src/tests/unit/test_lib.py b/src/tests/unit/test_lib.py
new file mode 100644
index 0000000..cefcdd1
--- /dev/null
+++ b/src/tests/unit/test_lib.py
@@ -0,0 +1,12 @@
+#!/usr/bin/python3
+
+
+class TestLib():
+    def test_pytest(self):
+        assert True
+
+    def test_nagioscharm(self, nagioscharm):
+        ''' See if the helper fixture works to load charm configs '''
+        assert isinstance(nagioscharm.charm_config, dict)
+
+    # Include tests for functions in lib_nagios_charm
diff --git a/src/tox.ini b/src/tox.ini
new file mode 100644
index 0000000..f1e64f7
--- /dev/null
+++ b/src/tox.ini
@@ -0,0 +1,37 @@
+[tox]
+skipsdist=True
+envlist = unit, functional
+skip_missing_interpreters = True
+
+[testenv]
+basepython = python3
+setenv =
+  PYTHONPATH = .
+
+[testenv:unit]
+commands = pytest -v --ignore {toxinidir}/tests/functional --cov=lib --cov=reactive --cov=actions --cov-report=term
+deps = -r{toxinidir}/tests/unit/requirements.txt
+       -r{toxinidir}/requirements.txt
+setenv = PYTHONPATH={toxinidir}/lib
+
+[testenv:functional]
+passenv =
+  HOME
+  JUJU_REPOSITORY
+  PATH
+commands = pytest -v --ignore {toxinidir}/tests/unit
+deps = -r{toxinidir}/tests/functional/requirements.txt
+       -r{toxinidir}/requirements.txt
+
+[testenv:lint]
+commands = flake8
+deps = flake8
+
+[flake8]
+exclude =
+    .git,
+    __pycache__,
+    .tox,
+    lib/pynag
+max-line-length = 120
+max-complexity = 10

References