File Access auf Netgear NAS

Ich habe seit einien Jahren ein kleines NAS, um dort Musik, Bilder, Backups und so weiter abzulegen. Nun war es so, dass sich anfänglich die Rechte nicht so sauber konfigurieren ließen, wie man es sich eigentlich wünscht. Und so kam es, dass ein anderer User des Systems nicht auf die Bilder zugreifen konnte, die ich auf dem NAS gespeichert habe und ich umgekehrt nicht auf die Bilder des anderen Users. Dies blieb leider auch so, nachdem die Software in der Lage war, ein sauberes Gruppenkonzept für die Rechtevergabe anzubieten. Damals vermutete ich, dass bereits gesetzte Berechtigungen nicht aktualisiert werden, wenn man die Berechtigungen im Web-Frontend anpasst. Irgendwie habe ich mich aber nicht eingehend mit dem Problem beschäftigt.

Zufällig ergab es sich nun, dass ich auf dem NAS unterwegs war und da dachte ich mir, es wäre ja mal eine gute Gelegeneheit, auch bei die Rechte zu schauen. Im ersten Schritt habe ich mal das klassische ls bemüht. Diese zeigte aber an, dass die Gruppe, in der beide Benutzer sind, eigentlich die korrekten Rechte hätte:

$ ls -dal HDR
drwxrwx---+ 1 pvitt users 258 Nov 13  2013 HDR

Schaut man sich das an, sollte man meinen, dass die Gruppe user Leserechte hätte. Dem ist aber nicht so. Nach einigem Überlegen hat mich dann das kleine + auf die ACLs gebracht. Selbst hatte ich damit noch nicht viele Berührungen (zumindest in der Linux-Welt), daher musste ich erst mal nachlesen. Wie so oft, kam mir hier das ArchLinux-Wiki zu Hilfe. Im ersten Schritt habe ich mir die ACLs für einen Datei anzeigen lassen:

$ getfacl Moi.JPG
# file: Moi.JPG
# owner: pvitt
# group: users
user::rwx
user:admin:rwx
user:pvitt:rwx
group::---
group:admin:rwx
group:users:---
mask::rwx
other::---

Dort sieht man schön, dass sowohl der admin als auch mein User auf die Datei zugreifen dürfen. Auch die admin-Gruppe hat Zugriff. Die interessante Gruppe user allerdings nicht. Im Arch-Wiki ist anschaulich beschrieben, wie man nun für alle Dateien den Schreib- und Lese-Zugriff für eine Gruppe freigibt:

$ setfacl -m "g:users:rwx" -R *

Im Anschluss sieht die Sache dann so aus:

$ getfacl Moi.JPG
# file: Moi.JPG
# owner: pvitt
# group: users
user::rwx
user:admin:rwx
user:pvitt:rwx
group::---
group:admin:rwx
group:users:rwx
mask::rwx
other::---

Ziel erreicht, Zugriff für alle Mitglieder der Gruppe user freigegeben.

Taskwarrior Context, extended

Wie man Taskwarrior auf einem uberspace installiert, hatte ich ja schon geschrieben. Dort erwähnte ich schon, dass ich Taskwarrior nicht nur für die private Aufgabenverwaltung nutze, sondern auch dienstliche Tasks damit verwalte. Nun ist Taskwarrior allerdings so aufgebaut, dass alle Tasks einer Taskwarrior-Instanz in einer gemeinsamen Datensenke landen. In meinem Fall ist das der Taskserver, der auf dem uberspace läuft. Schaue ich nun zu Hause meine Taskliste an, sehe ich auch alle dienstlichen Tasks, im Büro auch alle privaten. Nicht sehr schön.

