nginx error 500 php

in /etc/php-fpm.d/www.conf:

catch_workers_output = yes

and most importantly.. comment out the 5xx html page in nginx.conf, so you can see actual errors. Which in my case turned out to be permissions of /var/lib/php/[session, peclxml, opcache, wsdlcache]. They were still group owned by ‘apache’ instead of nginx


#display some actual useful errors please....
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }

Centos / Fedora firewalld firewall-cmd

I can never remember this…

firewall-cmd --list-all-zones

Look to see which is ‘active’. Should be FedoraServer on Fedora Server. Then..

firewall-cmd --zone=FedoraServer --add-port=80/tcp --permanent

Annoyingly, the –permanent means ‘just add to the startup configuration, but don’t do anything now’. If you leave off the –permanent, then it takes effect right away but only affects the running configuration and will be lost after a restart.

Either way, you need two commands – either the –permanent command above, followed by

firewall-cmd --reload

or, and this is probably wiser in case you do something wrong and lock yourself out, you should do the command without –permanent, then check that all works (no –reload will be needed), then add it in again with –permanent so that the rule will be present after a future restart.

So, in summary:

firewall-cmd --zone=FedoraServer --add-port=80/tcp

(check that things are as you want them)

firewall-cmd --zone=FedoraServer --add-port=80/tcp --permanent

