Archiv für die Kategorie ‘English’

Alexa Shopping list items to TickTick

4. April 2020 Keine Kommentare

Since Wunderlist is shutting down it’s service a lot of users might search for a new shopping list app. For us TickTick was the best fit….but it doesn’t offer an Alexa skill for every language – only english.

While I’m writing this blogpost in English my Alexa at home is talking in German.

In theory it should be possible to use the Wunderlist IFTTT applets and just send the email to TickTick instead of Wunderlist. I didn’t have success with Gmail on IFTTT at all. No matter what I did, IFTTT always said „There was a problem with the Gmail service„. So there seems to be a problem between IFTTT and Gmail which isn’t Applet related.

So I looked for an alternative which could be: Alexa => Google Spreadsheet => TickTick

The technical view on this is: Alexa => IFTTT => Google Spreadsheet => Google Apps Script => Gmail => TickTick

In order to configure this you need to setup the IFTTT applet called „Add new items on Alexa Shopping List to Google Drive spreadsheet„. The applet settings can all stay default. It needs permissions for Alexa and Google Spreadsheets.

After that add a new item to the Alexa shopping list. This should create a new spreadsheet in your Google Drive called „Alexa Shopping list„.

Go to Google Drive and open the spreadsheet. Go to Tools => Scripteditor and insert the following Google Apps Script.
Set the ticktick_address to your individual address you can find in your TickTick settings.
If you want the new items to be added to a specific list then set ticktick_list accordingly. The names must match exactly. Otherwise leave it empty to add new items to the Inbox.

