Erste Schritte mit Git für lokale und zentrale Repositories unter Eclipse – IV

Ich setze mit diesem Blog-Post meine kleine Serie von Artikeln zum Thema GIT-Einsatz unter Eclipse fort. Im ersten Beitrag
Erste Schritte mit Git für lokale und zentrale Repositories unter Eclipse – I
hatte ich ein einfaches Einsatz-Szenario für freiberufliche Entwickler dargestellt, die mobil unterwegs sein müssen und ihre Versionsentwicklung regelmäßig zwischen PCs, Laptops und einem oder mehreren zentralen Servern abgleichen müssen:

Im LAN des Homeoffice wird mit einem lokalen Git-Repositories auf dem Arbeitsplatz-PC gearbeitet. Änderungen sollen schon aus Backup-Gründen zeitnah in ein zentrales Git-Repository im LAN überführt werden. Über den LAN-Server soll bei Bedarf aber auch ein Laptop versorgt werden; das dortige lokale Repository wird zum Arbeiten während Reisen benutzt. Zur Sicherheit wird der Status auf dem Laptop mit einem zentralen Repository im Internet abgeglichen, wann immer sich dazu die Gelegenheit bietet.

Die Frage ist: Wir organisiert man das unter Eclipse? In den letzten zwei Beiträgen
Erste Schritte mit Git für lokale und zentrale Repositories unter Eclipse – II
Erste Schritte mit Git für lokale und zentrale Repositories unter Eclipse – III
habe ich mich deshalb zunächst mit der Anlage eines lokalen Repositorys auf einem PC mit Hilfe des EGit-Plugins unter Eclipse beschäftigt. [EGit ist übrigens auch als standalone Product unter dem Namen "GitEye" verfügbar.] Wir haben uns anschließend angesehen, wie man Commits durchführt, wie man Branches erzeugt und auch wieder mergt.

Im Zentrum dieses und kommender Blog-Beiträge steht aber vor allem ein zentraler Branch, der sog. "Master"-Branch". Er stellt in unserem Szenario das wichtigste Bindeglied zwischen den verschiedenen Repositories auf PC, Laptop und zentralen Servern dar. Alle Entwicklungsaktivitäten werden in unserem Szenario letztlich auf ihn ausgerichtet. Wir merken aber bereits an dieser Stelle an, dass sich alle später dargestellten Abgleichverfahren zwischen lokalen und zentralen Repositorys realtiv zwanglos auf mehrere Branches erweitern lassen.

Ich wende mich in diesem Artikel der Anlage eines zentralen Repositorys auf einem Server im LAN zu. In einem zweiten Schritt binde ich dann das erzeugte LAN-Repository an das lokale Repositories unseres Entwicklungs-PCs an. Abschließend wird eine Änderung im lokalen Repository auf das zentrale Repository übertragen ("Push"-Operation). Das Spektrum der behandelten Themen entspricht in etwa der Lösung der Aufgaben 4 bis 7 des ersten Artikels.

Voraussetzung: Funktionierender SSH-Server

SVN-Nutzer wissen, dass ein SVN-Server eine spezielle Konfiguration über definierte Konfigurationsdateien und -verzeichnisse erfordert. U.a sind dabei spezielle Zugriffsrechte festzulegen. Weitere Sicherheitsaspekte sind zu berücksichtigen, wenn man SVN-Dienste über einen Webserver und "https" anbieten will.

Aus meiner Sicht ist die Einrichtung eines GIT-Servers für unser Szenario (aber nicht nur dafür) relativ einfach: Benötigt wird im Grunde nur ein hinreichend konfigurierter SSH-Server, auf dem man den Zugriff auf Verzeichnisstrukturen und Objekte eines ".git"-Verzeichnisses über User- und Gruppen-Accounts steuert. Ansonsten muss dort unter Linux nur das für die jeweilige Distribution passende Git-Paket installiert sein. Mehr ist zum Aufsetzen eines privaten Git-Servers unter SSH fast nicht erforderlich! Hinzu kommen lediglich zwei weitere, einfache Schritte:

  • Das auf einem PC bereits vorhandene Repository (hier für das Eclipse-Projekt "alien1") ist zu klonen.
  • Der Git-Repository-Clone ist in ein definiertes Zielverzeichnis auf dem SSH-Server zu transferieren.

Man kann die oben genannten beiden Punkte mittels GIT theoretisch auch in einem Schritt erledigen; ich ziehe es aber der besseren Kontrolle wegen vor, hier zweistufig vorzugehen. Alle später einzurichtenden Git-Clients nehmen dann auf die URI des angelegten Git-Verzeichnisses auf dem Server Bezug.

Hinweis: Es gibt natürlich auch Möglichkeiten, eigene Git-Server über andere Protokolle und im Rahmen von Web-Server-Diensten einzurichten. Ich gehe in dieser Artikelserie aber nicht darauf ein. Ich sehe auch keinen Grund dafür, für unser einfaches privates Szenario nicht eine simple und sichere SSH-Variante zu nutzen.

Ich gehe in diesem Artikel zudem nicht auf die Bereitstellung und Konfiguration von SSH auf einem Server ein. Das habe ich an anderer Stelle dieses Blogs schon beschrieben. Ich gehe im LAN ferner von einem einfachen UID-bezogenen Login auf dem SSH-Server mittels eines Passwortes aus; für einen später zu kontaktierenden SSH-Server im Internet setze ich dagegen einen Login per RSA-Key (hinreichender Länge plus sicherem elliptischem KEX-Verfahren) voraus.

Unser LAN-Server heiße "debian8" und sei einer lokal definierten Domäne "lanracon.de" zugeordnet. Der Server sei aufgrund entsprechender DNS-Einträge aber auch direkt unter "debian8" ansprechbar. Ich gehe davon aus, dass wir auf diesem Server z.B. Giggle oder QGit installiert haben, um dort einen Blick auf neu installierte Repositories werfen zu können (s. hierzu auch den vorhergehenden Blog-Artikel). Das übergeordnete Zielverzeichnis für Git-Repositorys auf dem Server sei "/projekte/GIT/". Das zentral zu erzeugende Repository beziehe sich in unserem Beispiel - wie das zuletzt betrachtete PC-Repository auch - auf unser PHP-Eclipse-Projekt namens "alien1".

Erzeugen eines Repositories ohne Working Tree durch Klonen

Auf einem Git-Server benötigen wir in der Regel keinen Working Tree. Das Erzeugen eines Clones ohne Working Tree gelingt mit Hilfe des "git clone"-Befehls und bestimmter Optionen.

Ich bemühe an dieser Stelle die Kommandozeile einer Shell. Man kann zwar auch mit EGit ein vorhandenes Repository in lokale Verzeichnisse klonen; aber wir wollen ja anschließend die Clone-Dateien auch noch auf den Server bringen. Das ginge theoretisch zwar auch über geeignete grafische Eclipse-Tools für den Remote-Systems-Zugriff; warum aber mit Kanonen auf Spatzen schießen?

