02 Jan

Ein privates NPM Repository mit Sinopia und nginx erstellen

Motivation

Es gibt verschiedene Gründe ein privates npm-Repository für node-Pakete auf einem eigenen Server zu installieren. npmjs könnte down sein, man möchte nur spezifische Pakete oder Paketversionen bei den Entwicklern zulassen oder man will eigene Pakete publizieren, ohne dass sie der Öffentlichkeit zur Verfügung stehen.

Bei uns war vor allem die zusätzliche Sicherheit ausschlaggebend, dass verfügbare Pakete nicht einfach aus den öffentlichen Quellen verschwinden und uns zu ungünstigen Zeitpunkten zu einem Upgrade oder sogar einem Austausch des Pakets zwingen.

Die Kombination aus sinopia und nginx wurde gewählt, da sinopia sehr einfach zu installieren ist und ein paar sinnvolle Default-Einstellungen gleich mitbringt. Nginx wird vor sinopia gesetzt, um eine erhöhte Sicherheit zu gewährleisten und um zu garantieren, dass kein unautorisierter Zugriff möglich ist.

Voraussetzungen

Wir gehen für diese Anleitung davon aus, dass ein vollständig konfiguriertes Linux vorliegt (in unserem speziellen Fall wird Debian verwendet). Zusätzlich ist auf diesem System bereits node installiert, so dass die Befehle node und npm zur Verfügung stehen.

Wir werden keine vollständige Installationsanleitung von nginx erstellen, daher erwarten wir ein gewisses Grundverständnis der Einstellmöglichkeiten von nginx.

Vorbereitungen

Um eine gewisse Absicherung gegenüber Angriffen zu haben, werden wir das npm repository global installieren, aber unter einem eigenen User namens npm laufen lassen. Dazu installieren wir als root sinopia:

# npm install -g sinopia

und legen den Benutzer npm an. Wir erzeugen ihn als Systemkonto und ohne Loginmöglichkeiten.

# adduser --system --home /srv/npm --shell /bin/sh --disabled-login --gecos "NPM repository server" --group npm

Das Homeverzeichnis haben wir auf /srv/npm gelegt, um dort die eigentlichen Pakete, etc. abzulegen.

Um später eine htpasswd-Datei einfach anlegen zu können, installieren wir noch das htpasswd-Tool von Apache. Bei uns ist es im Debian Paket apache2-utils

# apt-get install apache2-utils

Grundkonfiguration Sinopia

Sinopia erzeugt eine Basiskonfiguration beim ersten Starten. Dazu wechseln wir von root zum Benutzer npm und starten sinopia

# su npm
$ cd ~
$ sinopia
warn --- config file - /srv/npm/sinopia/config.yaml
warn --- http address - http://localhost:4873/

Dies sagt uns, dass eine neue config-Datei angelegt wurde und sinopia unter http://localhost:4873/ auf unsere Anfragen horcht. Wir möchten auf jeden Fall beibehalten, dass sinopia nur von localhost Anfragen annimmt, denn nur so können wir garantieren, dass ein Zugriff nur über unsere nginx-Installation möglich ist.

Wir beenden sinopia, indem wir STRG+C drücken.

Sinopia weiter absichern

Dieser Blogpost wurde anhand sinopia@1.0.0-beta.2 verfasst. Eine vollständige Konfiguration kann auf github nachgelesen werden. Die aktuelle npm Version lautet 1.4.28. Da diese Absicherung wohl nicht dem Standard entspricht, können wir nicht garantieren, dass spätere npm-Versionen weiterhin mit diesem Trick funktionieren.

Unser Ziel ist es, dass diese sinopia-Instanz nicht allgemein zugänglich ist, sondern nur für Benutzer, die authentifiziert sind. Zusätzlich sollen sich keine neuen Benutzer einfach anmelden dürfen.

Dazu ändern wir als ersten Schritt in der config.yaml Datei von sinopia die Einstellung max_users auf “-1” und alle allow_access auf “$authenticated”.

Als zweiten Schritt erweitern wir unsere nginx-Konfiguration. Wir legen zwei neue Locations an, zum Einen die eigentliche Weiterleitung, zum Anderen eine Sonderregel, die eine erfolgreiche Registrierung eines Benutzers während npm adduser simuliert.

htpasswd Datei erstellen

Zuletzt muss noch die Datei /srv/npm/sinopia/htpasswd erstellt werden, damit sowohl nginx, also auch sinopia, die Benutzer authentifizieren können. Dazu nutzen wir das Tool htpasswd, um neue Benutzer “test” hinzuzufügen.

htpasswd /srv/npm/sinopia/htpasswd test

Die Passwörter in htpasswd sind zwar gehasht. Trotzdem sollte der Zugriff auf diese Datei so weit wie möglich eingeschränkt werden.

Clients konfigurieren

Um das private npm-Repository zu nutzen, muss auf jedem Rechner dieses bekannt gegeben und der Benutzer eingepflegt werden. Zusätzlich muss npm noch mitgeteilt werden, dass es sich beim Zugriff auf unser Repository immer authentifizieren muss.

npm set always-auth true
npm set registry https://hostname:14873/
npm adduser --registry https://hostname:14873/ --always-auth

Wobei hier der hostname und der Port durch die von ihnen in nginx gewählten Einstellungen ersetzt werden muss. Wir empfehlen außerdem dringend nginx so zu konfigurieren, dass https für die Kommunikation zwischen Client und nginx genutzt wird.

Fazit

Wir haben nun ein privates Repository für unsere npm-Pakete. Es ist sehr sicher, da nginx über den Zugriff wacht und eine https-Verbindung zur Kommunikation ermöglicht. Zusätzlich ist der Gesamtaufbau relativ einfach, da sinopia einfach und ohne Abhängigkeiten zu couchdb, etc. betrieben werden kann.

Share this

Leave a reply