HowTo: Tileserver with openstreetmap.org Style and Leaflet on Debian Jessie

Here i want to describe how i set up my own little Maps-Server just like openstreetmap.org or maps.google.com based on OpenStreetMap.
It is running on an average notebook (8GB RAM, i7, 1TB HDD, no SSD), without any fancy optimization and even in a chroot. It is not very fast and i just use it with Austria (the whole Planet would be way too big, there is no chance that this would work on this ordinary Notebook).
Ovarall i am very pleased and it is fast enough for one user to use it.

This HowTo is based on switchosm and debianwiki. I think that about 90% will be the same.

First, lets take a look at the result:
tileserver

This whole map here is running offline, without the need of any internet connection. You will realize that there is no search field and no navigation option. This is because it basically just displays tiles. Maybe i will look into adding navigation and a search bar in the future (there are Leaflet PlugIns for that or projects like nominatim).

Whats needed:

  • Mapnik to render tiles
  • Postgresql with postgis for the map data (it will be importet with osm2pgsql from some .osm.pbf file)
  • openstreetmap-carto, a Carto Style for Mapnik, which is basically like a CSS and tells Mapnik how it should render the map
    There are other styles like OSM Bright too.
  • Apache2 with mod_tile and renderd to serve the tiles
  • Leaflet to create a map out of tiles

Install some requirements

We will take as much as possible from the package manager, but we still have to compile things like mod_tile from source, so we need seome dev packages.

apt-get install libboost-all-dev subversion git-core tar unzip wget bzip2 build-essential autoconf libtool libxml2-dev libgeos-dev libgeos++-dev libpq-dev libbz2-dev libproj-dev munin-node munin libprotobuf-c-dev protobuf-c-compiler libfreetype6-dev libpng12-dev libtiff5-dev libicu-dev libgdal-dev libcairo-dev libcairomm-1.0-dev apache2 apache2-dev libagg-dev liblua5.2-dev ttf-unifont lua5.1 liblua5.1-0-dev 

Install postgresql

apt-get install postgresql postgresql-contrib postgis postgresql-9.3-postgis-2.1 osm2pgsql

Install mapnik and node-carto

apt-get install python-mapnik libmapnik-dev maptnik-utils node-carto curl

Install basic OpenStreetMap tools (it’s needed for the openstreetmap-carto style)

apt-get install osmosis gdal-bin

Setup Database

Start postgresql if it’s not already running:

/etc/init.d/postgresql start

First we have to change the postgresql tamplate to use UTF8.

su - postgres
psql -U postgres
postgres=# update pg_database set datallowconn = TRUE where datname = 'template0';
UPDATE 1
postgres=# \c template0
You are now connected to database "template0".
template0=# update pg_database set datistemplate = FALSE where datname = 'template1';
UPDATE 1
template0=# drop database template1;
DROP DATABASE
template0=# create database template1 with template = template0 encoding = 'UTF8';
CREATE DATABASE
template0=# update pg_database set datistemplate = TRUE where datname = 'template1';
UPDATE 1
template0=# \c template1
You are now connected to database "template1".
template1=# update pg_database set datallowconn = FALSE where datname = 'template0';
UPDATE 1
exit

Now we can create the Database. Our username will be tilesrv

su - postgres
createuser tilesrv
createdb -E UTF8 -O tilesrv gis
exit

Create the unix user:

sudo useradd -m tiesrv
sudo passwd tilesrv

Setup postgis in postgresql

su - postgres
psql
\c gis
CREATE EXTENSION postgis;
ALTER TABLE geometry_columns OWNER TO username;
ALTER TABLE spatial_ref_sys OWNER TO username;
\q
exit

Install mod_tile and rendr

There is no Debian Package for mod_tile, so we have to compile it from source

su - root
cd /usr/local/src
git clone git://github.com/openstreetmap/mod_tile.git
cd mod_tile
./autogen.sh
./configure
make
make install
make install-mod_tile
ldconfig
exit

Install openstreetmap-carto Style

We will download openstreetmap-carto from git (this needs to be done before importing the data with osm2pgsql because the style-file describes what data goes where into the database).

su - root
cd /usr/local/src
wget https://github.com/gravitystorm/openstreetmap-carto/archive/v2.29.1.tar.gz
tar -xzf v2.29.1.tar.gz

Now we need to build a style for mapnik out of openstreetmap-carto

cd ~/openstreetmap-carto-2.29.1/
./get-shapefiles.sh
#if your database is not named gis, you need to change it in ./project.mml before doing the next step
carto project.mml > style.xml
exit

Import OpenStreetMap Data to postgresql

We need to download OpenStreetMap data, don’t pick the whole planet.osm.pbf. Pick something smaller from geofabrik.de, like Austria.

mkdir /usr/local/share/maps/austria
chown tilesrv /usr/local/share/maps/austria
cd /usr/local/share/maps/austria
wget http://download.geofabrik.de/europe/austria-latest.osm.pbf

Now we can import this data to the postgresql database.
This will take some time. On my 8GB RAM Notebook without SSD it took 5 hours to import Austria! There are some pages and articles on how to tune your system on the OpenStreetMap wiki, so that it will take not as much time, like changing buffer sizes in /etc/postgresql/9.4/main/postgresql.conf.
You will need to adjust the -C value according to your RAM size.

su - tilesrv
osm2pgsql --slim -d gis -C 8000 --hstore -S /usr/local/srv/openstreetmap-carto-2.29.1/openstreetmap-carto.style /usr/local/share/maps/austria/austria-latest.osm.pbf