Das Repository und der Working Tree unseres Beispiels aus den letzten Blog-Posts waren auf unserem Entwicklungs-PC im Verzeichnis "/projekte/GIT/alien1" beheimatet. Ich lege mir für die Zwischenspeicherung des Clones und den anschließenden Transfer auf den Server im vorhandenen GIT-Verzeichnis des PCs (oder Laptops) aber ein separates Verzeichnis an - hier namens "alien1trans". Also

myself@mytux:/projekte/GIT> mkdir alien1trans
myself@mytux:/projekte/GIT> cd alien1trans/

Die Struktur des notwendigen "clone"-Befehls ist:

git clone --bare <em>Repo-Pfad Target-Dir-Pfad</em>

Für die Erzeugung eines Repositorys ohne "Working Tree"-Verzeichnis sorgt die Option "--bare". Wird der Target-Dir-Pfad des Verzeichnisses, in das geklont werden soll, nicht angegeben, wird der Clone im aktuellen Verzeichnis (Working Directory) angelegt. In unserem Fall ergibt sich:

myself@mytux:/projekte/GIT/alien1trans> git clone --bare ../alien1
Klone in Bare-Repository 'alien1.git' ...
Fertig.
myself@mytux:/projekte/GIT/alien1trans> ls -la
insgesamt 12
drwxr-xr-x 3 myself entw 4096  6. Mai 09:28 .
drwxr-xr-x 6 myself entw 4096  6. Mai 09:27 ..
drwxr-xr-x 7 myself entw 4096  6. Mai 09:28 alien1.git
myself@mytux:/projekte/GIT/alien1trans> du -s -h
60M     .
myself@mytux:/projekte/GIT/alien1trans> cd ../alien1
myself@mytux:/projekte/GIT/alien1> du -s -h
225M    .
myself@mytux:/projekte/GIT/alien1> du -s -h .git
60M     .git
myself@mytux:/projekte/GIT/alien1>
myself@mytux:/projekte/GIT/alien1> cd ../alien1trans/
myself@mytux:/projekte/GIT/alien1trans> mv alien1.git/ .git  
myself@mytux:/projekte/GIT/alien1trans> ls -la                                                                          
insgesamt 12                                                                                                       
drwxr-xr-x 3 myself entw 4096  6. Mai 11:25 .                                                                        
drwxr-xr-x 6 myself entw 4096  6. Mai 09:27 ..
drwxr-xr-x 7 myself entw 4096  6. Mai 09:28 .git

Wie man sieht, habe ich im Anschluss an das Klonen die korrekte Größe des Clone-Verzeicnisses geprüft. Das reine Repository (hier "alien1.git") ist offenbar deutlich kleiner als der Working Tree selbst! Am Schluss habe ich das Repository-Verzeichnis des Clones, das als Anteil immer den Namen des Ursprungsrepositories erhält, noch in ".git" umbenannt. Grund: Viele Git-GUI-Programme suchen automatisch nach einem Verzeichnis namens ".git".

Ok, wir haben nun einen Clone auf unserem PC. Wie bringen wir den jetzt auf den Server "debian8.lanracon.de"? Natürlich mittels SSH. Ich gehe mal davon aus, dass der User "myself" aus der Gruppe "entw" auch auf dem Server vertreten ist und sich dort per Passwort anmelden darf. Er verfüge über die notwendigen Schreibrechte im übergeordneten Zielverzeichnis auf dem Server, in dem wir spezifische GIT-Repositories aufbewahren wollen. Zunächst legen wir auf dem Server ein spezielles Zielverzeichnis für das "alien1"-Repository an:

myself@mytux:/projekte/GIT/alien1trans> ssh myself@debian8
Password: 
Last login: Sat May  6 11:41:46 2017 from xxx.xxx.xxx.xxx
Have a lot of fun...
myself@debian8:~> cd /projekte/GIT
myself@debian8:/projekte/GIT> mkdir alien1
myself@debian8:/projekte/GIT> exit
Abgemeldet
Connection to debian8 closed.
myself@mytux:/projekte/GIT/alien1trans>

Ich habe hier mal angenommen, dass wir auf dem Server bereits eine ähnliche Verzeichnisstruktur wie auf dem PC angelegt hatten. Das muss natürlich nicht so sein. Also das Zielverzeichnis bitte dort anlegen, wo man seine GIT-Repositories verwalten will.

Hinweis: An dieser Stelle können bereits Rechte (im Besonderen Gruppenrechte) eine Rolle für die spätere Nutzung des Repositories durch andere User spielen. Ich regele die korrekten Rechte auf Servern, die ich selbst komplett unter Kontrolle habe, meistens über ACLs und/oder das SGID-Bit. Das erspart einem viel Arbeit. Egal wie - es ist jedenfalls dafür zu sorgen, dass das Verzeichnis die richtige Gruppe und einen passenden Rechtekamm erhält.

Nun kopieren wir einfach die Dateien des geklonten ".git"-Verzeichnisses per "scp" vom PC auf den Server:

myself@mytux:/projekte/GIT/alien1trans> scp -r .git myself@debian8:/samba/GIT/alien1/
Password: 
...
....
99eaff29e3720789e5e75e9e8999a5bde77733                                           100%  290     0.3KB/s   00:00    
a816f7c5ebab36333b9fd8574d459176f3ff07                                           100% 2416     2.4KB/s   00:00    
5f11c90dbb0170c0b2082f1d5fec9a0e10522b                                           100%   17KB  17.1KB/s   00:00    
101f6958c4e18057cfdf7c975a1483eeeddea9                                           100% 1349     1.3KB/s   00:00    
2fd38f7570791c179ec4c94b886ec62027d3a3                                           100% 9190     9.0KB/s   00:00    
config                                                                           100%  127     0.1KB/s   00:00    
description                                                                      100%   73     0.1KB/s   00:00    
packed-refs                                                                      100%  289     0.3KB/s   00:00    
pre-commit.sample                                                                100% 1642     1.6KB/s   00:00    
pre-rebase.sample                                                                100% 4951     4.8KB/s   00:00    
pre-receive.sample                                                               100%  544     0.5KB/s   00:00    
prepare-commit-msg.sample                                                        100% 1239     1.2KB/s   00:00    
post-update.sample                                                               100%  189     0.2KB/s   00:00    
commit-msg.sample                                                                100%  896     0.9KB/s   00:00    
pre-applypatch.sample                                                            100%  424     0.4KB/s   00:00    
applypatch-msg.sample                                                            100%  478     0.5KB/s   00:00    
pre-push.sample                                                                  100% 1348     1.3KB/s   00:00    
update.sample                                                                    100% 3610     3.5KB/s   00:00    
HEAD                                                                             100%   23     0.0KB/s   00:00    
exclude                                                                          100%  240     0.2KB/s   00:00    
myself@mytux:/projekte/GIT/alien1trans> 

