Munki und AutoPKG

Um meine Software zu verteilen nutze ich Munki. Damit die enthaltenen Pakete auch immer aktuell sind und ich nicht jede einzelne Herstellerseite absurfen muss, kommt AutoPKG zum Einsatz. Diese Software lädt die Pakete von diversen Websites runter, fügt noch ggf. Installscripte hinzu und kopiert sie in das Munki-Repo. Nun muss ich also nur regelmäßig ein Script starten und das tut den Rest. Eine Installationsanleitung ist bei Github zu finden.

Für jede Software gibt es Recipes, also Rezepte (u.a. für den Download). Um diese den eigenen Bedürfnissen anzupassen, kann man Overrides erstellen.

$ autopkg search QuickLookCSV

Name                             Repo             Path                                    
----                             ----             ----                                    
QuickLookCSV.pkg.recipe          jps3-recipes     QuickLookCSV/QuickLookCSV.pkg.recipe    
QuickLookCSV.download.recipe     jps3-recipes     QuickLookCSV/QuickLookCSV.download.recipe
QuickLookCSV.munki.recipe        jps3-recipes     QuickLookCSV/QuickLookCSV.munki.recipe  

To add a new recipe repo, use 'autopkg repo-add <repo name>'

$ autopkg repo-add jps3-recipes
Attempting git clone...

Adding /Users/admin/Library/AutoPkg/RecipeRepos/com.github.autopkg.jps3-recipes to RECIPE_SEARCH_DIRS...
Updated search path:
  '.'
  '~/Library/AutoPkg/Recipes'
  '/Library/AutoPkg/Recipes'
[...]

$ autopkg make-override QuickLookCSV.munki.recipe
Override file saved to /Users/admin/Library/AutoPkg/RecipeOverrides/QuickLookCSV.munki.recipe

Um nun alle Recipes auszuführen, führe ich folgenden Befehl aus:

$ autopkg run /Users/admin/Library/AutoPkg/RecipeOverrides/*.recipe MakeCatalogs.munki

Wenn ich nun die AutoPKG-Installation zu einem neuen Rechner migieren möchte, kopieren ich nur die RecipeOverrides auf den neuen Rechner und führe danach folgendes Script aus:

#!/bin/sh
autopkg repo-add "recipes"
for recipe in ~/Library/AutoPkg/RecipeOverrides/*
do
    repo=$(cat "${recipe}" | grep ParentRecipe -A 1 | tail -n 1 | tr -d "[:blank:]" | sed "s/<string>(.*)</string>/1/" | sed "s/.*.github.(.*)..*..*/1/")
    repoarray+=("${repo}")
done

IFS=$'n' repoarray=($(sort <<<"${repoarray[*]}"))
IFS=$'n' repoarray=($(uniq <<<"${repoarray[*]}"))

for repo in "${repoarray[@]}"
do
    echo "${repo}"
    autopkg repo-add "${repo}-recipes"
done

Das Script liest aus jeder Override-Datei das Parent-Recipe und dessen Repository aus und fügt es per autopkg repo-add xxx hinzu. So wird auch automatisch ein Update des bisherigen Repos durchgeführt.

Munki mit Git

Ich setze für meine Softwareverteilung auf Macs Munki ein. Das ist eine Software, die serverseitig nur einen Webserver und ein paar XML-Dateien benötigt. Der Client fragt dann regelmäßig am Server an und erhält so Updates. Die Funktion und Einrichtung von Munki ist aber im offiziellen Wiki viel besser dokumentiert.

In diesem Beitrag soll es um die Versionierung des Munki-Repositories mit Git und anschließender Veröffentlichung auf einem Server gehen.

Ich habe einen Webserver lokal auf meinem iMac laufen. Hier werden neue Pakete in Munki importiert, Software getestet und die ganze Verteilung geprüft. Ein weiterer Webserver läuft im Internet, der das gleiche Munki-Repo anbietet, sodass alle meine (und befreundete) Macs den Update-Server erreichen und Software installieren können.

Ich gehe davon aus, dass deine Munki-Installation funktioniert und so oder so ähnlich wie im Demonstration Setup konfiguriert ist.

Munki-Repository mit Git versionieren