This is how osm2pgsql is beheaving when everything is fine:

$ time osm2pgsql --slim -d gis -C 8000 --number-processes 3 S /usr/local/srv/openstreetmap-carto-2.29.1/openstreetmap-carto.style /usr/local/share/maps/austria/austria-latest.osm.pbf
osm2pgsql SVN version 0.86.0 (64bit id space)

Using projection SRS 900913 (Spherical Mercator)
Setting up table: planet_osm_point
NOTICE:  table "planet_osm_point" does not exist, skipping
NOTICE:  table "planet_osm_point_tmp" does not exist, skipping
Setting up table: planet_osm_line
NOTICE:  table "planet_osm_line" does not exist, skipping
NOTICE:  table "planet_osm_line_tmp" does not exist, skipping
Setting up table: planet_osm_polygon
NOTICE:  table "planet_osm_polygon" does not exist, skipping
NOTICE:  table "planet_osm_polygon_tmp" does not exist, skipping
Setting up table: planet_osm_roads
NOTICE:  table "planet_osm_roads" does not exist, skipping
NOTICE:  table "planet_osm_roads_tmp" does not exist, skipping
Using built-in tag processing pipeline
Allocating memory for dense node cache
Allocating dense node cache in one big chunk
Allocating memory for sparse node cache
Sharing dense sparse
Node-cache: cache=8000MB, maxblocks=1024000*8192, allocation method=11
Mid: pgsql, scale=100 cache=8000
Setting up table: planet_osm_nodes
NOTICE:  table "planet_osm_nodes" does not exist, skipping
Setting up table: planet_osm_ways
NOTICE:  table "planet_osm_ways" does not exist, skipping
Setting up table: planet_osm_rels
NOTICE:  table "planet_osm_rels" does not exist, skipping

Reading in file: /usr/local/share/maps/austria/austria-latest.osm.pbf
Processing: Node(50300k 118.9k/s) Way(5427k 24.90k/s) Relation(99170 8.95/s)  parse time: 11722s

Node stats: total(50300269), max(4449627239) in 423s
Way stats: total(5427806), max(447905198) in 218s
Relation stats: total(99178), max(6648485) in 11081s
Committing transaction for planet_osm_point
Committing transaction for planet_osm_line
Committing transaction for planet_osm_polygon
Committing transaction for planet_osm_roads

Going over pending ways...
3675813 ways are pending

Using 3 helper-processes
Helper process 1 out of 3 initialised
Helper process 2 out of 3 initialised
Helper process 0 out of 3 initialised
Process 0 finished processing 1225271 ways in 829 sec
Process 2 finished processing 1225271 ways in 831 sec
Process 1 finished processing 1225271 ways in 831 sec

All child processes exited

3675813 Pending ways took 836s at a rate of 4396.91/s
Committing transaction for planet_osm_point
Committing transaction for planet_osm_line
Committing transaction for planet_osm_polygon
Committing transaction for planet_osm_roads

Going over pending relations...
0 relations are pending

Using 3 helper-processes
Process 2 finished processing 0 relations in 4 sec
Process 1 finished processing 0 relations in 4 sec
Process 0 finished processing 0 relations in 4 sec

All child processes exited
0 Pending relations took 4s at a rate of 0.00/s

Sorting data and creating indexes for planet_osm_point
node cache: stored: 50300269(100.00%), storage efficiency: 52.02% (dense blocks: 12150, sparse nodes: 42121688), hit rate: 100.00%
Sorting data and creating indexes for planet_osm_line
Sorting data and creating indexes for planet_osm_polygon
Sorting data and creating indexes for planet_osm_roads
Stopping table: planet_osm_nodes
Stopped table: planet_osm_nodes in 0s
Stopping table: planet_osm_ways
Building index on table: planet_osm_ways (fastupdate=off)
Stopping table: planet_osm_rels
Building index on table: planet_osm_rels (fastupdate=off)
Analyzing planet_osm_point finished
Analyzing planet_osm_roads finished
Analyzing planet_osm_line finished
Copying planet_osm_point to cluster by geometry finished
Creating geometry index on  planet_osm_point
Stopped table: planet_osm_rels in 77s
Copying planet_osm_roads to cluster by geometry finished
Creating geometry index on  planet_osm_roads
Creating osm_id index on  planet_osm_roads
Creating indexes on  planet_osm_roads finished
All indexes on  planet_osm_roads created  in 353s
Completed planet_osm_roads
Creating osm_id index on  planet_osm_point
Creating indexes on  planet_osm_point finished
All indexes on  planet_osm_point created  in 399s
Completed planet_osm_point
Analyzing planet_osm_polygon finished
Copying planet_osm_line to cluster by geometry finished
Creating geometry index on  planet_osm_line
Creating osm_id index on  planet_osm_line
Creating indexes on  planet_osm_line finished
All indexes on  planet_osm_line created  in 734s
Completed planet_osm_line
Copying planet_osm_polygon to cluster by geometry finished
Creating geometry index on  planet_osm_polygon
Creating osm_id index on  planet_osm_polygon
Creating indexes on  planet_osm_polygon finished
All indexes on  planet_osm_polygon created  in 1715s
Completed planet_osm_polygon
Stopped table: planet_osm_ways in 5640s

Osm2pgsql took 18205s overall
816.43user 65.39system 5:03:25elapsed 4%CPU (0avgtext+0avgdata 1029488maxresident)k
1009456inputs+0outputs (35major+452435minor)pagefaults 0swaps