Je nach Größe des Repositorys rast hier eine Reihe von Dateien, die mit Hashes bezeichnet sind, an uns vorüber. Um zu prüfen, ob das Verzeichnis auf dem Server richtig aussieht, nutze ich z.B. Giggle:

myself@mytux:/projekte/GIT/alien1trans> ssh myself@debian8
Password: 
Last login: Sat May  6 11:48:46 2017 from xxx.xxx.xxx.xxx
Have a lot of fun...
myself@debian8:~> export NO_AT_BRIDGE=1
myself@debian8:~> giggle & 

Hinweis:

Mir passiert es auf Servern mit etwas älterem Kernel regelmäßig, dass ich die Umgebungsvariable NO_AT_BRIDGE mittels
export NO_AT_BRIDGE=1
auf dem Server setzen muss, um Giggle oder QGit (über SSH) zum Laufen zu bringen. Siehe hierzu: https://wiki.archlinux.de/title/GNOME#Tipps_und_Tricks und https://bbs.archlinux.org/viewtopic.php?id=176663 sowie auch https://bugzilla.redhat.com/show_bug.cgi?id=1056820

Unter Giggle muss man dann das "Projekt" alien1 unter dem entsprechenden Pfad zum Repository öffnen. Ich gehe auf die Bedienung von Giggle oder QGit nicht näher ein. Die meisten Git-Anwendungen sind nach ein wenig Beschäftigung mit Git weitgehend selbsterklärend. Das Ergebnis ist jedenfalls:

Gut! Wir können die Branches des geklonten Repositories offenbar auch auf dem Server mit graphischen Tools einsehen.

Hinweis:

Für diesen Artikel habe ich faktisch einen unter KVM angelegten Linux-Server auf einem Laptop benutzt. Im LAN kann man bzgl. graphischer Tools auf Servern noch performant genug mit "ssh -X" arbeiten. Wer hingegen mit einer graphischen Oberfläche auf echten Remote-Servern im Internet arbeiten muss, findet ggf. mit X2GO ein passendes Toolset; s. z.B.:
Remote Desktop für Debian 8 mit X2Go auf Strato-vServern.

Dem Leser werden Teile der Branch-Grafik bekannt vorkommen; einen ähnlichen Graphen hatte ich bereits gegen Ende des letzten Artikels abgebildet. Dort war der Zugriff aber auf das Repository des PCs erfolgt.

Hinweis: Wer Speicherplatz sparen will, kann nach diesem positiven Check das Zwischenverzeichnis "alien1trans" und seinen Inhalt löschen ("rm -r alien1trans").

Anbinden des Master-Branches des Servers an den Master-Branch des PCs

Das Repository auf dem Server ist relativ nutzlos, wenn wir es nicht in Verbindung mit lokalen Repositories auf unseren PCs oder Laptops bringen. Wie also können wir von Eclipse/EGit aus auf das eben auf dem Server eingerichtete Repository zugreifen und wie füllen wir es mit Commits, die wir lokal durchgeführt haben?

Es gibt unter Eclipse/EGit mehrere Wege, einen Branch eines Remote-Git-Repositorys an einen korrespondierenden Branch eines lokalen Repositorys anzubinden. Ich wähle hier den Weg über den Punkt "Remotes" im hierarchisch organisierten Eclipse-View "Git Repositories" für die Darstellung lokaler Repositorys:

Im Kontextmenü zu "Remotes" findet sich ein Punkt "Create Remote", den wir anklicken:

Im nächsten Popup-Dialog müssen wir der neuen "Remote-Git-Anbindung" einen Namen geben:

Die vorgewählte Radiobox für die Push-Konfiguration lassen wir in ihrem Zustand. Ich komme auf die Alternative in einem späteren Artikel zurück. Das Drücken des OK-Buttons führt zu einem weiteren Dialogfenster:

Dort wählen wir den Button "Change", um die Verbindung zum Git-Server zu konfigurieren; es öffnet sich ein weiteres Dialogfenster (s.u.) mit mehreren Eingabefeldern, die wir wie folgt behandeln:

  • In das Feld "URI" geben wir zunächst nur den Pfad zum Repository auf dem Server an - also in unserem Beispiel:
    "/projekte/Git/alien1/.git".
  • In das Feld "Host" geben wir in unserem Fall natürlich "debian8" ein. In der Combobox "Protocol" wählen wir "ssh"; ggf. müssen wir auch noch einen Nicht-Standard-Port angeben, falls SSH auf dem Server unter einem speziellen Port angeboten wird.
  • Im Feld "User" geben wir unsere UID auf dem Server ein - hier "myself". Dann ergänzen wir noch das Password; das Feld "Store in Secure Store" lasse ich immer aktiv. Hier sammelt und verschlüsselt Eclipse die ihm anvertrauten Passwörter in einem Container, der wiederum ein Zugangspasswort erfordert.

Der Dialog baut den UR-Identifier im Zuge dieser Schritte vollständig auf:

Drücken auf den "Finish"-Button führt zum nächsten Dialog, der uns erlaubt, die sog. "Push-Reference"-Konfiguration vorzunehmen:

Worum geht es da? Für den Moment reicht es zu wissen, dass wir eine Beziehung zwischen einem lokalen Branch und einem Branch eines Remote-Repositories herstellen, so dass wir später neue, per Commit erstellte Knoten des lokalen Branches gezielt in den ausgewählten Remote-Branch überführen können.

Hinweis:

Faktisch kann man aber die nachfolgende einfache Konfiguration für genau einen Branch und einen Remote-Server auf verschiedene abzugleichende Branches und verschiedene Server im Rahmen ein und derselben Remote-Konfiguration ausdehnen. Dies ist insbesondere dann nützlich, wenn man lokale Repsitory-Änderungen gleichzeitig auf verschiedene Remote-Server übertragen will. Ich komme darauf in einem weiteren Blog-Beitrag zurück.

Folgende Schritte sind zunächst zu leisten, um eine Referenz des Remote Master-Branches zum lokalen herzustellen; zunächst wählen wir den lokalen Branch; es genügt ein "m" in die betreffende Zeile einzugeben. Das fenster bietet uns dann automatisch den (einzigen) passenden Branch zur Auswahl an. Dann wählen wir den Remote-Branch:

Bei letzterem Schritt muss die SSH-Verbindung richtig funktionieren! Auch hier sollte eine Vorgabe von "m" zur Auswahl des richtigen (Remote-) Master-Branches führen.

Übrigens: Bei Einsatz von asymmetrischen Schlüsseln zur SSH-Authentifizierung müssen diese vorab im Eclipse-Dialog SSH2-Dialog unter "Preferences => General => Network Connections => SSH2" definiert worden sein.

Man wird dann ggf. zur Eingabe der Passphrase für den lokalen Schlüssel aufgefordert.

Im unserem Push-Referenz-Dialog ergibt sich nun folgendes Bild:

Und schließlich:

Weitere Git-"Remotes"

Ganz analog kann man nun weitere "Remotes" für andere Server anlegen - soweit das denn sinnvoll ist. Man erhält schließlich eine Kollektion verschiedener Remote-Verbindungen zu Git-Servern:

Jede dieser Remote-Anbindungen enthält eine separate "Push"-Konfiguration, die man nach Bedarf unabhängig von anderen Remote-Verbindungen für notwendige Abgleichvorgänge bedienen kann. Aber Achtung:

In unserem Beispiel haben wir bisher nur eine funktionierende Push-Verbindung aufgebaut. Bereits die obige Abbildung verdeutlicht aber, dass es offenbar auch so etwas wie Fetch-Operationen gibt. Den Sinn und Zweck von "Fetches" behandle ich in einem kommenden Artikel.

Anwenden der Push-Verbindung zum LAN-Server - eine erste Push-Operation

Den Transfer lokaler Repository-Änderungen auf das Remote-Repository bezeichnet man als Push-Operation. Je nachdem, wer wann welche Änderungen auf dem Server eingespielt hat, setzt dies ggf. vorhergehende komplexe Merge-Operationen mit lokalen Branches voraus. In unserem Szenario, in dem wir alleine den Master-Branch auf dem LAN-Server beliefern, ist das aber, zumindest im Moment, noch völlig unerheblich. Die Änderungen erfolgen gemäß unserer Szenario-Beschreibung im ersten Beitrag ja sequentiell.

Also probieren wir einfach mal aus, was ein Push im momentanen ReositoryZustand bewirkt. Hierzu führen wir einen Klick mit dem rechten Mousebutton auf einer unserer angelegten Remote-Verbindungen aus; es öffnet sich ein Kontext-Menü, das u.a. die Push-Operation anbietet:

Ich habe die Push-Operation im abgebildeten Beispiel in Richtung auf einen Server durchgeführt, der sich in einem ähnlichen Zustand wie unser "debian8" aus der oben erläuterten Remote-Konfiguration befindet. Das führt dann zu folgender System-Reaktion und -Information:

Dieses Ergebnis war zu erwarten; das geklonte Repository befindet sich ja immer noch im selben Zustand wie das aktuelle auf dem PC unter Eclipse. Wir müssen lokal natürlich zuerst eine Änderung comitten; erst die lässt sich dann sinnvollerweise zum Server weiterreichen. Um die Änderung und ihren Hash lokal wie remote verfolgen zu können, lassen wir uns im Git-Repository-View unsere Branches anzeigen und öffnen dann per rechtem Mausklick das Kontextmenü des "Master"-Branches. Dort klicken wir auf den Menüpunkt "Show In => History". Der graphische History-View sieht in meinem Beispiel wie folgt aus:

Übrigens: Die Abbildung zeigt für den obersten Knoten auch, dass die HEAD-Version des Branches bislang mit denen definierter Remote-Server-Branches "loc_deb8/master" und "strat_deb/master" übereinstimmt!

Nun führen wir - wie im letzten Artikel erläutert - eine Änderung auf einer Testdatei aus und committen die über den Commit-Button des Git-Staging-Dialogs:

Wir erhalten dann nach einem Refresh des History-Views:

Hier erkannt man, dass sich die lokale Version nun von den letzten bekannten Versionen auf den Servern "loc_deb8/master" und "strat_deb/master" abweicht. (Wie das lokale Eclipse auf unserem PC erfährt, ob sich inzwischen möglicherweise durch andere Nutzer etwas auf den Server-Repositories geändert hat, behandle ich in einem anderen Artikel.) Man merke sich nun den Hash des letzten Knotens.

Nun führen wir nochmals die oben versuchte Push-Operation aus; ich nutze hier eine definierte Verbindung zu einem realen Server, die ich unter der Bezeichnung "loc_deb8" konserviert habe:

Wir klicken auf OK. Dann wechseln wir zur graphischen Oberfläche unseres Servers und refreshen das dort geöffnete Giggle (oder QGit, ..). Und tatsächlich:

Unsere lokale Änderung ist wohlbehalten im Remote Repository unseres Servers angekommen. Die Hashes der Knoten sind identisch.

Potentielle Probleme mit Push-Operation und Ausblick

Damit man lokale Änderungen so einfach wie oben beschrieben pushen kann, müssen diese von Git als echte Nachfolger des letzten Knotens im Remote-Branch identifiziert werden können. Es ergeben sich dann um sog. Fast-Forward-Merges, die mit keinen direkten formalen Konflikten zwischen verschiedenen Änderungen gleicher Code-Bereiche verbunden sind.

Für unser einfaches sequentielles Änderungsszenario, das wir im ersten Artikel beschrieben haben, sind Fast-Forward-Merges aus offensichtlichen Gründen immer möglich.

Man stelle sich aber eine Situation mit mehreren Anwendern vor. Dann können andere Entwickler unser zentrales Repository bereits mit ähnlichen Änderungen upgedated haben - bevor wir unsere Änderung pushen. Das führt dann potentiell zu Konflikten zwischen den verschiedenen Änderungen, die GIT nicht ohne unser Zutun auflösen kann. Unsere Push-Operation kann in einem echten Entwicklungsszenario deshalb auch schief gehen - genauer: in einen manuell zu bereinigenden Konflikt münden. (In der Praxis vermeidet man häufige Kollisionen mit den Inhalten zentraler Repositories übrigens auch durch organisatorische Maßnahmen; etwa dadurch, dass man nicht verschiedene Entwickler parallel an den gleichen Dateien bzw. gleichen Codebereichen arbeiten lässt.)

Konflikte können aber auch in einem 1-Personen-Szenario auftreten, in dem man vergessen hat, seine Änderungen auf verschiedenen Entwicklungssystemen (Laptop, PC) systematisch und sequentiell über zentrale Server abzugleichen.

Um eventuelle Konflikte vorab zu erkennen und ggf. durch Merges zu bereinigen, die man lokal vor einem Push ausführt, benötigt man eine Übertragung des Zustands eines Remote-Repositorys in das lokale System. Hierzu dienen Fetch- und Pull-Operationen; sie werden u.a. Thema unseres nächsten Artikels.

Dort wollen wir uns ferner damit befassen, wie wir den Stand unseres zentralen Repositorys auf einen Entwicklungs-Laptop übertragen.

SFTP mit Key-Authentication auf (gehosteten) Linux-Servern für Web-Entwickler mit unterschiedlichen Privilegien – II

Im ersten Artikel der Serie zur SFTP-Einrichtung auf gehosteten Servern

SFTP mit Key-Authentication auf (gehosteten) Linux-Servern für Web-Entwickler mit unterschiedlichen Privilegien – I

hatten wir erste grundlegende Aspekte der SSH-Einrichtung diskutiert. Im jetzigen Artikel diskutiere ich zunächst einige Verbesserungen der SSH-Einstellungen und wende mich dann der Einrichtung von 2 Usergruppen in der "/etc/sshd_config" zu.

Sicherheits-Hinweis für den Umgang mit der sshd-config auf Remote Servern

