GARTEN EDEN

#linux #programming #android #online #stuff

Chrome-Icon Probleme mit Docky

Seit einem Update von Docky oder Google Chrome war das Icon des Browsers nicht mehr hochauflösend und scharf, sondern sehr schlecht aufgelöst (vermutlich ein gestrecktes 16x16 Pixmap). Außerdem wurde beim Klick auf das im Dock hinterlegte Chrome-Icon der Browser zwar gestartet, aber nicht gematcht, d. h. das vorhandene Symbol wird nach Programmstart nicht als aktiv angezeigt, sondern ein neues erzeugt.

Dockys Window Matching anpassen

Nach etwas Recherche fand ich heraus, dass man das Window Matching von Docky anpassen kann.
Docky kann auf die WM_CLASS einer Applikation achten; diese gilt es jetzt für Chrome herauszufinden. Dazu kann man im Terminal folgendes eingeben und danach auf ein Chrome-Fenster klicken.

xprop | grep WM_CLASS | awk '{print $4}'
Dieser Befehl liefert bei mir zur Zeit "Google-chrome-stable".

Docky verstehen und anpassen

Docky funktioniert so, dass es beim Start (falls kein Cache vorhanden ist) nach allen Programmstartern des Systems sucht (z. B. in /usr/share/applications/) und sie für sich in einem Cache bereithält.
Das heißt, jetzt gilt es nur noch Chromes Starter so anzupassen, dass er auch noch die WM_CLASS enthält und Docky ihn daran wiedererkennt.

Mit einer Suche nach allen Chrome-Startern ("locate google-chrome.desktop") erhielt ich zwei Dateien, die ich beide (mit Root-Rechten) um den Eintrag StartupWMClass=Google-chrome-stable erweiterte.

Damit Docky die Dateien neu einliest, hab ich Docky beendet, dessen Cache gelöscht und es wieder gestartet. Voilà, Chrome wird richtig, das Icon ist schön.

Wie ich jetzt feststelle, muss auch die Cache-Datei in ~/.cache/docky/ um den Eintrag erweitert werden.

Update am 14.01.2014 20:19

12 Kommentare

Thunderbird mit Google Calendar: Fehler beim Synchronisieren

Aufgrund einiger Änderungen der CalDAV-Synchronisierung von Google Calendar tritt unter der Verwendung von Lightning in Thunderbird evtl. folgender Fehler auf: CalDAV: Error doing webdav sync: 400

Hintergrund ist, dass CalDAV auf Googles Server gemäß Standard RFC6578 einen gewissen Wert (sync-level) erwartet, der zur Zeit noch nicht von Lightning mitgesendet wird, weswegen die Kalendardatenabfrage scheitert. Während Mozilla an einem Bugfix arbeitet, kann man das Problem manuell lösen.

Workaround

Dieser Fix von Matthew Mecca [:mmecca] entstammt der Diskussion auf Bugzilla zu diesem Fehler.
Man öffne die Datei calDavRequestHandlers.js aus dem Thunderbird-Profil-Ordner (genauer dort in extensions/LIGHTNING-ADDON-KENNUNG/calendar-js/) und füge die markierte Zeile in Zeile 342 ein und lösche Zeile 359.
Beachte, dass die Zeilennummer abweichen kann, je nach Thunderbird-/Lightning-Version (bei mir aktuell TB 24 und Lightning 2.6).

                 let syncToken =     cal.xml.escapeString(this.calendar.mWebdavSyncToken);
                 syncTokenString = "<sync-token>" + syncToken + "</sync-token>";
             }
     
             let queryXml =
               xmlHeader +
               '<sync-collection xmlns="DAV:">' +
                 syncTokenString +
/*EINFUEGEN:*/   '<sync-level>1</sync-level>' +
                 '<prop>' +
                   '<getcontenttype/>' +
                   '<getetag/>' +
                 '</prop>' +
               '</sync-collection>';
     
             let requestUri = this.calendar.makeUri(null, this.baseUri);

             if (this.calendar.verboseLogging()) {
                 cal.LOG("CalDAV: send(" + requestUri.spec + "): " + queryXml);
             }
             cal.LOG("CalDAV: webdav-sync Token: " + this.calendar.mWebdavSyncToken);
             let httpchannel = this.calendar.prepHttpChannel(requestUri,
                                                             queryXml,
                                                             "text/xml; charset=utf-8",
                                                             this.calendar);
