Setup 2017

Ungeachtet der verbreiteten paranoid fear vor dem langsamen Verfall der macOS-Plattform beginne ich 2017 mit einem neuen Mac, und anders als in der Vergangenheit gehe ich bei der Einrichtung etwas systematischer vor. Statt sämtliche Daten zu transferieren und mich anschließend um die Betriebsumgebung zu kümmern, installiere ich zunächst alle potentiell schwierigen Komponenten und überführe die empfindsamen Daten erst zum Schluss.

Prerequisites

Mit Hilfe des neu angelegten Admin-Accounts werden XCode einschließlich der Command Line Tools (xcode-select --install) und die GNU Core utilities installiert:

tar -xzvf coreutils-8.26.tar.xz cd coreutils-8.26 ./configure --prefix=/usr/local; make; sudo make install

Außerdem benötige ich natürlich einen aktuellen Texteditor mit Clipboard-Unterstützung und eine Escape-Taste:

tar -xzvf vim-8.0.tar.bz2 cd vim-8.0 ./configure --prefix=/usr/local --with-features=huge; make; sudo make install sudo ln -s /usr/local/vim /usr/local/vi echo 'set clipboard=unnammed' > ~/.vimrc

Außerdem sorge ich für einen gesprächigeren Systemstart (sudo nvram boot-args="-v"). Damit ist eine konstruktive Arbeitsatmosphäre geschaffen.

Webstack

Mein kürzlich modernisierter Webstack hat mich schon einige Nerven gekostet. Um einige Frustrationsquellen auszuschließen, installiere ich Python 3.6 und MySQL 5.7.17 über ein macOS-Installationspaket, nur für PostgreSQL gilt wie üblich:

tar -xzvf postgresql-9.6.1.tar.xz cd postgresql-9.6.1 ./configure --prefix=/usr/local; make; sudo make install

Die Vermeidung der MySQL-Idiosynkrasien (cmake!) führt natürlich zu einem unpassenden Speicherort, so dass:

echo 'export PATH=/usr/local/mysql/bin:$PATH' > ~/.bash_profile

Ohne diese Zeile funktioniert nämlich die Installation des Datenbankkonnektors

tar xfz MySQL-python-1.2.5.tar.gz cd MySQL-python-1.2.5 python setup.py build sudo python setup.py install

– nicht. Der andere Datenbankkonnektor muss für beide Python-Versionen (3.6 und 2.7) installiert werden, weil erst eines der drei Django-Projekte auf Python 3 umgestellt wurde:

tar -xzvf psycopg2-2.6.2.tar.gz cd psycopg2-2.6.2 python setup.py build # python3 setup.py build sudo python setup.py install # sudo python3 setup.py build

Dasselbe gilt für Django selbst:

tar -xzvf Django-1.10.5.tar.gz cd Django-1.10.5 sudo python setup.py install # sudo python3 setup.py install

nginx verlangt weiterhin eine frische PCRE-Bibliothek, bevor es sich kompilieren lässt:

tar -xzvf pcre-8.3.9.tar-gz tar -xzvf nginx-1.11.8.tar.gz cd nginx-1.11.8 ./configure --prefix=/usr/local --with-http_gzip_static_module --with-pcre=../pcre-8.39

uwsgi und cssmin lassen sich dagegen sehr komfortabel über das mit Python 3.6 gelieferte pip installieren:

pip3 install uwsgi pip3 install cssmin

Außerordentlich schwierig ist dagegen die Kompilation von mod_wsgi. Graham Dumpleton selbst ist äußerst frustriert und formuliert diese Frustration auch im PyPI-Eintrag für mod_wsgi:

On some platforms, this latter method is actually the only option supported when using the operating system supplied Apache installation. For example, in MacOS X Sierra, Apple has completely broken the ability to install third party Apache modules using the apxs tool normally used for this task. History suggests that Apple will never fix the problem as they have broken things in the past in other ways and workarounds were required as they never fixed those problems either. This time there is no easy workaround as they no longer supply certain tools which are required to perform the installation.

Glücklicherweise macht die Python-basierte Installation –

tar -xzvf mod_wsgi-4.5.13.tar.gz cd mod_wsgi-4.5.13 sudo python setup.py install # no pip for Python 2.7

– keinerlei Schwierigkeiten. Lediglich httpd.conf muss an den exotischen Speicherort für Python-Pakete angepasst werden:

LoadModule wsgi_module /Library/Python/2.7/site-packages/mod_wsgi-4.5.13-py2.7-macosx-10.12-intel.egg/mod_wsgi/server/mod_wsgi-py27.so

Und schon stellt sich das belebende Gefühl von individuell praktizierter Pressefreiheit und die wohlige Illusion absoluter Kontrolle ein.

Mailstack

Der bewährte und mittlerweile recht komplexe Mailstack erweist sich als ziemlich pflegeleicht (obwohl er natürlich zur maximalen Verengung des personal focus einlädt). Sämtliche GnuPG-Komponenten lassen sich anstandslos installieren:

