Generell gibt es zwei Arten, unter Windows einen SSH-Schlüssel zu speichern:
ppk
)Viele Anleitungen beschränken sich auf die eine oder andere Methode zum Anlegen von SSH-Schlüsseln. Tatsächlich macht es aber unter Windows sehr viel Sinn, den eigenen Schlüssel in beiden Formate verfügbar zu haben. Das geht deutlich schmerzloser, wenn beide Schlüsselformate in einem Aufwasch angelegt werden.
puttygen
Schlüsselgenerator, pageant
Schlüsselagenten und das plink
SSH-Verbindungstool.mkdir -p ~/.ssh
angelegt werden.C:\Users\USERNAME\.ssh
) die insgesamt drei Dateien anzulegen, die zusammen alle Schlüssel-Komponenten darstellen.In PuttyGen selber wird es nun etwas trickreich:
C:\Users\USERNAME\.ssh\id_rsa.ppk
speichern.C:\Users\USERNAME\.ssh\id_rsa.pub
einfügen (mit der Funktion „Save public key“ wird der Public Key nicht im korrekten Format exportiert).C:\Users\USERNAME\.ssh\id_rsa
speichern. Wichtig ist hierbei, dass keine Dateiendung verwendet wird.In eurem SSH-Verzeichnis C:\Users\USERNAME\.ssh
sollten nun mindestens drei Dateien liegen:
id_rsa.ppk # Privater / öffentlicher Schlüssel für PuTTY
id_rsa.pub # Öffentlicher Schlüssel für OpenSSH
id_rsa # Privater Schlüssel für OpenSSH
Später werden in diesem Verzeichnis ggf. noch mehr Dateien auftauchen, wie z.B. known_hosts
, authorized_keys
und config
.
Übrigens solltet ihr mit der Git Bash mittels chmod 644 ~/.ssh/* && chmod 600 ~/.ssh/id_rsa
allen Dateien die korrekten Zugriffsrechte (-rw-r--r--
bzw. -rw-------
) geben, falls dies nicht schon geschehen ist.
Den öffentlichen Schlüssel könnt ihr nun auf allen Servern und Diensten bekannt machen, mit denen ihr euch später verbinden wollt. Auf eurem Rechner wiederum wird die Git Bash automatisch den privaten OpenSSH-Schlüssel verwenden, während andere Programme den privaten Schlüssel aus der id_rsa.ppk
entweder in den Einstellungen übergeben bekommen müssen, oder aber aus einem vorher zu startenden pageant
Schlüsselagenten übernehmen können. Falls ihr SSH-Schlüssel für eure tägliche Arbeit benutzt, könnt ihr den Pageant auch automatisch starten und den Schlüssel laden lassen.
Viele Windows-Programme können so euren SSH-Schlüssel nutzen, u.a.:
So oder so seid ihr nun mit beiden Schlüsselformaten ausgestattet, so dass z.B. auch der Wechsel des Betriebssystems oder die Verwendung von Virtualisierung euch die Weiterbenutzung eures SSH-Schlüssels erlaubt.
Unter Linux und Mac OSX ist der Vorgang übrigens etwas kürzer:
ssh-keygen -t rsa -b 4096 -C "YOUR@EMAIL"
]]>Schon lange sind die Zeiten vorbei, in denen man einfach via FTP Dateien vom heimischen Rechner auf den Kundenserver hochschieben sollte. Wenn ihr händisch mittels rsync
oder git
Quellcode auf Develop-, Staging- oder Produktiv-System schiebt, ist der Sprung zu einem automatischen Deployment gar nicht mehr so weit, wenn ihr Gitlab verwendet.
Warum solltet ihr automatische Deployments verwenden?
Nachfolgend findet ihr ein Deployment via git
, ohne weitere Zusätze. Nachdem das Prinzip verstanden ist, kann das Rezept auch für rsync
, npm
, composer
oder jede andere Form von Transportmethode angepasst werden, und um beliebige andere schlaue Handgriffe erweitert werden.
Ein Git-Deployment sieht für euch normalerweise wie folgt aus:
git clone
das Projekt ausgecheckt war.git pull
(plus ggf. weitere Kommandos durch).Genau diese Handgriffe führt ein Gitlab-Deployment für euch automatisch durch, wenn bestimmte Bedingungen im Git erfüllt sind. In der Regel ist diese Bedingung ein Commit in einen bestimmten Branch, oder das Auftauchen eines neuen Tags.
Falls ihr der ganzen Automatik nicht traut, könnt ihr auch festlegen, dass das Deployment mit einem Knopf aus dem Webfrontend von Gitlab gestartet wird.
Dreh- und Angelpunkt ist das installierte Gitlab-CI-Modul von Gitlab. Dies wird eurer lokalen Gitlab-Installation hinzugefügt. Danach könnt ihr jedes eurer Projekte mit einer Datei namens gitlab-ci.yml
ausstatten, in der ihr das Deployment beschreibt.
Meine Vorlage dafür sieht inzwischen wie folgt aus:
# Never use Docker image without pinned version
image: governmentpaas/git-ssh:f120938e7390ec36314ec037465a1b35a079243e
before_script:
- eval $(ssh-agent -s)
- mkdir -p ~/.ssh
- echo "${SSH_CONFIG}" > ~/.ssh/config
- echo "${SSH_KNOWNHOSTS}" > ~/.ssh/known_hosts
- ssh-add <(echo "${SSH_PRIVATEKEY}")
# Hier könnte Testing durchgeführt werden.
# Das Deployment wird nur durchgeführt, wenn der Test erfolgreich ist.
# test:
# image: cytopia/eslint
# stage: test
# only:
# - master
# - merge_requests
# script:
# - tools/ci/test.sh
deploy_production:
stage: deploy
environment:
name: production
url: ${PRODUCTION_URL}
variables:
ENVIRONMENT_HOST: ${CI_ENVIRONMENT_NAME}
ENVIRONMENT_DIR: ${PRODUCTION_DIR}
ENVIRONMENT_URL: ${PRODUCTION_URL}
only:
- master
# - tags
# when: manual
script:
#- ssh ${ENVIRONMENT_HOST} "cd ${ENVIRONMENT_DIR} && echo 'Start DB backup...'"
- ssh ${ENVIRONMENT_HOST} "cd ${ENVIRONMENT_DIR} && git pull && git checkout ${CI_COMMIT_SHA} ."
#- ssh ${ENVIRONMENT_HOST} "cd ${ENVIRONMENT_DIR} && echo 'Clear cache...'"
# deploy_staging:
# deploy_develop:
# Hier könnten weitere Deployments für andere Zielsysteme stehen,
# die man einfach von "deploy_production" kopieren kann
In dem Skript sind die Schritte für Building und Testing aktuell ausgeklammert, können von euch aber einfach aktiviert werden. Der eigentliche Clou ist hier, dass Gitlab mit einigen von euch hinterlegten Variablen in der letzten Zeile der Datei aufgefordert wird, eine SSH-Verbindung zu dem Zielhost aufzumachen und dort ein git checkout
durchzuführen.
Die eigentliche Magie ist dabei, dass Gitlab exakt den aktuellen ausgewählten Commit auf dem betreffenden Zielsystem auscheckt. Mit der direktive only
legt ihr z.B. einen bestimmten Branch oder ein Tag fest, mit when: manual
eine manuelle Ausführung. Und im Falle eines verpfuschten Deployments, könnt ihr aus dem Gitlab-Webfrontend auch einen älteren Commit deployen lassen!
Das Deployment-Skript lässt sich natürlich um weitere Kommandos erweitern, die man auf dem Zielsystem ausführen möchte. Caches leeren, Composer ausführen oder Backups anlegen – all dies kann man hier problemlos hinzufügen. Und außerdem sehr ihr bereits, wie man z.B. für ein Develop- oder Staging-System das Skript erweitern könnt. Mehr Informationen über das Thema findet ihr in der offizielen Gitlab-CI-Dokumentation.
Das obige Deployment-Skript ist ohne große Änderungen für viele Projekte verwendbar. Pro Projekt hinterlegt man in Gitlab nur noch ein paar Pipeline-Settings:
Variable | Inhalt |
---|---|
SSH_CONFIG |
Hier muss eine SSH-Config z.B. für production hinterlegt werden. Siehe unten. |
SSH_KNOWNHOSTS |
Hier muss das Ergebnis von ssh-keyscan [-p PORT] HOSTNAME für jeden der Hosts in SSH_CONFIG hinterlegt werden. |
SSH_PRIVATEKEY |
Der SSH-Key, mit dem sich Gitlab zum Produktions-System verbinden darf. |
PRODUCTION_URL |
Die URL, unter der das Produktions-System erreichbar ist. |
PRODUCTION_DIR |
Der Pfad, in dem die Produktions-Installation liegt. |
Die letzten drei Variablen kann man ggf. noch für DEVELOP_
und STAGING_
ausführen.
Die Variable SSH_CONFIG
benutzt einen kleinen Trick, um die für das Deployment notwendigen SSH-Zugangsdaten zu speichern: Eine sehr kompakte Art und Weise, um Serverdaten inklusive Ports, Benutzernamen und IPs aufzulisten, ist die SSH-Config. Für Gitlab kann man dieses Format ganz wunderbar verwenden, um die Server-Konfiguration für die Deployment-Server in einer Pipeline-Variable zu hinterlegen.
Host production
Hostname 192.168.178.12
Port 22
User www-data
Zu beachten ist dabei, dass in der SSH-Config keine Passwörter gespeichert werden können. Das ist aber auch in Ordnung, da man sinnigerweise die Authentifizierung des Zugangs über einen SSH-Schlüssel durchführt.
Nachdem all diese Handgriffe vollbracht sind, könnt ihr im Idealfall 30 Sekunden nach eurem Commit bereits euren Quellcode auf der jeweiligen Zielumgebung bewundern. Projektmanager und Tester werden es euch danken, jederzeit den aktuellsten Stand auf dem Entwicklungssystem vorzufinden – und ihr werdet es euch selber danken, beim Deployment nicht das Backup vergessen zu haben. 😉
Außerdem müsst ihr dem Rest des Teams nicht großartig erklären, wie Deployments jetzt funktionieren: Jedes Teammitglied, dass Git benutzt, kann ohne weiteres Vorwissen mustergültige Deployments hinlegen.
Update: Inzwischen gibt es eine überarbeitete Version des Artikels „Fehlerfreie Gitlab-Deployments für Shopware & Co“ auf den Seiten meines Arbeitgebers.
]]>Dreh- und Angelpunkt dafür ist das ~/.ssh
-Verzeichnis. Dieses Verzeichnis wird von vielen Programmen auf eurem Rechner als Quelle für SSH-Informationen verwendet. U.a. sind diese Programme:
Da alle regulär in diesem Verzeichnis liegenden Dateien einfache Textdateien sind, dienen sie gleichzeitig auch als Dokumentation für euch selber.
Unter Mac OSX bzw. Linux existiert dieses Verzeichnis in der Regel bereits. Auch unter Windows solltet ihr dieses Verzeichnis in eurem Benutzer-Ordner anlegen, was aber nur über die Eingabeaufforderung mit folgender Zeile funktioniert.
cd %USERPROFILE%
mkdir .ssh
In diesem Verzeichnis legt ihr unter anderem auch eure SSH-Schlüssel ab, und unter Windows die von PuttyGen erzeugte PPK-Datei, die man sinnigerweise id_rsa.ppk
nennt.
In diesem Verzeichnis wird sich später auch die Datei known_hosts
anlegen, in der alle Informationen über von euch als vertrauenswürdig eingestufte SSH-Hosts hinterlegt werden.
Unter Windows solltet ihr GitBash als Terminal-Programm verwenden, um die volle Power dieser Dateien nutzen zu können.
In dem SSH-Verzeichnis erzeugt ihr nun einen Datei namens config
– dies ist die SSH-Config-Datei. Euer .ssh
-Verzeichnis sollte nun wie folgt aussehen:
config
id_rsa
id_rsa.ppk # Windows
id_rsa.pub
known_hosts
In die SSH-Config-Datei kommen nun die Verbindungsdaten für Hosts, die ihr euch merken (oder vereinfachen) wollt. Eine SSH-Config ist eine einfache Textdatei, in der ihr für jeden Host ein paar Zeilen Konfiguration hineinschreibt. Das Format ist dabei denkbar einfach und selbsterklärend:
Host *.secret-site.com
User dwayne
Port 2020
Host my-blog blog.example.com
Hostname 192.168.178.12
Port 2222
User wayned
# --------------------------------------
# Fallback
Host *
User www-data
ServerAliveInterval 5
ServerAliveCountMax 10
Neben IPs, Hostnamen, Benutzernamen und Ports kann man eigentlich alle relevanten Informationen für eine SSH-Verbindung ablegen – mit Ausnahme eines Passworts. Da ihr SSH-Verbindung aber sowieso über einen SSH-Schlüssel aufbauen solltet, ist dies keine wirkliche Einschränkung.
Mit dem obigen Beispiel kann man sich ab sofort eine Menge Tipparbeit sparen. Statt länglicher Kombinationen aus Benutzernamen, IPs und Ports könnt ihr (und jeder der oben genannten Programme) den von euch definierten Shortcut aufrufen:
$ ssh -p 2222 wayne@192.168.178.12 # vorher
$ ssh my-blog # nachher
Das Tolle ist: Die SSH-Config-Datei ist nicht nur ein Shortcut und Bookmark, sondern dient eurer eigenen Dokumentation aller eurer Verbindung. Außerdem kann man sich ein relativ einfaches System überlegen, um z.B. projektspezifische Hostnamen einfach zu standardisieren:
# --------------------------------------
# Projekt A
Host PROJECTA-develop
# ... Konfiguration
Host PROJECTA-staging
# ... Konfiguration
Host PROJECTA-production
# ... Konfiguration
# --------------------------------------
# Projekt B
Host PROJECTB-develop
# ... Konfiguration
Host PROJECTB-staging
# ... Konfiguration
Host PROJECTB-production
# ... Konfiguration
Findige Naturen erkennen hier natürlich schöne Ansätze, um projektübergreifende Deployment-Tools zu entwickeln. 😉
Übrigens: Dieses Format eignet sich auch hervorragend zur Dokumentation von SSH-Zugangsdaten in Teams. So könnt ihr z.B. in Wikis SSH-Zugangsdaten hinterlegen, die der nächste Entwickler nur noch per Copy und Paste bei sich einfügen muss. Damit könnt ihr auch sicher stellen, dass alle Mitglieder eures Teams die selben Hostnamen verwenden, und z.B. interne Tools sich auf bestimmte Hostnamen verlassen können.
Mehr Details über die vielen Möglichkeiten von SSH-Configs findet ihr in der hervorragenden Anleitung zur Konfiguration der SSH-Config.
]]>Das Problem: Dateien müssen nur die Rechte für Lesen & Schreiben haben, Order brauchen noch zusätzlich ein Recht zum Ausführen. Da man nicht unbedingt alle Dateien ausführbar haben will, ergibt sich hier im Endeffekt die Anforderung, für Dateien chmod ugo+rw
und für Verzeichnisse chmod ugo+rwx
auszuführen. Sobald das ganze rekursiv auf einen ganzen Baum angewendet werden soll, kann das sehr kompliziert werden.
Hier also die bahnbrechende Lösung:
chmod -R ugo+rwX
Eine sehr gute Zusammenfassung gibt es auch bei der Stackoverflow-Seite zum Thema chmod
.
Übrigens: Der Ausdruck „aller Zeiten“ wird hier nicht leichtfertig verwendet, sondern bezieht sich tatsächlich auf die kommenden Jahrzehnte.
]]>