Um nun das Repo zu versionieren, muss zuerst ein Git-Repository erstellt werden. Dazu wechselt du im Terminal in dein Munki-Repo und gibst folgenden Befehl ein:

$ git init

Danach müssen noch sämtliche Dateien eingecheckt werden, die versioniert werden sollen. Da das mit Binärdaten aber eher nicht so toll funktioniert, ignoriere ich den Ordner pkgs per .gitignore im Hauptverzeichnis meines Git-Repos.

$ cat .gitignore
/pkgs/
.DS_Store
$ git add .
$ git commit -m "First commit"

So sind alle Dateien – außer die Installer-Dateien –  eingecheckt und somit versioniert. Wenn ich nun ein Softwarepaket verändere (im Beispiel den Katalog von testing auf production ändere), dann kann ich dies also in Zukunft nachvollziehen und im Zweifel rückgängig machen.

Bildschirmfoto 2015-09-04 um 14.32.01

Remote-Repository einrichten

Nun möchte ich dieses lokal konfigurierte und getestete Repository auf meinem Server im Internet bereitstellen. Dies ist relativ einfach mittels Remote-Repository zu erreichen.

Hierzu muss auf dem Webserver ein Git-Server laufen und ein Headles-Repository eingerichtet sein. Wie ein Git-Server installiert und eingerichtet wird, erfährst du an anderer Stelle.

$ mkdir munki-test.git
$ cd munki-test.git
$ git --bare init

Danach wird das Remote-Repository dem lokalen Git-Repository hinzugefügt.

Bildschirmfoto 2015-09-04 um 14.48.07

Und nun kann das lokale Branch an den Remote-Server gepusht werden.

Bildschirmfoto 2015-09-04 um 23.48.34

Die Eigenheit von einem Bare-Repository ist, dass es nur die Git-Metadaten vorhält und nicht einen Branch auscheckt. Somit liegt das Munki-Repository nicht im direkten Zugriff auf dem Server. Das Git-Repo muss nach dem Push noch in Richtung Webserver ausgecheckt werden.

git --work-tree=/var/www/munki_repo --git-dir=/home/git/munki-test.git checkout -f

Da dieser Befehl nach jedem Push (also Upload zum Server) passieren muss, kann man es über die sog. Git Hooks lösen. In dem Git-Ordner auf dem Server sollte eigentlich schon ein Unterordner namens hooks mit ein paar Beispiel-Dateien liegen. Hier wird eine neue Datei namens post-receive angelegt, die in etwa so aussehen kann:

#!/bin/sh
git --work-tree=/var/www/munki_repo --git-dir=/home/git/munki-test.git checkout -f

Eingangs hatte ich geschrieben, dass ich die Binaries nicht mittracke. Wenn ich das nicht tue, werden sie natürlich auch nicht mit hochgeladen und auf dem Webserver bereitgestellt. Dies mache ich separat mit einem rsync. Und damit es auch automatisch läuft, nutze ich in meinem lokalen Repository den pre-push-hook.

$ cat pre-push
#!/bin/sh

remote="$1"
url="$2"

z40=0000000000000000000000000000000000000000

IFS=' '
while read local_ref local_sha remote_ref remote_sha
do
    if [ "$local_sha" = $z40 ]
    then
        # Handle delete
        :
    else
        if [ "$remote_sha" = $z40 ]
        then
            # New branch, examine all commits
            range="$local_sha"
        else
            # Update to existing branch, examine new commits
            range="$remote_sha..$local_sha"
        fi

        ### do the rsync
        rsync -hrLvzp --size-only --ignore-errors --stats --timeout=60 --delete-after --progress --exclude-from="/Users/admin/munki/syncfolders.exclude" /Users/admin/munki/munki_repo/pkgs/ username@server:/var/www/munki_repo/pkgs
        if [ $? != 0 ]; then
            echo "rsync error"
            exit 1
        fi
        ssh username@server "chown -R www-data:www-data /var/www/munki_repo/pkgs"

        # Check for WIP commit
        commit=`git rev-list -n 1 --grep '^WIP' "$range"`
        if [ -n "$commit" ]
        then
            echo "Found WIP commit in $local_ref, not pushing"
            exit 1
        fi
    fi
done

exit 0

