Traefik: tls private key does not match public key

self signed certificates, combined pem

In case you’re using self-signed x509 certificates you may see this error message within the traefik logs – the solution is quite easy: the first certificate of your combined pem file (ca+intermediate+server) has to be the server certificate!

Node.js: Log static file requests with expressjs serve-static middleware

nodejs, express, static, logfile, analytics, statistics, download counter

In most cases, every web-application requires some kind of request logging. Especially package downloads will be counted for statistic purpose. By using expressjs, static content is served by the middleware module serve-static.

To count the successfull requests handled by this module, you can hook into the setHeaders callback which is invoked each time a file is ready for delivering (file exists, file is accessible).

Example#

// utility
const _path = require('path');

// expressjs
const _express = require('express');
let _webapp = _express();

// your statistic module
const _downloadStats = require('./download-counter');

// serve static package files
_webapp.use('/downloads', _express.static(_path.join(__dirname, 'downloads'), {
    // setHeaders is only called on success (stat available/file found)
    setHeaders: function(res, path, stat){
        // count request: full-path, file-stats, client-ip
        _downloadStats(path, stat, res.req.connection.remoteAddress);
    }
}));

 

Currently (v380.64_2) there is no out-of-the-box mechanism to setup persistent crontabs which survives a system reboot. But there is a simple workaround availabe.

Your Crontab File#

First of all, create a standard crontab file and store it in your persistent JFFS partition. In this example /jffs/configs/cron

# Syntax
# MM HH DayOfMonth Month DayOfWeek <action>

# Run Backup Script at 4am
0 4 * * * /jffs/scripts/backup.sh

Setup Crontabs on startup#

To load the crontab list on boot, add the following line to your init-start script in /jffs/scripts/init-start

cp /jffs/configs/cron /var/spool/cron/crontabs/admin

That’s it!

Redmine 3.2 – Redirect Users to my/page after Login

private issue tracking, user dashboard

Do you want to redirect users to their custom page/issue dashboard after login ? This is especially useful in case your redmine installation is set to private (login required).

Change the home Route#

Edit config/routes.rb

# comment out this line
#  root :to => 'welcome#index', :as => 'home'

# add the following line (keep the identation!)
  root :to => 'my#page', :as => 'home'

Ready! Just restart your Redmine service to apply the changes

 

Render Markdown/GFM Documents online using the GitHub v3 API

simple code snipped to convert markdown to html, public github api

Sometimes, you need to render parts of your Markdown documents – e.g. README.md or CHANGES.md – as html to embed it into your application, documentation or project website. There are a several markdown or especially GFM (GitHub Flavored Markdown) libraries are out there, but they require an additional setup and have to be maintained.

The simple Way#

Thanks to GitHub, there is a public API available which allows you to render your documents by the GitHub webservices.

PHP Client#

/**
 * Render Markdown content using the GitHub v3 Markdown API
 * @see https://developer.github.com/v3/markdown/
 * @source https://andidittrich.com/2016/05/render-markdown-gfm-documents-online-using-the-github-v3-api
 * @license: MIT
 * @return string(html)
 */
function renderGFM($text, $repositoryContext = null){

    // create the payload
    // @see https://developer.github.com/v3/markdown/
    $postdata = json_encode(
        array(
            'text' => $text,
            'mode' => ($repositoryContext != null ? 'gfm' : 'markdown'),
            'context' => $repositoryContext
        )
    );

    // prepare the HTTP 1.1 POST Request
    $opts = array('http' =>
        array(
            'method'  => 'POST',
            'protocol_version' => '1.1',
            'user_agent' => $repositoryContext,
            'header'  => array(
                'Content-type: application/x-www-form-urlencoded;charset=UTF-8',
                'Connection: close',
                'Accept: application/vnd.github.v3+json'
            ),
            'content' => $postdata
        )
    );

    // send request
    return file_get_contents('https://api.github.com/markdown', false, stream_context_create($opts));
}

