Frage zur Einrichtung von git und Berechtigungen

Photon

Rear Admiral
Registriert
Apr. 2006
Beiträge
5.140
Hallo Community,

ich arbeite an einem kleinen Webprojekt. Grob gesagt besteht das Projekt aus zwei Teilen: Framework und Inhalte. Das Framework ist öffentlich und auf Gitlab gehostet. Die Inhalte sind privat und liegen im Moment bei mir auf dem Rechner. Der Projektordner auf dem Rechner sieht in etwa so aus:

Projektordner
-> Frameworkordner
-> Inhaltsordner

Nun würde ich gerne die Ordnerstruktur so belassen, da die Pfade für den Inhalt im Framework entsprechend gesetzt sind. Im Moment löse ich das Problem so, dass ich den Inhalt des Inhaltsordners nicht adde, wenn ich einen Commit mache. Auf Gitlab ist also dieselbe Ordnerstruktur, nur der Inhaltsordner ist dort leer.

Nun liegt noch eine weitere Kopie des Projektordners bei mir auf einem Raspi, auf dem ein Webserver läuft, der das Projekt (hinter .htaccess) ins Internet stellt. Wenn ich die Inhalte verändere, dann schiebe ich sie via SSH (also scp) auf den Raspi.

Jetzt möchte ich einer weiteren Person Schreibzugriff auf die Inhalte, die auf dem Raspi-Webserver liegen, geben, ohne ihm aber SSH-Zugriff zu geben, da auf dem Raspi noch andere Sachen drauf sind. Ich dachte also daran auf dem Rapi ein Git-Repo speziell für den Inhaltsordner aufzusetzen. Da frage ich mich jetzt:

1. Der Ordner sitzt in /var/www/html und gehört root. Also habe ich weder via SSH noch via GIT Berechtigungen um da reinzuschreiben. Wer sich fragt, wie ich das bisher mit SSH gemacht hat: Habs nach /home/pi mit scp geschoben und von dort aus in einer SSH-Sitzung via sudo cp in den html-Ordner. Ist furchtbar unbequem. Wie kann man das besser lösen?

2. Wie binde ich das in meine Git-Repo auf dem Rechner ein, wo ja neben dem Inhalt noch das Framework liegt? Hab was von Subtree gehört, wär das was?

Danke für jeden Input und sorry für die Facepalms, die ich euch da mit meinem "unorthodoxen" Methoden beschere. ;)

Viele Grüße,
Photon
 
Ich benutze häufig Submodule. Damit kannst du ein Repo in ein anderes einbinden und zwar mit einem kontrollierten Versionsstand, d.h. bloß weil sich ein Repo weiterbewegt, tut es das andere nicht automatisch. Könnte ja sonst Inkompatibilitäten geben, wenn z.B. dein Framework voraus rennt.

Ich habe in einem ähnlichen Konstrukt (Inhalt kann von Dritten in Repo gepflegt werden, die aber nicht auf den Host sollen) ansible-pull benutzt, was in einem festen Intervall von x Minuten schaut, ob es Änderungen gibt und die ggf. anwendet. Das kannst du dir auch mit einem bash-Script und einem cronjob selbst bauen.

Ansonsten solltest du wohl dein Framework so bauen, dass du es als Bibliothek ausliefern und vernünftig (also über das dependency management der Sprache) einbinden kannst. Hängt von der Sprache ab, wie das dann aussieht, aber eigentlich gibt es das in allen Sprachen, die mir geläufig sind.
 
  • Gefällt mir
Reaktionen: new Account()
Dein Ausroll-Skript/Cron kann doch als root laufen und entsprechend die Rechte setzen, wie du es brauchst.
 
Hab jetzt das Problem mit folgenden HowTos gelöst:
https://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server

und

https://gist.github.com/noelboss/3f...da6KKGZl7VUF9Y6htk60A2NPfH-hDfaHhpU12QAhpZAOM

Habe also einen Nutzer git eingerichtet und ein Verzeichnis für das Repository unter /home/git/projekt.git. Der Nutzer git musste in die Gruppe www-data rein, die Schreibrechte für /var/www/html bekommen musste. Und dann wurde nach jedem Push mittels eines post-receive Git Hooks der Inhalt des Repos nach /var/www/html/projekt kopiert.

Das erste Problem ist also erst mal gelöst, das zweite ist im Moment nicht so dringend.

Danke für den Input! :)

edit: Das hier war auch ganz interessant in dem Kontext: https://www.saintsjd.com/2011/01/what-is-a-bare-git-repository/
 
Zuletzt bearbeitet:
Bedenke, dass das problematisch sein kann, wenn ein Webserver die Rechte hat, die Dateien, die er ausliefert, auch zu schreiben.

