Categories
Linux Miscellaneous

Raspberry Pi 3: Turn Monitor On/Off

This is the only way the touchscreen LCD at my Raspberry Pi 3 turns on and off:

vcgencmd display_power 0 # turn off
vcgencml display_power 1 # turn on
Categories
Linux Miscellaneous Shell

Using sendmail with a Relay Host

It is useful when Docker containers can send e-mail to you in case there is an error condition that needs attention. Here is how to.

Install the sendmail package from your distribution and edit the file /etc/mail/sendmail.mc. Add this line to the end of it:

define('SMART_HOST', '<dns-name-of-your-relay')

Done! Just restart sendmail:

/etc/init.d/sendmail stop
/etc/init.d/sendmail start
Categories
Apache Linux Perl

How to automate LetsEncrypt

A new service is born: Let’s Encrypt. It offers free SSL certificates that you can use for web servers, email servers or whatever service you want to secure with TLS. This blog post presents my strategy to automate certificate creation and renewal. Please, install Let’s Encrypt on your web server box before you start to follow the presented strategy.

The key to success is to have Let’s Encrypt running without any further interaction. I use webroot authentication – which allows me to leave the productive web service up and running while the certificates are being issued or renewed. Therefore, I created a file named “myserver.ini” in folder /etc/letsencrypt. This configuration file contains all details that are required for the certification process;

1
2
3
4
5
6
7
8
rsa-key-size = 4096
authenticator = webroot
webroot-path = /path/to/webroot/
server = https://acme-v01.api.letsencrypt.org/directory
renew-by-default = True
agree-tos
email = <my-email-address>
domains = domain1.com, domain2.com

The second component of my strategy is the central piece: a script called “renewCertificates.pl”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/usr/bin/perl
 
my $DOMAINS = {
    'myserver' => {
        'configFile' => '/etc/letsencrypt/myserver.ini',
        'leSubDir'   => 'domain1.com',
        'certDir'    => '/var/www/domain1.com/certs',
    },
};
 
my $domain;
my $renewed = 0;
chdir ('/usr/local/letsencrypt');
foreach $domain (keys(%{$DOMAINS})) {
    print "INFO  - $domain - START\n";
    my $cmd = '/usr/local/scripts/checkCertExpiry.sh 30 '.$DOMAINS->{$domain}->{'certDir'}.'/cert.pem >/dev/null';
    my $rc = system($cmd);
    if ($rc) {
        $cmd = './letsencrypt-auto certonly --config '.$DOMAINS->{$domain}->{'configFile'}.' --renew-by-default';
        $rc = system($cmd);
        if (!$rc) {
            $cmd = 'cp /etc/letsencrypt/live/'.$DOMAINS->{$domain}->{'leSubDir'}.'/* '.$DOMAINS->{$domain}->{'certDir'}.'/';
            $rc = system($cmd);
            if ($rc) {
                print "ERROR - $domain - Cannot deploy\n";
            } else {
                print "INFO  - $domain - Deployed\n";
                $renewed = 1;
            }
        } else {
            print "ERROR - $domain - Cannot generate certificates\n";
        }
    } else {
        print "INFO  - $domain - Certificate does not expire within 30 days\n";
    }
    print "INFO  - $domain - END");
}
 
if ($renewed) {
   system("/etc/init.d/apache2 reload");
}
 
exit 0;

This scripts allows renewal of multiple certificates by supporting multiple configurations. Lines 3-9 describe these configurations. leSubDir (line 6) is the sub directory that Let’s Encrypt creates in the certification process. It is the name of the first domain specified in the configuration file, here: domain1.com. certDir (line 7) is the target path where the certificates will be deployed to.

A second script supports this procedure by telling whether a certificate will expire within a certain number of days (see line 16 above):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
 
# First parameter specifies if certificate expire in the next X days
DAYS=$1
 
