Monitor NGINX met Nagios

Wij gebruiken op het werk Nagios om alle services te monitoren. Dat loopt netjes via een server buiten de farm. Helaas heeft Nagios standaard niet de functionaliteit om NGINX status te monitoren.

Voordat je het script kan gebruiken, moet je de status pagina wel kunnen bereiken. Dit kun je doen door het volgende stukje code te plaatsen in /etc/nginx/sites-available/default:

location /status/ {
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    deny all;
}

Herlaad NGINX en ga naar de pagina om te kijken of de status-pagina werkt.

Hieronder zie je een python script dat je kan gebruiken om NGINX te monitoren. Sla het script op in /usr/lib/nagios/plugins en geef het de juiste rechten zodat de Nagios-user het script kan lezen en uitvoeren.

#!/usr/bin/python
# check_nginx is a Nagios to monitor nginx status
# my blog: http://www.nginxs.com
# The version is 1.0.1
# MSN: yangzi2008@126.com

import string
import urllib2
import getopt
import sys

def usage():
   print """check_nginx is a Nagios to monitor nginx status
   Usage:

   check_nginx [-h|--help][-U|--url][-P|--path][-u|--user][-p|--passwd][-w|--warning][-c|--critical]

   Options:
          --help|-h)
            print check_nginx help.
          --url|-U)
            Sets nginx status url.
          --path|-P)
            Sets nginx status url path. Default is: off
          --user|-u)
            Sets nginx status BasicAuth user. Default is: off
          --passwd|-p)
            Sets nginx status BasicAuth passwd. Default is: off
          --warning|-w)
            Sets a warning level for nginx Active connections. Default is: off
          --critical|-c)
            Sets a critical level for nginx Active connections. Default is: off
  Example:
            The url is www.nginxs.com/status
            ./check_nginx -U www.nginxs.com -P /status -u eric -p nginx -w 1000 -c 2000
            if dont't have password:
            ./check_nginx -U www.nginxs.com -P /status -w 1000 -c 2000
            if don't have path and password:
            ./check_nginx -U www.nginxs.com -w 1000 -c 2000"""
 
   sys.exit(3)

try:
    options,args = getopt.getopt(sys.argv[1:],"hU:P:u:p:w:c:",["help","url=","path=","user=","passwd=","warning=","critical="])

except getopt.GetoptError:
   usage()
   sys.exit(3)

for name,value in options:
    if name in ("-h","--help"):
       usage()
    if name in ("-U","--url"):
       url = "http://"+value
    if name in ("-P","--path"):
       path = value
    if name in ("-u","--user"):
       user = value
    if name in ("-p","--passwd"):
       passwd = value
    if name in ("-w","--warning"):
       warning = value
    if name in ("-c","--critical"):
       critical = value
try:
   if 'path' in dir():
      req = urllib2.Request(url+path)
   else:
      req = urllib2.Request(url)
   if 'user' in dir() and 'passwd' in dir():
      passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
      passman.add_password(None, url+path, user, passwd)
      authhandler = urllib2.HTTPBasicAuthHandler(passman)
      opener = urllib2.build_opener(authhandler)
      urllib2.install_opener(opener)
   response = urllib2.urlopen(req)
   the_page = response.readline()
   conn = the_page.split()
   ActiveConn = conn[2]
   the_page1 = response.readline()
   the_page2 = response.readline()
   the_page3 = response.readline()
   response.close()
   b = the_page3.split()
   reading = b[1]
   writing = b[3]
   waiting = b[5]
   output = 'ActiveConn:%s,reading:%s,writing:%s,waiting:%s' % (ActiveConn,reading,writing,waiting)
   perfdata = 'ActiveConn:%s,reading:%s,writing:%s,waiting:%s' % (ActiveConn,reading,writing,waiting)

except Exception:
   print "NGINX STATUS unknown: Error while getting Connection"
   sys.exit(3)
if 'warning' in dir() and 'critical' in dir():
   if ActiveConn >= warning:
      print 'WARNING - %s|%s' % (output,perfdata)
      sys.exit(2)
   elif ActiveConn >= critical:
      print 'CRITICAL - %s|%s' % (output,perfdata)
      sys.exit(1)
   else:
      print 'OK - %s|%s' % (output,perfdata)
      sys.exit(0)
else:
   print 'OK - %s|%s' % (output,perfdata)
   sys.exit(0)