Was spricht denn gegen folgendes Pseudo-Script, ausgeführt per Cronjob als root oder meinetwegen von irgendeinem Hook getriggert?
  • git pull deines Repos in Ordner_A
  • cp der relevanten Dateien in Ordner_B (htdocs)
  • chown -R www-data:www-data Ordner_B

Theoretisch kannst du mit einem sparse checkout auch einzelne Unterordner direkt in den htdocs-Ordner clonen/pullen, da der Apache die ja nur lesen können muss.
 
Irgendwie bin ich gerade zu doof dafür. :) Ich würde das Deployment gerne direkt nach jedem Push ins Git-Repo triggern (sodass die Änderung sofort sichtbar ist und nicht erst, wenn der vom Cronjob angestoßerene regelmäßige pull kommt) und bisher sehe ich nicht, wie man das mit einem Cronjob erreichen soll. Und der Git Hook, der ja eigentlich genau dafür gedacht ist, wird vom User git ausgeführt, welcher also entsprechende Schreibrechte braucht.

Oder wie wäre es, wenn ich den Ordner für den Nutzer www-data (mit nur Lesezugriff) und die Gruppe git (mit Schreibzugriff, beinhaltet den Nutzer git) freigebe?
 
Zuletzt bearbeitet:
Photon schrieb:
Oder wie wäre es, wenn ich den Ordner für den Nutzer www-data (mit nur Lesezugriff) und die Gruppe git (mit Schreibzugriff, beinhaltet den Nutzer git) freigebe?
Klingt gangbar. 👍
 
  • Gefällt mir
Reaktionen: Photon
Tumbleweed schrieb:
Klingt gangbar. 👍
Uff, jetzt klappt es doch nicht so ganz... Die vom Git Hook reingeschobenen Dateien gehören dem Benutzer git und auch der Gruppe git, nicht aber der Gruppe www-data, in der der nginx-Nutzer www-data ist. Somit kann nginx die Dateien nur lesen, weil sie für others auch noch lesbar sind. Was an sich ok ist. Aber jetzt kann ich mit meinem Standard-Nutzer, mit dem ich via SSH auf den Server zugreife, die Dateien nicht editieren, weil sie nur für den Nutzer git beschreibbar sind und für niemanden sonst, nicht mal für die Mitglieder der Gruppe git...
 
@Tumbleweed Puh, ja, muss ich mich mal einlesen. Aber jetzt hab ich das Problem, für dessen Diagnose ich Schreibrechte direkt auf dem Server haben wollte, gelöst, also ist das erst mal geklärt.

Jetzt habe ich aber immer noch das Problem mit dem Einbinden der Git-Repos ineinander. Das bindet mir gewissermaßen die Hände, weil ich jetzt auf meinem PC zwei Ordner habe, einer weiterhin auf dem Stand des Gitlab-Repos (ohne Inhalt, da in die .gitignore eingetragen), der andere relativ frisch erstellt und mit der frischen Raspi-Repo synchronisiert. Die sind schon ein paar Commits auseinander und je mehr es werden, umso schwieriger wird es sie irgendwie wieder zu verheiraten... Im Moment spricht noch nichts dagegen die Raspi-Repo neu anzulegen, sodass sie auf dem Stand der Gitlab-Repo ist (nur mit Inhalten), aber das ist ja kein Dauerzustand... Bin also wieder etwas ratlos.
 
Also du hast Repo A (Framework) und Repo B (Inhalt)?

Dann kannst du überlegen, wie herum es dir sinnvoller erscheint und dann machst du in dem umschließenden Repo einfach
Code:
git submodule add <clone url des anderen Repos> [optionaler Ordnername in dem das abgelegt wird]
und bist erst mal fertig. Der .gitignore-Teil fällt weg. Das umschließende Repo merkt sich nur noch den Versionsstand, den es einbinden soll.

Wenn du dann das innere Repo auf einen neuen Stand bringen willst, geht das (stehend im äußeren Repo) mit
Code:
git submodule update --remote
git add <Ordnername des submodules>
git commit -m "Update des Submoduls"
git push

P.S.: man kann direkt in dem inneren Repo arbeiten und Änderungen pushen, aber dann muss man sich noch etwas mehr handwerklich mit git auseinandersetzen, weswegen es leichter ist, es separat nochmal zu klonen und dort zu arbeiten und die Aktualisierungen dann immer über den oben beschriebenen Weg reinzuziehen.
 