Nun wird also der Ordner pkgs per rsync zum Server synchronisiert, das Git-Repo zum Server gepusht und serverseitig das Git-Repo in den www-Ordner ausgecheckt.

Dieses ganze Szenario habe ich bisher nur in eine Richtung getestet. Also von meinem Client zum Server. Git ist ja für die verteilte Versionskontrolle bekannt. Besonders das rsync-Script ist aktuell nicht darauf ausgelegt, mehrere Quellen (also 2-3 Rechner von Munki-Admins, die Updates bereitstellen) zu bedienen.

WordPress Multisite

Die letzten Tage habe ich meine und befreundete Blogs in eine neue WordPress Multisite-Installation migriert. Dies hat die Vorteile, dass ich nun nur noch eine zentrale Blog-Installation mit entspr. Plugins pflegen muss. Auch das Bereitstellen eines neues Blogs ist nun in 1-3 Klicks erledigt. Das finde ich extrem entspannt 🙂

Alle Blogs sind nun unter beispiel.tmp-wordpress.kruemmel.it zu erreichen. Das Zuweisen von eigenen Domains habe ich mit dem Plugin WordPress MU Domain Mapping gelöst. Nun muss der jeweilige Blogbetreiber nur seine Domain im Webinterface eintragen und bei seinem Domain-Anbieter einen DNS-Eintrag ändern.

[appbox wordpress wordpress-mu-domain-mapping]

Photo by Phil Oakley

Gesammelte Links #3

Es nimmt kein Ende. Hier weitere Links. Ich kann mich einfach nicht trennen 😉

Gesammelte Links #2

Und hier weitere Links, die ich noch nicht wegschmeißen kann 😉

Gesammelte Links #1

Ich schmeiße hier mal ein paar gesammelte Links ab, die ich gerade beim aufräumen finde. Völlig zu­sam­men­hangs­los…

Adobe Lightroom – ein Katalog auf 2 Rechnern

Wenn ich Fragen im Netz lese/höre, wie man Lightroom auf mehreren Rechnern nutzt, läuft es meist auf folgende Empfehlung raus:

  • öffne Lightroom
  • wähle einen Ordner oder eine (smarte) Sammlung aus
  • klicke auf Datei – Als Katalog exportieren…
  • speichere den neuen Katalog mittels Export-Dialog auf eine externe Festplatte (oder ein anderen portables/zentrales Medium)

Ich finde dies etwas unglücklich. So hat man nur einen Teil seiner Bilder bei sich. Und wie der Re-Import in den Hauptkatalog aussieht, will ich gar nicht wissen.

Ich mache es mir da etwas einfacher. Ich nutze nur einen Katalog, der automatisch auf mein Notebook synchronisert. Ich importiere meine Bilder nach einem Shooting in Lightroom und lasse sie automatisch in Ordner nach Jahren, Monaten und Tagen importieren. Parallel dazu liegt ein Ordner namens „Lightroom“, der nur meinen Katalog (und dessen Backups) enthält. Ein weiterer Ordner heißt „MBA“ – dazu später mehr. Zusätzlich habe ich für die Bilder der letzten 1-3 Jahre Smart Previews erstellt, die sich dann ebenfalls im Katalog befinden.

Bildschirmfoto 2015-02-27 um 21.42.57Diesen Katalog-Order „Lightroom“ und den Ordner „MBA“ synchronisiere ich nun mit Bittorrent Sync zu meinem Notebook.

So habe ich alle (aktuellen) Bilder immer dabei und kann dank „Smart Previews“ die Bilder in vollem Umfang bearbeiten, korrigieren, zuschneiden und taggen.

Der Weg zurück

Wenn ich nun Bilder eines Shootings schon mobil importiere, mache ich das in den Ordner „MBA“. Auch hier drunter werden die Bilder von Lightroom automatisch in Ordner nach Datum sortiert. Jetzt kann ich natürlich den vollen Lightroom-Funktionsumfang nutzen. Vorteil: Beim taggen der Bilder steht mir die komplette History meiner Stichwörter zur Verfügung (da es ja nur ein Katalog ist).

Wenn ich nun wieder zu Hause bin, öffne ich nur mein Notebook, starte parallel meinen iMac und lasse Bittorrent Sync den Rest machen. Die beiden Ordner „Lightroom“ (mit dem Katalog) und der Ordner „MBA“ (mit den neuen Bildern) landen an passender Stelle auf meinem Hauptrechner.

