docker web dev

To simplify the development I tried docker for building the runtime environment. Here are the major steps to get it running.

Prerequisites

The docker installation is straight forward as described on the docker home page:

un-install old version

aptitude remove docker docker-engine docker.io

add reporitory

aptitude update

aptitude install apt-transport-https ca-certificates curl gnupg2 software-properties-common

add docker official key

curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -

check fingerprint

apt-key fingerprint 0EBFCD88

add repository

add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"

aptitude update

install docker from repo

aptitude install docker-ce

check if everything works

docker run hello-world

install docker compose

curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose

chmod +x /usr/local/bin/docker-compose

and check everything works

docker-compose --version

Docker Cheat Sheet

## List Docker CLI commands
docker
docker container –help

## Display Docker version and info
docker –version
docker version
docker info

## Execute Docker image
docker run hello-world

## List Docker images
docker image ls

## List Docker containers (running, all, all in quiet mode)
docker container ls
docker container ls –all
docker container ls -aq

Development Environment

create folder for docker environment

mkdir dockerproject

create yaml file for docker compose

vi docker-compose.yaml

At least the following sections should be available:

  • app
  • main application configuration

  • web
  • Webserver configuration is required

  • database
  • database configuration is required

and here comes an exmaple


version: '3'
services:
app:
build:
context: ./
dockerfile: app.dockerfile
working_dir: /var/www
volumes:
- ./../laravel:/var/www
environment:
- "DB_PORT=3306"
- "DB_HOST=database"
web:
build:
context: ./
dockerfile: web.dockerfile
working_dir: /var/www
volumes:
- ./../laravel:/var/www
ports:
- 8080:80
database:
image: mysql:5.6
volumes:
- dbdata:/var/lib/mysql
environment:
- "MYSQL_DATABASE=homestead"
- "MYSQL_USER=homestead"
- "MYSQL_PASSWORD=secret"
- "MYSQL_ROOT_PASSWORD=secret"
ports:
- "33061:3306"
volumes:
dbdata:

and now the app configuration


FROM php:7.1.3-fpm

RUN apt-get update
RUN apt-get install -y libmcrypt-dev
RUN apt-get install -y mysql-client
RUN apt-get install -y libmagickwand-dev --no-install-recommends
RUN pecl install imagick
RUN docker-php-ext-enable imagick
RUN docker-php-ext-install mcrypt pdo_mysql
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
RUN php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
RUN php composer-setup.php
RUN php -r "unlink('composer-setup.php');"
RUN mv composer.phar /usr/local/bin/composer
RUN apt-get install -y git
RUN apt-get update && apt-get install -y zlib1g-dev
RUN docker-php-ext-install zip

the web configuration


FROM nginx:1.10

ADD vhost.conf /etc/nginx/conf.d/default.conf

DPF – lcd4linux config

lcd4linux.conf

Layout 'Dockstar'

Display 'DPF'

Variables {
# Ticks:
second 1000
minute 60 * second

# Standard Dimensions:
linesize 53 # max line length, for status lines etc.
width100 51 # full width after padding (border)
width050 24 # 1/2 of full width
width033 17 # 1/3 of full width
width025 12 # 1/4 of full width
width010 5 # 1/10 of full width

# Colors:
# ToDo: Alphakanal ausnutzen
black '000000'
white 'ffffff'
red 'ff0000'
darkblue '000066'
lightgray 'b2b2b2'
darkgray '191919'
barcolor0 '5f5fff'
barcolor1 'ff5f5c'

# To be set later by timers:
SyslogMsg 'Dummy'
}

Display dpf {
Driver 'DPF'
Port 'usb0'
Font '6x8'
Foreground white
Background darkblue
Basecolor darkblue
}

Widget System {
class 'Text'
expression '*** ' . uname('nodename') . ' '. netinfo::ipaddr('eth0') . ' ' .
uname('machine') . ' ' . uname('release') . ' ***'
width linesize
align 'C'
update 0
Background lightgray
Foreground darkgray
}

Widget Time {
class 'Text'
expression strftime('%a, %d.%m.%Y -- %H:%M:%S', time()) . ' -- Up: ' . uptim
e('%d days %H:%M:%S')
width linesize
align 'C'
update 1 * second
Background lightgray
Foreground darkgray
}

Widget Busy {
class 'Text'
expression proc_stat::cpu('busy', 0.5 * second)
prefix 'Busy'
postfix '%'
width width050
precision 1
align 'R'
update 0.5 * second
}

Widget BusyBar {
class 'Bar'
expression proc_stat::cpu('busy', 0.5 * second)
expression2 proc_stat::cpu('system', 0.5 * second)
length width050
direction 'E'
update 0.5 * second
Background darkgray
BarColor0 barcolor0
BarColor1 barcolor1
}