Um diesem Problem etwas entgegenzusteuern, hat das Taskwarrior-Team Contexts eingeführt. Dabei handelt es sich im Grunde genommen um einen permanenten Filter, der bei jedem Kommando angewendet wird. Ein Beispiel: Ich möchte einen Context mit dem Namen work, der nur Tasks anzeigt, die das Tag +work haben. Das Kommando task context define work +work erstellt ebendieses Context. In der Konfigurationsdatei wird ein solcher Context ganz einfach mit der Zeile context.work=+work hinterlegt. Um diesen Context nun zu nutzen, muss er noch per task context work aktiviert werden. Rufe ich nun task list auf, werden nur noch die Tasks aufgelistet, die mit dem Tag +work versehen sind.

Prinzipiell eine super Sache. Nach einiger Gewöhnungszeit stieß ich allerdings schnell an die Grenze, dass mir dieses Konzept etwas zu unflexibel ist. Wenn ich im Büro sitze und mal eben schnell etwas in meiner privaten Taskliste nachschauen möchte, muss ich den Context von work nach private wechseln, dann mein Kommando ausführen, um dann wieder von private zurück nach work zu wechseln. Das ist gelegentlich in Ordnung, macht man das aber häufiger, wird es schnell nervig.

Auf der Suche nach einer Lösung für dieses Komfortproblem wurde ich auf der Taskwarrior-Mailingliste in eine Richtung geschubst, die ich gar nicht auf dem Schirm hatte. Dirk Deimke schlug vor, diese Context Peeking mit Hilfe eines Shell-Scripts zu lösen. Nun bin ich mit meinen gut drei Jahren Linux-Erfahrung ja noch eher ein Linux-Kindergartenkind, daher bin ich selbst gar nicht auf diese Idee gekommen, aber wie das mit Kindergartenkindern so ist, fangen sie sofort an zu spielen, wenn man ihnen ein neues Spielzeug gibt. So habe ich es auch gemacht.

Das resultierende Shell-Script sieht nun so aus:

# Make task work with contexts like I want it to
task () {
  # get the task binary to avoid recurrence
  tb=`which task`
  # extract the selected context by matching the regex
  # context has to be the first argument and consist only
  # of alphanumeric characters
  context=`echo $1 | egrep -o "(=)[[:alnum:]]*"`
  # check whether there was a = character
  if [ -n "$context" ]
  then
    # remove the = char
    context=`echo $context | cut -c 2-`
    # check whether a context name was given
    if [ -n "$context" ]
    then
      # name given, temporarily set this context
      $tb rc.context:$context "${@:2}"
    else
      # no name given, temporarily set no context
      $tb rc.context:none "${@:2}"
    fi
  else
    # no = char, so just call task with all arguments
    $tb "${@}"
  fi
}

Was macht das Script nun? Zum einen habe ich die Möglichkeit, beim einem Aufruf von Taskwarrior einen bestimmten Context vorzugeben. Dazu nutze ich die Syntax =Context. Will ich also auf der Arbeit kurz in meine private Liste schauen, verwende ich den Aufruf task =private list.

Zusätzlich zur Wahl eines bestimmten Contexts kann ich allerdings auch das Context-Feature temporär ausschalten. Dazu verwende ich =ohne Contextnamen. Der Aufruf task = list zeigt mir somit alle Tasks, unabhängig ihres Contexts, an.

Bisher hat mir dieses simple Script schon viele gute Dienste geleistet. Und außerdem hat es mir wieder einen weiteren Teil der Linux-/Unix-Welt nähergebracht.

Zertifikate für den Taskserver erneuern

Wenn man den Taskserver an Hand der Anleitung auf taskwarrior.org installiert hat, haben die Zertifikate zur Absicherung des Datenverkehrs nur eine Haltbarkeit von einem Jahr. Stolpert man dann irgendwann über Meldungen wie

Handshake failed. Error in the certificate.

Sync failed. Could not connect to the Taskserver.

dann ist bestimmt das Zertifikat abgelaufen und muss somit erneuert werden. Die Haltbarkeit des verwendeten Zertifikats kann man sich mit Hilfe des Tools certtool anzeigen lassen:

Wenn man nun sieht, dass das Zertifikat abgelaufen ist, muss ein neues erstellt werden. Dazu geht man wie bei der Installation des Taskservers vor:

  1. Man wechselt in das Installationsverzeichnis des taskd, in meinem Fall ist das die lokale Kopie des git-Repositories, welche im Verzeichnis ~/taskd.git liegt. cd ~/taskd.git/pki
  2. Dort überprüft man die Informationen in der Datei vars.
  3. Wenn dort noch alles stimmt oder man die Daten an die eigenen Bedürfnisse angepasst hat, erstellt man per ./generate ein neues Serverzertifikat.
  4. Die so erstellen Zertifikate kopiert man via cp ca.*.pem server.*.pem $TASKDDATA in das Verzeichnis, in welchem der Taskserver seine Daten ablegt.
  5. Nun muss noch ein neues Clientzertifikat erstellt werden: ./generate <user-name>
  6. Die beiden zusätzlichen Dateine <user-name>.cert.pem und <user-name>.key.pem müssen nun noch auf allen Sync-Clients in die dortigen $TASKDATA-Verzeichnisse kopiert werden.

Nun sollte die Synchronisierung wieder anstandslos funktionieren.

Weitere Informationen gibt es auf der Taskwarrior-Webseite zum Thema Server und Client.

git vs mercurial

Ich habe schon einige Versionsverwaltungssysteme eingesetzt, aber mit keinem habe ich so viele Probleme wie mit git. Für mich sind die git Kommandos unintuitiv und damit sehr schwer zu behalten. Da ich aber ich verschiedenen Projekten auch mit git in Berührung komme und immer wieder nach den oft gleichen Kommandos suchen muss, will ich hier eine eigene Sammlung anfangen, damit ich immer finde, was ich suche. Diese wird nach und nach erweitert.

Mercurial Git
hg pull git fetch
hg pull -u git pull
hg update git checkout
hg crecord git add --patch && git commit

Taskwarrior auf uberspace

Für die Verwaltung von Todos und anderen Dingen, die nicht in Vergessenheit geraten sollen, nutze ich Taskwarrior. Angefangen habe ich damit auf meinem Laptop, aber schon recht schnell wollte ich auch einen Taskwarrior in der Hosentasche, sprich auf dem Smartphone haben. Und auf der Arbeit leistet er mir auch gute Dienste. Allerdings bietet Taskwarrior keine Cloud-Lösung, um Daten zu synchronisieren. Und selbst wenn es diese Möglichkeit gegeben hätte, stellt sich noch immer die Frage, ob man sie auch hätte nutzen wollen. Nun ist es glücklicherweise so, dass es mit dem Taskserver eine Möglichkeit gibt, die Synchronisierung selbst zu bauen. Im Folgenden will ich daher beschreiben, was nötig ist, um den Taskserver auf einem uberspace zu installieren und was darüber hinaus noch für die Synchronisation der Daten erforderlich ist.

Taskserver installieren

Es gibt eine sehr ausführliche Dokumentation auf der Taskserver-Seite, wie man den Server installiert. Ich gehe daher an dieser Stelle nicht im Detail auf alle Punkte ein, sondern beschreibe nur die für uberspace interessanten Schritte etwas genauer.

Ich installiere den Taskserver aus einem tarball-Archiv, wer möchte, kann sich aber auch gern das git-Repository clonen.

Zunächst laden wir uns also das Archiv mit dem Quelltext, entpacken und bauen es. Das ist relativ einfach, da uberspace alle benötigten Tools bereitstellt und daher nichts zusätzliches installiert werden muss. Einzige Besonderheit und Abweichung von der Taskwarrior-Doku ist, dass wir de Taskserver nicht in /usr/bin installieren wollen. Dieses Verzeichnis ist auf einem shared host tabu, stattdessen gibt es das Verzeichnis ~/bin. Das erzielen wir dadurch, dass wir cmake ein INSTALL_PREFIX übergeben, das auf unser Userhome ~ verweist.