target=$2
if [ ! -f "$target" ]; then
    echo "Certificate does not exist (RC=2)"
    exit 2;
fi
 
openssl x509 -checkend $(( 86400 * $DAYS )) -enddate -in "$target" >/dev/null 2>&1
expiry=$?
if [ $expiry -eq 0 ]; then
    echo "Certificate will not expire (RC=0)"
    exit 0
else
    echo "Certificate will expire (RC=1)"
    exit 1
fi

This script returns 0 when the given certificate will not expire, otherwise it returns a non-0 value. The Perl script above will renew certificates 30 days before expiration only.

The last piece is the Apache configuration to be used on these domains:

1
2
3
4
    SSLEngine on
    SSLCertificateFile /var/www/domain1.com/certs/cert.pem
    SSLCertificateKeyFile /var/www/domain1.com/certs/privkey.pem
    SSLCertificateChainFile /var/www/domain1.com/certs/fullchain.pem

I run the central Perl script above daily and do not need to worry about certificates anymore 🙂

Categories
Linux Perl

Nonblocking sockets and Perl’s Net::Daemon

I was writing a Perl-based proxy for line-based SMTP protocol. The main reason doing this is because I receive unwanted e-mail bounces that are not filtered out by my SpamAssassin. The idea was to hook into the mail delivery chain and to collect e-mail addresses that I use. The proxy can later then filter out any bounce message that was not originated by myself.

I decided to use the Net::Daemon module which has a quite fancy interface. One just writes a single function which handles the client connection. As I didn’t want to learn every detail of SMTP protocol, I simply use non-blocking sockets. So whoever of the two parties wants to talk, it can do so and my proxy will just listen to the chat. The IO::Select documentation tells you to do this when you have multiple sockets to react on:

1
2
3
4
5
6
7
8
9
10
11
12
# Prepare selecting
$select = new IO::Select();
$select->add($socket1);
$select->add($socket2);
 
# Run until timed out / select socket
while (@CANREAD = $select->can_read(30)) {
    foreach $s (@CANREAD) {
        #... read the socket and do your stuff
    }
}
# Whenever there is a problem (like talk ended) the loop exits here

However, this code doesn’t work as expected. The can_read() function will not return an empty list when the sockets closed. It still returns any socket and the loop goes on forever. In fact, as we are in non-blocking mode, the script now eats up CPU time. 🙁

There are two solutions to it. The first is to check whether the given socket is still connected and then exit the loop:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Prepare selecting
$select = new IO::Select();
$select->add($socket1);
$select->add($socket2);
 
# Run until timed out / select socket
while (@CANREAD = $select->can_read(30)) {
    foreach $s (@CANREAD) {
        if (!$s->connected()) {
            return;
        }
        #... It's safe now to read the socket and do your stuff
    }
}

The second and more clean method is just to remove the closed socket from the IO::Select object:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Prepare selecting
$select = new IO::Select();
$select->add($socket1);
$select->add($socket2);
 
# Run until timed out / select socket
while (@CANREAD = $select->can_read(30)) {
    foreach $s (@CANREAD) {
        if (!$s->connected()) {
            $select->remove($s);
            next;
        }
        #... It's safe now to read the socket and do your stuff
    }
}

Then the selector runs empty and will exit the loop as well.

Categories
Java Linux

JavaMail: Sending mails fails

Ever stumbled across this?

javax.mail.SendFailedException: Sending failed;
   nested exception is:
      javax.mail.MessagingException: 501 5.0.0 HELO requires domain address

I wasn’t able for a long time to find the solution in the net although many people reported having this problem. The only hint you find is “There was an invalid entry in /etc/hosts”. But noone said exactly what the “invalid entry” was.

I myself found that there was no invalid entry but the configured hostname of the machine (issue “hostname” in a shell) cannot be resolved by DNS. The result is the given error message from the mail server.