Configure renderd

The renderd settings are in /usr/local/etc/renderd.conf, you need to check at least the following lines:

socketname=/var/run/renderd/renderd.sock
plugins_dir=/usr/lib/mapnik/2.2/input
font_dir=/usr/share/fonts/truetype
TILEDIR=/var/lib/mod_tile
XML=/usr/local/src/openstreetmap-carto-2.29.1/style.xml
HOST=localhost

And we need to create the directories for renderd

mkdir /var/run/renderd
chown tilesrv /var/run/renderd
mkdir /var/lib/mod_tile
chown tilesrv /var/lib/mod_tile

Configure Apache (mod_tile)

Now we have to configure Apache2.
Create a file /etc/apache2/conf-available/mod_tile.conf which contains:

LoadModule tile_module /usr/lib/apache2/modules/mod_tile.so

And add following lines to the section of /etc/apache2/sites-available/000-default.conf

LoadTileConfigFile /usr/local/etc/renderd.conf
ModTileRenderdSocketName /var/run/renderd/renderd.sock
# Timeout before giving up for a tile to be rendered
ModTileRequestTimeout 0
# Timeout before giving up for a tile to be rendered that is otherwise missing
ModTileMissingRequestTimeout 30

Enable the mod_tile configuration and restart Apache:

a2enconf mod_tile
/etc/init.d/apache2 restart

First test

Run renderd as user tilesrv:

su - tilesrv
renderd -f -c /usr/local/etc/renderd.conf

In a second console, reload apache2

service apache2 reload

Browse to http://localhost/osm_tiles/0/0/0.png and you should see a small picture of the world.

Install init-file for renderd

We want to autosrat renderd, so we need to install the init-script

cp /usr/local/src/mod_tile/debian/renderd.init /etc/init.d/renderd
chmod +x /etc/init.d/renderd

The init file /etc/init.d/renderd needs to be configured, change following lines:

DAEMON=/usr/local/bin/$NAME
DAEMON_ARGS=" -c /usr/local/etc/renderd.conf"
RUNASUSER=tilesrv

Start renderd:

/etc/init.d/renderd start

Install Leaflet

Last but not least we need install some fancy slippy map on our webserver. We choose Leaflet.
It should be usable without internet, so we download it.

cd /var/www/html
wget https://unpkg.com/leaflet@1.0.1/dist/leaflet.js
wget https://unpkg.com/leaflet@1.0.1/dist/leaflet.css

Now we create our /var/www/html/index.html file which will display a leaflet map in fullscreen:


Full Screen Leaflet Map

 
<div id="map"></div>
&nbsp;

Be sure to set the location in .setView, which is displayed first when visiting the site, to some tile with high zoomlevel which is available in your Map-Data.

Start everything

Restart all necessary services

/etc/init.d/postgresql restart
/etc/init.d/renderd restart
/etc/init.d/apache2 restart

Now everything is ready and you can browse to http://localhost
Be aware that the map will be very slow and you have to wait a few minutes for tiles with low zoomlevels. Don’t get impatient. Keep it open and wait. It will get faster over time when the server already rendered some tiles.

Neo2 Tastaturlayout mit QWERTZ-Buchstabenverteilung in Linux

Neo2 ist ein spezeiell für die deutsche Sprache entwickeltes, ergonomisch optimiertes Tastaturlayout.
Allerdings wird es nicht nur wegen seiner besseren Buchstabenverteilung geschätzt, sodern vorallem wegen den zusätzlichen Ebenen – z.B. ist auf der QWERTZ Caps-Lock- und #-Taste eine Ebene speziell mit Sonderzeichen, ideal für Programmierer. So sind die Klammern und Schrägstriche {}[]()<>\/ sehr einfach zugänglich und man muss keine AltGr-Verrenckungen vollführen.
Auch die Ebenen mit mathematischen Symbolen und griechischen Buchstaben sind überaus praktisch (Caps+Shift+a ergibt Alpha).

Ich war nicht an den Buchstabenverteilungen interessiert, weil meine Schreibgeschwindigkeit mit QWERTZ bereits mehr als ausreichend ist, aber die zusätzlichen Ebenen musste ich haben (wer braucht schon Caps-Lock). Dementsprechend habe ich kurzerhand das per Default vorhandene neo-Layout unter den deutschen Layouts in /usr/share/X11/xkb/symbols/de kopiert (in derselben Datei), es auf neoq umbenannt und die Buchstaben in den Ebenen auf die klassische QWERTZ-Verteilungen geändert.

Hier der zusätzliche Abschnitt in /usr/share/X11/xkb/symbols/de

// German Neo-Layout Version 2 - MODIFIED with QWERTZ 2016
// adopted 2004 by Hanno Behrens <Hanno.Behrens@gmx.de>
// inspired by Dvorak/de-ergo  http://www.goebel-consult.de/de-ergo/
//
// Authors:
//      Stephan Hilb <stephan at ehilb dot de>
//      <lucky at zankt dot net>
//      Benjamin Kellermann <Benjamin dot Kellermann at gmx dot Germany>
//      Erik Streb <mail at erikstreb dot de>
//        and many other contributors
//
//      http://www.neo-layout.org
//
// Half is qwertz