/*ENTF:      httpchannel.setRequestHeader("Depth", "1", false); */
             httpchannel.requestMethod = "REPORT";
             // Submit the request
             httpchannel.asyncOpen(this, httpchannel);

Nach einem Neustart des Programms war der Fehler bei mir behoben.

Systemweite Änderung

Für systemweite Änderung muss dieselbe Datei zusätzlich in /usr/lib/thunderbird-addons/ bearbeitet werden.

Update am 01.10.2013 14:30: Auf Bugzilla wurde eine neue Version des Fixes veröffentlicht. Ich habe die Änderungen angepasst. Danke auch an Andreas Becker.

6 Kommentare

Sicherer und schneller Webserver mit nginx auf einem Raspberry Pi

Wer einen flinken, leichtgewichtigen Webserver betreiben möchte, greift aktuell nicht zu Apache, sondern zu nginx. Der Funktionsumfang ist ähnlich groß und längst gehört der freie HTTP-Server zu den etablierten Größen im Internetgeschäft (12% Marktanteil laut Netcraft).
Anders als ein nur im lokalen Netzwerk erreichbarer Dienst muss ein für alle Welt offener Server deutlich höhere Sicherheit garantieren. Auch in dieser Kategorie ist man mit nginx (und einigen zusätzlichen Vorkehrungen) gut aufgestellt. Da wir außerdem nicht nur statischen Content ausliefern wollen, installieren wir zusätzlich PHP, welches wir ebenfalls absichern und mittels XCache beschleunigen.

SFTP statt FTP

Das unsichere FTP hat übrigens ausgedient. Längst gibt es mit SFTP eine deutlich bessere Alternative, die auch unter allen Betriebssystemen verfügbar ist; wenn nicht mit Boardmitteln wie bei GNOME (Orte → Verbindung zu Server…), so zumindest mit dem beliebten FileZilla. SFTP verwendet dabei eine verschlüsselte Verbindung über den SSH-Dienst des Raspberrys, der sowieso für viele Aufgaben benötigt wird und standardmäßig und zu Recht aktiv ist.

Verbindung zum RPi

Da ein Monitor am RPi vertane Mühe ist, verbinden wir uns an einem anderen Computer mit dem kleinen Racker über SSH, wobei die Variablen natürlich zu ersetzen sind.

ssh IP-ADRESSE -l BENUTZERNAME

Installation und Backup

Als nächstes installieren wir den Webserver, PHP und die PHP-Beschleunigung. Beim Webserver wähle ich die light-Variante aus den Debian Packages, weil die enthaltenen Module für meine Zwecke ausreichend sind und Unnötiges nur unnötig Angriffsfläche bietet. Wer mehr braucht, installiert eben die umfangreicheren Pakete.

sudo apt-get install nginx-light php5-fpm php5-xcache

Für den Fall der Fälle legen wir noch Backups aller zu bearbeitenden Dateien an.

sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bku
sudo cp /etc/nginx/fastcgi_params /etc/nginx/fastcgi_params.bku
sudo cp /etc/php5/fpm/php-fpm.conf /etc/php5/fpm/php-fpm.conf.bku
sudo cp /etc/php5/fpm/php.ini /etc/php5/fpm/php.ini.bku

Dateien bearbeiten

Um die nachfolgenden config-Dateien zu bearbeiten, empfiehlt es sich, die Dateien auf dem lokalen Rechner zu öffnen (z. B. mit gedit) und dann per Konsole und sudo in die entsprechenden Ordner zu kopieren. Die passenden Dateirechte setzen wir erst ganz zu Schluss.

Design

Alle serverspezifischen Dateien sollen sich am Ende im Verzeichnis /var/www/ befinden. Im Unterverzeichnis nginx/ die für den Webserver, in php-fpm/ die für PHP, in sockets/ sind die jeweiligen Unix-Sockets von PHP verlinkt (also sozusagen die Verbindungsports zu der PHP-Engine, auf die die jeweilige nginx-Site zugreift) und zu guter Letzt erhält jede Site ihr eigenes Verzeichnis.
In meinem Beispiel exisitiert nur die Site rpidisplay, die mein an den RPi angeschlossenes Display ansteuert.
Alle aus dem Internet erreichbaren Dateien liegen im Verzeichnis SITE/docs/, bei mir also /var/www/rpidisplay/docs/. Die zugehörigen Logdateien werden in SITE/logs/ gespeichert. Die anderen Verzeichnisse sind nur der Vollständigkeit halber aufgeführt.
Die gesamte Verzeichnisstruktur sieht also folgendermaßen aus:

/var/www/
├── nginx/
│   └── rpidisplay.conf
├── php-fpm/
│   └── rpidisplay.conf
├── rpidisplay/
│   ├── bin/
│   ├── docs/
│   │   └── index.html
│   ├── home/
│   ├── local/
│   │   └── bin
│   ├── logs/
│   │   └── access.log
│   │   └── error.log
│   ├── tmp/
│   └── usr/
│       ├── bin/
│       └── share/
└── sockets/
    └── rpidisplay.socket

nginx konfigurieren

Der Webserver selbst bekommt aus Sicherheitsgründen einen eigenen User nginx, der per se für das restliche System keine Schreibrechte erhält. Außerdem werden nicht-standardkonforme HTTP-Header ignoriert und weil der RPi nur einen Core hat, reicht ein worker_process. Was es mit der optionalen gzip-Kompression auf sich hat, steht weiter unten und dient nur der Performance. Wohlgemerkt steht in dieser Datei die Standardkonfiguration für alle Sites, die betrieben wird. Die include-Zeile lädt für jeden Virtual Host noch weitere Einstellungen nach.
Meine nginx-Konfiguration sieht nun folgendermaßen aus:
/etc/nginx/nginx.conf:

user nginx nginx;
worker_processes 1;
pid /var/run/nginx.pid;

events {
	worker_connections 768;
}

