diff --git a/checkmk/checkmk-files/apache_status b/checkmk/checkmk-files/apache_status
deleted file mode 100644
index ad11fc97f85ea5fba06ce278d1d55ea846820262..0000000000000000000000000000000000000000
--- a/checkmk/checkmk-files/apache_status
+++ /dev/null
@@ -1,182 +0,0 @@
-#!/usr/bin/python
-# -*- encoding: utf-8; py-indent-offset: 4 -*-
-# +------------------------------------------------------------------+
-# |             ____ _               _        __  __ _  __           |
-# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
-# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
-# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
-# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
-# |                                                                  |
-# | Copyright Mathias Kettner 2014             mk@mathias-kettner.de |
-# +------------------------------------------------------------------+
-#
-# This file is part of Check_MK.
-# The official homepage is at http://mathias-kettner.de/check_mk.
-#
-# check_mk is free software;  you can redistribute it and/or modify it
-# under the  terms of the  GNU General Public License  as published by
-# the Free Software Foundation in version 2.  check_mk is  distributed
-# in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with-
-# out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A
-# PARTICULAR PURPOSE. See the  GNU General Public License for more de-
-# tails. You should have  received  a copy of the  GNU  General Public
-# License along with GNU Make; see the file  COPYING.  If  not,  write
-# to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor,
-# Boston, MA 02110-1301 USA.
-
-# Check_MK-Agent-Plugin - Apache Server Status
-#
-# Fetches the server-status page from detected or configured apache
-# processes to gather status information about this apache process.
-#
-# To make this agent plugin work you have to load the status_module
-# into your apache process. It is also needed to enable the "server-status"
-# handler below the URL "/server-status".
-#
-# By default this plugin tries to detect all locally running apache processes
-# and to monitor them. If this is not good for your environment you might
-# create an apache_status.cfg file in MK_CONFDIR and populate the servers
-# list to prevent executing the detection mechanism.
-#
-# It is also possible to override or extend the ssl_ports variable to make the
-# check contact other ports than 443 with HTTPS requests.
-import os
-import re
-import socket
-import sys
-import urllib2
-
-
-config_dir = os.getenv("MK_CONFDIR", "/etc/check_mk")
-config_file = config_dir + "/apache_status.conf"
-
-if not os.path.exists(config_file):
-    config_file = config_dir + "/apache_status.cfg"
-
-# We have to deal with socket timeouts. Python > 2.6
-# supports timeout parameter for the urllib2.urlopen method
-# but we are on a python 2.5 system here which seem to use the
-# default socket timeout. We are local here so  set it to 1 second.
-socket.setdefaulttimeout(5.0)
-
-# None or list of (proto, ipaddress, port) tuples.
-# proto is 'http' or 'https'
-servers = None
-ssl_ports = [443]
-
-
-if os.path.exists(config_file):
-    execfile(config_file)
-
-
-def try_detect_servers():
-    results = []
-
-    for line in os.popen('netstat -tlnp 2>/dev/null').readlines():
-        parts = line.split()
-        # Skip lines with wrong format
-        if len(parts) < 7 or '/' not in parts[6]:
-            continue
-
-        pid, proc = parts[6].split('/', 1)
-        to_replace = re.compile('^.*/')
-        proc = to_replace.sub('', proc)
-
-        procs = [
-            'apache2',
-            'httpd',
-            'httpd-prefork',
-            'httpd2-prefork',
-            'httpd2-worker',
-            'httpd.worker',
-            'fcgi-pm',
-        ]
-        # the pid/proc field length is limited to 19 chars. Thus in case of
-        # long PIDs, the process names are stripped of by that length.
-        # Workaround this problem here
-        procs = [ p[:19 - len(pid) - 1] for p in procs ]
-
-        # Skip unwanted processes
-        if proc not in procs:
-            continue
-
-        address, port = parts[3].rsplit(':', 1)
-        port = int(port)
-
-        # Use localhost when listening globally
-        if address == '0.0.0.0':
-            address = '127.0.0.1'
-        elif address == '::':
-            address = '[::1]'
-        elif ':' in address:
-            address = '[%s]' % address
-
-        # Switch protocol if port is SSL port. In case you use SSL on another
-        # port you would have to change/extend the ssl_port list
-        if port in ssl_ports:
-            proto = 'https'
-        else:
-            proto = 'http'
-
-        results.append((proto, address, port))
-
-    return results
-
-
-if servers is None:
-    servers = try_detect_servers()
-
-
-if not servers:
-    sys.exit(0)
-
-
-sys.stdout.write('<<<apache_status>>>\n')
-for server in servers:
-    if isinstance(server, tuple):
-        proto, address, port = server
-        page = 'server-status'
-    else:
-        proto = server['protocol']
-        address = server['address']
-        port = server['port']
-        page = server.get('page', 'server-status')
-
-    portspec = port and ":%d" % port or ""
-
-    try:
-        url = '%s://%s%s/%s?auto' % (proto, address, portspec, page)
-        is_local = address in ("127.0.0.1", "[::1]", "localhost")
-        # Try to fetch the status page for each server
-        try:
-            request = urllib2.Request(url, headers={"Accept" : "text/plain"})
-            if is_local and proto == 'https':
-                import ssl
-                no_cert_context = ssl.create_default_context()
-                no_cert_context.check_hostname = False
-                no_cert_context.verify_mode = ssl.CERT_NONE
-                fd = urllib2.urlopen(url, context=no_cert_context)
-            else:
-                fd = urllib2.urlopen(request)
-        except urllib2.URLError, e:
-            if 'unknown protocol' in str(e):
-                # HACK: workaround misconfigurations where port 443 is used for
-                # serving non ssl secured http
-                url = 'http://%s%s/server-status?auto' % (address, portspec)
-                fd = urllib2.urlopen(url)
-            else:
-                raise
-
-        for line in fd.read().split('\n'):
-            if not line.strip():
-                continue
-            if line.lstrip()[0] == '<':
-                # Seems to be html output. Skip this server.
-                break
-
-            sys.stdout.write("%s %s %s\n" % (address, port, line))
-    except urllib2.HTTPError, e:
-        sys.stderr.write('HTTP-Error (%s%s): %s %s\n' % (address, portspec, e.code, e))
-
-    except Exception, e:
-        sys.stderr.write('Exception (%s%s): %s\n' % (address, portspec, e))
diff --git a/checkmk/checkmk-files/apache_status.py b/checkmk/checkmk-files/apache_status.py
new file mode 100644
index 0000000000000000000000000000000000000000..992fea29d49cd1ba3a3e352a193c06901f88b8c0
--- /dev/null
+++ b/checkmk/checkmk-files/apache_status.py
@@ -0,0 +1,252 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+# Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2
+# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
+# conditions defined in the file COPYING, which is part of this source code package.
+
+__version__ = "2.0.0p12"
+
+# Checkmk-Agent-Plugin - Apache Server Status
+#
+# Fetches the server-status page from detected or configured apache
+# processes to gather status information about this apache process.
+#
+# To make this agent plugin work you have to load the status_module
+# into your apache process. It is also needed to enable the "server-status"
+# handler below the URL "/server-status".
+#
+# By default this plugin tries to detect all locally running apache processes
+# and to monitor them. If this is not good for your environment you might
+# create an apache_status.cfg file in MK_CONFDIR and populate the servers
+# list to prevent executing the detection mechanism.
+#
+# It is also possible to override or extend the ssl_ports variable to make the
+# check contact other ports than 443 with HTTPS requests.
+
+import os
+import re
+import sys
+
+if sys.version_info < (2, 6):
+    sys.stderr.write("ERROR: Python 2.5 is not supported. Please use Python 2.6 or newer.\n")
+    sys.exit(1)
+
+if sys.version_info[0] == 2:
+    from urllib2 import Request, urlopen  # pylint: disable=import-error
+    from urllib2 import URLError, HTTPError  # pylint: disable=import-error
+else:
+    from urllib.request import Request, urlopen  # pylint: disable=import-error,no-name-in-module
+    from urllib.error import URLError, HTTPError  # pylint: disable=import-error,no-name-in-module
+
+
+def get_config():
+    config_dir = os.getenv("MK_CONFDIR", "/etc/check_mk")
+    config_file = config_dir + "/apache_status.conf"
+
+    if not os.path.exists(config_file):
+        config_file = config_dir + "/apache_status.cfg"
+
+    # None or tuple of ((proto, cacert), ipaddress, port, instance_name).
+    #  - proto is 'http' or 'https'
+    #  - cacert is a path to a CA certificate, or None
+    #  - port may be None
+    #  - instance_name may be the empty string
+    config = {
+        "servers": None,
+        "ssl_ports": [443],
+    }
+    if os.path.exists(config_file):
+        exec(open(config_file).read(), config)
+    return config
+
+
+def get_instance_name(host, port_nr, conf):
+    """
+    Get Instance name either from config
+    or from detected sites
+    """
+    search = "%s:%s" % (host, port_nr)
+    if search in conf['custom']:
+        return conf['custom'][search]
+    if 'omd_sites' in conf:
+        return conf['omd_sites'].get(search, host)
+    return ""
+
+
+def try_detect_servers(ssl_ports):
+    results = []
+
+    for netstat_line in os.popen('netstat -tlnp 2>/dev/null').readlines():
+        parts = netstat_line.split()
+        # Skip lines with wrong format
+        if len(parts) < 7 or '/' not in parts[6]:
+            continue
+
+        pid, proc = parts[6].split('/', 1)
+        to_replace = re.compile('^.*/')
+        proc = to_replace.sub('', proc)
+
+        procs = [
+            'apache2',
+            'httpd',
+            'httpd-prefork',
+            'httpd2-prefork',
+            'httpd2-worker',
+            'httpd.worker',
+            'httpd-event',
+            'fcgi-pm',
+        ]
+        # the pid/proc field length is limited to 19 chars. Thus in case of
+        # long PIDs, the process names are stripped of by that length.
+        # Workaround this problem here
+        procs = [p[:19 - len(pid) - 1] for p in procs]
+
+        # Skip unwanted processes
+        if proc not in procs:
+            continue
+
+        server_address, _server_port = parts[3].rsplit(':', 1)
+        server_port = int(_server_port)
+
+        # Use localhost when listening globally
+        if server_address == '0.0.0.0':
+            server_address = '127.0.0.1'
+        elif server_address == '::':
+            server_address = '[::1]'
+        elif ':' in server_address:
+            server_address = '[%s]' % server_address
+
+        # Switch protocol if port is SSL port. In case you use SSL on another
+        # port you would have to change/extend the ssl_port list
+        if server_port in ssl_ports:
+            scheme = 'https'
+        else:
+            scheme = 'http'
+
+        results.append((scheme, server_address, server_port))
+
+    return results
+
+
+def _unpack(config):
+    if isinstance(config, tuple):
+        if len(config) == 3:
+            # Append empty instance name.
+            config += ("",)
+        if not isinstance(config[0], tuple):
+            # Set cacert option.
+            config = ((config[0], None),) + config[1:]
+        return config + ("server-status",)
+    return ((config['protocol'], config.get('cafile', None)), config['address'], config['port'],
+            config.get("instance", ""), config.get('page', 'server-status'))
+
+
+def get_ssl_no_verify_context():
+    import ssl
+    context = ssl.create_default_context()
+    context.check_hostname = False
+    context.verify_mode = ssl.CERT_NONE
+    return context
+
+
+def get_response_body(proto, cafile, address, portspec, page):
+    response = get_response(proto, cafile, address, portspec, page)
+    return response.read().decode(get_response_charset(response))
+
+
+# 'context' parameter was added to urlopen in python 3.5 / 2.7
+def urlopen_with_ssl(request, timeout):
+    result = None
+    if (sys.version_info[0] == 3 and sys.version_info >= (3, 5)) or \
+        (sys.version_info[0] == 2 and sys.version_info >= (2, 7)):
+        result = urlopen(request, context=get_ssl_no_verify_context(), timeout=timeout)
+    else:
+        if sys.version_info[0] == 2:
+            from urllib2 import HTTPSHandler, build_opener, install_opener  # pylint: disable=import-error
+        else:
+            from urllib.request import HTTPSHandler, build_opener, install_opener  # pylint: disable=import-error,no-name-in-module
+        install_opener(build_opener(HTTPSHandler()))
+        result = urlopen(request, timeout=timeout)
+    return result
+
+
+def get_response(proto, cafile, address, portspec, page):
+    url = '%s://%s%s/%s?auto' % (proto, address, portspec, page)
+    request = Request(url, headers={"Accept": "text/plain"})
+    is_local = address in ("127.0.0.1", "[::1]", "localhost")
+    # Try to fetch the status page for each server
+    try:
+        if proto == "https" and cafile:
+            return urlopen(request, cafile=cafile, timeout=5)
+        if proto == "https" and is_local:
+            return urlopen_with_ssl(request, timeout=5)
+        return urlopen(request, timeout=5)
+    except URLError as exc:
+        if 'unknown protocol' in str(exc):
+            # HACK: workaround misconfigurations where port 443 is used for
+            # serving non ssl secured http
+            url = 'http://%s%s/server-status?auto' % (address, portspec)
+            return urlopen(url, timeout=5)
+        raise
+
+
+def get_response_charset(response):
+    if sys.version_info[0] == 2:
+        charset = response.headers.getparam("charset")
+    else:
+        charset = response.info().get_content_charset()
+    return charset or "utf-8"
+
+
+def get_instance_name_map(cfg):
+    instance_name_map = {'custom': cfg.get("CUSTOM_ADDRESS_OVERWRITE", {})}
+    if cfg.get('ENABLE_OMD_SITE_DETECTION') and os.path.exists('/usr/bin/omd'):
+        for line in os.popen('omd sites').readlines():
+            sitename = line.split()[0]
+            path = "/opt/omd/sites/%s/etc/apache/listen-port.conf" % sitename
+            with open(path) as site_cfg_handle:
+                site_raw_conf = site_cfg_handle.readlines()
+                site_conf = site_raw_conf[-2].strip().split()[1]
+                instance_name_map.setdefault('omd_sites', {})
+                instance_name_map['omd_sites'][site_conf] = sitename
+    return instance_name_map
+
+
+def main():
+    config = get_config()
+    servers = config["servers"]
+    ssl_ports = config["ssl_ports"]
+
+    if servers is None:
+        servers = try_detect_servers(ssl_ports)
+
+    if not servers:
+        return 0
+
+    sys.stdout.write('<<<apache_status:sep(124)>>>\n')
+    for server in servers:
+        (proto, cafile), address, port, name, page = _unpack(server)
+        portspec = ':%d' % port if port else ''
+
+        try:
+            response_body = get_response_body(proto, cafile, address, portspec, page)
+            for line in response_body.split('\n'):
+                if not line.strip():
+                    continue
+                if line.lstrip()[0] == '<':
+                    # Seems to be html output. Skip this server.
+                    break
+                if not name:
+                    name = get_instance_name(address, port, get_instance_name_map(config))
+                sys.stdout.write("%s|%s|%s|%s\n" % (address, port, name, line))
+        except HTTPError as exc:
+            sys.stderr.write('HTTP-Error (%s%s): %s %s\n' % (address, portspec, exc.code, exc))
+
+        except Exception as exc:  # pylint: disable=broad-except
+            sys.stderr.write('Exception (%s%s): %s\n' % (address, portspec, exc))
+
+    return 0
+
+
+if __name__ == "__main__":
+    sys.exit(main())
diff --git a/checkmk/debian/apache_status/init.sls b/checkmk/debian/apache_status/init.sls
index 19ce0cd3d02530763408557ac0f852110f1d1008..69c522ff0a157bf16a9d16537b0b2f6c52e4e425 100644
--- a/checkmk/debian/apache_status/init.sls
+++ b/checkmk/debian/apache_status/init.sls
@@ -1,7 +1,7 @@
 apache_status_plugin:
   file.managed:
     - name: /usr/lib/check_mk_agent/plugins/apache_status
-    - source: salt://checkmk/checkmk-files/apache_status
+    - source: salt://checkmk/checkmk-files/apache_status.py
     - mode: 755
     - user: root
     - group: root