partial alphanumeric_keys modifier_keys keypad_keys
xkb_symbols "neoq_base" {

// Levels in Neo jargon
// --------------------------------------------------------------
// Ebene 1: normal
// Ebene 2: Shift
// Ebene 3: Mod3
// Ebene 4: Mod4 (for marking something use Shift + Mod4)
// Ebene 5: Shift + Mod3
// Ebene 6: Mod3 + Mod4
// Compose (not a level): Mod3 + Tab
// Feststelltaste (Capslock): Shift + Shift
// Mod4-Lock: Mod4 + Mod4
// Mod4-Lock: Shift + Mod3 + Tab

// Legend
// ===============
// Levels in Xkbmap jargon to be found here in the definitions.
// These are the levels used, and Xorg's translations:
// --------------------------------------------------------------
// Xorg:       Level1                   Level2                   Level3                   Level4                   Level5                   Level6                   Level7                   Level8
// Neo:        Ebene1                   Ebene2                   Ebene3                   Ebene5                   Ebene4                   Pseudo-Ebene             Ebene6                   ???
// Keys (Neo): None                     Shift                    Mod3                     Mod3 + Shift             Mod4                     Mod4 + Shift             Mod3 + Mod4              Mod3 + Mod4 + Shift


// Alphanumeric-keys
// ===============
key.type[Group1] = "EIGHT_LEVEL";

// Tab as Multi_key (Compose)
// --------------------------------------------------------------
key  <TAB> { [ Tab,                     ISO_Left_Tab,            Multi_key,               ISO_Level5_Lock,         NoSymbol,                NoSymbol,                NoSymbol,                ISO_Level5_Lock          ] };


// Number row
// --------------------------------------------------------------
key <TLDE> { [ dead_circumflex,         dead_caron,              U21BB,                   U02DE,                   dead_abovedot,           Pointer_EnableKeys,      dead_belowdot,           NoSymbol                 ] };

key <AE01> { [ 1,                       degree,                  onesuperior,             onesubscript,            ordfeminine,             NoSymbol,                notsign,                 NoSymbol                 ] };
key <AE02> { [ 2,                       section,                 twosuperior,             twosubscript,            masculine,               NoSymbol,                logicalor,               NoSymbol                 ] };
key <AE03> { [ 3,                       U2113,                   threesuperior,           threesubscript,          numerosign,              NoSymbol,                logicaland,              NoSymbol                 ] };
key <AE04> { [ 4,                       guillemotright,          U203A,                   femalesymbol,            NoSymbol,                NoSymbol,                U22A5,                   NoSymbol                 ] };
key <AE05> { [ 5,                       guillemotleft,           U2039,                   malesymbol,              periodcentered,          NoSymbol,                U2221,                   NoSymbol                 ] };
key <AE06> { [ 6,                       dollar,                  cent,                    U26A5,                   sterling,                NoSymbol,                U2225,                   NoSymbol                 ] };

key <AE07> { [ 7,                       EuroSign,                yen,                     U03F0,                   currency,                NoSymbol,                rightarrow,              NoSymbol                 ] };
key <AE08> { [ 8,                       doublelowquotemark,      singlelowquotemark,      U27E8,                   Tab,                     ISO_Left_Tab,            U221E,                   NoSymbol                 ] };
key <AE09> { [ 9,                       leftdoublequotemark,     leftsinglequotemark,     U27E9,                   KP_Divide,               KP_Divide,               variation,               NoSymbol                 ] };
key <AE10> { [ 0,                       rightdoublequotemark,    rightsinglequotemark,    zerosubscript,           KP_Multiply,             KP_Multiply,             emptyset,                NoSymbol                 ] };

key <AE11> { [ ssharp,                  emdash,                  NoSymbol,                U2011,                   KP_Subtract,             KP_Subtract,             hyphen,                  NoSymbol                 ] };
key <AE12> { [ dead_acute,              dead_cedilla,            dead_abovering,          dead_dasia,              dead_diaeresis,          NoSymbol,                dead_macron,             NoSymbol                 ] };

// Top row
// --------------------------------------------------------------
key.type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC";
key <AD01> { [ q,                       Q,                       ellipsis,                U03D5,                   Prior,                   Prior,                   U211A,                   NoSymbol                 ] };
key <AD02> { [ w,                       W,                       underscore,              Greek_omega,             BackSpace,               BackSpace,               Greek_OMEGA,             NoSymbol                 ] };
key <AD03> { [ e,                       E,                       bracketleft,             Greek_epsilon,           Up,                      Up,                      U2203,                   NoSymbol                 ] };
key <AD04> { [ r,                       R,                       bracketright,            Greek_rho,               Delete,                  Delete,                  U211D,                   NoSymbol                 ] };
key <AD05> { [ t,                       T,                       asciicircum,             Greek_tau,               Next,                    Next,                    partialderivative,       NoSymbol                 ] };

key <AD06> { [ z,                       Z,                       exclam,                  Greek_zeta,              exclamdown,              NoSymbol,                U2124,                   NoSymbol                 ] };
key <AD07> { [ u,                       U,                       less,                    NoSymbol,                KP_7,                    KP_7,                    includedin,              NoSymbol                 ] };
key <AD08> { [ i,                       I,                       greater,                 Greek_iota,              KP_8,                    KP_8,                    integral,                NoSymbol                 ] };
key <AD09> { [ o,                       O,                       equal,                   Greek_omicron,           KP_9,                    KP_9,                    elementof,               NoSymbol                 ] };
key <AD10> { [ p,                       P,                       ampersand,               Greek_pi,                KP_Add,                  KP_Add,                  Greek_PI,                NoSymbol                 ] };

key <AD11> { [ udiaeresis,              Udiaeresis,              U017F,                   Greek_finalsmallsigma,   U2212,                   NoSymbol,                union,                   NoSymbol                 ] };

key.type[Group1] = "EIGHT_LEVEL";
key <AD12> { [ plus,              dead_tilde,              dead_stroke,             dead_psili,              dead_doubleacute,        NoSymbol,                dead_breve,              NoSymbol                 ] };

// Middle row
// --------------------------------------------------------------
key.type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC";
key <AC01> { [ a,                       A,                       backslash,               Greek_alpha,             Home,                    Home,                    U2200,                   NoSymbol                 ] };
key <AC02> { [ s,                       S,                       slash,                   Greek_sigma,             Left,                    Left,                    Greek_SIGMA,             NoSymbol                 ] };
key <AC03> { [ d,                       D,                       braceleft,               Greek_delta,             Down,                    Down,                    Greek_DELTA,             NoSymbol                 ] };
key <AC04> { [ f,                       F,                       braceright,              Greek_phi,               Right,                   Right,                   Greek_PHI,               NoSymbol                 ] };
key <AC05> { [ g,                       G,                       asterisk,                Greek_gamma,             End,                     End,                     Greek_GAMMA,             NoSymbol                 ] };

key <AC06> { [ h,                       H,                       question,                Greek_psi,               questiondown,            NoSymbol,                Greek_PSI,               NoSymbol                 ] };
key <AC07> { [ j,                       J,                       parenleft,               Greek_theta,             KP_4,                    KP_4,                    Greek_THETA,             NoSymbol                 ] };
key <AC08> { [ k,                       K,                       parenright,              Greek_kappa,             KP_5,                    KP_5,                    multiply,                NoSymbol                 ] };
key <AC09> { [ l,                       L,                       minus,                   Greek_lambda,            KP_6,                    KP_6,                    Greek_LAMBDA,            NoSymbol                 ] };
key <AC10> { [ odiaeresis,              Odiaeresis,              colon,                   NoSymbol,                KP_Separator,            comma,                   intersection,            NoSymbol                 ] };

key <AC11> { [ adiaeresis,              Adiaeresis,              at,                      Greek_upsilon,           period,                  KP_Decimal,              U2135,                   NoSymbol                 ] };

// Bottom row
// --------------------------------------------------------------
key <AB01> { [ y,                       Y,                       numbersign,              Greek_upsilon,           Escape,                  Escape,                  nabla,                   NoSymbol                 ] };
key <AB02> { [ x,                       X,                       dollar,                  Greek_xi,                Tab,                     Tab,                     Greek_XI,                NoSymbol                 ] };
key <AB03> { [ c,                       C,                       bar,                     Greek_chi,               Insert,                  Insert,                  U2102,                   NoSymbol                 ] };
key <AB04> { [ v,                       V,                       asciitilde,              NoSymbol,                Return,                  Return,                  radical,                 NoSymbol                 ] };
key <AB05> { [ b,                       B,                       grave,                   Greek_beta,              Undo,                    Redo,                    U21D0,                   NoSymbol                 ] };

key <AB06> { [ n,                       N,                       plus,                    Greek_nu,                colon,                   NoSymbol,                U2115,                   NoSymbol                 ] };
key <AB07> { [ m,                       M,                       percent,                 Greek_mu,                KP_1,                    KP_1,                    ifonlyif,                NoSymbol                 ] };
key.type[Group1] = "EIGHT_LEVEL";
key <AB08> { [ comma,                   endash,                  quotedbl,                U03F1,                   KP_2,                    KP_2,                    U21D2,                   NoSymbol                 ] };
key <AB09> { [ period,                  enfilledcircbullet,      apostrophe,              U03D1,                   KP_3,                    KP_3,                    U21A6,                   NoSymbol                 ] };
key.type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC";
key <AB10> { [ minus,                   underscore,                       semicolon,               Greek_theta,             semicolon,               NoSymbol,                Greek_THETA,             NoSymbol                 ] };
key.type[Group1] = "EIGHT_LEVEL";

// Space key
// --------------------------------------------------------------
key <SPCE> { [ space,                   space,                   space,                   nobreakspace,            KP_0,                    KP_0,                    U202F,                   NoSymbol                 ] };


// Keypad-keys
// ===============

// The former Numlock key:
key <NMLK> { [ Tab,                     ISO_Left_Tab,            equal,                   approxeq,                notequal,                Pointer_EnableKeys,      identical,               NoSymbol                 ] };

// Topmost row
// --------------------------------------------------------------
key <KPDV> { [ KP_Divide,               KP_Divide,               division,                U2300,                   U2215,                   NoSymbol,                U2223,                   NoSymbol                 ] };
key <KPMU> { [ KP_Multiply,             KP_Multiply,             U22C5,                   U2299,                   multiply,                NoSymbol,                U2297,                   NoSymbol                 ] };
key <KPSU> { [ KP_Subtract,             KP_Subtract,             U2212,                   U2296,                   U2216,                   NoSymbol,                U2238,                   NoSymbol                 ] };

// Top row
// --------------------------------------------------------------
key  <KP7> { [ KP_7,                    U2714,                   U2195,                   U226A,                   KP_Home,                 KP_Home,                 upstile,                 NoSymbol                 ] };
key  <KP8> { [ KP_8,                    U2718,                   uparrow,                 intersection,            KP_Up,                   KP_Up,                   U22C2,                   NoSymbol                 ] };
key  <KP9> { [ KP_9,                    dagger,                  U20D7,                   U226B,                   KP_Prior,                KP_Prior,                U2309,                   NoSymbol                 ] };
key <KPAD> { [ KP_Add,                  KP_Add,                  plusminus,               U2295,                   U2213,                   NoSymbol,                U2214,                   NoSymbol                 ] };

// Middle row
// --------------------------------------------------------------
key  <KP4> { [ KP_4,                    club,                    leftarrow,               includedin,              KP_Left,                 KP_Left,                 U2286,                   NoSymbol                 ] };
key  <KP5> { [ KP_5,                    EuroSign,                colon,                   U22B6,                   KP_Begin,                KP_Begin,                U22B7,                   NoSymbol                 ] };
key  <KP6> { [ KP_6,                    U2023,                   rightarrow,              includes,                KP_Right,                KP_Right,                U2287,                   NoSymbol                 ] };

// Bottom row
// --------------------------------------------------------------
key  <KP1> { [ KP_1,                    diamond,                 U2194,                   lessthanequal,           KP_End,                  KP_End,                  downstile,               NoSymbol                 ] };
key  <KP2> { [ KP_2,                    heart,                   downarrow,               union,                   KP_Down,                 KP_Down,                 U22C3,                   NoSymbol                 ] };
key  <KP3> { [ KP_3,                    U2660,                   U21CC,                   greaterthanequal,        KP_Next,                 KP_Next,                 U230B,                   NoSymbol                 ] };
key <KPEN> { [ KP_Enter,                KP_Enter,                KP_Enter,                KP_Enter,                KP_Enter,                KP_Enter,                KP_Enter,                NoSymbol                 ] };
key <KPEQ> { [ KP_Equal,                NoSymbol,                NoSymbol,                NoSymbol,                NoSymbol,                NoSymbol,                NoSymbol,                NoSymbol                 ] };

// Bottommost row
// --------------------------------------------------------------
key  <KP0> { [ KP_0,                    U2423,                   percent,                 U2030,                   KP_Insert,               KP_Insert,               U25A1,                   NoSymbol                 ] };
key <KPDL> { [ KP_Separator,            period,                  comma,                   minutes,                 KP_Delete,               KP_Delete,               seconds,                 NoSymbol                 ] };
};

