newspaint

Documenting Problems That Were Difficult To Find The Answer To

Strawberry Perl for Windows – Makefile Temporary Directory

I had a problem. My assigned company laptop would only allow me to execute (run) files from a single path (e.g. C:\Permitted\).

When I tried to use cpan to install a module, or I downloaded the zip of the module and tried to build the module myself, I would always get errors about a file in C:\Users\username\AppData\Local\Temp\makennnnnn.bat being attempted to be executed.

Now, downloading a module from CPAN and unzipping it, then running perl -w Makefile.PL was no problem.

The issue occurred when running gmake. In debugging mode it would output similar to the following:

Creating temporary batch file C:\Users\username\AppData\Local\Temp\make90123-1.bat
Batch file contents:
        @echo off
        rem
CreateProcess(C:\Users\username\AppData\Local\Temp\make90123-1.bat,C:\Users\username\AppData\Local\Temp\make90123-1.bat,...)

The solution was found in this linked thread. That linked to Microsoft documentation for the GetTempPathA function which specified that the temporary path returned was either:

  1. the path specified by the TMP environment variable, or if not exists
  2. the path specified by the TEMP environment variable, or if not exists
  3. the path specified by the USERPROFILE environment variable, or if not exists
  4. the Windows directory

So it is a simple matter of setting an environment variable and GNU make (gmake) will create the temporary batch files there instead.

Using FFmpeg to Encode a Video for WhatsApp

WhatsApp seems very picky about what video formats it will actually forward. FFmpeg can be used to process a video into a format that WhatsApp is more likely to accept for transmission.

The settings I have used are:

-vf "scale=-2:480" \
-c:v libx264 \
-preset slow \
-crf 21 \
-profile:v baseline \
-level 3.0 \
-pix_fmt yuv420p \
-r 25 \
-g 50 \
-c:a aac \
-b:a 160k \
-r:a 44100 \
-af "aformat=channel_layouts=stereo,highpass=f=40,volume=1.40,compand=attacks=0.1 0.1:decays=3.0 3.0:points=-900/-900 -100/-70 -70/-45 -45/-30 -40/-15 -20/-9 -10/-6 0/-4:soft-knee=0.50:gain=0:volume=-900:delay=3.0" \
-f mp4 \

Here’s an explanation of what the lines do (you can choose what to include yourself):

  • -vf “scale=-2:480” – sets up a video filter to scale the image, in this case it dynamically scales the width to a number divisible by 2, and sets the height to 480 pixels
  • -c:v libx264 – sets the video codec to H.264
  • -preset slow – chooses how much time to spend encoding the video, the slower the smaller the output (usually)
  • -crf 21 – chooses the constant rate factor (CRF) which determines what image quality the output will try and achieve (0 is lossless, 23 is default, 51 is worst quality possible)
  • -profile:v baseline – chooses the specific H.264 profile, some devices (maybe WhatsApp) only support the more limited baseline or main profiles
  • -level 3.0 – seems to be necessary with the above baseline flag to be as compatible with as many devices as possible, including Android
  • -pix_fmt yuv420p – QuickTime compatibility
  • -r 25 -g 50 – 25 frames per second, and an index frame every 50 frames
  • -c:a aac – set audio codec to AAC
  • -b:a 160k – set bitrate of audio to 160k
  • -r:a 44100 – set audio sampling rate to 44.1KHz
  • -af “aformat=channel_layouts=stereo,highpass=f=40,volume=1.40,compand=attacks=0.1 0.1:decays=3.0 3.0:points=-900/-900 -100/-70 -70/-45 -45/-30 -40/-15 -20/-9 -10/-6 0/-4:soft-knee=0.50:gain=0:volume=-900:delay=3.0” – whole host of audio filters going on here, the big one is the compand which makes the audio as loud as possible (may not always work for you, test before using)
  • -f mp4 – output file as mp4 format

You should add the input file (with the -i flag) at the start of the ffmpeg command, and finish with the path/name of the file (with the .mp4 extension) you wish to output to.

Copy Timestamp From One File to Another in Linux

