diff options
Diffstat (limited to 'blog_src/git_server.md')
| -rw-r--r-- | blog_src/git_server.md | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/blog_src/git_server.md b/blog_src/git_server.md new file mode 100644 index 0000000..4fc5505 --- /dev/null +++ b/blog_src/git_server.md @@ -0,0 +1,174 @@ +# How to make your own git server/website + +## Server setup + +We're going to create a `git` user and group, will be used for accessing our git repositories without needing to be root. + +```sh +useradd -m git +mkdir /srv/git +chown git:git /srv/git +``` + +The repositories will be stored as bare, this mean that we will only store the `.git` folder to save space. + +>To create a bare repo: `git init --bare` + +>To clone a repo as bare: `git clone bare <location>` + +You can either add a password for the git user or put your ssh public key in `/home/git/.ssh/authentication_keys` and disable password authentication for ssh. + +You can now clone from your server with `git clone git@<hostname>:/srv/git/<reponame>` + +## Better server interaction with git-shell + +Permit the git user to have a regular shell can be a security issue, +we would like that to restrict him to a few action, +like creating/deleting a repository, importing a repository, listing the repo currently stored + +Make the git-shell a valid shell `echo $(which git-shell) >> /etc/shells` + +Change the shell of the git user `chsh -s $(which git-shell) git` + +If you try to ssh as the git user, you will be greeted with something along the line of: + +``` +fatal: Interactive git shell is not enabled. +hint: ~/git-shell-commands should exist and have read and execute access. +Connection to <host> closed. +``` + +As suggested by the hint we have to create the directory `/home/git/git-shell-commands` and put the commands (executable) that the git user is allowed to execute in. + +Here is a script to create a repo: + +```sh +#!/bin/sh +[ $# -ne 1 ] && echo "Usage: $0 name" && exit 1 +repo_path="/srv/git/$1.git" +[ -d "$repo_path" ] && echo "$0: Error: $repo_path already exist" && exit 2 +mkdir "$repo_path" +git -C "$repo_path" init --bare +``` + +Put it under `git-shell-commands/create` and make it executable then try to ssh as the git user once again. + +You should have a prompt like `git> `, you can call the `create` command with a repo name as the first argument and it should create a new repository for you. + +## Allow anyone to clone with git-daemon + +The git daemon will allow annone to clone your repos with something like `git clone git://<host>/<repo>` + +`git daemon --reuseaddr --base-path=/srv/git/ /srv/git/` and that's it + +You should make it a service in your service supervisor, example with systemctl: + +``` +[Unit] +Description=Start Git Daemon +[Service] +ExecStart=/usr/bin/git daemon --reuseaddr --base-path=/srv/git/ /srv/git/ +Restart=always +RestartSec=500ms +StandardOutput=syslog +StandardError=syslog +SyslogIdentifier=git-daemon +User=git +Group=git +[Install] +WantedBy=multi-user.target +``` + +Put it in `/etc/systemctl/system/git-daemon.service` and run `systemctl enable git-daemon` then `systemctl start git-daemon`. + +### Public/private repo + +You may want to introduce a distiction of which repo is public and which is private + +A simple way to do this is by creating a `public` directory in `/srv/git` which will contain symbolic link to the repo in `/srv/git` + +``` +/srv/git +|- foo.git +|- bar.git +|- qux.git +|- public + |- foo.git -> /srv/git/foo.git + |- bar.git -> /srv/git/bar.git +``` + +You can change the git daemon to only serve the public repositories `git daemon --reuseaddr --base-path=/srv/git/public /srv/git/public` + +## Generate a static website + +Here we will create a site that look's like [this](https://git.suckless.org) with [nginx](https://nginx.org), [stagit](https://git.codemadness.org/stagit/) and a few scripts. + +If you don't like the minimalistic appearence of the site, [here](https://git.wiki.kernel.org/index.php/Interfaces,_frontends,_and_tools#Web_Interfaces) is a list of alternative. + +Install nginx (on Debian based distro): `apt install nginx` + +Create a basic configuration file for your site: + +``` +server { + root /var/www/git; + index index.html index.htm; + + server_name git.<hostname> www.git.<hostname>; + + location / { + try_files $uri $uri/ =404; + } +} +``` + +It's a convention to put it in a `git.` subdomain. +`systemctl enable nginx && systemctl start nginx` + +Install stagit: + +``` +git clone git://git.codemadness.org/stagit +cd stagit +make +make install +``` + +To generate a static page for a repo `stagit /path/to/repo`. +To generate an index for multiple repositories `stagit-index repo1 repo2 repo3 > index.html` + +Here is a script to generate a site for all repo in `/srv/git/public` + +```sh +#!/bin/sh + +repos=$(find /srv/git/public/ -type l) +current=$(pwd) + +for repo in $repos; do + repo_name=$(basename "$repo" | sed 's/\.git//') + repo_static_path="/var/www/git/$repo_name" + mkdir -p "$repo_static_path" + cd "$repo_static_path" || exit 1 + echo "git://cacharle.xyz/$repo_name" > "$repo/url" + stagit "$repo" + ln -sf "$repo_static_path/log.html" "$repo_static_path/index.html" + echo "Generated $repo_static_path" +done + +echo "Creating index" +stagit-index $repos > /var/www/git/index.html + +cd "$current" || exit 1 +chown -R git:git /srv/git +``` + +There is more smart ways to handle this to rebuild the webpages each time someone pushes to the repo with [git hooks](https://git.codemadness.org/stagit/file/README.html#l92). + +## Sources + +* [Setting up \*Your Own\* Git Server](https://www.youtube.com/watch?v=ju9loeXNVW0) +* [Git book - setting up the server](https://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server) +* [Git book - git daemon](https://git-scm.com/book/en/v2/Git-on-the-Server-Git-Daemon) +* [stagit - Static website generator for git repository](https://git.codemadness.org/stagit/) +* [git-shell man](https://git-scm.com/docs/git-shell.html) |