partial alphanumeric_keys modifier_keys keypad_keys
xkb_symbols "neoq" {

include "de(neoq_base)"

name[Group1]= "German (NeoQ 2)";

include "shift(both_capslock)"
include "level3(caps_switch)"
include "level3(bksl_switch)"
include "level5(lsgt_switch)"
include "level5(ralt_switch)"
};

Damit dieses Layout erkannt wird, müssen noch in /etc/X11/xkb/rules folgende Dateien bearbeitet werden (die Synthax ist selbsterklärend – einfach den neo-Eintrag kopieren und auf neoq ändern):

  • base.lst
  • base.xml
  • evdev.lst
  • evdev.xml

Anschließend sollte das neue neoq Tataturlayout in den Tastatureinstellungen vorhanden sein und kann nun verwendet werden.
Unter Windows gibt es mit NeoVar übrigens ein portables Programm, welches das Neo-Layout umsetzt und auch die Option hat, die Buchstabenverteilung bei QWERTZ zu belassen.

Fedora – Dark KDE-Theme and GNOME-Applications

If you select dark Themes like Breeze Dark (Color and Symbols) in the KDE Systempreferences, you will notice that it will not work out of the box with GNOME (gtk) Applications like Firefox and GIMP. While GIMP and most other gtk-Applications are still useable – they just don’t really fit in and are still light-grey –  it is really horrible with inkscape:

inkscape-fail
Notice that the symbols on the left are not identifiable.

To fix this, you will have to change the gtk-theme too. The options to do that are not enabled per default, you will have to install kde-gtk-config (and if you want the Breeze theme, also breeze-gtk) with

dnf install kde-gtk-config breeze-gtk

. Now you have a new entry named „GNOME Application-Style“ in the Systempreferences.
gnome-stil
Change everything to Breeze-Dark, make a restart and your GNOME-Applications should be fixed.
inkscape-right

If there are still some flaws, you will have to edit ~/gtkrc-2.0 (for gtk-2.0 applications) or the theme in /usr/share/themes/<Your_Theme_Name>/Gtk-3.0/gtk.css (for gtk-3.0 applications) manually.
For example, if you add this in ~/gtkrc-2.0, it will change the tooltip color:

style "gnome-color-chooser-tooltips"
{
bg[NORMAL] = "#FFFFAF"
fg[NORMAL] = "#000000"
}
widget "gtk-tooltip*" style "gnome-color-chooser-tooltips"

KDE-Connect auf Fedora

KDE-Connect funktioniert bei Fedora nicht out-of-the-box – es muss zuerst in den Firewall-Einstellungen zugelassen werden. Dies funktioniert auf Anhieb ganz ohne Kommandozeile:

  1. Im Verbindungs-Editor die jeweilige Verbindung bearbeiten und in die Firewall-Zone „home“ hinzufügen
    Firewallzone
  2. in der Firewall-Konfiguration unter der Zone „home“ das Häckchen bei kde-connect setzen
    kde-firewall
  3. Firewalleinstellungen mit „Optionen->Runtime nach Dauerhaft“ speichern.

Das wars auch schon, nach einer Neuverbindung ins Netzwerk sollten alle KDE-Connect-Geräte problemlos erkannt werden.