Usage#

The optional $repositoryContext argument allows your to define the context which should be used for rendering to e.g. enable issue linking

// fetch the document (example)
$document = file_get_contents('https://raw.githubusercontent.com/AndiDittrich/WordPress.Enlighter/master/CHANGES.md');

// render html using the GitHub GFM API
$html = renderGFM($document, 'AndiDittrich/WordPress.Enlighter');

// show it!
echo $html;

 

 

You may have noticed, that normal users (especially Author’s and Contributor’s) are not allowed to use all kind of HTML Tags and related Attributes.

Those elements got removed by the WordPress buil-in KSES Filter – and it’s a very useful feature in matter of security to prevent html-code-injection.

But sometimes it is required to enable some additional html tags and/or attributes. You can modify the list of allowed html tags and attributes by appling a custom filter:

The Filter#

Example how to allow EnlighterJS related attributes for pre and code tags

function ksesAllowHtmlCodeAttributes($data, $context){
    // only apply filter on post-context
    if ($context === 'post'){

        // list of all available enlighterjs attributes
        $allowedAttributes = array(
            'data-enlighter-language' => true,
            'data-enlighter-theme' => true,
            'data-enlighter-group' => true,
            'data-enlighter-title' => true,
            'data-enlighter-linenumbers' => true,
            'data-enlighter-highlight' => true,
            'data-enlighter-lineoffset' => true
        );

        // apply to pre and code tags
        $data['pre'] = array_merge($data['pre'], $allowedAttributes);
        $data['code'] = array_merge($data['code'], $allowedAttributes);
    }

    return $data;
}

// add the filter function (2 arguments and priority 100)
add_filter('wp_kses_allowed_html', 'ksesAllowHtmlCodeAttributes', 100, 2);

 

 

 

Sometimes it can be very useful to have magical constants like __FILENAME__ or __LINE__ available within your sourcecode – especially for debugging or in merged files. Unfortunately, such feature is missing in javascript but it is possible to implement it by yourself using a file-postprocessing filter in your gulp build script. Thanks to gulp-concat-util, it’s […]

Howto: (re-)Enable SCP/SSH Login on Synology DSM 6.0 for non admin users [UPDATE]

a update which may break your backup tasks! change the user shell permanently

When updating to the latest DSM 6.0 final, you may have noticed that your scp backup accounts won’t work anymore (this also affects ssh the login). It is caused by a reset of the login shell settings in /etc/passwd ! It is happened in part of a “security enhancement” – normal users, which does not […]

Tweaking Minidlna Media Server on AsusWRT Merlin

usb storage, disable album arts, performance

You’re running AsusWRT Merlin and have some trouble with minidlna, e.g. bad media indexing performance or broken media databases ?

This can be caused by using an USB Stick as media database storage! Internally, minidlna is using an SQLite database to store the media file index – and sometime this database may broke (slow, unsynced file operations, user terminated processes).

As a workaround, it’s possible to move the media database to the temporary filesystem (ramdisk). As a disadvantage, on every system shutdown (reboot/power cycle) the database will be destroyed. But it only takes a view minutes to recreate it, because the ramdisk storage is a lot faster than the attached USB drive!

Just create an additional user config file in your JFFS /jffs/configs/minidlna.conf.add (will be automatically appended to the system generated minidlna.conf file!)

# Move the database to the tmp directory (ramdisk, will be recreated on reboot !!)
db_dir=/tmp/.minidlna

# create a custom minidlna logfile
log_dir=/var/log

# disable album art indexing
album_art_names=NO_ALBUM_ARTS.x

 

Create Static Social-Media “Share” Buttons without Javascript

no external resources required, corporate privacy compliance

Social-Media Share Buttons are everywhere, but most of them are working with external hosted javascript resources which are loaded on each page request. Depending on the servers cache settings this can cause multiple additional http request for your visitors. Additionally it can raise some privacy issues becaue of the possibility that your users can be […]