Widget Load {
class 'Text'
expression loadavg(1)
prefix 'Load'
postfix loadavg(1) > 1.0 ? '!' : ' '
width width050
precision 1
align 'R'
update 0.5 * second
# Foreground loadavg(1) > 1.0 ? red : white
}

Widget LoadBar {
class 'Bar'
expression loadavg(1)
max 4.0
length width050
direction 'E'
update 0.5 * second
Background darkgray
BarColor0 barcolor0
BarColor1 barcolor1
}

Widget Disk {
class 'Text'
# disk.[rw]blk return blocks, we assume a blocksize of 512
# to get the number in kB/s we would do blk*512/1024, which is blk/2
# expression (proc_stat::disk('.*', 'rblk', 0.5 * second)+proc_stat::disk('.
*', 'wblk', 0.5 * second))/2
# with kernel 2.6, disk_io disappeared from /proc/stat but moved to /proc/di
skstat
# therefore you have to use another function called 'diskstats':
expression (diskstats('sd[a-z]$', 'read_sectors', 0.5 * second) + diskstats(
'sd[a-z]$', 'write_sectors', 0.5 * second)) / 2 / 1024
prefix 'Disk'
postfix ' MB/s'
width width050
precision 1
align 'R'
update 0.5 * second
}

Widget DiskBar {
class 'Bar'
#expression proc_stat::disk('.*', 'rblk', 0.5 * second)
#expression2 proc_stat::disk('.*', 'wblk', 0.5 * second)
# for kernel 2.6:
expression diskstats('sd[a-z]$', 'read_sectors', 0.5 * second) / 2 / 1024
expression2 diskstats('sd[a-z]$', 'write_sectors', 0.5 * second) / 2 / 1024
length width050
direction 'E'
update 0.5 * second
Background darkgray
BarColor0 barcolor0
BarColor1 barcolor1
}