Prinzipiell ist es egal, in welches Verzeichnis der Taskserver installiert wird, letztendlich sollte dieses Verzeichnis lediglich in der Umgebungsvariable PATH eingetragen sein, damit er von überall erreichbar ist.

$ curl -LO http://taskwarrior.org/download/taskd-latest.tar.gz
$ tar -xzf taskd-latest.tar.gz
$ cd taskd-1.1.0
$ cmake -DCMAKE_BUILD_TYPE=release -DCMAKE_INSTALL_PREFIX=~ .
. .
$ make
...
$ make install
...

Nun sollte der Taskserver im eigenen Binary-Verzeichnis ~/bin vorhanden sein.

Taskserver einrichten

Als nächstes muss der Taskserver konfiguriert werden. Damit wird zum einen sichergestellt, dass der Taskserver erreichbar ist, zum anderen, dass nur berechtigte Personen an die Daten des Taskservers kommen. Da es auch hierzu wieder eine sehr gute Dokumentation auf der Webseite des Taskservers gibt, spare ich mir zum einen die Arbeit, es hier noch einmal zu beschreiben, und vermeide damit aber auch das Risiko, dass diese Anleitung einmal veraltet sein sollte, weil sich etwas am Setup des Taskservers geändert hat.

Auch bei diesem Schritt muss man lediglich darauf achten, dass der vorgeschlagene Pfad für die Daten des Taskservers, nämlich /var/taskd, auf einem shared host nicht verfügbar ist. Hier bietet sich auch wieder die lokale Variante ~/var/taskd an.

Taskserver erreichbar machen

Während der Einrichtung des Taskservers wurde ein Port gewählt, über den der Taskserver erreichbar sein soll. Dieser Port ist allerdings nicht unbedingt frei, kann also gegebenenfalls bereits von einem anderen Ubernauten auf euren host benutzt werden. Daher gibt es ein Script, um einen Port anzufordern und diesen auch gleich in der Firewall freizuschalten.

$ uberspace-add-port -p tcp --firewall
🚀  All good! Opened tcp port 65432.

Dieser Port, der bei euch natürlich anders lauten kann, muss nun noch in der Konfigurationsdatei des Taskservers eingetragen werden:

$ taskd config server xxxx.uberspace.de:65432

Nun ist der Taskserver fertig eingerichtet und von außen erreichbar. Er kann nun via taskdctl start gestartet werden.

<img src="https://vg06.met.vgwort.de/na/4659e8be39234b6b90f5ab070487fcd6" width="1" height="1" alt="">

vim und die Spalte 80

Ich benutze seit einiger Zeit vim als Standardeditor, wenn ich mich auf *n*xoden Systemen bewege. Dazu habe ich über die Zeit doch einige nützliche Einstellungen angesammelt, die mein Leben mit dem Editor einfacher gestalten. Eine solche Einstellung ist die graphische Hervorhebung der Spalte 80. Auch wenn es im Jahre 2017 Displays mit 4k-Auflösung gibt, so gibt es doch immer wieder Anwendungsfälle, in denen der Platz im Terminal etwas begrenzt ist. Und sei es auch nur, dass man mehrere Terminals nebeneinander geöffnet hat. Als kleinster gemeinsamer Nenner für beengte Platzverhältnisse hat sich, historisch bedingt, eine Breite von 80 Zeichen bewährt. Aber es gibt auch andere Begrenzungen. Letztendlich muss es jeder Entwickler oder jedes Team für sich entscheiden, wie es Text strukturiert.

Unabhängig von der gewählten Zeilenlänge ist es aber hilfreich, wenn der Editor diese Breite visuell anzeigt, damit man nicht immer mit einem Auge auf die Cursorposition schielen muss. vim bietet dazu die Möglichkeit, eine Spalte mit einem andersfarbigen Hintergrund zu versehen:

let &colorcolumn="80,120"
highlight ColorColumn ctermbg=235 guibg=#2c2d27

Hier habe ich die Spalten 80 und 120 mit der Farbe 235, einem dunklen Grau, eingefärbt. Somit sieht man nun auf Anhieb, wann man eine Grenze erreicht oder überschreitet und kann somit zeitig die Zeile umbrechen. Sollte einem das Grau nicht zusagen, kann man natürlich auch eine beliebige andere Farbe wählen.

Subdomain für den Blog

Der Blog, den du gerade liest, liegt in meinem uberspace in einem Verzeichnis unterhalb von html, nämlich html/blog. Allerdings ist er über den URL blog.pvitt.de erreichbar. Damit die Anfragen an diese Adresse auch dort ankommen, wo der Blog tatsächlich liegt, ist ein bisschen Konfigurationsarbeit nötig.

Zuerst musste ich die Subdomain dem uberspace hinzufügen. Das hatte ich ja schon mit der eigentlichen Domain gemacht, daher sollte das kein Neuland sein. Dazu ruft man uberspace-add-domain -d blog.pvitt.de -w auf. Nun ist die Domain in der uberspace-Konfiguration registriert. Außerdem fallen aus dem Script wieder die Angaben für die Namensauflösung heraus. Diese habe ich daher im Anschluss auf der Webseite des Registrars, der die verwendete Domain betreut, eingetragen. Nach einiger Zeit sollte sich der Eintrag herumgesprochen haben, sodass man nun zumindest eine Fehlermeldung des eigenen Apaches bekommen sollte. Denn dieser weiß noch nichts mit der Anfrage anzufangen. Das gilt es daher nun zu ändern.

Damit der Webserver weiß, was er auf die Anfrage nach blog.pvitt.de antworten soll, müssen wir ihm dies in der Datei .htaccess mitteilen:

RewriteBase /
RewriteCond %{HTTP_HOST} ^blog\.pvitt\.de$ [NC]
RewriteCond %{REQUEST_URI} !^/blog(/|$) [NC]
RewriteRule ^(.*)$ blog/$1 [L]

Diese Zeilen bewirken, dass Anfragen nach blog.pvitt.de auf das Verzeichnis pvitt.de/blog umgeleitet werden, dies aber für den Benutzer nicht sichtbar ist. Dieser sieht in seiner Adressleiste weiterhin blog.pvitt.de. So soll es sein.

Bereits gestern habe ich ein SSL-Zertifikat für alle vorhandenen Domains erstellt. Dieses Zertifikat umfasst nun allerdings die neue Subdomain noch nicht. Daher muss ich auch noch ein neues SSL-Zertifikat erstellen. Dazu verschiebe ich zuerst meine alte Konfiguration:

mv /home/pvitt/.config/letsencrypt/cli.ini /home/pvitt/.config/letsencrypt/cli.ini.old

...um dann eine neue zu erstellen:

uberspace-letsencrypt

Nun erneut Let's Encrypt aufrufen:

letsencrypt certonly

...und das neue Zertifikat mit der Subdomain sollte erstellt werden. Dieses nun noch importieren:

uberspace-add-certificate -k ~/.config/letsencrypt/live/pvitt.de/privkey.pem -c ~/.config/letsencrypt/live/pvitt.de/cert.pem

...und die neue Subdomain ist einsatzbereit. Nun sollte man allerdings noch etwas aufräumen, denn das alte Zertifikat, welches die Subdomain nicht beinhaltete, ist ja auch noch da. Daher lassen wir uns erst die Liste der vorhandenen Zertifikate anzeigen, suchen dort den Namen des zu löschenden Zertifikats und entfernen dieses:

uberspace-list-certificates
..
uberspace-del-certificate -c pvitt.de

<img src="https://vg06.met.vgwort.de/na/80e102a5830b48e9a9c631635131aef4" width="1" height="1" alt="">

Einrichtung der Domains