Fehler sind menschlich. Durch Zerstören der SSHD-Konfiguration kann man sich von gehosteten Servern selbst aussperren. Bevor man also an der sshd_config rumspielt, sollte man sich immer einen weiteren Zugangsweg zum Server für Notfälle sichern.

Server-Hoster bieten für den Ernstfall ein Booten in einen Maintenance-Modus an. Dass das funktioniert, sollte man mal getestet haben. Ein Gleiches gilt für evtl. Backup-Verfahren. Ferner sollte man bei sich Kopien aller wichtigen Konfigurationseinstellungen haben. Ich selbst lege vor Änderungen immer eine Kopie der funktionierenden ssd_config an. Die kann man im Ernstfall im Maintenance-Modus wieder zurückspielen.

Ferner sollte man 2 bis 3 andere ssh-Verbindungen offen halten, bevor man den sshd-Dämon neu startet. Der Server setzt normalerweise eine Grace-Time für bereits geöffnete Verbindungen. Dieses Zeitintervall kann man dann im Ernstfall noch für Änderungen der sshd_config oder ein Zurückspielen einer funktionierenden Konfigurationsdatei nutzen!

Von Vorteil ist es auch, eine von der Gruppe, für die die Einstellungen manipuliert werden, unabhängige, SSH-fähige UserID zur Verfügung zu haben.

Verbesserungen der SSH-Enrichtung

Aufgrund der schon seit einiger Zeit erhöhten Sicherheitsanforderungen Anforderungen müssen wir die SSH-Einrichtung verbessern. Ich kann an dieser Stelle leider nicht auf Details eingehen - es sind aber vor allem bekannte Probleme im Bereich des initialen "Key Exchange" [KEX] zu beheben:

Einerseits sind Standardparameter und Schlüssellängen für bestimmte zugehörige asymmetrische Algorithmen, die auf Primfaktorzerlegung und Modulo-Verfahren beruhen, unzulänglich. Leider sieht der Standard selbst Verfahren als Fallback-Optionen verbindlich vor, die aktuellen Anforderungen nicht mehr genügen. Andererseits muss man leider auch hinter Standard-Parameter für elliptische Kryptographie große Fragezeichen hinsichtlich ihrer Zufälligkeit setzen.

Ein Teil der Probleme wurde bereits 2015 adressiert; siehe z.B.:
https://weakdh.org/imperfect-forward-secrecy-ccs15.pdf.
Informationen bzgl. möglicher Maßnahmen findet man etwa hier:
https://stribika.github.io/2015/01/04/secure-secure-shell.html.

Der erste Schritt zur Aufrüstung ist, dass wir uns die aktuelle Version von OpenSSH (z.Z. 7.2p2) beschaffen. Für Opensuse (ab der Version 13.1) nutzt man hierzu das "network"-Repository ; siehe hierzu http://download.opensuse.org/repositories/network/.

Danach lassen wir nur die Protokollvariante 2 und lediglich zwei z.Z. noch als sicher eingeschätzte initiale Schlüsselaustausch-Verfahren des SSH-Protokolls zu. Ferner schränken wir die Klassen der für die Serveridentifikation möglichen Schlüssel ein. Hierzu dienen die folgenden Statements in der Datei "/etc/ssh/sshd_config" unseres Servers "serv":

# We only allow for SSH protocol version 2 
Protocol 2

# We restrict the Key Exchange Algorithms !!!
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

# Minimum length in DH 
KexDHMin 2048

# We restrict HostKeys types for Host authentification for protocol version 2
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key

# We restrict Ciphers 
#RekeyLimit default none
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr

# UsePam can be set to "yes" to get more control options via PAM 
# siehe hierzu die Diskussion in einem kommenden Artikel
UsePAM  yes 

 
Man sollte für Zwecke im privaten oder Geschäftsumfeld zudem zugehörige flankierende Einstellungen in der lokalen Client-Konfigurations-Datei "/etc/ssh_config" vornehmen. Siehe den oben angegebenen Link.

Zwei Usergruppen und zweier Beispieluser

Im Folgenden verschaffen wir zwei exemplarischen SFTP-Usern

  • alpha : Mitglied der Entwicklergruppe "devgrp1" und der Gruppe "devgrp2"
  • beta : Mitglied der Entwicklergruppe "devgrp2".

einen ersten elementaren SFTP-Zugang zu den Verzeichnissen "/srv/www/htdocs/webs/project/alpha", "/srv/www/htdocs/webs/project/adm", "/srv/www/htdocs/webs/project/test/beta".

Zugang zu unterschiedlichen chroot-Verzeichnissen

Wir legen in einem ersten Anlauf zunächst das Verzeichnis "/srv/www/htdocs/webs/project/" als Dachverzeichnis an.

Dieses Verzeichnis wird uns gleichzeitig als chroot-Verzeichnis für alle beteiligten SFTP-User der Gruppe "devgrp1" dienen.

Ein weiteres untergeordnetes Verzeichnis "/srv/www/htdocs/webs/project/test" wird dagegen als chroot-Verzeichnis für die Mitglieder der Gruppe "devgrp2" verwendet.

An dieser Stelle muss auf einen wichtigen Punkt hingewiesen werden.

Jedes Verzeichnis, das unter SFTP als chroot-Jail für eine Usergruppe dienen soll, muss root gehören und nur root darf darauf Schreibrechte besitzen.

Ansonsten läuft man bei der Einrichtung des SFTP-Zugangs in Probleme, wie sie etwa hier geschildert sind:
http://superuser.com/questions/394298/sftp-chroot-result-in-broken-pipe

Also geben wir als User root auf dem Web/SFTP-Server "serv" Folgendes ein :

mytux:~ # mkdir /srv/www/htdocs/webs/project
mytux:~ # chgrp devgrp1 /srv/www/htdocs/webs/project
mytux:~ # chmod 750 mkdir /srv/www/htdocs/webs/project
mytux:~ # mkdir /srv/www/htdocs/webs/project/test
mytux:~ # chgrp devgrp2 /srv/www/htdocs/webs/project/test
mytux:~ # chmod 750 mkdir /srv/www/htdocs/webs/project/test
mytux:~ # mkdir /srv/www/htdocs/webs/project/alpha
mytux:~ # chgrp devgrp1 /srv/www/htdocs/webs/project/alpha
mytux:~ # chmod 770 mkdir /srv/www/htdocs/webs/project/alpha
mytux:~ # mkdir /srv/www/htdocs/webs/project/adm
mytux:~ # chgrp devgrp1 /srv/www/htdocs/webs/project/adm
mytux:~ # chmod 770 mkdir /srv/www/htdocs/webs/project/adm
mytux:~ # mkdir /srv/www/htdocs/webs/project/test/beta
mytux:~ # chgrp devgrp2 /srv/www/htdocs/webs/project/test/beta
mytux:~ # chmod 770 mkdir /srv/www/htdocs/webs/project/test/beta

 
Mitglieder der Gruppe "devgrp1" legen wir später auch als Mitglieder der Gruppe "devgrp2" an. Sie dürfen daher mit SFTP alle unter "/srv/www/htdocs/webs/project" liegenden Verzeichnisse einsehen; u.a. auch solche, die "devgrp2" zugänglich sind, aber zusätzlich auch weitere Verzeichnisse. "devgrp1" hat gegenüber der Gruppe "devgrp2" also mehr Privilegien. Mitglieder der Gruppe "devgrp2" sehen theoretisch zunächst nur den Inhalt von Verzeichnissen unterhalb "/srv/www/htdocs/webs/project/test".