tar -xzvf libgpg-error-1.26.tar.bz2 cd libgpg-error-1.26 ./configure --prefix=/usr/local; make; sudo make install cd .. tar -xzvf libksba-1.3.5.tar.bz2 cd libksba-1.3.5 ./configure --prefix=/usr/local; make; sudo make install cd .. tar -xzvf libassuan-2.4.3.tar.bz2 cd libassuan-2.4.3 ./configure --prefix=/usr/local; make; sudo make install cd .. tar -xzvf libgcrypt-1.7.5.tar.bz2 cd libgcrypt-1.7.5 ./configure --prefix=/usr/local; make; sudo make install cd .. tar -xzvf pinentry-1.0.0.tar.bz2 cd pinentry-1.0.0 ./configure --prefix=/usr/local; make; sudo make install cd .. tar -xzvf npth-1.3.tar.bz2 cd npth-1.3 ./configure --prefix=/usr/local; make; sudo make install cd .. tar -xzvf gnupg-2.1.17.tar.bz2 cd gnupg-2.1.17 ./configure --prefix=/usr/local; make; sudo make install cd .. tar -xzvf gpgme-1.8.0.tar.bz2 cd gpgme-1.8.0 ./configure --prefix=/usr/local; make; sudo make install

Lediglich gpgme meldet einen Fehler, den ich aber geflissentlich (und folgenlos) ignoriere.

mutt erwartet eine Datenbankmanagementbibliothek für den Header-Cache und beschwert sich bitterlich über die indecent version von OpenSSL unter macOS Sierra (sowie über eine veraltete SASL-Implementierung), deshalb bekommt es die gdbm und ein hochaktuelles OpenSSL:

tar -xzvf gdbm-1.12.tar.gz cd gdbm-1.12 ./configure --prefix=/usr/local; make; sudo make install cd .. tar -xzvf openssl-1.1.0c.tar.gz cd openssl-1.1.0c ./configure --prefix=/usr/local; make; sudo make install cd .. tar -xzvf mutt-1.7.2.tar.gz cd mutt-1.7.2 ./configure --enable-imap --enable-smtp --with-curses --with-regex --enable-hcache --with-sasl=/usr --with-ssl=/usr/local --prefix=/usr/local --enable-gpgme; make; sudo make install

Nachträglich realisiere ich, dass mutt dank OfflineIMAP und msmtp nicht mehr mit der Außenwelt kommunizieren muss und sich daher auch nicht um Sicherheitslücken kümmern sollte (anders ausgedrückt: ./configure --with-curses --with-regex --enable-hcache --prefix=/usr/local --enable-gpgme dürfte künftig genügen).

Während OfflineIMAP sich unauffällig verhält, wünscht msmtp aus unerfindlichen Gründen ein aktuelles pkg-config, das seinerseits mit einem zusätzlichen Flag konfiguriert werden muss:

tar -xzvf offlineimap-7.0.12.tar.gz cd offlineimap-7.0.12 make clean; make; sudo python setup.py install cd .. tar -xzvf pkg-config-0.29.1.tar.gz cd pkg-config-0.29.1 ./configure --prefix=/usr/local --with-internal-glib; make; sudo make install cd .. tar -xzvf msmtp-1.6.6.tar.xz cd msmtp-1.6.6 ./configure --prefix=/usr/local --with-ssl=openssl; make; sudo make install

Tim Grays Adressbuchkonnektor für mutt und dessen Helferlein melden ebenfalls keine Probleme:

tar -xzvf tgray-muttqt-0.1.0-5-gde3985f.tar.gz cd tgray-muttqt-0.1.0-5-gde3985f make; sudo make install cd .. unzip contacts-master.zip cd contacts-master make; sudo make install

Zwar warnt Apple bei jedem Aufruf von contacts energisch vor einer fehlerhaften Implementierung –

CoreData: warning: dynamic accessors failed to find @property implementation for 'uniqueId' for entity ABCDInfo while resolving selector 'uniqueId' on class 'ABCDInfo'. Did you remember to declare it @dynamic or @synthesized in the @implementation ?

– aber die Anbindung zwischen Adressbuch und mutt wird dadurch nicht beeinträchtigt (stattdessen funktioniert der Transfer des Adressbuchinhaltes mittels Archiv-Datei nicht, und erst ein Umweg über das VCard-Format hilft).

Applications

Die Installation der Mac-Anwendungen –

– ist fast so schnell gemacht wie der Download der Apps aus dem App Store (Reeder, PCalc, Deckset, Pixelmator, HTTP Client), und auch MacTex bietet keine Überraschungen (wenn man nach der Installation den rituellen Abstieg ins Terminal mit sudo texhash; updmap --enable MixedMap pad.map vornimmt). Microsoft Office 2016 verweigert dagegen seinen Dienst, was mit Sicherheit nicht an meinen Proxy-Einstellungen liegt. Seltsamerweise bietet der versteckte Updater (/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate) nur ein Update für Word an, so dass ich die bereits aktualisierten Excel- und Powerpoint-Versionen manuell von der alten Festplatte (/Applications) kopieren muss.

