Hosting Pushjet with Apache

Prepare MySQL-Database for pushjet

# mysql -u root -p
CREATE USER 'pushjet'@'localhost' IDENTIFIED WITH mysql_native_password AS '***';
GRANT ALL PRIVILEGES ON `pushjet`.* TO 'pushjet'@'localhost'

Install gunicorn and pushjet via Shell

sudo su
apt-get install gunicorn python-pip libmysqlclient-dev
cd /opt
mv Pushjet-Server-Api-master/ pushjet
cd pushjet
pip install -r requirements.txt
cp config{.example,}.py
cat database.sql | mysql -uroot -p{insert root password} -D pushjet

Create gunicorn config for pushjet /etc/gunicorn.d/pushjet

  'mode': 'wsgi',
  'working_dir': '/opt/pushjet/',
  'python': '/usr/bin/python2',
  'args': (

Modify pushjet config /opt/pushjet/

# Must be a mysql database!
database_uri = 'mysql://pushjet:password@localhost/pushjet'
# Google Cloud Messaging configuration (required for android!)
google_api_key = 'ABCDEF....XYZ' 
# Change this to your FCM server key
google_gcm_sender_id = 512345678900 
# Change this to your GCM sender id

How to create the required key and id is documented here.

Create apache site config

<VirtualHost *:443>
    SSLEngine On
    SSLCertificateFile /path/to/fullchain.pem
    SSLCertificateKeyFile /path/to/privkey.pem
    RequestHeader set Front-End-Https "On"
    Header edit Location "^http:(.*)$" "https:$1"
    ProxyPass / unix:/var/run/gunicorn/pushjet.sock|http://localhost/
    RedirectMatch ^/$

Alternatively you can also publish pushjet as sub directory

<Location /pushjet> 
    ProxyPass unix:/var/run/gunicorn/pushjet.sock|http://localhost/

Enable the apache site and restart gunicorn and apache

sudo a2ensite pushjet.conf
systemctl restart gunicorn
systemctl restart apache2.service

Test it

To test it just go to
The result should look like this:

  "sender_id": 512345678900

Configure Pushjet Client

Open the pushjet settings:
Server URL:
Custom Sender ID: 512345678900

Use Sonoff S20 pins for Sensors with espeasy

The Sonoff S20 has only a 4 pin header (GND, TX, RX, VCC).

To use this pins (TX=GPIO1, RX=GPIO3) for sensors, the serial interface has to be disabled:
Tools – Advanced – Enable Serial port: uncheck

Now it is possible to use gpio1 and gpio3 for Devices:

This is the first test on a breadboard with DHT11
I don’t think that a humidity sensor makes any sense inside the socket. Therefore, I think I will use DS12B20 soldered on a female pin header in the final version.

And this is the result:

The values are also published via mqtt:

# mosquitto_sub -h -t "#" -v
/sonoff-s20/DHT11/Temperature 24.00
/sonoff-s20/DHT11/Humidity 33.00

Sonoff S20 and espeasy

Flash espeasy

Image can be found here.
To boot the sonoff into flash mode, press and hold the button while connecting it to power.

./ --port /dev/ttyUSB0 write_flash 0x000 ESPEasy_R120_1024.bin -fs 8m

Connect to wifi and configure

Connect to ESP_0 with password configesp and set up the wifi connection.

After connecting to wifi open the webinterface http://ip.of.sonoff/config and configure the name and unit number. The name of my sonoff is sonoff-s20.

Configure Hardware and Devices.

espeasy-hardware espeasy-button espeasy-relay

Enable rules: Tools – Advanced – Rules: Checked

Now there is a new menu entry named Rules

On Button#State=1 do
  if [Relay#State]=0

Now you can toggle the relay with the button.

MQTT usage

I use the protocol OpenHAB MQTT. So I can subscribe these events:

# mosquitto_sub -h my.mqtt.server -t "#" -v
/sonoff-s20/Relay/State 1
/sonoff-s20/Relay/State 0

To switch on and off you can publish these messages:

# mosquitto_pub -h -t "/sonoff-s20/gpio/12" -m "1"
# mosquitto_pub -h -t "/sonoff-s20/gpio/12" -m "0"

It is also possible to change „Relay“ to „gpio“ and „State“ to „12“. In this case, the subscribed and published strings are the same, but the rules also have to be modified.

openHAB configuration

After configuration of the mqtt-binding in openhab.cfg I created a new item-file

Switch sonoff01 "Sonoff Socket" {mqtt=">[mosquitto:/sonoff-s20/gpio/12:command:ON:1],>[mosquitto:/sonoff-s20/gpio/12:command:OFF:0],<[mosquitto:/sonoff-s20/Relay/State:state:MAP(]", autoupdate="false"}

I also created the file transforms/


Detect duplicate SusClientIds on WSUS side

In a large environment with many active directory domains and some servers which are not domain members, it is difficult to find all duplicate SusClientIds. Remote registry queries are not an option because there are many systems in protected networks behind firewalls.

So I decided to use the IIS Failed Request Log to detect duplicate SusClientIds.

Install IIS Tracing

Start the Server-Manager and install the following role service:
Tracing (under World Wide Web Services – Health and Diagnostics – Tracing)

Enable Failed-Request Tracing

  1. Open the Internet Information Services (IIS) Manager
  2. In the Connections pane, expand the machine name, expand Sites, and then click on the Site, where WSUS runs.
  3. In the Actions pane, under Configure, click Failed Request Tracing…


  • Select the Enable check box.
  • Set Maximum number of trace files to [number of WSUS clients x 5]

Configure Failed Request Tracing Rule

  1. Double-click Failed Request Tracing Rules.
  2. In the Actions pane, click Add…


  3. In the Add Failed Request Tracing Rule wizard, on the Specify Content to Trace page, select Custom and enter the value ReportingWebService.asmx. Click Next.
  4. On the Define Trace Conditions page, select the Status code(s) check box and enter 200 as the status code to trace. Click Next.FailedRequestRule3
  5. On the Select Trace Providers page, under Providers, select the WWW Server check box. Under Areas, select the Compression check box and clear all other check boxes. Compression is not what we are looking for, but it is required to select at least one Area.
  6. Under Verbosity, select Verbose.
  7. Click Finish.

Analyze Logfiles

After some logging (minimum 24h) in the Path C:\inetpub\logs\FailedReqLogFiles\W3SVC[xxxxxxxxx] are many new xml-files are created. This is the work directory for the following steps.

To analyze this files, I wrote the script get-susclientids.ps1 to get a list of all IPs and SusClientIds.

$list = @()
Foreach ($file in (Get-ChildItem *.xml)){
    $entry = New-Object -TypeName PSObject
    $filecontent = Get-Content $
    $SCIline = ($filecontent | ? { $_ -like "*;&lt;Sid&gt;*"})
    $remoteaddrline = ($filecontent | ? { $_ -like "*<Data Name=""RemoteAddress"">*"})
    $remoteaddr = $remoteaddrline.Substring($remoteaddrline.IndexOf("""RemoteAddress"">")+16,$remoteaddrline.Length-36)
    If($SCIline -and $SCIline.IndexOf(";&lt;Sid&gt;") -gt 0){
        Add-Member -InputObject $entry -MemberType NoteProperty -Name RemoteAddr -Value $remoteaddr
        Add-Member -InputObject $entry -MemberType NoteProperty -Name SusClientId -Value $SCIline.substring($SCIline.IndexOf(";&lt;Sid&gt;")+12,36)
        If(@($list | ? { $_.remoteaddr -eq $remoteaddr }).count -lt 1){
            $list += $entry
$list | export-csv -path susclientids.csv

The result can be queried with this command:
Import-Csv .\susclientids.csv

Example output:

RemoteAddr                              SusClientId
----------                              -----------                                aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee                                ffffffff-0000-1111-2222-333333333333                                aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee

Finding Duplicates

To find duplicate SusClientIds I wrote the script get-duplicate.ps1:

$duplicates = Import-Csv .\susclientids.csv | sort susclientid | group susclientid | ? { $_.count -gt 1}
$list = @()
foreach ($duplicateSCI in $duplicates){
    foreach ($system in $duplicateSCI.Group){
        $entry = New-Object -TypeName PSObject
        Add-Member -InputObject $entry -MemberType NoteProperty -Name RemoteAddr -Value $system.remoteaddr
        try {
            $fqdn = ([System.Net.Dns]::GetHostEntry($system.remoteaddr).Hostname)
        } catch {
            $fqdn = ""
        Add-Member -InputObject $entry -MemberType NoteProperty -Name FQDN -Value $fqdn
        Add-Member -InputObject $entry -MemberType NoteProperty -Name SusClientId -Value $system.SusClientId
        $list += $entry

Example output:

RemoteAddr     FQDN               SusClientId
----------     ----               -----------   aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee   aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee

Now it’s time to reset the SusClientId on the listed systems.

Bearbeitung von Gruppenrichtlinie schlägt fehl: „Der Datenträger einer Datei wurde extern so geändert, dass die geöffnete Datei nicht mehr gültig ist.“

Es gibt schon komische Fehlermeldungen, zum Beispiel die obenstehende. Über diese bin ich gestolpert, als ich versucht habe in einer Domäne die Default Domain Controller Policy zum bearbeiten zu öffnen. Vollständig sah das Ganze so aus:

Das Gruppenrichtlinienobjeckt konnte nicht geöffnet wererror_edit_gpoden. Möglicherweise verfügen Sie nicht über die erforderlichen Rechte.
Der Datenträger einer Datei wurde extern so geändert, dass die geöffnete Datei nicht mehr gültig ist.

Eigentlich würde man meinen, wenn es nur eine einzige Policy betrifft, dann kann man die ja einfach mal neu erstellen. Da es sich hier aber um die Default Domain Controller Policy handelt, war ich von dem Gedanken nicht unbedingt angetan.

Nach ein paar Tests mit Procmon habe ich festgestellt, dass sich die Konsole an einer leeren registry.pol-Datei im Unterordner USER der Policy stört. Beim bearbeiten einer Default Domain Controller Policy einer anderen Domäne wurde für die genannte Datei ein „NOT FOUND“ geloggt. Bei der „beschädigten“ Policy hingegen nicht und relativ kurz darauf brach er mit oben genanntem Fehler ab.

Einfach die 0kb große Datei \\domain.loc\SYSVOL\domain.loc\Policies\{policy-guid}\USER\registry.pol in registry.old.pol umbenennen.

Betroffen davon scheint auch nur Windows Server 2012 bzw. 2012 R2. Auf einem Windows Server 2008 R2 konnte ich das Problem nicht nachstellen.

Raspberry Pi und analoger Sound

Vor einiger Zeit habe ich mir, wie viele andere auch, einen Raspberry Pi zugelegt, auf dem ich eine XBMC (mittlerweile Kodi) betreibe. Seinerzeit habe ich mir den Raspberry Pi Modell B in der 512MB Ram version angeschafft.

Aufgrund der doch begrenzten Tonqualität des verwendeten Bildschirms war ich darauf angewiesen ein paar externe PC-Lautsprecher zu verwenden. Hierbei stieß ich in der Anfangsphase auf viele Probleme. Darunter lautes Knacken beim Senderwechsel und diverse andere Tonstörungen. Mit diversen XBMC-Updates besserte sich die Lage, es gab das Knacken nur noch beim Starten und beenden. Nur diverse Tonstörungen, welche an ruhigen Stellen im Film zu hören waren, störten etwas. Es klang schon so, als ob man Hört, wie der Raspberry arbeitet.

Mit Raspberry Pi B+ bzw. Raspberry Pi 2 wird alles besser…

Mit dem Raspberry Pi B+ wurde ein verbesserter analoger Sound beworben, klang schon mal nicht schlecht, aber deshalb einen neuen Raspberry kaufen? Eher nicht.

Nun kam mittlerweile der Raspberry Pi 2 auf den Markt, welcher natürlich auch genannte Verbesserungen haben soll. Als sich die Chance bot, diesen relativ günstig zu erwerben schlug ich zu.

Kaum kam das Paket an wurde auch schon alles vorbereitet. Der Raspberry Pi 2 an sich ist schon wirklich super. Alles um einiges schneller und die Bedienung von Kodi absolut flüssig. So macht das wirklich Spaß. Die ersten Tontests hingegen waren doch sehr ernüchternd.

Das Knacken war hier weniger das Problem. Problematisch empfand ich ein permanentes Brummen/Rauschen. Dieses ließ sich nur verringern, indem ich den Lautstärkepegel an den Lautsprechern senkte. Für Filme mag das reichen, ab für Musik, die man auch mal lauter machen möchte ist das nicht praktikabel, da man hier wieder physisch an den Lautsprechern drehen muss.

Einziger Ausweg

Als Lösung bot sich hier scheinbar nur noch ein USB-Audio-Adapter:

Ich habe doch etwas hin und her überlegt, welchen Adapter ich bestelle und habe mich am Ende für den günstigsten Adapter aus China für unschlagbare 1,64€ inkl. Versand über eBay entschieden. Mittlerweile gibt es diesen sogar noch günstiger (1,16€). Es gibt auch noch Varianten als einfacher Adapter, aber ich fand es nützlich am Raspberry noch dieses kleine Verlängerungskabel zu haben, um den Adapter anders zu Positionieren. Dass man hier keinen hochqualitativen Artikel erhält, kann man bei dem Preis erahnen. Aber auch günstiges Plastik reicht, solange man den Adapter nicht dauernd abzieht und neu ansteckt.

Läuft sogar out of the box!

An den Raspberry angesteckt wurde der Adapter nach einem Neustart von Kodi erkannt und konnte über Optionen – System – Audio-Ausgabe – Audioausgabegerät: „ALSA: USB PnP Sound Device, Analog“ aktiviert werden.

Der Adapter meldet sich als:

Bus 003 Device 012: ID 0d8c:013c C-Media Electronics, Inc. CM108 Audio Controller


Was die Soundqualität angeht, kann ich nicht all zu viel sagen. Ich habe mal mit dem Onboard-Chip meines ASUS Z97-A unter Verwendung eines Logitech Z523 2.1 Soundsystems getestet und kann im direkten Vergleich keinen wirklichen Unterschied erkennen. Auf jeden Fall um Längen besser als der analoge Sound des Raspberry Pi.

check the version including update rollup of all Exchange servers in organization

After I realized that there is no Exchange 2010 cmdlet to determine the complete version number of all Exchange servers, I decided to write a script for this.

The result is one ps1 script and a csv file with the version numbers and the version name. I got the version informations from this Article.

The version csv looks like this:

"14.0.639.21","Microsoft Exchange Server 2010 RTM"
"14.0.682.1","Microsoft Exchange Server 2010 RTM Update Rollup 1"
"14.0.689.0","Microsoft Exchange Server 2010 RTM Update Rollup 2"
"","Microsoft Exchange Server 2010 SP3 Update Rollup 7"
"","Microsoft Exchange Server 2010 SP3 Update Rollup 8-v2"

To check the version, the script gets the installation path from registry and reads the file info of the exsetup.exe via smb (admin shares).

And this is the script:

# read versions and versiontext from csv
$versions = @{}
$csvversions = (Import-Csv -Path .\get-ExchangeServerVersion.csv)
$csvversions | foreach { $versions[($_.version)] = $_.Text }

# create list object for output
$output = @()

$version ="UNKNOWN!"

# get exchange servers in the organization filtered by version 14.*
$exServers = Get-ExchangeServer | ? { $_.AdminDisplayVersion -like "Version 14.*"} | sort fqdn | select name,fqdn
foreach ($exServer in $exServers){
    Write-Debug $exserver
    # create PowerShell object for output line
    $outputEx = New-Object -TypeName PSObject

    # get Exchange installation path
    $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $exServer.fqdn)
    $RegKey= $Reg.OpenSubKey("SOFTWARE\\Microsoft\\ExchangeServer\\V14\\Setup")
    $InstallPath = $RegKey.GetValue("MsiInstallPath")

    # get Version from Exchange binary
    $version = ([Version](Get-Item ($ExSetupPath)).VersionInfo.ProductVersion).tostring()

    # add server name to ps object
    Add-Member -InputObject $outputEx -MemberType NoteProperty -Name Name -Value $exServer.fqdn

    # add version to ps object, if the version is not in the version list, use the version instead of text
        Add-Member -InputObject $outputEx -MemberType NoteProperty -Name Version -Value $versions["$($version)"]
    } else {
        Add-Member -InputObject $outputEx -MemberType NoteProperty -Name Version -Value $version

    # reset Version to unknown for next loop
    $version ="UNKNOWN!"
    $ExSetupPath = ""

    # add ps object to output




Server-Manager hängt bei „Installation wird gestartet…“

Windows bringt einen schon manchmal zum verzweifeln. Hier habe ich mal wieder ein Beispiel, was mich einiges an Nerven gekostet hat.

Bei der Installation einer Rolle oder eines Features unter Windows Server 2012 hatte ich das Problem, dass er immer am Punkt „Installation wird gestartet…“ hängen blieb.

Nach etwas Recherche bin ich darüber gestolpert, dass WinRM die Ursache sein könnte. Also versuchte ich es wie gewohnt über die Kommandozeile mit „winrm quickconfig“ zu aktivieren, was in folgender Fehlermeldung resultierte:

Der WinRM-Dienst wird auf diesem Computer bereits ausgeführt.
    Message = Der WinRM-Client hat einen Status in Bezug auf einen HTTP-Serverfehler (500) empfangen, 
aber der Remotedienst hat keine anderen Informationen zur Fehlerursache bereitgestellt.

Fehlernummer:  -2144108176 0x80338170
Der WinRM-Client hat einen Status in Bezug auf einen HTTP-Serverfehler (500) empfangen, aber der 
Remotedienst hat keine anderen Informationen zur Fehlerursache bereitgestellt.

Nach weiterer Suche ist mir dann aufgefallen, dass im Server-Manager unter Lokaler Server bei dem Punkt Remoteverwaltung nur „Unbekannt“ stand. Beim Klick darauf sah das ganze dann so aus:


Die genaue Fehlermeldung lautete hier:

Interner Fehler beim Lesen des Remotingzustands: Der WinRM-Client hat einen Status in Bezug auf einen HTTP-Serverfehler (500) empfangen, 
aber der Remotedienst hat keine anderen Informationen zur Fehlerursache bereitgestellt.

Hier hat es geholfen, die Remoteverwaltung zu deaktivieren, mit OK zu bestätigen und wieder erneut zu aktivieren.

Allerdings muss ich dabei anmerken, dass das Problem einige Tage später, eventuell nach einem Neustart, wieder auftrat.

NRPE von NSClient++ testen

Wenn man selbst nicht der Nagiosadmin ist, aber einen NSClient++ konfigurieren muss um dem Nagiosadmin entsprechende NRPE-Befehle bereitzustellen, ist es auch sinnvoll diese selbst testen zu können.

Dies ist direkt über den NSClient möglich, allerdings muss hierfür erst einmal zu den „allowed_hosts“ aufgenommen werden. Hierfür muss die Datei nsclient.cfg angepasst werden:


Anschließend muss der NSClient dienst neugestartet werden. Anschließend kann über folgenden Befehl ein definierter check aufgerufen werden:

C:\Program Files (x86)\NSCP>nscp nrpe --host --command check_ok
OK: Lets pretend everything is going to be ok.

Auch Checks mit Argumenten können getestet werden, allerdings nur wenn der Parameter „allow_arguments=1“ gesetzt ist.

C:\Program Files (x86)\NSCP>nscp nrpe --host --command checkcpu --arguments MaxWarn=80 time=5m
OK CPU Load ok.|'5m'=1%;80;0

Nagios NRPE Server für Enigma2

Nagios ist ja schon was Tolles, auch in einem Heimnetz. Reine Portüberwachung und Ping-Checks sind aber irgendwann nicht mehr genug.

Daher habe ich mich mal daran gemacht, den nagios-nrpe-server auf meiner Dreambox mit Enigma2 zum Laufen zu bekommen (fertiges Paket am Ende des Artikels).

Dazu habe ich mir die neuste Version aus dem Debian Repository in der mipsel-Version heruntergeladen.

mkdir sources
cd sources
mkdir nagios-nrpe-server_2.12-4_mipsel
dpkg-deb -x nagios-nrpe-server_2.12-4_mipsel.deb nagios-nrpe-server_2.12-4_mipsel/
rm -r nagios-nrpe-server_2.12-4_mipsel/usr/share/
mkdir package
cp nagios-nrpe-server_2.12-4_mipsel/* -r package
mkdir package/CONTROL
vim package/CONTROL/control

Nun die Datei control unterhalb des Ordners CONTROL mit folgendem Inhalt füllen:

Package: nagios-nrpe-server
Version: 2.12-4-r0
Description: Nagios NRPE Server
Architecture: mipsel
Section: extra
Priority: optional
Maintainer: skin master <***>
Depends: libwrap0

Nun die Datei conffiles unterhalb des Ordners CONTROL mit folgendem Inhalt füllen:


Nun die Datei preinst unterhalb des Ordners CONTROL mit folgendem Inhalt füllen:

addgroup -g 9000 nagios
adduser -D -H -s /bin/false -G nagios -u 9000 nagios

Nun die Datei postinst unterhalb des Ordners CONTROL mit folgendem Inhalt füllen:

ln -s ../init.d/nagios-nrpe-server /etc/rc0.d/K20nagios-nrpe-server
ln -s ../init.d/nagios-nrpe-server /etc/rc1.d/K20nagios-nrpe-server
ln -s ../init.d/nagios-nrpe-server /etc/rc2.d/S20nagios-nrpe-server
ln -s ../init.d/nagios-nrpe-server /etc/rc3.d/S20nagios-nrpe-server
ln -s ../init.d/nagios-nrpe-server /etc/rc4.d/S20nagios-nrpe-server
ln -s ../init.d/nagios-nrpe-server /etc/rc5.d/S20nagios-nrpe-server
ln -s ../init.d/nagios-nrpe-server /etc/rc6.d/K20nagios-nrpe-server
/etc/init.d/nagios-nrpe-server start

Nun die Datei prerm unterhalb des Ordners CONTROL mit folgendem Inhalt füllen:

/etc/init.d/nagios-nrpe-server stop
rm /etc/rc0.d/K20nagios-nrpe-server
rm /etc/rc1.d/K20nagios-nrpe-server
rm /etc/rc2.d/S20nagios-nrpe-server
rm /etc/rc3.d/S20nagios-nrpe-server
rm /etc/rc4.d/S20nagios-nrpe-server
rm /etc/rc5.d/S20nagios-nrpe-server
rm /etc/rc6.d/K20nagios-nrpe-server

Nun die Datei postrm unterhalb des Ordners CONTROL mit folgendem Inhalt füllen:

deluser nagios
delgroup nagios

Anschließend noch alle pre- und post-Scripte unterhalb von CONTROL ausführbar machen und das ganze zusammenschnüren:

chmod +x package/CONTROL/p*
./ package/

Als Resultat gibts dann eine nagios-nrpe-server_2.12-4-r0_mipsel.ipk

Ob das ganze hier alles so richtig ist, weiß ich nicht. Manches lässt sich vielleicht besser/einfacher lösen, aber es funktioniert.

Die IPK-Datei ist schnell installiert und wer einen NRPE-Agent schon ein mal eingerichtet hat, kommt ab hier sicher auch gut allein zurecht.

Script: ipkg-build
Howto: IPK Pakete erstellen
Download: fertiges Paket