Tested on Ubuntu 16.04.

# get last modified time in seconds past the epoch
export SECS=$(/usr/bin/stat -c "%Y" "${FILE_SRC})

# set modified time to seconds past the epoch
touch --date=@${SECS} "${FILE_DST}"

Audacious Only Plays One Song Then Stops

If Audacious is only playing a single song then stopping – even though you have a large playlist – then it may be the following:

  • open the menu by clicking on the tiny icon to the left of the word “AUDACIOUS” at the top left of the player window
  • choose Playback > No Playlist Advance (Ctrl+N) if ticked

IG CFD Sneaky Premium Penalty (CRPREM)

What is “controlled risk premium”, or CRPREM? Turns out – the IG website will not tell you. It’s something that will bite you when you least expect it – and it will hurt – because it isn’t fair, and it isn’t even remotely clear.

I was playing around making CFDs (contracts for difference) – up a hundred dollars or so – feeling quite happy with myself. Then I made the mistake of making a CFD on the Italian index:

IG CFD Italy Index Deal Window

IG CFD Italy Index Deal Window

Instantly my stop was triggered. I don’t know how or what happened but when I checked my transaction history I saw the following entry:

MarketName ProfitAndLoss
Italy 40 Cash (€1) converted at 1.8553 A$-185.54

So far, so good, I lost $185 or thereabouts on the market going in the wrong direction.

Then this entry floored me:

MarketName ProfitAndLoss
Italy 40 Cash (€1) CRPREM DIAAAAEHD5….. Converted at 1.8553 A$-89.06

Wait, what??! Another $90 fee? For what? What is CRPREM?

See that circled number in the deal window titled “Stop premium (if triggered)”? That means that’s the number of extra points you’re charged as a “controlled risk premium” should you fail to close your position and it gets closed automatically.

In my case the fee was 2 controls times 24 points (stop premium) = 48 times the exchange rate of 1.8553 = AU$89. Ouch.

I should have looked at the window more carefully before I placed the order. But here’s the thing.. all they display is the margin – no hint or indication or the stop premium if triggered – even though it is mandatory to provide a stop.

Doesn’t seem fair or right, does it. But you probably landed here because you were charged an outrageous fee – and want to know why – and there appears to be no customer service at IG to tell you – or a web page on the subject, either – at least I didn’t find one.

Changing Active Titlebar Background on Greybird Theme in Xubuntu/XFCE

Simply edit the file /usr/share/themes/Greybird/xfwm4/title-1-active.png with the background colour you want (which will be replicated along the width of the title bar of the active window).

Then go to the menu, select Settings > Window Manager, then go to the Style tab, and choose a different Theme (such as Default) and then select the newly edited theme Greybird again.

Perl WWW::Mechanize or LWP::UserAgent and AWS SSL Handshake Failure

TL;DR (too long, didn’t read) summary:

Force protocol and cipher:

my $ua = WWW::Mechanize->new();
$ua->ssl_opts(
  'SSL_version' => 'TLSv1_2',
  'SSL_cipher_list' => 'ECDHE-RSA-AES256-GCM-SHA384',
);

I had a script using WWW::Mechanize (which uses LWP::UserAgent under the hood) which used to work with a website. But then the website was moved and hosted on Amazon Web Services.

Suddenly my script started reporting:

SSL connect attempt failed error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure at /usr/share/perl5/LWP/Protocol/http.pm line 47.

I tried debugging using a technique I found elsewhere and that was providing a command line switch to enable SSL debugging:

$ perl -MIO::Socket::SSL=debug4 myscript.pl
DEBUG: .../IO/Socket/SSL.pm:2700: new ctx 53819024
DEBUG: .../IO/Socket/SSL.pm:612: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:614: socket connected
DEBUG: .../IO/Socket/SSL.pm:636: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:669: using SNI with hostname www.thetarget.domain
DEBUG: .../IO/Socket/SSL.pm:704: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:723: set socket to non-blocking to enforce timeout=15
DEBUG: .../IO/Socket/SSL.pm:736: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:739: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:749: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:759: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:779: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:736: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:739: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:742: SSL connect attempt failed

DEBUG: .../IO/Socket/SSL.pm:742: local error: SSL connect attempt failed error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
DEBUG: .../IO/Socket/SSL.pm:745: fatal SSL error: SSL connect attempt failed error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
DEBUG: ...erl5/Net/HTTPS.pm:69: ignoring less severe local error 'IO::Socket::IP configuration failed', keep 'SSL connect attempt failed error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure'
DEBUG: .../IO/Socket/SSL.pm:2733: free ctx 53819024 open=53819024
DEBUG: .../IO/Socket/SSL.pm:2738: free ctx 53819024 callback
DEBUG: .../IO/Socket/SSL.pm:2745: OK free ctx 53819024

I tried capturing the session with tcpdump and viewing the session in Wireshark to make sense of what was happening:

time=0.291136 client>server protocol=TLSv1.2 message=Client Hello
time=0.581841 server>client protocol=TLSv1.2 message=Alert (Level: Fatal, Description: Handshake Failure)

So basically AWS was outright rejecting the “Client Hello” packet without any negotiation at all. Neither was it citing a reason for the handshake failure.

At this point it became guesswork. Initially I considered forcing the protocol using the ssl_opts() function:

my $ua = WWW::Mechanize->new();
$ua->ssl_opts(
  'SSL_version' => 'TLSv1_2',
);

But this gave exactly the same result.

Then I thought about forcing the cipher. But to which cipher? I looked up Amazon’s list of accepted ciphers but that didn’t help much. You can try running the following but it gives too many options:

$ openssl ciphers
ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:SRP-DSS-AES-256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:SRP-AES-256-CBC-SHA:...

So then I tried doing a connect using openssl to see what cipher it chose:

$ # note you can also add the -servername <domain> option for SNI
$ openssl s_client -connect www.thetarget.domain:443
...
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
...

So I then tried my Perl script setting the cipher to that reported by openssl:

my $ua = WWW::Mechanize->new();
$ua->ssl_opts(
  'SSL_version' => 'TLSv1_2',
  'SSL_cipher_list' => 'ECDHE-RSA-AES256-GCM-SHA384',
);

This time my script worked!

$ perl -MIO::Socket::SSL=debug4 myscript.pl
DEBUG: .../IO/Socket/SSL.pm:2700: new ctx 38327392
DEBUG: .../IO/Socket/SSL.pm:612: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:614: socket connected
DEBUG: .../IO/Socket/SSL.pm:636: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:669: using SNI with hostname www.thetarget.domain
DEBUG: .../IO/Socket/SSL.pm:704: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:723: set socket to non-blocking to enforce timeout=15
DEBUG: .../IO/Socket/SSL.pm:736: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:739: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:749: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:759: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:779: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:736: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:2601: did not get stapled OCSP response
DEBUG: .../IO/Socket/SSL.pm:2554: ok=1 [2] /O=Digital Signature Trust Co./CN=DST Root CA X3/O=Digital Signature Trust Co./CN=DST Root CA X3
DEBUG: .../IO/Socket/SSL.pm:2554: ok=1 [1] /O=Digital Signature Trust Co./CN=DST Root CA X3/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
DEBUG: .../IO/Socket/SSL.pm:2554: ok=1 [0] /C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3/CN=www.thetarget.domain
DEBUG: .../IO/Socket/SSL.pm:1664: scheme=www cert=40017248
DEBUG: .../IO/Socket/SSL.pm:1674: identity=www.thetarget.domain cn=www.thetarget.domain alt=2 www.thetarget.domain
DEBUG: .../IO/Socket/SSL.pm:739: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:749: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:759: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:779: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:736: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:739: done Net::SSLeay::connect -> 1
DEBUG: .../IO/Socket/SSL.pm:794: ssl handshake done

Configuring RAS Daemon for Lenovo ThinkServer TS140

The RAS daemon (rasdaemon) can be installed on Ubuntu Linux 16.04 using the command:

$ sudo apt-get install rasdaemon

Once this is installed the ThinkServer TS140 requires a custom file to be created in /etc/ras/dimm_labels.d/ with the following file format:

# Vendor: 
#   Model: 
#     :  ...

… although it seems the old Edac label format is also valid:

# Vendor: 
#   Model: 
#     :  ..

In order to discover the values required one can run the following commands:

$ for i in /sys/devices/system/edac/mc/mc0/rank*; do \
  echo ==$i==; \
  cat "$i/dimm_location"; echo -ne "\n"; \
done

==/sys/devices/system/edac/mc/mc0/rank0==
csrow 0 channel 0 
==/sys/devices/system/edac/mc/mc0/rank1==
csrow 0 channel 1 
==/sys/devices/system/edac/mc/mc0/rank2==
csrow 1 channel 0 
==/sys/devices/system/edac/mc/mc0/rank3==
csrow 1 channel 1 
==/sys/devices/system/edac/mc/mc0/rank4==
csrow 2 channel 0 
==/sys/devices/system/edac/mc/mc0/rank5==
csrow 2 channel 1 
==/sys/devices/system/edac/mc/mc0/rank6==
csrow 3 channel 0 
==/sys/devices/system/edac/mc/mc0/rank7==
csrow 3 channel 1 

The board name and vendor can also be found:

$ cat /sys/devices/virtual/dmi/id/board_vendor
LENOVO
$ cat /sys/devices/virtual/dmi/id/board_name
ThinkServer TS140

Then a file (e.g. “lenovo-thinkserver-ts140.txt”) can be created in /etc/ras/dimm_labels.d/:

Vendor: LENOVO
  Model: ThinkServer TS140
    DIMM1_0: 0.0.0
    DIMM1_1: 0.0.1
    DIMM2_0: 0.1.0
    DIMM2_1: 0.1.1
    DIMM3_0: 0.2.0
    DIMM3_1: 0.2.1
    DIMM4_0: 0.3.0
    DIMM4_1: 0.3.1

And the rasdaemon restarted:

$ sudo systemctl status rasdaemon
$ sudo systemctl restart rasdaemon

Then the script can be run:

$ ras-mc-ctl --layout
          +-----------------------------------------------+
          |                      mc0                      |
          |  csrow0   |  csrow1   |  csrow2   |  csrow3   |
----------+-----------------------------------------------+
channel1: |  4096 MB  |  4096 MB  |  4096 MB  |  4096 MB  |
channel0: |  4096 MB  |  4096 MB  |  4096 MB  |  4096 MB  |
----------+-----------------------------------------------+

$ ras-mc-ctl --print-labels
LOCATION                            CONFIGURED LABEL     SYSFS CONTENTS      
mc0 csrow 0 channel 0               DIMM1_0              DIMM1_0             
mc0 csrow 0 channel 1               DIMM1_1              DIMM1_1             
mc0 csrow 1 channel 0               DIMM2_0              DIMM2_0             
mc0 csrow 1 channel 1               DIMM2_1              DIMM2_1             
mc0 csrow 2 channel 0               DIMM3_0              DIMM3_0             
mc0 csrow 2 channel 1               DIMM3_1              DIMM3_1             
mc0 csrow 3 channel 0               DIMM4_0              DIMM4_0             
mc0 csrow 3 channel 1               DIMM4_1              DIMM4_1    

The first time you do this the new labels may not be registered, e.g. you see the following:

$ ras-mc-ctl --print-labels
LOCATION                            CONFIGURED LABEL     SYSFS CONTENTS      
mc0 csrow 0 channel 0               DIMM1_0              mc#0csrow#0channel#0
mc0 csrow 0 channel 1               DIMM1_1              mc#0csrow#0channel#1
mc0 csrow 1 channel 0               DIMM2_0              mc#0csrow#1channel#0
mc0 csrow 1 channel 1               DIMM2_1              mc#0csrow#1channel#1
mc0 csrow 2 channel 0               DIMM3_0              mc#0csrow#2channel#0
mc0 csrow 2 channel 1               DIMM3_1              mc#0csrow#2channel#1
mc0 csrow 3 channel 0               DIMM4_0              mc#0csrow#3channel#0
mc0 csrow 3 channel 1               DIMM4_1              mc#0csrow#3channel#1

The “SYSFS” contents can be found:

$ for i in /sys/devices/system/edac/mc/mc0/rank*; \
  do echo "$i/dimm_label: $(cat $i/dimm_label)"; \
done
/sys/devices/system/edac/mc/mc0/rank0/dimm_label: mc#0csrow#0channel#0
...
/sys/devices/system/edac/mc/mc0/rank7/dimm_label: mc#0csrow#3channel#1

So you can register the configured labels by running:

$ sudo ras-mc-ctl --register-labels
$ ras-mc-ctl --print-labels
LOCATION                            CONFIGURED LABEL     SYSFS CONTENTS      
mc0 csrow 0 channel 0               DIMM1_0              DIMM1_0
...

In Ubuntu the rasdaemon service is defined in /etc/systemd/system/multi-user.target.wants/rasdaemon.service and contains the line:

ExecStart=/usr/sbin/rasdaemon -f -r

This instructs the daemon to start in foreground mode and to record events to a SQLite3 database.

The SQLite3 database is located at /var/lib/rasdaemon/ras-mc_event.db:

$ sqlite3 /var/lib/rasdaemon/ras-mc_event.db .tables
aer_event     extlog_event  mc_event      mce_record  

$ sqlite3 /var/lib/rasdaemon/ras-mc_event.db ".schema mc_event"
CREATE TABLE mc_event (
  id INTEGER PRIMARY KEY,
  timestamp TEXT,
  err_count INTEGER,
  err_type TEXT,
  err_msg TEXT,
  label TEXT,
  mc INTEGER,
  top_layer INTEGER,
  middle_layer INTEGER,
  lower_layer INTEGER,
  address INTEGER,
  grain INTEGER,
  syndrome INTEGER,
  driver_detail TEXT
);

Add LetsEncrypt to Reverse Proxy in Ubuntu Xenial

A rough picture of what is being attempted here is as follows (although I haven’t split out SSL and non-SSL virtual hosts here):

              ____________          ______________
             |            |        |              |
Internet --> | Rev Proxy  | - / -> |   Backend    |
             | 172.16.5.5 |        | 172.16.11.11 |
             |____________|        |______________|
                   |
             /.well-known/
              _____V_____
             | port 9876 |
             | 127.0.0.1 |
             |  certbot  |
             |___________|

First the certbot utility needs to be installed. To do this add the certbot repository to the /etc/apt/sources.list file:

deb http://ppa.launchpad.net/certbot/certbot/ubuntu xenial main

Attempt to update the apt repository.

$ sudo apt-get update
Get:5 http://ppa.launchpad.net/certbot/certbot/ubuntu xenial InRelease [24.3 kB]
Ign:5 http://ppa.launchpad.net/certbot/certbot/ubuntu xenial InRelease         
Get:10 http://ppa.launchpad.net/certbot/certbot/ubuntu xenial/main amd64 Packages [18.6 kB]
Get:11 http://ppa.launchpad.net/certbot/certbot/ubuntu xenial/main Translation-en [10.9 kB]
Fetched 3,495 kB in 1s (2,800 kB/s)                                
Reading package lists... Done
W: GPG error: http://ppa.launchpad.net/certbot/certbot/ubuntu xenial InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 8C47BE8E75BCA694
W: The repository 'http://ppa.launchpad.net/certbot/certbot/ubuntu xenial InRelease' is not signed.
N: Data from such a repository can't be authenticated and is therefore potentially dangerous to use.
N: See apt-secure(8) manpage for repository creation and user configuration details.

We need to import the key to be able to install from this repository.

$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 8C47BE8E75BCA694
Executing: /tmp/tmp.X7oOFSoctO/gpg.1.sh --keyserver
keyserver.ubuntu.com
--recv-keys
8C47BE8E75BCA694
gpg: requesting key 75BCA694 from hkp server keyserver.ubuntu.com
gpg: key 75BCA694: public key "Launchpad PPA for certbot" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)