Daten

Nun fehlen nur noch die Daten. Nach einem frischen Klon der alten Festplatte mit SuperDuper kopiere ich zunächst die relevanten Ordner (Documents, Music etc) und anschließend manuell die Konfigurationsdateien aus ~/ bzw. ~/Library.

Anschließend starte ich den Dropbox-Client und aktiviere die Vault-Synchronisation via Dropbox, und erkläre Launchbar und Typinator zu login items.

Ein kurzer Moment der Spannung – Mails lassen sich schreiben, signieren/verschlüsseln und versenden. Auch OfflineIMAP läuft, nachdem ich den entsprechenden LaunchAgent aktiviert habe (launchctl start net.janeden.offlineimap).

Anlässlich der Aktivierung der iCloud Photo Library weist Apple mich darauf hin, dass 200 GB iCloud-Speicherplatz niemals für die Ablage aller Bilder ausreichen (die Bibliothek umfasst allerdings nur ca. 150 GB), und erzwingt ein Upgrade auf 1 TB Speicherplatz. Der reichlich vorhandene Platz ändert nichts daran, dass die Photos-Anwendung weiterhin über irgendein Bild stolpert und den Upload kommentarlos einstellt. Immerhin erscheinen meine Termine nach dem Login bei Google in der Calendar-Anwendung.

Um diese ernüchternde Erfahrung auszugleichen, konzentriere ich mich auf die Inbetriebnahme des Webstacks. Zunächst wird /etc/hosts um die Namen der lokalen Websites ergänzt, anschließend initialisiere ich PostgreSQL und befülle die Datenbanken:

# PostgreSQL sudo mkdir /usr/local/data/postgres sudo chown _postgres:wheel /usr/local/data/postgres sudo -u _postgres /usr/local/bin/initdb -D /usr/local/data/postgres sudo -u _postgres /usr/local/bin/postgres -D /usr/local/data/postgres/ # _postgres needs a password psql -U _postgres postgres postgres=# ALTER USER _postgres WITH PASSWORD '...'; ALTER ROLE postgres=# CREATE USER myuser WITH PASSWORD '...'; CREATE ROLE postgres=# CREATE DATABASE db1; CREATE DATABASE postgres=# CREATE DATABASE db2; CREATE DATABASE postgres=# CREATE DATABASE db3; CREATE DATABASE postgres=# GRANT ALL ON DATABASE db1 TO myuser; GRANT postgres=# GRANT ALL ON DATABASE db2 TO myuser; GRANT postgres=# GRANT ALL ON DATABASE db3 TO myuser; GRANT postgres=# \q psql db1 < ~/Sites/site1/dbdump/db1.sql psql db2 < ~/Sites/site1/dbdump/db2.sql psql db3 < ~/Sites/site1/dbdump/db3.sql # MySQL mysql -u root -p # .my.cnf should be copie to ~/ AFTER this step GRANT ALL ON db2.* TO myuser@localhost IDENTIFIED BY 'new_password'; exit mysql -u myuser -p CREATE DATABASE db4; exit mysql -u myuser db4 -p < ~/Sites/site4/dbdump/db4.sql

Über das vergessene Root-Passwort des MySQL-Servers und seine Rücksetzung (--skip-grant-tables!) breite ich den Mantel des Schweigens.

Im zweiten Schritt werden httpd.conf, nginx.conf und uwsgi.ini an den passenden Stellen des Dateisystems platziert. Wie üblich moniert nginx den fehlenden Ordner /Library/Caches/nginx, aber das Hauptproblem stellen die nicht modernisierten Django-Projekte dar: Die Fehlermeldung Target WSGI script '/var/ww/wsgi.py' cannot be loaded as Python module., gefolgt von ImportError: No module named doc deutet nicht etwa auf fehlende Leserechte oder die verbreiteten Pfaddefizite (→ python-path) hin, sondern auf eine veraltete Syntax in urls.py (und vermutlich vielen anderen Dateien). Zur Überarbeitung der beiden Projekte fühle ich mich heute nicht berufen und unterstelle deshalb, dass im Prinzip alles funktioniert.

Feierlich aktiviere ich die LaunchDaemons (PostgreSQL, nginx, uwsgi) bzw. LaunchAgents (staticiste, autobackup, phildb, cottagesdb), befülle ~/Backup mit meinen Zertifikaten (certs) und der Konfiguration meines virtuellen Servers in Montabaur (conf_server) sowie mit Symlinks auf alle wichtigen Daten, aktiviere FileVault und die Firewall, richte die Drucker ein, entzappele den Finder (defaults write com.apple.finder DisableAllAnimations -bool True; killall Finder) und nenne es einen Tag.