Widget Eth0 {
class 'Text'
expression (netdev('eth0', 'Rx_bytes', 0.5 * second) + netdev('eth0', 'Tx_by
tes', 0.5 * second)) * 8 / 1024 / 1024
prefix 'eth0'
postfix ' Mbit/s'
width width050
precision 1
align 'R'
update 0.5 * second
}

Widget Eth0Bar {
class 'Bar'
expression netdev('eth0', 'Rx_bytes', 0.5 * second) * 8 / 1024 / 1024
expression2 netdev('eth0', 'Tx_bytes', 0.5 * second) * 8 / 1024 / 1024
length width050
direction 'E'
update 0.5 * second
Background darkgray
BarColor0 barcolor0
BarColor1 barcolor1
}

Widget DVB {
class 'Text'
expression dvb('signal_strength') * 100
prefix 'DVB Signal'
postfix '%'
width width050
precision 1
align 'R'
update 0.5 * second
}

Widget DVBBar {
class 'Bar'
expression dvb('signal_strength')
expression2 dvb('snr')
# expression2 dvb('ber')
min 0
max 1
length width050
direction 'E'
update 0.5 * second
Background darkgray
BarColor0 barcolor0
BarColor1 barcolor1
}

Widget MemoryTitle {
class 'Text'
expression 'Memory'
width width050
align 'L'
update 0
}

Widget MemoryTotal {
class 'Text'
expression meminfo('MemTotal') / 1024
prefix 'Total '
postfix ' MB'
width width050
precision 0
align 'R'
update 0
}

Widget MemoryFree {
class 'Text'
expression (meminfo('MemFree') + meminfo('Cached')) / 1024
prefix 'Free '
postfix ' MB'
width width050
precision 0
align 'R'
update 1 * second
}

Widget MemorySwapped {
class 'Text'
expression (meminfo('SwapTotal') - meminfo('SwapFree')) / 1024
prefix 'Swap used '
postfix ' MB'
width width050
precision 0
align 'R'
update 1 * second
}

Widget HDDTempTitle {
class 'Text'
expression 'Disk Temperature°C'
width width050
align 'L'
update 0
}

Widget HDDTemp1 {
class 'Text'
expression hddtemp('/dev/sda')
width width010
precision 1
align 'R'
update 10 * second
}

Widget HDDTemp2 {
class 'Text'
expression hddtemp('/dev/sdb')
width width010
precision 1
align 'R'
update 10 * second
}

Widget HDDTemp3 {
class 'Text'
expression hddtemp('/dev/sdc')
width width010
precision 1
align 'R'
update 10 * second
}

Widget FSSpaceTitle {
class 'Text'
expression 'Disk Space available'
width width050
align 'L'
update 0
}

Widget FSSpace1 {
class 'Text'
expression statfs('/', 'bavail') * statfs('/', 'bsize') / 1024 / 1024 / 1024
prefix '/ (Root FS)'
postfix ' GB'
width width050
precision 2
align 'R'
update 10 * second
}

Widget FSSpace2 {
class 'Text'
expression statfs('/home', 'bavail') * statfs('/home', 'bsize') / 1024 / 102
4 / 1024
prefix '/home'
postfix ' GB'
width width050
precision 2
align 'R'
update 10 * second
}

Widget FSSpace3 {
class 'Text'
expression statfs('/backup', 'bavail') * statfs('/backup', 'bsize') / 1024 /
1024 / 1024
prefix '/backup '
postfix ' GB'
width width050
precision 2
align 'R'
update 10 * second
}

Widget FSSpace4 {
class 'Text'
expression statfs('/mnt/platte', 'bavail') * statfs('/mnt/platte', 'bsize')
/ 1024 / 1024 / 1024
prefix '/platte '
postfix ' GB'
width width050
precision 2
align 'R'
update 10 * second
}

Widget FSSpace5 {
class 'Text'
expression statfs('/mnt/var', 'bavail') * statfs('/mnt/var', 'bsize') / 1024
/ 1024 / 1024
prefix '/var '
postfix ' GB'
width width050
precision 2
align 'R'
update 10 * second
}

Widget ServicesTitle {
class 'Text'
expression 'Services'
width width100
align 'C'
Background lightgray
Foreground darkgray
}

Widget PortmapStatus {
class 'Text'
expression 'Portmap '
width width050
postfix strstr(exec('/etc/init.d/portmap status', 10 * second), 'running') >
0 ? 'up' : 'down!'
update 10 * second
}

Widget SSHdStatus {
class 'Text'
expression 'SSHd '
width width050
postfix strstr(exec('/etc/init.d/ssh status', 10 * second), 'running') > 0 ?
'up' : 'down!'
update 10 * second
}

Widget RsyslogStatus {
class 'Text'
expression 'Rsyslog '
width width050
postfix strstr(exec('/etc/init.d/rsyslog status', 10 * second), 'running') >
0 ? 'up' : 'down!'
update 10 * second
}

Widget pyloadStatus {
class 'Text'
expression 'pyload'
width width050
postfix strstr(exec('/etc/init.d/pyload status', 10 * second), 'running') >
0 ? 'up' : 'down!'
update 10 * second
}

Widget NFSdStatus {
class 'Text'
expression 'NFSd '
width width050
postfix strstr(exec('/etc/init.d/nfs-kernel-server status', 10 * second), 'r
unning') > 0 ? 'up' : 'down!'
update 10 * second
}

Widget LighttpdStatus {
class 'Text'
expression 'Lighttpd '
width width050
postfix strstr(exec('/etc/init.d/lighttpd status', 10 * second), 'running')
> 0 ? 'up' : 'down!'
update 10 * second
}

Widget MiniDLNAStatus {
class 'Text'
expression 'MiniDLNA '
width width050
postfix strstr(exec('/etc/init.d/minidlna status', 10 * second), 'running')
> 0 ? 'up' : 'down!'
update 10 * second
}

Widget MySQLStatus {
class 'Text'
expression 'MySQL '
width width050
postfix strstr(exec('/sbin/status mysql', 10 * second), 'running') > 0 ? 'up
' : 'down!'
update 10 * second
}

Widget MythTVStatus {
class 'Text'
expression 'MythTV Backend '
width width050
postfix strstr(exec('/sbin/status mythtv-backend', 10 * second), 'running')
> 0 ? 'up' : 'down!'
update 10 * second
}

Widget PostfixStatus {
class 'Text'
expression 'Postfix '
width width050
postfix strstr(exec('/etc/init.d/postfix status', 10 * second), 'not running
') > 0 ? 'down!' : 'up'
update 10 * second
}

Widget ProFTPStatus {
class 'Text'
expression 'ProFTP '
width width050
postfix strstr(exec('/etc/init.d/proftpd status', 10 * second), 'not running
') > 0 ? 'down!' : 'up'
update 10 * second
}

Widget SambaStatus {
class 'Text'
expression 'Samba '
width width050
postfix strstr(exec('/sbin/status smbd', 10 * second), 'running') > 0 ? 'up'
: 'down!'
update 10 * second
}

Widget SambaStatusDS {
class 'Text'
expression 'Samba '
width width050
postfix strstr(exec('/etc/init.d/samba status', 10 * second), 'running') > 0
? 'up' : 'down!'
update 10 * second
}

Widget SSHStatus {
class 'Text'
expression 'SSH '
width width050
postfix strstr(exec('/sbin/status ssh', 10 * second), 'running') > 0 ? 'up'
: 'down!'
update 10 * second
}

Widget SSHStatusDS {
class 'Text'
expression 'SSH '
width width050
postfix strstr(exec('/etc/init.d/ssh status', 10 * second), 'running') > 0 ?
'up' : 'down!'
update 10 * second
}

Widget SWRAIDStatus {
class 'Text'
expression 'SW RAID '
width width050
postfix strstr(exec('cat /proc/mdstat', 10 * second), '[UUU]') > 0 ? 'up' :
'attention!'
update 10 * second
}

Widget TwonkyStatus {
class 'Text'
expression 'Twonkymedia '
width width050
postfix strstr(exec('/sbin/status twonkymedia', 10 * second), 'running') > 0
? 'up' : 'down!'
update 10 * second
}

Widget SyslogTitle {
class 'Text'
expression '/var/log/syslog'
width width100
align 'C'
Background lightgray
Foreground darkgray
}

Widget SetSyslogMsg {
class 'Timer'
expression SyslogMsg = exec('tail -n 1 /var/log/syslog', 2 * second)
active 1
update 2 * second
}

Widget Syslog1 {
class 'Text'
expression substr(SyslogMsg, 0 * width100, width100)
width width100
align 'L'
Background darkgray
update 2 * second
}

Widget Syslog2 {
class 'Text'
expression substr(SyslogMsg, 1 * width100, width100)
width width100
align 'L'
Background darkgray
update 2 * second
}

Widget Syslog3 {
class 'Text'
expression substr(SyslogMsg, 2 * width100, width100)
width width100
align 'L'
Background darkgray
update 2 * second
}

Widget Syslog4 {
class 'Text'
expression substr(SyslogMsg, 3 * width100, width100)
width width100
align 'L'
Background darkgray
update 2 * second
}

Widget Debug {
class 'Text'
# expression cfg('Layout')
expression '$Revision: 1.25 $ -- DPF Driver by hackfin'
width linesize
align 'C'
Foreground lightgray
}

Widget na {
class 'Text'
expression 'n/a'
width 3
align 'L'
}

Widget Bgnd {
class 'Image'
file '/usr/local/share/backgrounds/mythbuntu-320x240.png'
reload 0
update 0
inverted 0
visible 1
}

Widget BgndDS {
class 'Image'
file '/usr/local/share/backgrounds/dockstar-320x240.png'
reload 0
update 0
inverted 0
visible 1
}

Layout Ubuntu {
Row01.Col01 'System'
Row02.Col01 'Time'
Row04.Col02 'Busy'
Row05.Col02 'BusyBar'
Row07.Col02 'Load'
Row08.Col02 'LoadBar'
Row10.Col02 'Disk'
Row11.Col02 'DiskBar'
Row13.Col02 'Eth0'
Row14.Col02 'Eth0Bar'
Row16.Col02 'DVB'
Row17.Col02 'DVBBar'

Row04.Col28 'MemoryTitle'
Row05.Col29 'MemoryTotal'
Row06.Col29 'MemoryFree'
Row07.Col29 'MemorySwapped'
Row09.Col28 'HDDTempTitle'
Row10.Col29 'HDDTemp1'
Row10.Col35 'HDDTemp2'
Row10.Col41 'HDDTemp3'
Row12.Col28 'FSSpaceTitle'
Row13.Col29 'FSSpace1'
Row14.Col29 'FSSPace2'
Row15.Col29 'FSSpace3'
Row16.Col29 'FSSpace4'
Row17.Col29 'FSSpace5'

Row19.Col02 'ServicesTitle'
Row20.Col02 'ApacheStatus'
Row21.Col02 'MySQLStatus'
Row22.Col02 'MythTVStatus'
Row23.Col02 'PostfixStatus'
Row20.Col29 'SambaStatus'
Row21.Col29 'SSHStatus'
Row22.Col29 'SWRAIDStatus'
Row23.Col29 'TwonkyStatus'

Row25.Col02 'SyslogTitle'
Row26.Col02 'Syslog1'
Row27.Col02 'Syslog2'
Row28.Col02 'Syslog3'
Row29.Col02 'Syslog4'

Row30.Col01 'Debug'

Timer1 'SetSyslogMsg'

# Layer 2 {
# X1.Y1 'Bgnd'
# }

}

Layout Dockstar {
Row01.Col01 'System'
Row02.Col01 'Time'
Row04.Col02 'Busy'
Row05.Col02 'BusyBar'
Row07.Col02 'Load'
Row08.Col02 'LoadBar'
Row10.Col02 'Disk'
Row11.Col02 'DiskBar'
Row13.Col02 'Eth0'
Row14.Col02 'Eth0Bar'

Row04.Col28 'MemoryTitle'
Row05.Col29 'MemoryTotal'
Row06.Col29 'MemoryFree'
Row07.Col29 'MemorySwapped'
Row09.Col28 'HDDTempTitle'
Row10.Col29 'na'
Row12.Col28 'FSSpaceTitle'
Row13.Col29 'FSSpace1'
# Row14.Col29 'FSSpace2'
Row14.Col29 'FSSpace4'
Row15.Col29 'FSSPace5'

Row16.Col02 'ServicesTitle'
Row17.Col02 'PortmapStatus'
Row18.Col02 'SSHdStatus'
Row19.Col02 'RsyslogStatus'
Row20.Col02 'NFSdStatus'
Row21.Col02 'pyloadStatus'
# Row22.Col02 'PostfixStatus'
# Row23.Col02 'ProFTPStatus'
# Row17.Col29 'SambaStatusDS'
# Row18.Col29 'SSHStatusDS'

Row23.Col02 'SyslogTitle'
Row24.Col02 'Syslog1'
Row25.Col02 'Syslog2'
Row26.Col02 'Syslog3'
Row27.Col02 'Syslog4'

Row30.Col01 'Debug'

Timer1 'SetSyslogMsg'

# Layer 2 {
# X1.Y1 'BgndDS'
# }

}

VirtualBox USB in guest

To add a USB device connected to the host to the guest, I found the following procedure beneficial:

  • start VirtualBox
  • open USB connection setup page
  • connect USB device
  • add filter for newly connected USB device in VBox setup
  • if necessary eject device from host (diskutil eject /dev/disk?)
  • start guest and see if connection was successful
  • reconnect if necessary

snmp v3

to get the net-snmp-config tool the libsnmp-dev package must be installed:

# apt-get install libsnmp-dev
# net-snmp-config –create-snmpv3-user -ro -A ‘geheim’ -X ‘secret’ -a SHA -x AES icinga

you may also create a new user using snmp commands:

#snmpusm -v 3 -u -l authNoPriv -a MD5 -A localhost passwd

to simplify the usage a local user profile should be created in ~/.snmp/snmp.conf:

defSecurityName
defContext “”
defAuthType MD5
defSecurityLevel authNoPriv
defAuthPassphrase defVersion 3

now a simple command looks like:

#snmpget localhost sysUpTime.0

Mirror – semi-transparent mirror info panel

I recently started building my own version of a semi-transparent mirror info panel. The server inside is running as a main service station for basically everything.
The server is hosting an external hard disk to serve videos, music and hard disk space via minidlna, nfs, appletalk and samba. Further the server is hosting my mail, imap, icinga, etc services.

A web front end is showing the basic information on an LCD behind the semi-transparent screen and here comes the PHP behind:

<?php ############# HEAD  ############################
$refresh_period = "3600";# refresh once in an hour only
$PHP_SELF = htmlspecialchars($_SERVER['PHP_SELF']); # use one file only which will be reload with new parameters all the time
header("Refresh: $refresh_period; url=$PHP_SELF");
echo "<!DOCTYPE html>\n";
echo "<html>\n<head>\n <meta http-equiv='refresh' content='.".$refresh_period."'><meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1.0'>\n";
require_once('simpleCalDAV/SimpleCalDAVClient.php');
$client = new SimpleCalDAVClient();
$zeiger = array("Stunde", "Minute", "Sekunde");
############# Configuration ##########################
$numberClocks = array("Shenzen" => 2, "Saarbruecken" => 0);
$calendar_config = array('server' => '<server adress>/remote.php/dav/calendars/olkn/personal/', 
						'login' => '<login>', 
						'password' => '<password>',
						'calendar' => 'personal');
$tokens = array('SUMMA', 'DESCR', 'DTSTA', 'LOCAT', 'DTEND');// tokens to check for in calendar entry
############# style sheets ########################
echo "<link rel='stylesheet' type='text/css' href='stylesheet.css'>\n";
echo "<style>\n";
foreach ($numberClocks as $ort => $zeitzone){
	$rotation["Stunde"] = (date("h") + $zeitzone) * 30 + round(date("i")/2);# define hour rotation including timezone and minute part
	$rotation["Minute"] = date("i") * 6;# define minute rotation and
	$rotation["Sekunde"] = date("s") * 6;# second rotation
	foreach ($zeiger as $zeigername){
		$rotstart = $rotation[$zeigername];$rotstop = $rotation[$zeigername]+360;
		$temp = $zeigername.$ort;# CSS class name is StundeShenzen, etc
		echo ".".$temp." { \n\t-moz-animation-name: drehen".$temp.";\n\t-webkit-animation-name: drehen".$temp." ;\n\t";
		echo "-o-animation-name: drehen".$temp.";\n\t-ms-animation-name: drehen".$temp.";\n\tanimation-name: drehen".$temp.";\n\t";
		echo "-moz-animation-iteration-count: infinite;\n\t-webkit-animation-iteration-count: infinite;\n\t";
		echo "-o-animation-iteration-count: infinite;\n\t-ms-animation-iteration-count: infinite;\n\t";
		echo "animation-iteration-count: infinite;\n\t-moz-animation-direction: normal;\n\t-webkit-animation-direction: normal;\n\t";
		echo "-o-animation-direction: normal;\n\t-ms-animation-direction: normal;\n\tanimation-direction: normal;\n\t";
		if ($zeigername == "Sekunde"){# second hand will go in steps rather than continously
			echo "-moz-animation-timing-function: steps(60);\n\t-webkit-animation-timing-function: steps(60);\n\t";
			echo "-o-animation-timing-function: steps(60);\n\t-ms-animation-timing-function: steps(60);\n\tanimation-timing-function: steps(60);\n\t}\n";
		} else {
			echo "-moz-animation-timing-function: linear;\n\t-webkit-animation-timing-function: linear;\n\t";
			echo "-o-animation-timing-function: linear;\n\t-ms-animation-timing-function: linear;\n\tanimation-timing-function: linear;\n\t}\n";
		}
		echo "@-moz-keyframes drehen".$temp." { \n\tfrom { -moz-transform: rotate(".$rotstart."deg); } \n\tto { -moz-transform: rotate(".$rotstop."deg); } \n}\n";
		echo "@-webkit-keyframes drehen".$temp." { \n\tfrom { -moz-transform: rotate(".$rotstart."deg); } \n\tto { -moz-transform: rotate(".$rotstop."deg); } \n}\n";
		echo "@-o-keyframes drehen".$temp." { \n\tfrom { -moz-transform: rotate(".$rotstart."deg); } \n\tto { -moz-transform: rotate(".$rotstop."deg); } \n}\n";
		echo "@-ms-keyframes drehen".$temp." { \n\tfrom { -moz-transform: rotate(".$rotstart."deg); } \n\tto { -moz-transform: rotate(".$rotstop."deg); } \n}\n";
		echo "@keyframes drehen".$temp." { \n\tfrom { -moz-transform: rotate(".$rotstart."deg); } \n\tto { -moz-transform: rotate(".$rotstop."deg); } \n}\n";
	}
}
echo "</style>\n";
echo "<title>Mirror</title>\n</head>\n<body>\n\n";
############################## MAIN ##################################
date_default_timezone_set('Europe/Berlin');# set time zone
############## show weather on top right #############################
echo "<a href='second.php'><div class='header'>\n";
echo "<div id='cont_29118c24cbd1fe3b37edea315a92451d'><span id='h_29118c24cbd1fe3b37edea315a92451d'>";
echo "</span><script type='text/javascript' async src='https://www.daswetter.com/wid_loader/29118c24cbd1fe3b37edea315a92451d'>";
echo "</script></div>";
echo "</div>\n";# header
############### show calender and clock on bottom ####################
echo "<div class='footer'>\n";
echo "<div class='calendar'>\n";
try {
	$client->connect($calendar_config['server'], $calendar_config['login'], $calendar_config['password']);
	$arrayOfCalendars = $client->findCalendars();# get all available calendars
	$client->setCalendar($arrayOfCalendars[$calendar_config['calendar']]);# choose specific calendar
	$events = $client->getEvents(date('Ymd')."T000000Z", date('Ymd')."T240000Z"); # get list of events for today
	echo "<div class='calendar_header'>".date("l d.F Y")."</div>\n";# show current date
	foreach ($events as $event){
		$results = array();
		$event_data = explode("\n", $event->getData());
		foreach ($event_data as $line){
			list($key, $value) = explode(":", $line);
			if ($key == "BEGIN" && $value == "VEVENT") $trigger = true;// only check VEVENT entries
			elseif ($key == "END") $trigger = false;// other entries will be ignored
			if ($trigger){
				$key = substr($key, 0, 5);// DTSTART and END use complexe format, so the beginning of the word is enough
				if (in_array($key, $tokens)){// we found a relevant token, so store it in array for this event
					$results[$key] = $value;
				}
			}//end of triggering
		}//mext line of ICALENDAR Event
		echo "<div class='calendar_contents'>\n";
		if (strstr($results['DTSTA'], 'T') && strstr($results['DTEND'], 'T')){//we have a specific time (no whole day entry)
			echo "<div class='calendar_time'>".str_split(substr($results['DTSTA'], -6), 2)[0].":".str_split(substr($results['DTSTA'], -6), 2)[1];
			echo " - ".str_split(substr($results['DTEND'], -6), 2)[0].":".str_split(substr($results['DTEND'], -6), 2)[1];
			echo "</div>\n";//calendar_time
		}//event time processing
		echo $results['SUMMA']."\n<div class='calendar_entry'>".$results['DESCR']."</div>\n";//calendar_entry
		if (isset($results['LOCAT'])) echo "<div class='calendar_location'>".$results['LOCAT']."</div>\n";//calendar_location
		echo "</div>\n";//calender_contents
	}// next event
}
catch (Exception $e) {
	echo $e->__toString();
	echo "Error during catching calendar entries from Server<br>";
}
echo "</div>\n";# calender
############### show two clocks for worldtime ########################
echo "<div class='clock'>\n";
foreach ($numberClocks as $ort => $zeitzone){
	echo "<div class='clock_inner'>\n";
	echo "\t<div class='uhr'>\n";
	echo "\t<ul class='markierungen'>\n<li id='mark01'><div></div></li><li id='mark02'><div></div></li>\n";
	echo "\t<li id='mark03'><div></div></li><li id='mark04'><div></div></li>\n<li id='mark05'><div></div></li>";
	echo "\t<li id='mark06'><div></div></li>\n<li id='mark07'><div></div></li><li id='mark08'><div></div></li>\n";
	echo "\t<li id='mark09'><div></div></li><li id='mark10'><div></div></li>\n<li id='mark11'><div></div></li>";
	echo "\t<li id='mark12'><div></div></li>\n</ul>\n";
	foreach ($zeiger as $zeigername){
		echo "\t<div class='".$zeigername.$ort."' id='".$zeigername."'></div>";
	}
	echo "\t</div><div class='clock_location'>".$ort."</div>\n";
	echo "</div>\n";# clock_inner
}
echo "</div>\n";# clock
echo "</div>\n</a>";# footer
############### close ####################################################
echo "</body>\n</HTML>\n";
########### END ###################################?>

There is also a second page, which is showing some statistics about the server:

<?php ############# HEAD  ############################
echo "<!DOCTYPE html>\n";
echo "<html>\n<head>\n <meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1.0'>\n";
############# style sheets ########################
echo "<link rel='stylesheet' type='text/css' href='stylesheet.css'>";
echo "<title>Mirror</title>\n</head>\n<body>\n\n";
############# Configuration ##########################
$PHP_SELF = htmlspecialchars($_SERVER['PHP_SELF']); # use one file only which will be reload with new parameters all the time
$display_size = array(1024, 768);
###### debug output of POST
function debug_output(){
        echo "<pre><br><h1>Hier kommt der schamass!</h1>";
        print_r($_POST);
        echo "</pre>"; return ;
}
######################################################################
############################## MAIN ##################################
######################################################################
echo "<body><form method='POST' action='$PHP_SELF'>\n";# page header with headline and table headers
echo "<a href='index.php'><section class='contents'>";
############## show weather on top right #############################
echo "<table width='100%' border=1><tr>";
echo "<td><img src='<cacti-server-adress>/graph_image.php?local_graph_id=12&rra_id=1&graph_width=500&graph_height=120&graph_nolegend=true'></td>";
echo "<td><img src='<cacti-server-adress>/graph_image.php?local_graph_id=24&rra_id=1&graph_width=500&graph_height=120&graph_nolegend=true'></td>";
echo "</tr><tr>";
echo "<td><img src='<cacti-server-adress>/graph_image.php?local_graph_id=20&rra_id=1&graph_width=500&graph_height=120&graph_nolegend=true'></td>";
echo "<td><img src='<cacti-server-adress>/graph_image.php?local_graph_id=38&rra_id=1&graph_width=500&graph_height=120&graph_nolegend=true'></td>";
echo "</tr><tr>";
echo "<td><img src='<cacti-server-adress>/graph_image.php?local_graph_id=40&rra_id=1&graph_width=500&graph_height=120&graph_nolegend=true'></td>";
echo "<td><img src='<cacti-server-adress>/graph_image.php?local_graph_id=9&rra_id=1&graph_width=500&graph_height=120&graph_nolegend=true'></td>";
echo "</tr><tr>";
echo "<td><img src='<cacti-server-adress>/graph_image.php?local_graph_id=23&rra_id=1&graph_width=500&graph_height=120&graph_nolegend=true'></td>";
echo "<td><img src='<cacti-server-adress>/graph_image.php?local_graph_id=9&rra_id=1&graph_width=500&graph_height=120&graph_nolegend=true'></td>";
echo "</tr></table>";
echo "Nagios Entries!";
echo "</section>";
############# cleanup and end ########################################
#debug_output();
echo "</form>\n<footer id='footer'>My personal page hosted on my own server &copy; olkn</footer></a></body></HTML>\n";
########### END ###################################?>

sda sleep with smartmon

My new server is using an external 1TB disk to store all what seems necessary. In order to keep the disk under surveillance of smartmontools without loosing the power management and spin down options of hdparm I am using the following settings:

/etc/hdparm.conf:
/dev/sda {
spindown_time = 24
}

/etc/smartd.conf:

DEVICESCAN -d removable -n standby -m root -M exec /usr/share/smartmontools/smartd-runner

-m root: send email notification to root user
-n standby: only run tests if device is not in standby mode

mirror.sketch

The sketch for my mirror with display:

/* mirror
*
* control PWM for fan, read temperatures from DS1820 and interface to PIR
*/
#include
#include
#include // interrupt routine
#define ONE_WIRE_BUS 3 // define port for DS1820 interface
#define TEMP_DEVICE_IN 28E08F3606000003
#define TEMP_DEVICE_EX 289A78370600002C
#define TEMP_DEVICE_BOARD 2873163706000020
#define LED 4
#define PIR_INTERFACE 5 // define port for PIR
#define FANSENSE 8
#define FANPWM 9
#define THRESHOLD_OFF 25
#define THRESHOLD_LOW 30
#define THRESHOLD_HIGH 40
#define THRESHOLD_ON 45
#define TASTER_DOWN 6
#define TASTER_UP 7

DeviceAddress devices[] = {TEMP_DEVICE_IN, TEMP_DEVICE_EX, TEMP_DEVICE_BOARD };
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
int buttonPressed = 0;

void setup() {
Serial.begin(9600);// start serial port
sensors.begin();// Start up the library
for( int i=0; i < 3; i++){ sensors.setResolution(devices[i], 10);// set the resolution to 10 bit } pinMode(PIR_INTERFACE, INPUT);// read PIR status from external Board pinMode(FANSENSE, INPUT); // read RPM data from sense of FAN digitalWrite(FANSENSE, HIGH); // activate internal Pull Up pinMode(LED, OUTPUT); // LED for status info pinMode(TASTER_DOWN, INPUT); // external key for navigation input pinMode(TASTER_DOWN, INPUT); } void setLED(int pulse){ if(pulse > 0){
digitalWrite(LED, HIGH);
delay(10*pulse);
digitalWrite(LED, LOW);
delay(10*pulse);
}
}

void loop() {
/* main loop sends list of values via serial line in format:
* up/down (PIR status flag), TempExternal, TempInternal, TempBoard, RPM from Fan
*/
float Temperature = 0;
double frequency = 0;
unsigned long pulseDuration = 0;
int pirStatus = 0;
pirStatus = digitalRead(PIR_INTERFACE);
if( digitalRead(TASTER_UP) == HIGH ){
buttonPressed = 2; // up taster pressed
} else if ( digitalRead(TASTER_UP) == HIGH ) {
buttonPressed = 1; // down taster pressed
} else {
buttonPressed = 0; // no button pressed
}
if (pirStatus == HIGH) {
Serial.print("up,");
} else {
Serial.print("down,");
}
for(int i = 0; i < 3; i++){ Temperature = Temperature + sensors.getTempC(devices[i]); Serial.print(Temperature); Serial.print(","); } Temperature = Temperature / 3; // Temperature Hytherese pulseDuration = pulseIn(FANSENSE, LOW); frequency = 1000000/pulseDuration; Serial.print(frequency); Serial.println();// new line for next data // analogWrite(FANPWM, 70); //set PWM signal }

mirror – setup

Software Installations for Min Server

  • fetchmail
  • postfix
  • cups
  • dnsmasq
  • logwatch
  • smartmontools
  • ClamAV
  • fail2ban
  • dovecot
  • shellInABox
  • nagios
  • cacti
  • rsyslog
  • Mysql
  • netsnmp
  • spamassassin
  • git
  • apache
  • webalizer
  • wordpress
  • nextcloud
  • glype
  • gitlist
  • roundcube
  • gitlist
  • libreoffice
  • php
  • imagemagick
  • amavis
  • spamd
  • managesieve
  • VPN Tunnel
  • ntpd
  • nfs
  • samba
  • music streamer
  • video streamer

Nagios Components

  • postfix
  • dovecot
  • apache
  • dnsmasq
  • cups
  • mysql
  • clamav
  • nextclou
  • wordpress
  • rsyslog
  • ntpd
  • git
  • smartd
  • shellinanbox
  • spamd
  • nfs
  • minidlna
  • samba
  • timemachine
  • afpd
  • cups

actual to do:

  • shinken als nagios Ersatz
  • samba/timemaschine
  • shellinabox

git cli

To backup my arduino sketches I will use a remote git repository hosted on my own server. So lets start

  • git init – initialize a new local repository
  • git clone @: – check out/clone from a remote reporitory

The local repo is devided into a working copy, the index as interim stage und the head which is a link to the last commit.

  • git add – add a file to local repository
  • git commit -m “
  • git push origin master – sync local repository with remote repo

If the local repo was not cloned but should be linked to a remote repository use:

  • git remote add origin

To sync the local repository use:

  • git pull – fetch remote changes and merge them with the local files
  • git add – inform git about solved merge problems after solving

Summary:

git init

git add .

git commit -am “

git remote add origin @:

git push -u origin master