Da die Ordnerstruktur auf meinem Rechnern die gleiche ist, stimmen natürlich sämtliche Dateipfade und alle Bilder sind in Lightroom zugreifbar.

Weil Ordnung so toll ist – und natürlich auch um wieder Platz auf dem Notebook zu schaffen – verschiebe ich in Lightroom die Bilder aus dem Ordner „MBA“ in meinen Haupt-Bilderordner. Sofort unterstützt mich Bittrorrent Sync wieder und synchronisiert den nun leeren MBA-Ordner wieder zum Notebook.

Warum nur der Katalog?

Warum synchronisiere ich nur den Katalog und nicht meinen gesamten Bilderordner inklusive aller Rohdaten? Ganz einfach: Zu wenig Platz.

Auf dem MacBook Air habe ich nicht so viel Platz zur Verfügung, um alle Bilder parat zu haben. Aber das ist ja dank Smart Previews auch gar nicht notwendig.

Mein Lightroom-Katalog selbst hat aktuell ca. 8GB, die Rohdaten (JPEGs oder RAWs bzw. DNGs) schlagen mit knapp 70GB zu buche.

Android-Feldtest hiermit für beendet erklärt

Mein Umstieg auf Zeit auf das Betriebssystem Android habe ich am 17. Mai angekündigt. Geplant war dieser Feldtest für knapp 4 Wochen. Nun – nach ziemlich genau 3 Wochen – ziehe ich ein Fazit.

Manche Dinge finde ich toll, wie z.B. die optionale Tastatur von SwiftKey und die Widgets im Lockscreen oder Homescreen. Allerdings habe ich die Widgets nicht genutzt. Bin dafür wohl nicht empfänglich. Die Tastatur werde ich vermissen… Aber wohl auch nur bis Herbst, da diese Funktion nun auch in Apple iOS 8 Einzug erhält.

Wie ich in dem Artikel zu Google Chrome, Pocket, Wunderlist, etc schon festgestellt habe, funktionieren die Apps der großen Anbieter nahezu identisch. Also weder pro noch contra.

Nun zu den negativen Erfahrungen. Die meisten Apps sind einfach hässlich, nicht intuitiv genug zu bedienen, haben einen eingeschränkten Funktionsumfang oder sind einfach gar nicht vorhanden. Ich will damit nicht sagen, dass ich die Arbeit der Programmierer besser machen könnte, aber aktuell steckt die Entwicklung immer noch in den Kinderschuhen. Und das ist mir nach knapp 5 1/2 Jahren Bestand am Markt ein Rätsel.

Warum stürzt mir die Kamera-App ab und ich muss das Smartphone neu starten? Ich will JETZT ein Foto machen und nicht in 3 Minuten. Dies ist mir 3 Mal passiert.

Warum stürzt das Smartphone ab, wenn ich mich morgens wecken lassen will. Ich habe tatsächlich 2 Mal den Alarm nicht aus bekommen und musste das Gerät hart ausschalten.

Unter’m Strich hat mich Android 4 nicht überzeugt. Ich bin nun also seit Freitag wieder iOS-Benutzer und glücklich damit. Leider muss ich noch bis Herbst warten, um echt großartige Features zu bekommen, die mir jetzt noch fehlen…

Artikel aus der Serie Android-Feldtest.

Android-Feldtest: Podcatcher

Ich höre sehr gerne und sehr viele Podcasts. Bisher kam bei mir Instacast und aktuell Pocket Casts auf dem iPhone zum Einsatz.

Aktuell teste ich AntennaPod. Leider ist hier die Playlist-Verwaltung rudimentär bzw. gar nicht vorhanden. Besonders hübsch ist es leider auch nicht. Pocket Casts ist auch für Android vorhanden. Wahrscheinlich werde ich es mir kaufen, da ich auf iOS damit zufrieden war.

Ich bin aber für jeden Vorschlag offen 🙂

Ein Vergleich (leider nicht mehr top-aktuell) ist auf einem Google Spreadsheet zu sehen. http://tinyurl.com/podcastclients

Artikel aus der Serie Android-Feldtest.