http {

	##
	# Basic
	##

	sendfile on;
	keepalive_timeout 65;
	types_hash_max_size 2048;
	server_tokens off;
	ignore_invalid_headers on;
	server_name_in_redirect off;
	tcp_nodelay off;
	tcp_nopush on;

	include /etc/nginx/mime.types;
	default_type application/octet-stream;


	##
	# Logging 
	##

	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;


	##
	# Gzip
	##

	gzip on;
	gzip_static on;
	gzip_disable "msie6";

	gzip_vary on;
	gzip_proxied any;
	gzip_comp_level 3;
	gzip_buffers 16 8k;
	gzip_http_version 1.1;
	gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml rss text/javascript text/mathml application/atom xml application/xhtml xml image/svg xml;


	##
	# Virtual Host Configs
	##

	include /var/www/nginx/*.conf;
	#include /etc/nginx/conf.d/*.conf;
	#include /etc/nginx/sites-enabled/*;
}

FastCGI konfigurieren

FastCGI kümmert sich um die Einbindung externer Module in den Webserver, in unserem Fall das php-fpm-Modul. Bei den FastCGI Parametern sind die wichtigsten der DOCUMENT_ROOT und SCRIPT_FILENAME. Und damit nicht jeder unsere Serverversion erfahren kann, wird auch SERVER_SOFTWARE gekürzt.
/etc/nginx/fastcgi_params

fastcgi_index index.php;

fastcgi_connect_timeout 65;
fastcgi_send_timeout    180;
fastcgi_read_timeout    180;

fastcgi_param	QUERY_STRING		$query_string;
fastcgi_param	REQUEST_METHOD		$request_method;
fastcgi_param	CONTENT_TYPE		$content_type;
fastcgi_param	CONTENT_LENGTH		$content_length;

fastcgi_param	DOCUMENT_ROOT		/docs;
fastcgi_param	SCRIPT_FILENAME		/docs$fastcgi_script_name;
fastcgi_param	SCRIPT_NAME		$fastcgi_script_name;
fastcgi_param	REQUEST_URI		$request_uri;
fastcgi_param	DOCUMENT_URI		$document_uri;
fastcgi_param	DOCUMENT_ROOT		$document_root;
fastcgi_param	SERVER_PROTOCOL		$server_protocol;

fastcgi_param	GATEWAY_INTERFACE	CGI/1.1;
fastcgi_param	SERVER_SOFTWARE		nginx;

fastcgi_param	REMOTE_ADDR		$remote_addr;
fastcgi_param	REMOTE_PORT		$remote_port;
fastcgi_param	SERVER_ADDR		$server_addr;
fastcgi_param	SERVER_PORT		$server_port;
fastcgi_param	SERVER_NAME		$server_name;

fastcgi_param	HTTPS			$https;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param	REDIRECT_STATUS		200;

Verzeichnisse und Benutzer anlegen

Erstellen wir nun die nötigen Verzeichnisse, Benutzer und Gruppen. Wir brauchen mindestens den User und die Gruppe nginx und zusätzlich für jede Site einen User und eine Gruppe. Anschließend muss nginx noch zu der Gruppe der jeweiligen Site hinzugefügt werden, damit der Webserver auch die Dateien ausliefern kann. Der Unix-Befehl adduser erstellt einen User und die dazugehörige Gruppe, sodass die nötigen Befehle wie folgt lauten:

sudo adduser --no-create-home --disabled-login nginx
sudo adduser --no-create-home --disabled-login rpidisplay
sudo usermod -G rpidisplay nginx

Nun erstellen wir die Verzeichnisse. Zuerst die für alle Sites, dann die für meinen rpidisplay-Host.

sudo mkdir /var/www/ /var/www/sockets/ /var/www/nginx/ /var/www/php-fpm/
cd /var/www/
sudo mkdir rpidisplay/ rpidisplay/bin/ rpidisplay/docs/ rpidisplay/home/ rpidisplay/logs/ rpidisplay/tmp/ rpidisplay/usr/ rpidisplay/usr/bin/ rpidisplay/usr/share/ rpidisplay/local/ rpidisplay/local/bin/

Site-spezifische Konfiguration

Wie die Site sich verhält und Inhalte ausliefert, wird in der jeweiligen Einstellungsdatei definiert. Diese wird, wie oben erwähnt, aus der Hauptdatei von nginx aufgerufen.
Dort steht auf welchem Port der Server lauscht und auf welchen Servernamen er reagiert. Außerdem sind hier die Logdateien der Site definiert und wo das Hauptverzeichnis liegt (root).
Zusätzlich möchte ich nicht, dass Dateien ausgeliefert werden, die mit einem Punkt beginnen. Der PHP-Abschnitt aktiviert die Weiterleitung an das PHP-Socket. Der letzte Teil definiert die Cache-Dauer für statische Inhalte. Da sich auf meiner Site nicht-dynamische Inhalte standardmäßig nicht ändern, ist der Wert entsprechend hoch.
/var/www/nginx/rpidisplay.conf

server { 
	listen 80;
	server_name rpidisplay;

	access_log /var/www/rpidisplay/logs/access.log;
	error_log /var/www/rpidisplay/logs/error.log warn;

	root /var/www/rpidisplay/docs;


	# deny access to dot-files
	location ^~ /\\. {
		access_log off;
		log_not_found off;
		deny all;
	}


	# enable PHP
	location ~ ^(.*)\\.php$ {
		if (!-f $request_filename) {
			return 404;
		}

		include /etc/nginx/fastcgi_params;
		fastcgi_pass unix:/var/www/sockets/rpidisplay.socket;
	}


	# enable browser cache control for static files including html
	location ~* \\.(html|htm|jpg|jpeg|gif|png|css|js|ico|xml)$ {
		access_log off;
		log_not_found off;
		expires 360d;
	}
}

PHP konfigurieren

Auch PHP muss noch gesagt bekommen, welche Einstellungen gelten. Um einen besseren Überblick und eine schnelle Anpassbarkeit auch der PHP-Optionen zu haben, möchte ich die Einstellungsdatei im /var/www-Verzeichnis liegen haben. Weisen wir PHP-FPM (das für uns das Socket öffnet, auf dem PHP verfügbar ist) also an, dort nach einer Konfigurationsdatei zu sehen. Das geschieht in der Datei /etc/php5/fpm/php-fpm.conf durch anhängen der Zeile

include=/var/www/php-fpm/*.conf

Damit die Standardkonfigurationsdatei nicht mehr geladen wird, benennen wir sie um.

sudo mv /etc/php5/fpm/pool.d/www.conf /etc/php5/fpm/pool.d/www.conf.bku

In der neu anzulegenden FPM-Konfigurationsdatei definieren wir beginnend mit dem Site-Namen nun also den Ort des zu öffnenden Sockets, Dateirechte und ein paar Variablen. Der Socketpfad muss mit dem übereinstimmen, auf den ngnix zugreifen will (s. o.) und die Datei- und Gruppenrechte entsprechen dem neu angelegten User für unsere Site.
/var/www/php-fpm/rpidisplay.conf:

[rpidisplay]
listen = /var/www/sockets/rpidisplay.socket
listen.owner = rpidisplay
listen.group = rpidisplay
listen.mode = 0666

listen.backlog = -1
listen.allowed_clients = 127.0.0.1

user = rpidisplay
group = rpidisplay

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.max_requests = 500

chroot = /var/www/rpidisplay
chdir = /docs

env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
env[HOME] = /home
env[DOCUMENT_ROOT] = /docs

Nun fehlt nur noch die altbekannte php.ini, die noch abgesichert werden muss. In den neueren PHP-Versionen sind viele Einstellungen von vornherein recht sicher gewählt. Je nach Belieben kann man noch Warnung und Fehler unterdrücken, zumindest sollte man aber einige Betriebssystemfuntionen deaktivieren, um serverweite Angriffe zu erschweren.
/etc/php5/fpm/php.ini:

disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,exec,system,passthru,shell_exec,popen,escapeshellcmd,proc_open,proc_nice,ini_restore

PHP-timezone-Fehler beheben

Mit den eingeschränkten (sicheren) Rechten, mit denen PHP nun läuft, funktionieren Zugriffe auf einige Betriebssystemfuntionen nicht mehr zuverlässig, so z. B. die meisten Zeitfunktionen. Das liegt daran, dass der PHP-User nicht auf /usr/share/zoneinfo/ zugreifen kann. Das Problem ist behoben, wenn man die dort liegenden Informationen in das /usr/share/-Verzeichnis des PHP-Nutzers kopiert.

sudo cp -aR /usr/share/zoneinfo /var/www/rpidisplay/usr/share/

Abschlussarbeiten

Jetzt würde ich noch die Standardsite von nginx deaktivieren, indem ich es aus dem Hauptpfad für aktive Sites entferne. Unsere Sites liegen jetzt ja in /var/www/.

sudo rm /etc/nginx/sites-enabled/default 

Außerdem müssen nun die Zugriffsrechte für die Dateien und Ordner gesetzt werden. Sprich: Alle Dateien in dem docs/-Verzeichnis müssen vom User der Site gelesen werden können, in meinem Fall vom User rpidisplay; nginx kann es dann automatisch, weil der Server ja zur selben Gruppe gehört.

sudo chown -R rpidisplay:rpidisplay /var/www/rpidisplay/docs/

Abschließend starten wir nginx und PHP neu, damit die Änderungen geladen werden.

sudo service nginx restart 
sudo service php5-fpm restart

Wenn keine Fehler ausgegeben werden, läuft auf unserem Debian-System nun ein schneller, leichtgewichtiger, dynamischer, funktionsreicher und vor allem sicherer Webserver.
Wird eine Datenbank benötigt, empfiehlt sich z. B. SQLite.

Warum gzip compression?

In der nginx-Hauptkonfigurationsdatei aktivierten wir die gzip-Kompression. Das bringt den Webserver dazu, bei einer aufgerufenen Datei immer zuerst nach einer komprimierten Version zu suchen und diese auszuliefern, sprich: Wird index.html aufgerufen, wird zuerst geschaut, ob index.html.gz vorhanden ist und wenn ja, diese an den Nutzer gesendet. Dadurch sinkt die Übertragungsgröße enorm, deshalb habe ich diese Option auch für alle statischen Dateitypen aktiviert.
Einschränkungen: nginx komprimiert nicht live, also muss man jede Datei, die man verändert, selbst komprimieren. Das erlaubt einem allerdings auch gleich die höchste Kompressionsstufe zu wählen, ohne dass der Server belastet wird. Außerdem gibt es Berichte darüber, dass es zu Fehlern kommen kann, wenn die Originaldatei und ihr gzip-Pendant nicht dasselbe Änderungsdatum haben, also empfiehlt es sich, die Dateien vorher alle zu touchen.

Quellen

Inspiration fand ich auf folgenden Quellen:

30 Kommentare

⇓   Ältere Artikel   ⇓