for localhost only stuff (e.g. powerdns stats on

firewall-cmd --zone=trusted --add-port=8081/tcp
firewall-cmd --zone=trusted --add-port=8081/tcp --permanent

To remove / undo:

firewall-cmd --zone=FedoraServer --remove-port=80/tcp
firewall-cmd --zone=FedoraServer --remove-port=80/tcp --permanent

For some known services (not sure which.. maybe it just uses /etc/services ?) you can give the service name instead of the port/protocol:


instead of



Petya / NotPetya cyber attack 27th June 2017

Petya (a.k.a NotPetya) is another ransom-ware file-encrypting virus worm. The latest big thing.

Apparently it spreads through the same mechanism as the WannaCry virus (NHS cyber attack May 2017), but there are also reports of it being sent through emails.
That method of spreading from one computer to another was due to a security flaw in Microsoft Windows. The code to exploit this flaw, which the US government found years ago but kept to themselves, had been called EternalBlue. A patch/fix for this was released by Microsoft in March 2017, and also included in subsequent update roll-ups.

During the NHS cyber attack crisis, I took steps to ensure that all client’s computer had this and other important updates installed. For this reason, you are already patched against EternalBlue, however you must still be vigilant with regard to opening email attachments.

As it happens, security researchers have discovered a sort of ‘vaccine’, however it will only work for the current outbreak. If the virus does get to your computer, perhaps through the opening of an email attachment, it first checks whether some other files are present on the computer, and if they are, then the virus shuts itself down and does no harm. So this is sort of like a kill switch.

I have sent a popup message to your computer to let you know that these vaccine files have been put in place on your computer, as well as to explain the patch situation above.

Gemalto smartcard reader not working after Windows 10 creators update.

For some reason the Gemalto / eSigner stuff wasn’t working after the Windows 10 Creators update.
The ‘Certificate Propagation’ service would not start, and this was due to policy settings. Apparently the Gemalto stuff doesn’t require this, and has its own method of importing certificates from smartcards.

Regardless, the systray tool said ‘Unknown card’, and this was fixed when the Certificate Propagation service was re-enabled and started:

Set the following key to 00000001 [HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\CertProp]
And start the service: Certificate Propagation.

samba smb3 multichannel on 802.3ad/lacp bond

Still working on this.
Need to alias the bond “ip link add link bon0 name bond0-alias address 11:22:33:44:55:66 type macvlan” doesn’t quite work because the bonding driver just flips through the same slave interfaces regardless of whether alias or original bond0 device is being used.

Next thing to try: alias the slaves and create a separate bond from them. This is on the NAS box (CentOS 7) running NFS and Samba.

On the Windows side, Server 2016 is running on Proxmox which is using a similar quad-NIC LACP bond. A duplicate virtIO interface was added to the Windows guest in Proxmox. Windows guest seems to be sending and receiving over both interfaces quite happily (but only at half rate), not sure what Proxmox/Linux is doing on the host side yet.

Compiling gr-fosphor on Fedora 25 / CentOS 7 with intel opencl

Download the Intel OpenCL runtime & libraries (you don’t need the sdk).
install those RPMs. They will install to /opt/intel/opencl

cd gr-fosphor/build

here is the key step:

cmake -DOpenCL_LIBRARY=/opt/intel/opencl/ -DOpenCL_INCLUDE_DIR=/opt/intel/opencl/include ..

then just carry on with the normal instructions:

sudo make install
sudo ldconfig

Cisco SPA phones not getting IP via DHCP

This is a pain, and I keep forgetting the cause. So to save myself the trouble in future, here it is..

It’s simple – another device has the IP address that your DHCP server is handing out to the SPA504g/spa508g phones, and so the phones are refusing to accept this IP address.

The Cisco SPA phone is being handed e.g. by your DHCP server, but another device is using this IP address already. It may be the DHCP server that is at fault. In my case, Windows 2008 DHCP server does not have a record of some of the existing IPs in use / previously leased. Perhaps the SPA phones are not honoring the lease expiration time and failing to renew, just continuing to use an IP address, and then DHCP server thinks the IP is free to hand out to another phone when it restarts or is unplugged and plugged back in. There’s a DHCP server configuration option to do an ARP check or something before handing out a lease.. might be worth looking into that.

Look in your DHCP lease table, find the MAC of the offending phone, have a look what IP the DHCP server thinks is has leased to the phone. With the phone powered off, check if you can ping that IP. If you can ping that IP, then you know that the DHCP server is OFFERing out an IP address that is already in use.

If the DHCP server is Windows, and the scope is e.g. –, then a quick fix is to temporarily change the scope range to something like  –, thus forcing the DHCP server to hand out a different IP address than the original that it was handing out. The phones will then work, and then you can set the scope back to the original range. The DHCP server will record the lease and hand out that new IP address in future.

Patton SmartNode BRI ISDN as an Asterisk gateway.

I’ve looked at and tried a few configuration files out there, and used Patton’s web wizard. None are particularly clear about who registers with who, etc. I also had problems with “The other person has hung up” recorded message from BT, when the other party hung up the call (cured by “allow early disconnect” in the SmartNode SIP profile).

Anyway, here is a configuration file for a Smartnode 4554 dual-BRI. There is no registration or SIP authentication. It is meant for a back-to-back Asterisk <-> Smartnode setup.

Before I get started, here is the trunk configuration, from FreePBX. It is using chan_sip, not chan_pjsip. In my builds, I disable pjsip (for the time being), and move chan_sip back to the former default of UDP port 5060. This is because I use a lot of mixed equipment and the troubleshooting has been extensive, and still, some minor issues persist between PJSIP on Asterisk/FPBX and the various brands of desk phones, cordless phones, gateways, and SIP trunk providers that I use.

One thing to note: I had to turn off “Send Progress” in my ‘RingAll’ Ring Group in FreePBX. The caller did not hear a ringback tone when calling in, if the destination was this ring group.

As usual, you do not need to enter anything at all on the ‘incoming’ settings in FreePBX. Yes this is counter-intuitive, and yes this system makes both incoming and outgoing calls via the gateway, but this is just how FreePBX manages the trunk setup. I never have, and never do put anything in the ‘incoming’ settings part of the chan_sip trunk setup in FreePBX, whether I am using a SIP trunk from an ITSP (Gamma, Voiceflex), a Cisco 2811 with an E1 PRI module, or this Patton Smartnode BRI gateway.

In these configuration examples, FreePBX is on The Smartnode Sn4554 is on

OK, so once again, this is the FreePBX chan_sip trunk configuration. Just put the following in the Outgoing ‘Peer Details’ box (change the host= to be the IP address that you use for the Smartnode).


Next we have the SmartNode configuration. Copy and paste this into notepad, save it, then use the import facility in the web front-end to import it. Do note the “interface WAN -> ipaddress” stuff. You can change it to “dhcp” if you like, or alter the IP address before you do the import.

#                                                                #
# SN4554/2BIS/EUI                                                #
# R5.9 2012-09-05 SIP                                            #
# 2016-12-30T14:17:37                                            #
# SN/00A0BA0528A1                                                #
# Generated configuration file                                   #
#                                                                #

cli version 3.20
clock local default-offset +00:00
webserver port 80 language en


  ic voice 0

  clock-source 1 bri 0 1

profile ppp default

profile tone-set default

profile voip default
  codec 1 g711alaw64k rx-length 20 tx-length 20
  codec 2 g711ulaw64k rx-length 20 tx-length 20
  fax transmission 1 relay t38-udp
  fax transmission 2 bypass g711alaw64k rx-length 20 tx-length 20
  fax transmission 3 bypass g711ulaw64k rx-length 20 tx-length 20
  modem transmission 1 bypass g711alaw64k rx-length 20 tx-length 20
  modem transmission 2 bypass g711ulaw64k rx-length 20 tx-length 20

profile pstn default

profile sip default
  no autonomous-transitioning

profile aaa default
  method 1 local
  method 2 none

context ip router

  interface WAN

context cs switch
  national-prefix 0
  international-prefix 00

  routing-table called-e164 RT_ISDN_TO_SIP
    route .T dest-interface IF_SIP

  interface isdn IF_ISDN_00
    route call dest-table RT_ISDN_TO_SIP
    call-reroute emit
    diversion emit

  interface isdn IF_ISDN_01
    route call dest-table RT_ISDN_TO_SIP
    call-reroute emit
    diversion emit

  interface sip IF_SIP
    bind context sip-gateway GW_SIP
    route call dest-service SRV_HG

  service hunt-group SRV_HG
    drop-cause normal-unspecified
    drop-cause no-circuit-channel-available
    drop-cause network-out-of-order
    drop-cause temporary-failure
    drop-cause switching-equipment-congestion
    drop-cause access-info-discarded
    drop-cause circuit-channel-not-available
    drop-cause resources-unavailable
    route call 1 dest-interface IF_ISDN_00
    route call 2 dest-interface IF_ISDN_01

context cs switch
  no shutdown

location-service SER_LOC
  domain 1

context sip-gateway GW_SIP

  interface IF_GWSIP
    bind interface WAN context router port 5060

context sip-gateway GW_SIP
  bind location-service SER_LOC
  no shutdown

port ethernet 0 0
  bind interface WAN router
  no shutdown

port bri 0 0
  clock auto
  encapsulation q921

    protocol pp
    uni-side auto
    encapsulation q931

      protocol dss1
      uni-side user
      bchan-number-order ascending
      encapsulation cc-isdn
      bind interface IF_ISDN_00 switch

port bri 0 0
  no shutdown

port bri 0 1
  clock auto
  encapsulation q921

    protocol pp
    uni-side auto
    encapsulation q931

      protocol dss1
      uni-side user
      bchan-number-order ascending
      encapsulation cc-isdn
      bind interface IF_ISDN_01 switch

port bri 0 1
  no shutdown



beginnings of arduino dual i2c slave for mi-light remote RGB+CCT dual white

This is as far as I got, then I had to refocus my life for a bit.

it acts as two independent i2c slaves on the same address (two separate buses). The idea is to take the place of the two capacitive touch-sensors in the MiLight remote, and pretend to be them, and get the microcontroller on the little RF header board in the remote to send out the commands we want. This should overcome the need to understand the new RGB+DualWhite (RGB+CCT) MiLight protocol with its as yet unbroken encryption.

This code is terrible and it will only spit out the same packet, but it’s a start. I was able to unpredictably get the bulb to change from off to on or flashing or blue.

I used a Feather M0, the ARM one, which can run two i2c buses at the same time via its sercom thing.

I think I left some of the code commented out for the second i2c bus, before I went to sleep.. i was just experimenting. you can uncomment it, it was working.

// Wire Slave Sender
// by Nicholas Zambetti <>

// Demonstrates use of the Wire library
// Sends data as an I2C/TWI slave device
// Refer to the "Wire Master Reader" example for use with this

// Created 29 March 2006

// This example code is in the public domain.
#include <Wire.h>
#include "wiring_private.h" // pinPeripheral() function

TwoWire myWire(&sercom1, 13, 11); // first pin is SDA, second pin is SCL

int reqNo_ch1 = 0;
int reqNo_ch2 = 0;
int on = 0;

char val1;
char val2;
char ch1read;
char ch2read;
char ch1write;
char ch2write;

byte data1[5];
byte data2[5];
byte cmdon[] = {0x02, 0x00, 0x01, 0x00, 0x00};
byte cmdoff[] = {0x02, 0x00, 0x02, 0x00, 0x00};
byte btnReleased[] = {0x02, 0x00, 0x00, 0x00, 0x00};

void setup() {
Wire.begin(0x53); // join first i2c bus with address 0x53
Wire.onRequest(requestEvent1); // register event for i2c bus 1
Wire.onReceive(receiveEvent1); // register receive event (for Writes from master) for i2c bus 1
myWire.begin(0x53); // join second i2c bus with address 0x53
pinPeripheral(11, PIO_SERCOM);
pinPeripheral(13, PIO_SERCOM); // Assign pins 13 & 11 to SERCOM functionality
myWire.onRequest(requestEvent2); // register event for i2c bus 2
myWire.onReceive(receiveEvent2); // register receive event (for Writes from master) for i2c bus 2
// while (!Serial);
Serial.begin(115200); // start serial for output


void loop() {
if (ch1read == 1) {
if (on == 1) Serial.print("R1 on ");
if (on == 0) Serial.print("R1 off ");
ch1read = 0;
if (ch1write == 1) {
PrintHex83(data1, 5);
ch1write = 0;

if (ch2read == 1) {
ch2read = 0;
if (ch2write == 1) {
PrintHex83(data2, 5);
ch2write = 0;

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent1() {
ch1read = 1;
if (reqNo_ch1 >1) {
if (on == 0) {
Wire.write(cmdon, 5); // respond with "on"
on = 1;
//reqNo_ch1 = ;
else {
Wire.write(cmdoff, 5); // respond with "off"
on = 0;
//reqNo_ch1 = 0;
else {
Wire.write(btnReleased, 5); // respond with "button released"
reqNo_ch1 = 5;

void receiveEvent1(int howMany)
ch1write = 1;
int x = 1;
while (Wire.available())
data1[x] =; // receive byte as a character

void requestEvent2() {
ch2read = 1;
// if (reqNo_ch2 >1) {
// if (on == 0) {
// myWire.write(cmdon, 5); // respond with "on"
// on = 1;
// reqNo_ch2 = 0;
// }
// else {
// myWire.write(cmdoff, 5); // respond with "off"
// on = 0;
// }
// reqNo_ch2--;
// }
// else {
myWire.write(btnReleased, 5); // respond with "button released"
// reqNo_ch2 = 5;
// }

void receiveEvent2(int howMany)
ch2write = 1;
int x=1;
while (myWire.available())
data2[x] =; // receive byte as a character

extern "C" {
void SERCOM1_Handler(void) {

void PrintHex83(uint8_t *data, uint8_t length) // prints 8-bit data in hex
char tmp[length*2+1];
byte first ;
int j=0;
for (uint8_t i=0; i<length; i++)
first = (data[i] >> 4) | 48;
if (first > 57) tmp[j] = first + (byte)39;
else tmp[j] = first ;

first = (data[i] & 0x0F) | 48;
if (first > 57) tmp[j] = first + (byte)39;
else tmp[j] = first;
tmp[length*2] = 0;