derStandard.at TopPosting-Balken entfernen und andere userstyles

Diese Tage wurde im Forum der Nachrichtenplattform derStandard.at eine Funktion hinzugefügt, mit der so ziemlich keiner der Poster zufrieden ist: „Besondere“ Postings, welche nach einem geheimen Algorithmus ausgewählt werden, werden als TopPosting mit einem dicken gelben Balken links vom Posting markiert.

topposting1

Lange hat es nicht gedauert, bis die ersten Poster dieses Problem gelöst hatten, und daraus sind zahlreiche praktische Userstyles zur schöneren Darstellung des Standard-Forums entstanden – Mittel zum Zweck ist hierbei die Erweiterung Stylish für Chrome und Firefox, mit der sich CSS leicht selbst modifizieren lassen.

topposting2

Diese Styles möchte ich hier auflisten (ich entschuldige mich, dass ich die Autoren hier nicht auflisten kann, eine von mir erstellte Autorenliste wäre unvollständig und vermutlich nicht korrekt).

  • Abstand zwischen Postings verringern:
    .posting {
    padding-top: 0px;
    padding-bottom: 0px;}
  • Artikelbild entfernen:
    #content-aside {
    display: none;
    }
  • Eigene Postings markieren:
    div.posting[data-communityname="POSTINGNAME"] {
    border-left: 8px solid violet;} 
  • Sidebar entfernen:
    #weiterLesen{
    display: none;
    }
  • Toolbar entfernen:
    html.fixed-supported body.no-touch #forum-tb.is-fixed .forum-tb-context {
    display: none;
    } 
  • gelben TopPosting-Balken entfernen:
    @namespace url(http://www.w3.org/1999/xhtml);
    .forum .posting.is-topposting .posting-container {
    border-left: none;
    }
  • Alle TopPostings entfernen:
    .forum .posting.is-topposting .posting-container {
    display:none;} 
  • Werbung entfernen:
    div.SuperBannerGrosz {
    display: none;
    }
    div.WerberahmenOben {
    display: none;
    }
    #Sitebar {
    display: none;
    }
    #baselinead {
    display: none;
    }

    (dieses Userstyle erkennt der Standard nicht als AdBlocker)

Um diese Userstyles zu installieren muss man in Stylish unter „Manage installed styles“ mit „Write new Style“ jeweils ein neues Userstyle erstellen und darin wird der Code eingefügt, optimalerweise wird noch „Applies to“ auf „URLs on the domain“ und „derstandard.at“ gesetzt.

Boolean algebra with Wolfram Mathematica

Here is a little Wolfram Mathematica Notebook, which is able to do basic Boolean Algebra calculations:
Note: „+“ is OR; „*“ is AND, „n“ is NOT ( e.g. „nc“ is NOT C) – But you can change that interpretation in the Script easily.

  • Minimize an equation and show it in NAND-Form:
    NAND
  • Show the Truth-Table of an equation and minimize it:
    Tabel
  • Create an equation according to a truth-table of 4 variables:
    BoolTab[4] (*It will show an truthtable and you just need to click on the checkboxes – if you need an „Dont Care“, enter BoolTab[4,1] and there will be 1 line less*)
    Tabel2

DOWNLOAD IT HERE

Backup NTFS-Partition from within Linux

This is a brief overview of some options you have if you want to backup your windows partition. There are lots of (commercial) tools out there to do that task, but basically they all work with one of the following principles.

Full partiton backup (dd):

dd if=/dev/sda1 of=./backup.img bs=1M

dd copies every single bit of the partition. That means that the backup-file is as big as the partition itself (but of course you can compress it with e.g. bzip) and it takes a long time create. But dd doesn’t care about the filesystem, so you don’t have to worry about bootsectors or (not well documented) hidden stuff or attributes and you can mount the image with ‚mount -o loop ./backup.img /mnt‘ if you just need some specific file of the backup.

Full partition backup (ntfsclone):

ntfsclone /dev/sda1 ./backup.img

ntfsclone works like dd, but instead of copying everything, it checks if a disk sector is actually used, and if not, it will skip it. The resulting backup-file will be a sparse file.
ntfsclone is faster than dd, because if only 10% of the partition is used, it will just copy those 10%.
If you use the –save-image flag, it will creat a special image file and not a sparse file (you can use that, if you don’t have a filesystem with sparse-file-support).
You can mount a sparse file exactly like a dd-image-file, but not an special image file.

If you want to backup the windows system-partition, dd and ntfsclone are the only reliable options you have, because they dont really care about the filesystem, they will copy every strange exotical file attribute, junction point, symlink, permission and bootsector.
But they have one big disadvantage: If you already have a backup-file, you can not just ‚update‘ it or copy just the changed parts, you have to copy everything again.

Rsync-Backup:

rsync is the best backup and syncing solution for Linux, it’s fast and it will only copy the changed parts of changed files – it’s perfect if you already have a backup and you want to „update“ it, so why should we not use it in ntfs-filesystems?

First lets make sure where to save the backup, you could create a ntfs-partition on the backup-drive, you could use an existing image-file or you could create a new one with ‚fallocate -l 50G ntfs-image.img‘ (this file will be 50GB big) and ‚mkfs.ntfs ./ntfs-image.img‘. You can mount the image wth ‚mount -o loop ./ntfs-image.img /mnt/backup‘.