Next, install certbot.

$ sudo apt-get install certbot
0 to upgrade, 31 to newly install, 0 to remove and 3 not to upgrade.
Need to get 2,142 kB of archives.
After this operation, 11.4 MB of additional disk space will be used.
Do you want to continue? [Y/n] y

Now, update the Apache site configuration to proxy-pass (reverse proxy) certbot validation requests to a port that certbot will listen to during certificate requests. For example, I put the following into /etc/apache2/sites-enabled/000-default.conf:

  ProxyPass "/.well-known/" "http://127.0.0.1:9876/.well-known/"
  ProxyPassReverse "/.well-known/" "http://127.0.0.1:9876/.well-known/"

If you haven’t already you’ll need to include the proxy modules into Apache:

$ cd /etc/apache2/mods-enabled
$ sudo ln -s ../mods-available/proxy.* .
$ sudo ln -s ../mods-available/proxy_http.* .
$ sudo service apache2 restart

Now we can do a dry-run of certbot to test everything is functioning:

$ sudo certbot certonly \
    --preferred-challenges http-01 --http-01-port=9876 \
    --no-verify-ssl --dry-run \
    --domain www.mydomain.com.au \
    -v

Saving debug log to /var/log/letsencrypt/letsencrypt.log

How would you like to authenticate with the ACME CA?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Spin up a temporary webserver (standalone)
2: Place files in webroot directory (webroot)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1

