Enabling UDP load-balancing with Nginx on Debian 9 (Stretch)

User Datagram Protocol (UDP) is commonly used for DNS resolution and video/voice streaming applications. The advantage of UDP over TCP is that it has less overhead (smaller packet size). You can therefore send more data on your network with less latency. However this comes at the expense of data reliability.

Lemme guide you to how setup an Nginx server (10.0.0.5) which forwards UDP packets from port 514 to a Graylog server (10.0.0.10) on port 514 itself. We will be sending logs from a VM on 10.0.0.2

On your nginx server:

# echo “deb http://nginx.org/packages/debian/ stretch nginx” > /etc/apt/sources.list.d/nginx.list
# apt-get update
# apt-get install nginx

You should now have nginx installed. Paste the following snippet in your `/etc/nginx/nginx.conf`

stream {
  upstream graylog_upstreams {
    server 10.0.0.10:514;
  }

  server {
    listen 514 udp;
    proxy_pass graylog_upstreams;
    proxy_responses 0;
    proxy_bind $remote_addr transparent;
  }
}

Check if Nginx is listening on UDP port 514

root@prod-r7-nginx:~# ss -ntplu

However if you sending data to this port from another machine, you’ll notice that no data is sent to the backend server. Despite `tcpdump` will see the data coming and being sent.

IP 10.0.0.2.38696 > 10.0.0.5.514: SYSLOG kernel.info, length: 120
IP 10.0.0.2.45605 > 10.0.0.10.514: SYSLOG kernel.info, length: 120

We need to tell the kernel to actually route IP addresses which doesn’t belong to him thus acting like a router. We do so by the following command

sed -i "s/#net.ipv4.ip_forward.*/net.ipv4.ip_forward=1/" /etc/sysctl.conf
echo 1 > /proc/sys/net/ipv4/ip_forward

And that’s it ūüôā

Do you like nginx’s UDP loadbalancing feature?

Can Debian Stretch run on Ubuntu 16.04 LTS via LXC/LXD?

There is this never ending flame wars about whether Debian or Ubuntu is better. My personal servers have been historically on Ubuntu LTS due to the fact that they are known to have more updated packages that Debian. As I was planning to try MariaDB’s Galera cluster, I found that Debian Stretch has a more recent version of MariaDB than Ubuntu 16.04LTS.

No problem! I’ll run MariaDB inside a Debian container rather than an Ubuntu’s one. Here’s how to proceed:

# We download and create a container based on debian/stretch and we’ll call the VM mariadb-1

lxc launch images:debian/stretch mariadb-1

# We install an SSH server inside the VM to access it

lxc exec mariadb-1 — apt-get install ssh

# I put my public key inside the VM so that I can SSH into it.

# But before that, we need to create the .ssh directory

lxc exec¬†mariadb-1 — sh -c ‘mkdir -p /root/.ssh/’

lxc exec mariadb-1 — sh -c ‘echo “ssh-rsa AAAAB3N…+j/ nayar@macbook.local” > /root/.ssh/authorized_keys’

# The keys should be readable only by the owner

lxc exec¬†mariadb-1 — sh -c ‘chmod -R 600 /root/.ssh/’

And now your container should be accessible via SSH. You can use it like a VM. You may use the command below to find it’s IP

lxc list

| mariadb-1     | RUNNING | 10.195.197.123 (eth0)

Tips: If by doing so, the VM still asks you for password while trying to ssh on it, make sure you have properly pushed your ssh agent. On your laptop, try the following

ssh-add -k

ssh -A root@myserver.com “ssh root@10.195.197.123

Don’t repeat the same procedure for every container you need to create. Just copy from one:

lxc copy mariadb-1 mariadb-2

There you go. You have a new container under 5 seconds. Hope you liked this mini tutorial. Feel free to comment below.

UNIX: Root denied permission to modify files

WordPress notified me that an update was due. There are different ways to allow WordPress to update itself from the admin panel. One would be to use your FTP credentials (which I don’t have) and the other would be to give WordPress permission to edit its files i.e. give `www-data`, the user who run the web server, permission to read/write in /var/www.

However by doing so, I’d get a permission denied error:

root@apache:/var/www# chown -R www-data: nayarweb.com
chown: changing ownership of 'nayarweb.com/poweredbynayarweb.png': Operation not permitted

When you’re actually root, it’s not common to be denied rights to do stuffs. The files were owned by `nobody`.

-rwxrwxrwx  1 nobody nogroup 8.1K Oct  9  2013 poweredbynayarweb.png

Reading some stackoverflow posts, someone suggested that the files might not be owned by the OS as it might be mounted from a remote location. It is the source server who actually decides what could be done with the files. One common case of the scenario is mounting your files via NFS. Then I realised that my apache VM is actually an LXD container on a KVM host.

I had to find to uid with which apache (`www-data`) was running inside the LXD container. In my case, it was 100033.  Running the following command on my LXD host machine fixed the problem

chown -R 100033 /var/lib/lxd/.../nayarweb.com/

RFID and LoRa on Arduino

Last time I got a LoRa Server and LoRa Client to communicate to each other. It was about time to give them something to talk about i.e. start exchanging sensor data rather than just “Hello World”.

RFID tags

I plugged in my RFID reader which I bought like a years ago. My Arduino UNO was getting scrambled data on its serial. I tried connecting the RFID reader alone. The Arduino detected the device but whenever I’d place an RF tag on it, no data would be read.

RFID-RC522

The forums suggested to solder the pins on the board for better connection but it didn’t work in my case. Most probably my device was faulty.

Fortunately my friend Damien from DM Electronics¬†had the device is his stock which he sold to me. I’d highly recommend you to buy your electronic devices from there if you’re in Mauritius. He’s an awesome guy who has a deep understanding about how the devices actually operate on the inside.

I followed the tutorial above with Damien’s RC522 and it worked. But this is only half of my problems. I still need to put the LoRa shield back on.

Making LoRa and RFID reader work together

The LoRa shield and RC5222 use Serial Peripheral Interface (SPI) to communicate with the Arduino. SPI was new to me since I was familiar with 3 pin sensors (Ground, 3.3V and Data). SPI consists of:

  1. 3.3V: Provides power. Easy
  2. Ground: Well, ground
  3. RST: Reset: Still no idea what it does. Can you tell me in the comments?
  4. SS: Slave Select: It sends a signal when the device shall listen and transmit data.
  5. MOSI: Master Out Slave In: The line which is used to receive data from the Arduino
  6. MISO: Master In Slave Out: The line which is used to send data to the Arduino.

Since the SS line exists, it should be possible to mute the RFID reader while LoRa is transmitting/receiving data. The MFRC522 library allows the user to set a custom SS and RST pin.

#define RST_PIN 6
#define SS_PIN 7

MFRC522 mfrc522(SS_PIN, RST_PIN);

The default 9,10 pins will be used by LoRa and 6,7 pins will be used by RFID Reader. I tried manually setting turning of LoRa shield by setting the SS pin high without success

pinMode(10, OUTPUT);      // sets the digital pin as output
digitalWrite(10, HIGH);

Reading the source code of the SPI library (“SPI.h”), I came across the method `end()`. The RH_RF95 library also has a `sleep()` method. My final code looks like this:

void setup() {
  Serial.begin(9600); 
}

void loop() {
  readCard();
  delay(5000);
}

void readCard() {
  SPI.begin();
  mfrc522.PCD_Init();  
  ...
  SPI.end();
  lora(datafromcard);
}

void lora(String data) {
  rf95.init()
  ...
  rf95.send(data.c_str(), data.length());
  ...
  rf95.sleep();
}

And there you go. LoRa and RFID working together.