Zuletzt bearbeitet:
Tumbleweed schrieb:
Also du hast Repo A (Framework) und Repo B (Inhalt)?
Ich hab Repo A (Framework und Dummy-Inhalt plus tatsächlicher Inhalt, der nur drin liegt, aber nicht geadded/commitet/gepusht wird). Das ist das Gitlab-Repo. Und Repo B, das als Kopie von Repo A angefangen hat und in ein leeres Repo auf dem Raspi kopiert, dort gepusht und nun zum eigenständigen Repo geworden ist, allerdings mit tatsächlichem Inhalt. Repo B hat also nicht die Commit-History von Repo A, nur dieselben Dateien zum Abzweigungszeitpunkt.

Weiß nicht, ob man mit dieser Erklärung was anfangen kann, sorry wenn sie umständlich ist. :)
 
Ja doch, ich glaube, ich verstehe es. Da du das Framework-Repo ja wahrscheinlich unabhängig halten willst, sollte darin auch kein submodule eingebunden werden, denn diese Information wäre Bestandteil des Repos, d.h. wenn ein Dritter das Framework nutzen will, hat er immer diesen Verweis auf ein submodule drin, der ins Leere zeigt.

Wenn du es umdrehst und das Framework-Repo in dein Inhalts-Repo als submodule einbindest, hast du das Problem nicht. Ggf. musst du dann ein paar Pfade anpassen, weil sich die Ordner-Struktur vielleicht verändern wird.

Du stellst dich also auf dem Pi in dein Repo B und fügst Repo A als submodule hinzu. Erst mal bis dahin und dann schauen wir weiter. ;)
 
Ok, puh, ich versuch das mal. :) Werd wohl ein Repo C zum Rumspielen anlegen, sonst wird das mit Repo B eine Operation am offenen Herzen, denn Repo B wird ja beim Pushen ins Verzeichnis des Webservers kopiert, Git Hooks sei dank.

Ist wohl auch besser so herum, denn ehrlich gesagt, ist die tatsächliche Struktur so, dass es vier Ordner mit Inhalt gibt und einen mit dem Framework. Sollte die Ordnerstruktur vielleicht mal überarbeiten und die vier Ordner in einen gemeinsamen Content-Ordner packen, aber im Moment ist es so. Ist alles etwas Wildwuchs, früher war die Ordnerstruktur noch wesentlich unübersichtlicher, hab schon eine Aufräumaktion des Repos und ein Code-Refactoring hinter mir, aber offenbar gibt es da noch mehr zu tun. :D
 
Unter uns Profis nennen wir das "historisch gewachsen". Legitimiert alle Schweinereien. ;)
 
Oh ja, das nehm ich definitiv in mein Vokabular auf. :D

Hmm, irgendwie klappt das Hinzufügen des Submodules in einem Bare-Repo nicht. Ich brauch ja, so weit ich es verstanden hab, ein Bare-Repo, um dorthin pushen zu können. Doch da gibt es dann kein "working tree", das Problem hatte ich vorher schon mal. Sieht in etwa so aus:

Bash:
pi@raspberrypi:/home/git $ sudo mkdir test.git
pi@raspberrypi:/home/git $ cd test.git/
pi@raspberrypi:/home/git/test.git $ sudo git init --bare
Initialized empty Git repository in /home/git/test.git
pi@raspberrypi:/home/git/test.git $ git submodule add https://gitlab.com/Photon89/tpiq-experimental.git
fatal: $program_name cannot be used without a working tree.
pi@raspberrypi:/home/git/test.git $ ls -la
total 40
drwxr-xr-x 7 root root 4096 Apr  7 20:12 .
drwxr-xr-x 6 git  git  4096 Apr  7 20:10 ..
drwxr-xr-x 2 root root 4096 Apr  7 20:12 branches
-rw-r--r-- 1 root root   66 Apr  7 20:12 config
-rw-r--r-- 1 root root   73 Apr  7 20:12 description
-rw-r--r-- 1 root root   23 Apr  7 20:12 HEAD
drwxr-xr-x 2 root root 4096 Apr  7 20:12 hooks
drwxr-xr-x 2 root root 4096 Apr  7 20:12 info
drwxr-xr-x 4 root root 4096 Apr  7 20:12 objects
drwxr-xr-x 4 root root 4096 Apr  7 20:12 refs

Ist es möglich, dass ich das Submodul am anderen Ende, also bei einer geclonten Kopie des Bare-Repos auf dem Rechner einfügen muss statt direkt am Raspi?

P.S.: Alles gehört root, da ich nicht mit dem Nutzer git arbeiten kann, sondern nur mit dem Nutzer pi, also sudo brauche - der Nutzer git ist auf eine git shell beschnitten worden, da er für den Zugriff von anderen Menschen freigegeben ist, die aber keinen direkten SSH-Zugriff erhalten sollen. Nachdem alles läuft, würde ich den Besitz für den kompletten Ordner an Nutzer und Gruppe git übertragen.
 