What is happening? JavaMail resolves its own hostname by asking for the local hostname. The SMTP protocol requires the sending domain while handshaking. The server will try to resolve the domain by its DNS. If the hostname sent cannot be resolved then the server responds with “HELO requires domain address” as stated above.

I hope that this issue now becomes clearer to all of you.

PS: Solution is make sure your hostname can be resolved by DNS. Fix your hostname if it’s wrong or add the DNS entry.

Categories
Linux

Ubuntu 11.10 Upgrade Problems

Grrr, that was nasty. I upgraded my Ubuntu to 11.10 after the 11.04 installation on my Lenovo laptop did not boot anymore with the latest kernel update. I usually install all updates that Ubuntu’s Update Manager proposes and never had problems so far. Until yesterday when the last kernel update was received.

The laptop did not boot anymore. It halted somewhere without any further notice. Switching to the console with Ctrl-Alt-F1 and checking the X11 log at /var/log/Xorg.0.log revealed that NVIDIA graphics driver could not be loaded anymore. Re-installing the driver did not fix the problem :(. Well, at least I could boot the old kernel and check systems out.

However, I wasn’t able to make the newest kernel working with NVIDIA’s kernel module. So I finally tried the distribution upgrade to 11.10. But again, the system stuck in the boot. Even worse, I had a new symptom:

Unable to connect to the system bus: Failed to connect to socket /var/run/dbus/system_bus_socket: Connection refused

An internet research turned up this excellent forum thread which told me that the distribution upgrade had failed to migrate two directories. Following the instructions of #24 – using mv command and setting chmod 1777 /run/lock did finally help me to repair the system.

So guys, if you observe the weird behaviour after upgrading a kernel on an NVIDIA based computer, check out:

  • The X11 log for messages about your kernel module
  • Wiki page http://wiki.ubuntuusers.de/Grafikkarten/NVIDIA/nvidia
  • Wiki page http://wiki.ubuntuusers.de/Grafikkarten/Nvidia
  • and of course, google your boot log error

 

 

Categories
Linux

Convinient GRUB multi-boot configuration

These two lines in /etc/default/grub let grub2 remember what system you booted last time and will automatically start this system when rebooting:

GRUB_DEFAULT=saved
GRUB_SAVEDEFAULT=true

You need to update grub2 afterwards to have the new configuration activated:

update-grub
Categories
Linux Miscellaneous

PDF Printer with Linux

I use a PDF Printer on my professional Windows notebook. It enables me to create PDF documents from whatever application. So, how about Linux then. Thanks God, there is cups-pdf. A German tutorial can be found here. If you find a English HowTo, just post the link here.

Categories
Linux

Switch Off Caps-Lock

I was always annoyed by CAPS-LOCK key on my Linux notebook. Thanks god, there is a solution:

xmodmap -e "remove lock = Caps_Lock"

will switch this damn thing off. 🙂

Categories
Linux

Extending filesystem on RHEL with LVM

You need to extend a filesystem on a RedHat box? Check the filesystems with df -H. You might get something like

Filesystem             Size   Used  Avail Use% Mounted on
/dev/mapper/system-root
11G   8.0G   2.0G  81% /
/dev/cciss/c0d0p1      104M    18M    81M  19% /boot
tmpfs                  2.1G      0   2.1G   0% /dev/shm
/dev/mapper/system-tmp
4.2G   146M   3.9G   4% /tmp
/dev/mapper/system-var
4.2G   873M   3.1G  23% /var
/dev/mapper/system-mysqllv
11G   8.1G   1.8G  83% /var/lib/mysql
/dev/mapper/system-srvlv
47G    16G    29G  35% /srv

You need to increase the volume capacity first, e.g. for /srv mount:

lvextend -L +15G /dev/system/srvlv

where +15G tells the command to extend the volume by another 15GB.

Last step is to adjust the filesystem to that volume’s new size:

resize2fs /dev/mapper/system-srvlv

That’s it 🙂