IMPORTANT NOTES:
 - The dry run was successful.
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.

Now create the certificate (do the same but without a dry run):

$ sudo certbot certonly \
    --preferred-challenges http-01 --http-01-port=9876 \
    --no-verify-ssl \
    --domain www.mydomain.com.au \
    -v

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/www.mydomain.com.au/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/www.mydomain.com.au/privkey.pem
   Your cert will expire on 2020-03-31. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Next we’ve got to add the created certificate to our Apache site configuration for the SSL virtual server, in my case this is file /etc/apache2/sites-enabled/001-default-ssl.conf:

    SSLCertificateFile /etc/letsencrypt/live/www.mydomain.com.au/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/www.mydomain.com.au/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/www.mydomain.com.au/fullchain.pem

As for the reverse proxy part – you can reverse proxy to a SSL website internally using something like the following for your SSL virtual server configuration (within the <VirtualHost> tags).

    # disable SSL certificate checks for back-end server
    SSLProxyEngine on
    SSLProxyCheckPeerName off
    SSLProxyCheckPeerExpire off
    SSLProxyVerify none
    SSLProxyCheckPeerCN off

    # set X-Forwarded-For header to track actual IP of incoming request
    ProxyPreserveHost On

    ProxyPass "/" "https://172.16.11.11/"
    ProxyPassReverse "/" "https://172.16.11.11/"