Dabei gilt:

Schreiben und Unterverzeichnisse anlegen dürfen Mitglieder von "devgrp1" bzw. "devgrp2" aber nur in den Unter-Verzeichnissen "alpha" bzw. "beta" !

Berücksichtigung der künftigen SFTP-User-Gruppen in der SSHD-Konfigurationsdatei

Wir müssen den Usern "alpha" und "beta" zur Nutzung von SFTP zunächst grundsätzlich die Nutzung von SSH zugestehen. Dies führt zur Modifikation des "AllowUsers"-Eintrags in der Konfigurationsdatei, der im letzten Artikel diskutiert wurde :

AllowUsers usu alpha beta

Bei wenigen einzelnen Usern und Gruppen kann man vielleicht so arbeiten. Bei steigender Useranzahl werden die User aber typischerweise in Gruppen angeordnet. Dann ist es wichtig zu wissen, dass es auch die Direktive "AllowGroups" gibt. Insgesamt werden vom SSH-Daemon 4 Direktiven in folgender Reihenfolge abgearbeitet:

DenyUsers
AllowUsers
DenyGroups
AllowGroups

Das zuerst getroffene Muster zählt dabei unabhängig von nachfolgenden Muster-Treffern! Siehe:
https://en.wikibooks.org/wiki/OpenSSH/Server
Nicht zutreffende Treffer führen automatisch zu einem Default-Ausschluss von der Nutzung.

Beachtet bitte auch, dass host-spezifische Zusätze der Form USER@HOST nur zu User-IDs - nicht aber (!) zu Gruppen-IDs - möglich sind. Siehe:
http://manpages.ubuntu.com/manpages/hardy/man5/sshd_config.5.html
Wildcards in Host-Ergänzungen sind unter obigem Link auch beschrieben:
http://manpages.ubuntu.com/manpages/hardy/man5/ssh_config.5.html

Ist der User "usu" ein Mitglied der Gruppe "adm", so hätten wir in unserem Fall also auch schreiben können:

AllowGroups adm devgrp?

Man beachte, dass kein Komma sondern ein Blank zur Abtrennung mehrerer User oder Usergruppen voneinander benutzt wird.

Begrenzung des Zugriffs auf CHROOT-Verzeichnisse

Nun müssen wir bestimmte Verzeichnisse vorgeben, auf die sich der Zugang beschränken soll. Hierfür sind zwei Direktiven erforderlich:

  • Zum einen eine Einstellung zur Nutzung des internen SFTP-Mechanismus durch den jeweiligen User
  • und zum anderen eine Einstellung zur Definition eines alle Aktionen begrenzenden und kapselnden CHROOT-Verzeichnisses für jeden User.

Ich nehme diese Einstellung in user- und/oder gruppenspezifischen Segmenten der Konfigurationsdatei "/etc/sshd_config" vor. Solche Bereiche leitet man am Ende der Konfiguationsdatei durch die Schlüsselworte "Match Group" (oder "Match User") ein.

Bei den nachfolgenden Direktiven für die Gruppe oder den User wiederhole ich dabei einen Teil der generellen sicherheitsrelevanten SSH-Einstellungen. Der Grund hierfür ist:

Muss ich mal auf die Schnelle und testweise grundlegende SSH-Einstellungen ändern, so setze ich die Direktiven für meine kritischen SFTP-User nicht automatisch außer Kraft.

Also ergänzen wir genau am Ende der Datei "/etc/ssh/sshd_config":

Match Group devgrp1
        ForceCommand internal-sftp
        # ForceCommand internal-sftp -u 0007</strong>
        ChrootDirectory /srv/www/htdocs/webs/project
        RSAAuthentication yes
        PubkeyAuthentication yes
        PasswordAuthentication no 
        X11Forwarding no
        AllowTcpForwarding no
        AllowAgentForwarding no
        GatewayPorts no
Match  Group devgrp2,!devgrp1 
        ForceCommand internal-sftp
        # ForceCommand internal-sftp -u 0007
        ChrootDirectory /srv/www/htdocs/webs/project/test
        RSAAuthentication yes
        PubkeyAuthentication yes
        PasswordAuthentication no 
        X11Forwarding no
        AllowTcpForwarding no
        AllowAgentForwarding no
        GatewayPorts no

 
Interessant ist hier zunächst die zweite Match-Vorgabe

Match Group devgrp2,!devgrp1

Hier drücken wir aus, dass die nachfolgenden Parameter grundsätzlich für die Mitglieder/User der Gruppe "devgrp2" gelten soll, aber nicht für Mitglieder der Gruppe "devgrp1". Die logische Negation erfolgt durch den Operator "!".

In unserem Beispiel gelten die Anweisungen nach der zweiten "Match"-Zeile also lediglich für den User "beta" und evtl. andere User der Gruppe "devgrp2".

Hinweis:

Zwischen den beiden Kriterien für die Gruppenmitgliedschaft ist ein Komma einzufügen, aber kein Blank vor oder nach dem trennenden Komma!

Interessant ist ferner die potentielle Option "-u" hinter der auskommentierten ForceCommand Anweisung:

ForceCommand internal-sftp -u 0007

Diese Direktive setzt für Open-SSH-Versionen ≥ 5.5 gezielt eine "umask", die angeblich systemweite umask-Definitionen überschreibt. Nun ja - stimmt das wirklich? Wir kommen darauf im nächsten Artikel dieser Serie zurück.

Home-Verzeichnisse der User "alpha" und "beta"- und Ausschluss des Shell-Zugangs

Auf die Schritte zur User-Anlage und User-Zuordnung zu Gruppen gehe ich hier nicht genauer ein. Interessanter ist die Frage, wo sich eigentlich die Home-Verzeichnisse der User alpha und beta befinden sollen.

Diverse Artikel im Internet, die sich mit dem Aufsetzen von User-bezogenen Verzeichnissen unterhalb eines Chroot-Verzeichnisses befassen (s. die Links am Ende des Artikels), enthalten für unser Szenario eher verwirrende Information.

Zudem gilt:
Der SSHD-Dämon erwartet später die Public Key Files unserer User bei Default-Einstellungen an bestimmten Stellen in der Verzeichnisstruktur. Experimente mit einer Verlagerung der Home-Verzeichnisse in andere Bereiche des Dateibaums führen nach meiner Erfahrung schnell ins Chaos und zu mühsamem Suchen nach Fehlern. Das gilt selbst dann, wenn man später Pfade zu den Autorisierungsfiles explizit setzt. Also:

Einfach die Home-Verzeichnisse da lassen, wo sie normalerweise erzeugt werden. Wir entziehen unseren Entwicklern sowieso den Shell-Zugriff und engen ihren Wirkungskreis weiter per Chroot ein.

serv:~ # useradd -g devgrp1 -s /sbin/nologin -m -d /home/alpha -k /etc/skel alpha
serv:~ # passwd alpha 
serv:~ # useradd -g devgrp2 -s /sbin/nologin -m -d /home/beta -k /etc/skel beta
serv:~ # passwd beta 
serv:~ # usermod -G devgrp2 alpha

 

Generieren eines SSH-Schlüsselpaars pro SFTP-User

Da wir sicherheitsbewusste Administratoren sind, erlauben wir den eben angelegten Usern SSH/SFTP-Zugang nur auf Basis von SSH-Key-Authentication.

Wir wählen für unsere künftigen SFTP-User natürlich die Erzeugung eines SSH-Schlüssel-Paars, bei der der private Schlüssel mit einem Passwort geschützt wird. Schon aus Gründen einer durchgehenden Sicherheitsphilosophie.

In Übereinstimmung mit den Sicherheitsrichtlinien von https://stribika.github.io/2015/01/04/secure-secure-shell.html führen wir zur Schlüsselgenerierung folgende Kommandos aus - und kopieren danach den jeweiligen Public Keys zum SSH/SFTP-Server.

Wir zeigen das am Beispiel des Users "alpha" auf dem Client "mytux". Wir erzeugen sowohl ein Key-Paar, das auf elliptischer Kryptographie basiert und eines, das bei hinreichender Schlüssel-Länge RSA unterstützt. Schlüssellängen unter 2048 Bit sind für RSA-angelehnte Verfahren (also nicht elliptische Verfahren) nicht mehr als sicher anzusehen.

Dabei setzen wir voraus, dass "alpha" ein Verzeichnis "~/.ssh" angelegt hat.

alpha@mytux:~/.ssh> ssh-keygen -t ed25519 -f ssh_host_ed25519_key
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in ssh_host_ed25519_key.
Your public key has been saved in ssh_host_ed25519_key.pub.
The key fingerprint is:
SHA256:wri++5yVtLbMQeinXxdqiduWm2gGAbTNaB8YPFJkNV8 ufo@mytux.mydomain
The key's randomart image is:
+--[ED25519 256]--+
|   =*.o   E      |
|  ..+B o .       |
|   .=o+ .        |
|   . +.o         |
|    . =.S   .    |
|     o.+ + o .   |
|    . ..O =..    |
|   . . OoOoo     |
|    ++=+B.+.     |
+----[SHA256]-----+

alpha@mytux:~/.ssh> ls
known_hosts  ssh_host_ed25519_key  ssh_host_ed25519_key.pub