Gestern habe ich die statischen Generator eingerichtet, heute stand dann die Einrichtung der Domain an. Ich hatte die Domain bereits vor einigen Tagen beim Registrar beantragt, und nach Zahlung und Registrierung stand sie mir dann heute zur Verfügung.

Im ersten Schritt habe ich sie dann entsprechend der uberspace-Dokumentation zu meinem uberspace hinzugefügt und anschließend den Nameserver mit den IPs gefüttert. Dann musste ich warten, bis meine Änderungen im DNS wirksam wurden, denn erst dann klappt die Namensauflösung.

Nachdem die Namensauflösung funktionierte, habe ich dann ein SSL-Zertifikat installiert. Schließlich muss ja nicht jeder wissen, wer sich was auf meiner Webseite anschaut. Dazu habe ich mich an die uberspace-Dokumentation zu Let's Encrypt gehalten.

Und damit die Leute nicht immer https:// vor die Adressen schreiben müssen, kann man sie auf die richtige Seite umleiten, sollten sie mal die falsche ansteuern. Auch dazu gibt es eine uberspace-Doku

Ich bin wirklich begeistert, wie einfach es mit der vorhandenen Dokumentation und den Scripten ist, den uberspace zu verwalten. Ich hätte das sicherlich auch alles allein hinbekommen, aber als jemand, der sich nicht täglich mit Webservern, SSL-Zertifikaten und dem ganzen Kram auseinandersetzt, hätte es einige Stunden Studium der einschlägigen Dokumentationen bedeutet. So habe ich mir das Wissen zwar nicht selbst angeeignet, wahrscheinlich hätte ich es aber auch relativ schnell wieder vergessen. Und ein wirklich nicht zu unterschätzender Vorteil ist, dass die Scripte und die Doku von Leuten geschrieben wurden, die wissen, was sie tun. Auch nach dem intensivsten Selbststudium ist man noch immer nur ein Laie ohne Erfahrung und kann viele Dinge nicht einschätzen. Die Erfahrung, die die Jungs von uberspace in die unscheinbaren Scripte haben einfließen lassen, ist daher Gold wert.

Mein Umzug - Neues Heim renovieren

Ich bin seit einiger Zeit stolzer Besitzer eines Uberspace. Anfänglich aus reiner Neugier, um mal zu sehen, was man damit wohl so anfangen kann. Wie so oft kam dann der Hunger mit dem Essen.

Wie alles begann

Den ersten Dienst, den ich auf dem Uberspace habe laufen lassen, ist Taskwarrior. Ich denke, ich werde irgendwann auch mal darüber schreiben, daher will ich es hier auch einfach bei der Nennung belassen. Danach kam irgendwann ein TinyTinyRss-Server, da ich es leid war, dass ich meine Feeds nicht auf verschiedenen Geräten lesen konnte, ohne dass ich die Nachrichten alle doppelt und dreifach vorgesetzt bekomme. Vor wenigen Tagen dann habe ich mir dann ein neues Konzept für meine verschiedenen Blogs überlegt. Irgendwie hatte ich das Gefühl, dass ich mehr mit Wordpress, dessen Updates und dem Kommentarspam beschäftigt war, als dass ich sinnvoll Zeit darein investieren konnte, etwas zu tun und anschließend darüber zu schreiben. Ich weiß nicht genau, wie ich dann auf statische Generatoren aufmerksam wurde, aber irgendwann fand ich mich vor der langen Liste von staticgen.com wieder, um mir mehr oder weniger alle dort verzeichneten Generatoren anzuschauen. Hängen geblieben bin ich nun bei Nikola, einem in Python geschriebenen Generator mit aktiver Community.

Und hier ist er nun, der erste mit Nikola erstellte Blogeintrag. In den nächsten Tagen werde ich sicherlich immer mal wieder etwas über die Einrichtung von Nikola, über die Migration meiner bisherigen Blogs in das neue System und auch über die anderen Dienste, die auf meinen uberspace laufen, schreiben.