Het script is afkomstig van de pagina: https://exchange.nagios.org/directory/Plugins/Web-Servers/nginx/check_nginx/details

WordPress permalinks met Nginx

Meestal werkt WordPress gewoon out-of-the-box met Nginx, je kan al vrij snel beginnen met het plaatsen van je berichten – totdat je permalinks gaat aanzetten. Dan kom je er al snel achter dat Nginx extra configuratie nodig hebt.

Om permalinks mogelijk te kunnen maken moet je het volgende toevoegen aan je configuratie. Zoek op
'location /' {
en voeg het volgende toe:

try_files $uri $uri/ /index.php?$args;

Vervolgens kun je de nginx configuratie ‘reloaden’ en zul je zien dat permalinks nu ook werken!

Jenkins; client drama

Als je ook Jenkins gebruikt, hoef ik je niet vertellen hoe slecht de foutmeldingen zijn. Als er een fout binnen Jenkins optreed (bijv. het niet starten van de slave-client) heb je geen idee waar je moet zoeken.

Zo kreeg ik laatste de volgende melding / stacktrace

[04/14/17 17:22:06] [SSH] Checking java version of java
[04/14/17 17:22:06] [SSH] java -version returned 1.7.0_121.
[04/14/17 17:22:06] [SSH] Starting sftp client.
[04/14/17 17:22:06] [SSH] Copying latest slave.jar...
[04/14/17 17:22:06] [SSH] Copied 719,269 bytes.
Expanded the channel window size to 4MB
[04/14/17 17:22:06] [SSH] Starting slave process: cd "/home/jenkins" && java     -jar slave.jar -text
<===[JENKINS REMOTING CAPACITY]===><===[HUDSON TRANSMISSION BEGINS]===channel started
Slave JVM has not reported exit code. Is it still running?
[04/14/17 17:22:11] Launch failed - cleaning up connection
ERROR: Connection terminated
java.io.EOFException
at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2625)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:3100)
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:854)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:350)
at hudson.remoting.ObjectInputStreamEx.<init>(ObjectInputStreamEx.java:48)
at hudson.remoting.AbstractSynchronousByteArrayCommandTransport.read(AbstractSynchronousByteArrayCommandTransport.java:34)
at hudson.remoting.SynchronousCommandTransport$ReaderThread.run(SynchronousCommandTransport.java:59)
Caused: java.io.IOException: Unexpected termination of the channel
at hudson.remoting.SynchronousCommandTransport$ReaderThread.run(SynchronousCommandTransport.java:73)
[04/14/17 17:22:11] [SSH] Connection closed.

Na eindeloos zoeken; was het een outdated java client. Dit was vervolgens goed op te lossen door gewoonweg java8 te installeren.

Alle HTTP verkeer doorsturen naar HTTPS

Tegenwoordig wilt iedereen https draaien, zo ook mijn werk. Ik moet daarom ook regelmatig nieuwe vhosts toevoegen die alleen op HTTPS mogen draaien. Dit is voor zowel NGINX als Apache2 heel gemakkelijk toe.

Apache configuratie

Voor Apache2 moet je zorgen dat je mod_rewrite aan hebt staan en het volgende defineren in je vhost:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{SERVER_NAME}/$1 [R,L]

NGINX configuratie

Voor NGINX kan je het volgende defineren:

return 301 https://$host$request_uri;

Zorg wel dat je de server name hebt geconfigureerd, het redirecten gebeurd namelijk o.b.v. de server name!

Kleine tip!

Omdat certificaten kunnen verlopen, kan ik je adviseren om een aparte configuratie bestand te maken en die te includen. Als je dan bijv. een wildcard certificaat hebt, hoef je maar een keer een configuratie bestand te updaten.

Apache includes

Maak een nieuw bestand aan; bijvoorbeeld; /etc/apache2/ssl-configuratie.conf en zet daar je SSL configuratie in. Je kunt dit bestand vervolgens weer includen door het volgende in je normale vhost configuratie te zetten:

Include /etc/apache2/ssl-configuratie.conf

NGINX includes

Maak een nieuw bestand aan; bijvoorbeeld /etc/nginx/ssl-configuratie.conf en zet daar de SSL configuratie in. Je kun het bestand incluen door het volgende in je normale vhost configuratie te plaatsen;

include  /etc/nginx/ssl-configuratie.conf