alpha@mytux:~/.ssh> ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in ssh_host_rsa_key.
Your public key has been saved in ssh_host_rsa_key.pub.
The key fingerprint is:
SHA256:cQfc/m7HrB1fLFsL8TA27FtiYYDJa2BIGoS3JRS607w ufo@mytux.mydomain
The key's randomart image is:
+---[RSA 4096]----+
|  +=..   ...     |
| ..o+.. . +..    |
| ...+. o.+.o.    |
|  +.  . .o..+    |
| o o    So   @   |
|  . .   .   + O. |
|   E         *.*+|
|            . B=O|
|             oo+o|
+----[

 
Analog erzeugen wir ein zweites separates Schlüsselpaar für die Entwickler der Gruppe "devgrp2". Wir legen dann als Schutz gegen Verlust Kopien dieser Schlüsselpaare in einem verschlüsselten Verzeichnis auf einem selbst kontrollierten Backup-Server an.

Dann bringen wir die Public (!) Key Datei für jeden User auf den Server. Dazu nutzen wir einen entsprechend privilegierten Benutzer (hier "usu"), der SSH-Zugang erhalten hat. Wir erinnern uns, dass wir bei der SSH-Einrichtung einen direkten SSH-Zugang des Users "root" verboten hatten. root auf dem System "mytux" kopiert den Public Key zwischenzeitlich in ein Verzeichnis "/home/usu/key_transfer" des Dummy Users "usu". Dann transferieren wir mittels "scp":

usu@mytux:~>scp -P 6xxxx -i ~/.ssh/id_rsa_usu /home/usu/key_transfer/ssh_host_ed25519_key.pub usu@serv.myhoster.net:/home/usu/key_transfer/
Enter passphrase for key '/home/ich/.ssh/id_rsa_usu': 
ssh_host_ed25519_key.pub    100%  390     0.4KB/s   00:00

 
"6xxxx" steht dabei für den verschobenen Port, unter dem der Server SSH anbietet. (Siehe hierzu den letzten Artikel dieser Serie).

Dann als root auf "serv":

serv:~ # mkdir /home/alpha/.ssh
serv:~ # chown alpha.devgrp1 /home/alpha/.ssh
serv:~ # cp /home/usu/key_transfer/ssh_host_ed25519_key.pub /home/alpha/.ssh/ssh_host_ed25519_key.pub
serv:~ # chown alpha.devgrp1 /home/alpha/.ssh/ssh_host_ed25519_key.pub 
serv:~ # rm /home/usu/key_transfer/ssh_host_ed25519_key.pub 
serv:~ # touch /home/alpha/.ssh/authorized_keys
serv:~ # chown alpha.devgrp1 /home/alpha/.ssh/authorized_keys
serv:~ # cat /home/alpha/.ssh/ssh_host_ed25519_key.pub >> /home/alpha/.ssh/authorized_keys
serv:~ # chmod 600 /home/alpha/.ssh/authorized_keys
serv:~ # chmod 600 /home/alpha/.ssh/ssh_host_ed25519_key.pub 
serv:~ # chmod 700 /home/alpha/.ssh

 
Analog für alle anderen Public Keys und User. Andere Verfahren - auch manuelle - um den Public key auf den Server zu bringen, werden hier diskutiert:
https://www.digitalocean.com/community/tutorials/how-to-configure-ssh-key-based-authentication-on-a-freebsd-server

Bitte beachtet:

Die Rechtesetzungen sind wichtig! Bei unzureichendem Schutz wird SSH die Keys ggf. nicht akzeptieren.

Test

Wir sind nun so weit, dass wir einen ersten Test durchführen können. Bevor wir den SSH-Server auf unserem Testsystem neu starten, checken wir nochmal, dass die notwendigen Einstellungen für Key-Authentifzierung in der Datei schon vorgenommen wurden:

AllowUsers usu alpha beta
AllowGroups adm devgrp1 devgrp2 
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile      .ssh/authorized_keys
PasswordAuthentication no
ChallengeResponseAuthentication no

 
Dann erfolgt ein Restart von sshd :

serv:~ # systemctl restart sshd.service 

Wir probieren nun den Zugang mittels des Kommandos "sftp"; man beachte, dass die Option für den Port hier ein großes "P" erfordert !

ich@mytux:~> sftp -P 6xxxx -i ~/.ssh/ssh_host_ed25519_key beta@serv.myhoster.net
Enter passphrase for key '/home/ich/.ssh/ssh_host_ed25519_key': 
Connected to serv.myhoster.net
sftp> ls
beta 
sftp> pwd
Remote working directory: /
sftp> cd ../alpha
Couldn't stat remote file: No such file or directory
sftp> cd beta
sftp> pwd
Remote working directory: /beta
sftp> mkdir classes
sftp> ls -la
drwxr-xr-x    3 beta     devgrp2      4096 Feb 10 17:30 .
drwxr-xr-x    3 root     root         4096 Feb 10 16:30 ..
drwxr-xr-x    2 beta     devgrp2      4096 Feb 10 17:30 classes
sftp> cd classes
sftp> put /home/ich/classes/*
Uploading /home/ich/classes/class_ufo.php to /beta/classes/class_ufo.php
/home/ich/classes/class_ufo.php                                        100%    0     0KB/s   00:00    
Uploading /home/ich/classes/class_ufo2.php to /beta/classes/class_ufo2.php
/home/ich/classes/class_ufo2.php                                       100%    0     0KB/s   00:00    
sftp> ls
class_ufo.php    class_ufo2.php   
sftp>exit 
ich@mytux:~> 

 
Die letzten zwei Testfiles hatte ich als leere Files angelegt; daher die 0-Übertragungsrate!

Nun noch ein Kurztest für den User "alpha":

ich@mytux:~> sftp -P 6xxxx -i ~/.ssh/ssh_host_ed25519_key alpha@serv.myhoster.net
Enter passphrase for key '/home/ich/.ssh/ssh_host_ed25519_key': 
Connected to serv.myhoster.net
sftp> ls
adm    alpha  test 
sftp> ls /test/beta/classes
/test/beta/classes/class_ufo.php   /test/beta/classes/class_ufo2.php
sftp> mkdir /test/beta/uploads
sftp> ls /test/beta
/test/beta/classes   /test/beta/uploads   
sftp> exit
ich@mytux:~>

 
Damit genug für heute. Im nächsten Artikel dieser Serie gehe ich dann etwas genauer auf Rechtethemen beim Anlegen von Files per SFTP ein.

Links

Generelles zu SSH/SFTP
http://en.wikibooks.org/wiki/OpenSSH/Cookbook/SFTP
http://wiki.ubuntuusers.de/SSH
http://www.computerhope.com/unix/sftp.htm

Userbezogene Chroot-Verzeichnisse
https://www.mynakedgirlfriend.de/sichere-chroot-umgebung-fur-ssh-dateiubertragungen-sftp/
http://www.thegeekstuff.com/2012/03/chroot-sftp-setup/
https://wiki.archlinux.org/index.php/Talk:SFTP_chroot

SSH – Qt5-Anwendungen – KDE/Plasma 5 – falsche Fonts und fehlende Icons

Wenn man sich unter KDE 5 mit
"ssh -X remoteuser@sshhost"
auf einem Host "sshhost"einloggt und dann Qt5-Anwendungen startet, werden die in der Regel nicht richtig angezeigt: Es fehlen Icons und die Fonts sind falsch.
("remoteuser" und "sshhost" sind im Beispiel natürlich nur Dummy-Bezeichnungen, die durch richtige Werte ersetzt werden müssen.)

Ursache des Darstellungsproblems:
Qt5-Applikationen suchen die Einstellungen der aktuell laufenden Desktopumgebung - im Beispiel also auf auf dem per SSH angesprochenen Host "sshhost". Dort wird aber KDE nicht erkannt, weil eine Umgebungsvariable nicht gesetzt ist, die normalerweise beim Start der Desktop-Umgebung belegt wird. Dort läuft ja aber für die ssh-Shell gar kein Desktop.

Ich hatte das Problem schon mal behandelt - allerdings für root-Shells und lokale Starts von Qt5-Anwendungen auf ein und demselben System (siehe http://linux-blog.anracom.com/2016/01/27/opensuse-leap-42-1-kde-5-unzureichende-darstellung-und-kleine-fonts-in-qt5-anwendungen-die-von-root-gestartet-werden/).

Die gleiche Thematik verfolgt einen aber natürlich auch in Shells, die mit SSH geöffnet werden.

Lösungsansatz:
Man kann der SSH-Sitzung die notwendige Umgebungsvariable am Prompt nachliefern. Nämlich über:

remoteuser@sshhost:~>export XDG_CURRENT_DESKTOP=KDE

Erfolgte die SSH-Sitzung aus einem Gnome-Desktop heraus, so wählt man natürlich eher:

remoteuser@host:~>export XDG_CURRENT_DESKTOP=GNOME

Arbeitet man lokal und remote grundsätzlich nur unter KDE, so kann man die Einstellung

export XDG_CURRENT_DESKTOP=KDE

auch in der Datei "~/.profile" verankern. Die Umgebungsvariable wird dann für alle Login-Sitzungen gesetzt.

Arbeitet man allerdings nicht nur remote auf dem Host "sshhost" und wechselt man dort (!) gelegentlich zwischen KDE und Gnome, so ist wohl eine vorherige Abfrage in der "~/.profile" sinnvoller - und man entscheidet sich nur im Zweifel für KDE:

[ "$XDG_CURRENT_DESKTOP" = "KDE" ] || [ "$XDG_CURRENT_DESKTOP" = "GNOME" ] || export XDG_CURRENT_DESKTOP=KDE

Bessere interaktive Lösung:
Man verankert in der "~/.profile" für den Fall einer SSH-Verbindung eine interaktive Abfrage, die den SSH-Nutzer festlegen lässt, welche Desktop-Umgebung den anschließend gestarteten Qt5-Anwendungen vorgegaukelt werden soll. Die entsprechende Desktop-Umgebung muss auf dem SSH-Host natürlich vom User konfiguriert worden sein.

Der Aufbau eines entsprechenden Shellskripts ist eine nette kleine Übungsaufgabe, bei deren Lösung ggf. folgender Link weiterhilft:
http://unix.stackexchange.com/questions/9605/how-can-i-detect-if-the-shell-is-controlled-from-ssh

Nachtrag 01.11.2016: SSH, KDE und User root

Will man aus irgendwelchen Gründen für den User "root" über SSH grafische Anwendungen starten, so nützt im Gegensatz zur Situation in einer bereits laufenden grafischen KDE-Umgebung nichts, einfach "kdesu ..." zu benutzen. Wir hatten dieses Vorgehen im Artikel Opensuse Leap 42.1 / KDE 5 – unzureichende Darstellung (kleine Fonts, fehlende Icons) von Qt5-Anwendungen, die von root gestartet werden empfohlen. Ist eine SSH-Shell dazwischengeschaltet, so muss die oben erläuterte Umgebungsvariable vor Anwendung des "kdesu"-Befehls für eine grafische Qt5-Anwendung explizit gesetzt werden.