Photon schrieb:
Ist es möglich, dass ich das Submodul am anderen Ende, also bei einer geclonten Kopie des Bare-Repos auf dem Rechner einfügen muss statt direkt am Raspi?
Genau. Einmal klonen, submodule hinzufügen, pushen, tadaaa.
 
Mhh, ok, das funktioniert! Aber ich bin mir nicht ganz sicher, wie weiter. Er hat von Gitlab den kompletten Ordner als Submodule geklont, dort heißt ja der Überordner wie der Projektname. Also ganz konkret heißt mein Test-Repo C auf dem Raspi test.git und der Projektname bei Gitlab ist tpiq-experimental. Also habe ich jetzt drin

test/tpiq-experimental/web (das ist das Framework)
test/tpiq-experimental/tex (das sind die Dummy-Inhalte)

Ich habe nun die richtigen Inhalte rein kopiert, das sind zum Einen Dateien, die nach test/tpiq-experimental/tex gehen, zum anderen weitere Unterordner von test/tpiq-experimental/. Die Ordnerstruktur in test/tpiq-experimental/ ist nach dem Reinkopieren der Inhalte wie folgt:

Bash:
$ ls -l
insgesamt 28
drwxr-xr-x 2 photon users 4096  7. Apr 20:41 exercises
drwxr-xr-x 2 photon users 4096  7. Apr 20:41 external
drwxr-xr-x 2 photon users 4096  7. Apr 20:41 solutions
drwxr-xr-x 2 photon users 4096  7. Apr 20:42 tex
-rw-r--r-- 1 photon users 6125  7. Apr 20:30 TODO
drwxr-xr-x 5 photon users 4096  7. Apr 20:30 web

Und nun sieht das so aus:

Bash:
$ git status
Auf Branch master

Noch keine Commits

Zum Commit vorgemerkte Änderungen:
  (benutzen Sie "git rm --cached <Datei>..." zum Entfernen aus der Staging-Area)
    neue Datei:     .gitmodules
    neue Datei:     tpiq-experimental

Änderungen, die nicht zum Commit vorgemerkt sind:
  (benutzen Sie "git add <Datei>...", um die Änderungen zum Commit vorzumerken)
  (benutzen Sie "git restore <Datei>...", um die Änderungen im Arbeitsverzeichnis zu verwerfen)
  (committen oder verwerfen Sie den unversionierten oder geänderten Inhalt in den Submodulen)
    geändert:       tpiq-experimental (geänderter Inhalt, unversionierter Inhalt)

[photon@photon-desktop test]$ git add -A
[photon@photon-desktop test]$ git status
Auf Branch master

Noch keine Commits

Zum Commit vorgemerkte Änderungen:
  (benutzen Sie "git rm --cached <Datei>..." zum Entfernen aus der Staging-Area)
    neue Datei:     .gitmodules
    neue Datei:     tpiq-experimental

Änderungen, die nicht zum Commit vorgemerkt sind:
  (benutzen Sie "git add <Datei>...", um die Änderungen zum Commit vorzumerken)
  (benutzen Sie "git restore <Datei>...", um die Änderungen im Arbeitsverzeichnis zu verwerfen)
  (committen oder verwerfen Sie den unversionierten oder geänderten Inhalt in den Submodulen)
    geändert:       tpiq-experimental (geänderter Inhalt, unversionierter Inhalt)

[photon@photon-desktop test]$ git commit -m "Initial commit"
[master (Root-Commit) de585d0] Initial commit
 2 files changed, 4 insertions(+)
 create mode 100644 .gitmodules
 create mode 160000 tpiq-experimental
[photon@photon-desktop test]$ git status
Auf Branch master
Ihr Branch basiert auf 'origin/master', aber der Upstream-Branch wurde entfernt.
  (benutzen Sie "git branch --unset-upstream" zum Beheben)

Änderungen, die nicht zum Commit vorgemerkt sind:
  (benutzen Sie "git add <Datei>...", um die Änderungen zum Commit vorzumerken)
  (benutzen Sie "git restore <Datei>...", um die Änderungen im Arbeitsverzeichnis zu verwerfen)
  (committen oder verwerfen Sie den unversionierten oder geänderten Inhalt in den Submodulen)
    geändert:       tpiq-experimental (geänderter Inhalt, unversionierter Inhalt)

keine Änderungen zum Commit vorgemerkt (benutzen Sie "git add" und/oder "git commit -a")

Aus irgendeinem Grund zeigt er also direkt nach einem Commit vom kompletten Repo-Ordner (git add -A), dass es Änderungen gibt, die nicht zum Commit vorgemerkt sind. Was hab ich denn da für einen Mist gebaut?
 
Zurück
Oben