function sendToTickTick() {
  ticktick_address = '';
  ticktick_list = 'Shopping';
  var lock = LockService.getScriptLock();
  doc = SpreadsheetApp.getActiveSpreadsheet();
  rows = doc.getDataRange().getValues();  
  for (var i = rows.length; i>=1; i--) {
    var item = rows[i - 1][2];
    if (ticktick_list) {
      subject = item + ' ^' + ticktick_list;
    } else {
      subject = item;
    var body = '';
    GmailApp.sendEmail(ticktick_address, subject, body);
    Logger.log('Added item: ' + item);

function createSpreadsheetChangeTrigger() {
  var doc = SpreadsheetApp.getActiveSpreadsheet();

Once the script is edited save it and give it a name. The name doesn’t matter. After that click on Execute => function => createSpreadsheetChangeTrigger

This will install an App trigger which fires whenever a new item gets added.

Now add another item to the Alexa shopping list. It should get added to the TickTick list and get automatically removed from the spreadsheet as well. You can see the script logs in the Apps Script Console.

You will get a copy of every email. It’s possible to delete those automatically with an Gmail filter for the To: address which is your TickTick email address.


TickTick is currently working on it’s public API and also native integration for IFTTT and other services. Once it’s ready workarounds like this or email based integrations in general are not needed anymore. Hopefully this will be ready soon, even though it’s kind of fun to build stuff like that ;)

KategorienDies & Das, English

SSH Server Upload Speed Limit

26. März 2020 Keine Kommentare

Some daemon processes which handle user connections don’t have an internal mechanism to limit the bandwidth. One popular example is OpenSSH.

In theory SFTP could eat up all the bandwidth available, which is especially bad for home connections, since a fully utilized uplink is sometimes worse than a fully utilized downlink.

In order to apply a speed limit to daemon processes which use fork, tools like trinkle are not an option, but tc can do the job.

The following example configures a 10MBit/s upload speed limit (10,5Mbit/s burst limit) to the SSH server (sport 22) running on eth0.

tc qdisc add dev eth0 root handle 1:0 htb

tc class add dev eth0 parent 1:0 classid 1:1 htb \
 rate 10000kbps ceil 10500kbps prio 0

tc filter add dev eth0 protocol ip parent 1:0 prio 0 \
 u32 match ip sport 22 0xffff flowid 1:1

To watch the applied rules and the status:

tc -s -d class show dev eth0

To remove the applied configuration:

tc qdisc del dev eth0 root

This is completely done using the Kernel API. So it can be done with every service by specifying the source port and doesn’t bring any noticeable performance degradation beside having a speed limit applied.

If you want to limit all the upload traffic on a certain interface there doesn’t need to be an filter rule. This is done using a default.
The following example sets the limit from above to all upload traffic on eth0

tc qdisc add dev eth0 root handle 1:0 htb default 1

tc class add dev eth0 parent 1:0 classid 1:1 htb \
 rate 3500kbps ceil 4000kbps prio 0
KategorienEnglish, Linux

Debian 10 – PHP / Matomo GeoIP2 Installation

24. März 2020 Keine Kommentare

The old GeoIP legacy release (aka. GeoIPCity.dat) has been deprecated and doesn’t receive updates for quit some time. It will get removed from Matomo with the next major release.
If you would like to have accurate location detection in Matomo / Piwik the new GeoIP2 module should be used.

Since Debian Buster doesn’t ship it with it’s php packages, there are some manual steps needed to achieve that.

First of all install the needed library, build-tools and the php-dev package:

apt-get install libmaxminddb-dev php-dev git build-essential

Next step is to clone the MaxMind-DB-Reader-php repository in order to compile the PHP module.

cd /usr/local/src
git clone
cd MaxMind-DB-Reader-php/ext
make && make install

After that the new PHP module needs to be enabled and Apache or PHP (when using FPM) restarted:

echo "" > /etc/php/7.3/mods-available/maxminddb.ini
phpenmod maxminddb

# The folder /usr/share/GeoIP needs to be added
# to the PHP open_basedir setting in your php.ini

apache2ctl graceful
service php7.3-fpm restart

Now the database GeoIP2-City.mmdb needs to be installed locally. Since the free version is updated once a month, this is done via a download cronjob.

apt-get install python3-requests

mkdir -p /usr/share/GeoIP

cat >> /usr/local/sbin/ << EOF
#!/usr/bin/env python3
import requests
import datetime
import gzip
import sys

db = '/usr/share/GeoIP/GeoIP2-City.mmdb'
url = ''
now =
date = now.strftime('%Y-%m')

r = requests.get(url + 'dbip-city-lite-{}.mmdb.gz'.format(date))
if r.status_code ==
  with open(db, 'wb') as f:
  print('GeoIP2 download failed: ' + str(r.status_code))

chmod 700 /usr/local/sbin/

cat >> /etc/cron.d/geoip2-update << EOF
0 7 28 * *     root  /usr/local/sbin/

Now the GeoIP2 database gets updated once a month automatically and the script should be executed once to get the current version right now and to test the setup as well.


In order to use GeoIP2 in Matomo two settings need to be done. First of all a database Symlink needs to be created in order to use the GeoIP2 database in Matomo.

# adjust path to your matomo misc folder
ln -s /usr/share/GeoIP/GeoIP2-City.mmdb /var/www/matomo/misc/

After that the Plugin GeoIp2 needs to be activated. It’s a core package and should be already listed on the Matomo Plugins page in the Admin UI.

Now it should be possible to activate the new module under Geolocation. If your location is listed on the right side, enable the GeoIP2 box and click Save.

That’s it. The results are much more accurate and quicker.

If you don’t use Matomo a PHP GeoIP2 testscript could be used instead.


use MaxMind\Db\Reader;
$reader = new Reader('/usr/share/GeoIP/GeoIP2-City.mmdb');
$record = $reader->get($_SERVER['REMOTE_ADDR']);

print($record['continent']['names']['en'] . "\n");
print($record['country']['names']['en'] . "\n");
print($record['subdivisions'][0]['names']['en'] . "\n");
print($record['city']['names']['en'] . "\n");


Your continent, country, subdivision and city should be listed after executing the script via the webserver.