Now we have to make sure to have access to every data we can (savely) get out of our ntfs-filesystem, like extended attributes.
NTFS-3g (our linux-ntfs-implementation) needs to know how it should map the attributes, so we have to create a textfile .NTFS-3G/XattrMapping in both, our ntfs-partition and our (ntfs-formated) backup-partition (or image-file). Here is an example XattrMapping-file:

system.ntfs_attrib:user.ntfs_attrib
system.ntfs_times:user.ntfs_times
system.ntfs_reparse_data:user.ntfs_reparse_data
system.ntfs_acl:user.ntfs_acl

Quick expanation: ntfs_attrib are attributes like hidden-file, ntfs_reparse_data is used by symlinks and junction points, ntfs_acl is the Access Control List.

Next we have to (re-)mount the partition with

mount -t ntfs-3g -o user_xattr,streams_interface=xattr,efs_raw /dev/sda1 /mnt/ntfs-partition
mount -t ntfs-3g -o user_xattr,streams_interface=xattr,efs_raw /path/to/ntfs-image.img /mnt/backup

user_xattr and streams_interface=xattr should be enabled by default, but i still use it, just to make sure. efs_raw is needed for encryptet files (you can’t decrypt it, but you can copy the raw file). Here are the mount-options explained: CLICK.

Now we are ready for the backup:

rsync -aHXv --inplace --no-links --delete /mnt/ntfs-partition/* /mt/backup/

-H for Hardlinks (a „Hardlink“ is basically a file with two filenames), -X for extended attributes

This command will NOT backup symlinks (–no-links) and junction points – NTFS-3G interprets junction points as symlinks and it will not work if you just copy them. It would be possible if you have access to the proper ntfs_reparse_data extended attribute and fiddle around with it, but i think it will be way more reliable, if you just make your first backup with dd or ntfsclone and use rsync to update that image from time to time (but this will still be no accaptable solution for the windows system-partition, you will have to use dd and ntfsclone on every backup there).

Backup-Applications:

There are some backup-solutions out there like fsarchiver, but if you want to use those, you have to check if they have proper ntfs-support and if they are suitable for the system-partition of your windows-version. If they work at block-level (like dd and ntfsclone), you don’t have to worry about that, but fsarchiver works on filesystem-level (like rsync) and the ntfs-support is just experimental.

Split Pages of a scanned (2 pages per sheet) Book

Lets assume that you scanned a book and now you have a PDF with 2 pages per landscape-sheet.

There are many possible ways to split the pages, like scantailor.
But here i want to post a solution with pdfutils and imagemagick:

  1. Convert the PDF to a bunch of image-files (one per sheet):
    pdftoppm filename.pdf images
  2. Split the image-files:
    convert -crop 50%x100% images* +repage outputname_%d.tiff
  3. Rename the 0,1-9 files to 00,01-09:
    rename 's/outputname_(\d)\./outputname_0$1\./' outputname_*tiff
  4. Convert the image-files to PDFs:
    for file in *tiff; do tiff2pdf -z -p A5 -F $file -o $file.pdf; done
  5. Join the PDF-files:
    pdfjoin outputname_*.pdf

The final PDF will be called outputname_XX-joined.pdf

Duplex-Printing Tricks and Linux (Booklet)

Lets say you want to have multiple pages on one side of the paper or you want to print a booklet – you could use the printing-dialog (if it provides the options you want and doesn’t mess up the whole thing), or you could modify the pdf with pdfjam (part of the package pdfutils).

Sometimes, examples are the best way to explain something:

  • 4 pages on one sheet:
    pdfnup --nup '2x2' filename.pdf
  • 4 pages per sheet with space between each other:
    pdfnup --nup '2x2' --delta '0.5cm 0.5cm' filename.pdf
  • 4 pages per sheet, scaled to 80% and with offset
    pdfnup --nup '2x2' --offset '1cm 0.5cm' --scale '0.8' filename.pdf
  •  8 slides of a 4:3-presentation per side:
    pdfnup --no-landscape --nup '2x4' filename.pdf
  • 8 slides of a 4:3-presentation per side which are orientated in columns:
    pdfnup --no-landscape --nup '2x4' --column 'true' filename.pdf
  • Create a booklet:
    pdfbook filename.pdf
  • Create a 90 degrees turned booklet:
    pdfbook --no-landscape filename.pdf

Note:  The booklets are supposed to be printed in long-edge duplex mode, if you don’t want that, use ‚–shorte-edge‘ as first argument in pdfbook

Duplex-Printing-Option disappears in Linux (Evince)

If you have a printer which is able to print on both sides, it is a common problem that the Duplex Option in the printing-dialog magically disappears or isn’t there at all.
And there are many possible reasons for that.

First, make sure that CUPS knows that the printer is able to print duplex, you can check that with lpoptions -l
If the DuplexOption (or whatever it is called) is set to False, correct it:

lpoptions -o OptionDuplex=True

Now that CUPS is OK, lets check the appropriate client.
Some printers aren’t able to print duplex with specific paper-sources (like „A4 Borderless“) and if you select that, the Duplex-Option vanishs and does not come back (which is obviously a bug).
To fix that, try to print some paper with normal A4 and hope that next time you open the printing-dialog the DuplexOption appears.
If that does not work, have a look at the specific options of the application.

For Example, Evince:
There’s a config file for the printing-dialog of evince:

cat .config/evince/print-settings | grep Duplex

Make sure that the Duplex-Options are set to „True“ or remove that file at all.

And finally: If nothing works, try to reinstall the printer.