On the backend server you’ll probably want to log the actual IP of the external request, rather than the IP of the reverse proxy.

To do this enable the mod_remoteip module to your enabled modules:

$ cd /etc/apache2/mods-enabled
$ sudo ln -s ../mods-available/remoteip.* .
$ sudo service apache2 restart

Configure your virtual server to use the remoteip module as well as update the custom logging configuration:

  # note %h is usually present in LogFormat for host, but use %a instead for mod_remoteip
  LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined_forwarded

  # use the address from X-Forwarded-For in access log instead of the reverse proxy
  CustomLog /var/log/apache2/access_ssl.log combined_forwarded

  # use the IP address from the X-Forwarded-For from requests from reverse proxy
  RemoteIPHeader X-Forwarded-For
  RemoteIPTrustedProxy 172.16.5.5

Don’t Want to Register Your New Kindle

I purchased a new Amazon Kindle, model J9G29R.

Upon turning it on it asked me to connect to WiFi, which I did.

It then asked me to register with an Amazon account, or create a new one. There was no cancel or return option.

I held down the power button for 5 seconds until a menu appeared with the options “CANCEL”, “RESTART”, and “SCREEN OFF”. I chose “RESTART” and the Kindle restarted (took about a minute or two to finish loading). It did not ask me to register with an Amazon account after restarting, instead went straight to the main menu.