Setting Up My Own Git Server On A Pi

Edit:
Did use additional spare time during the last few months to familiarize myself with Ansible - and to transform this worklog into an Ansible Playbook. Means you can now download this project, follow the readme and Ansible will do the work for you :slight_smile:


Having recently switched to Pi 4 (4GB) for my openHAB setup I decided to use the free Pi 3 to set up my own git server.
While my setup might only be relevant for a few, parts of it might be useful for different setups:

I have two different openHAB servers, each in a different LAN. Parts of the (docker-based) setup are shared, the rest is unique for each openHAB instance (for example: same docker-compose-file but different things-files1).

git_setup
(Generated with plantUML2)

I’m not really comfortable with pushing whole configuration, including passwords and other sensitiv data, to a commercial provider (aka GitHub), so I had the following requirements:

  • Hosted on my own hardware
  • Reachable from each LAN
  • Reachable from outside of my LAN(s)
  • Where possible the openHAB server should automatically and instantly pull new relevant commits3
  • As secure as possible for me4
    • no outgoing connections
    • no forwarding
    • key-based authentification
    • no (internet) exposure for my openHAB servers
    • no exposure for the rest of my LAN

So much for my motivation, let’s get going:

  • Setting up the OS
  • Install Git
  • Hardening
  • Port Forwarding
  • Client Configuration
  • Pull on Commit

Setting up the OS

  • download Rasbian Lite https://www.raspberrypi.org/downloads/
  • write image to SD card https://www.raspberrypi.org/documentation/installation/installing-images/README.md
    • eject & reinsert SD card
    • enable ssh: touch /Volumes/boot/ssh
    • eject & insert SD card into your Raspby
  • connect via ssh: ssh pi@raspberrypi (password raspberry)
  • change standard username5
    • add temp user: sudo useradd -m tempuser -s /bin/bash
    • set password: sudo passwd tempuser
    • add to sudo group: sudo usermod -a -G sudo tempuser
    • [if you have troubles check: grep sudo /etc/group ]
    • reconnect as tempuser and change to /etc/: cd /etc/
    • change references:
      • backup files: sudo tar -cvf authfiles.tar passwd group shadow gshadow sudoers systemd/system/autologin@.service sudoers.d/*
      • replace: sudo sed -i.$(date +'%y%m%d_%H%M%S') 's/\bpi\b/<my user>/g' passwd group shadow gshadow sudoers systemd/system/autologin@.service sudoers.d/*
      • move homedirectory: sudo mv /home/pi /home/<my user>
      • create soft link: sudo ln -s /home/<my user> /home/pi
    • reconnect as
      • change password: passwd <my user>
      • remove tempuser: sudo userdel tempuser
      • remove homefolder: sudo rm -Rf /home/tempuser
  • Change hostname: sudo sed -i 's/raspberrypi/git’ /etc/hostname /etc/hosts
    • reboot: sudo reboot
  • Configuration: sudo raspi-config
    • 7/A1: Expand Filesystem
    • 8: Update
  • Optional - I prefere vim, but you can simply use nano instead which is already installed: install vim

Git Setup

  • Install git: sudo apt install git
    • set username: git config --global user.name „<my user>“
    • set email: git config --global user.email <my email>
    • add git shell
      • see if git-shell is already known: cat /etc/shells
      • if not make sure git-shell is installed on your system: which git-shell
      • and add the path to git-shell from last command to: sudo vim /etc/shells
  • Add user git: useradd git
    • set password: sudo passwd git
    • add <my user> to group git: sudo usermod -a -G git <my user>
    • check: grep git /etc/group
    • switch user: su - git
    • create ssh folder: mkdir /home/git/.ssh && chmod 700 .ssh
    • create key file: touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys
    • copy keys from clients6
      • on Mac/Linux: ssh-copy-id git@git
      • on Windows: manually copy the content of C:\Users<my user.ssh\id_rsa.pub to (on server) /home/git/.ssh/authorized_keys
    • forbid forwarding - add no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty and a space in front of every key
    • initialize git
      • mkdir /home/git/repos
      • cd /home/git/repos
      • if you already have a repo: git clone --bare ssh://<my user>@<my computer>/path/to/repo openhab.git
      • otherwise: git init --bare
    • switch back to <my user> exit
    • Allow only git shell for user git: sudo chsh git -s $(which git-shell)
    • add message:
      • sudo mkdir /home/git/git-shell-commands
      • sudo vim /home/git/git-shell-commands/no-interactive-login
      • insert:
#!/bin/sh
printf '%s\n' "Hi $USER! You've successfully authenticated, but you are not“
printf '%s\n' „provided with interactive shell access."
exit 128
EOF
      • sudo chmod +x /home/git/git-shell-commands/no-interactive-login
      • change ownership for git home folder: sudo chown -R git:git /home/git

Hardening7

#!/bin/sh
sudo apt-get update && sudo apt-get upgrade -y
sudo rpi-update
sudo apt-get autoremove
sudo apt-get autoclean
sudo reboot
    • make executable: sudo chmod +x ~/auto-update/script/update.sh
    • create log folder: sudo mkdir ~/auto-update/logs
    • create log file: touch ~/auto-update/logs/cronjob.log
    • create cronjob: crontab -e
      • add at the bottom (choose a value between 0 and 59 for ): <x> 0 * * * sh /home/<my user>/auto-update/script/update.sh 2>/home/<my user>/auto-update/logs/cronjob.log
  • firewall
    • install: sudo apt install ufw
    • allow ssh: sudo ufw allow <custom ssh port>/tcp
    • activate: sudo ufw enable
      • yes
    • list current rules: sudo ufw status
  • fail2ban - check for suspicious login activity
    • install: sudo apt install fail2ban
    • configure for ufw10
      • copy config: sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
      • open /etc/fail2ban/jail.local and
        • find banaction - change value to ufw
        • find Jails / sshd and add enabled = true

Port Forwarding

To access your git server from outside your LAN you need to enable port forwarding on your router to your git server on your custom ssh port. How to do that is specific to your router.
Ideally you would move your git server into a network seperated from the LAN your devices are sharing (a guest network or even a full blown DMZ). Sadly, not every router supports a DMZ or port forwarding into the guest network…

Additionally you need an Dynamic DNS Service (some routers provide there own, if not a google search might help) or a static IP address to conntact your router from outside your LAN.

Client Configuration

  • ssh-config:
    • Mac/Linux: sudo vim /etc/ssh/ssh_config
    • Windows: C:\Program Files\Git\etc\ssh\
    • put the following text after the intro but before the line Host *
Host git
    Hostname <your DynDNS or static IP address>
    Port <your custom ssh port>
  • create local repo:
    • cd ~/repos
    • push always to upstream branch: git config --global push.default upstream
    • for every branch (common, server_a, server_b)
      • clone server repo: git clone ssh://git@git/home/git/repos/openhab.git <branch>-openhab
      • cd <branch>-openhab
      • create master branch and track server branch: git checkout -b master origin/<branch>
      • show log with all branches: git log --oneline --decorate --graph --all
      • Delete branches other than master: git branch -d <other branch>
      • cd ..
  • add aditional clients (e.g. openhab server)
    • client
      • see section client configuration/ssh_config
      • if no key exists: ssh-keygen -o
      • copy the result: cat ~/.ssh/id_rsa.pub
    • git server
      • sudo vim /home/git/.ssh/authorized_keys
      • insert client key in a new line
      • insert no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty and a space in front of the new key

Pull on Commit

  • on client, in local branch repo folder: git config --local alias.xpush '!git push && ./notifyServer.sh'
    • create script notifyServer.sh
#!/bin/bash
ssh <my user>@<openhab-server> /path/to/my/openhab/repo/pullUpdates.sh
echo "executed post-commit"
EOF
    • chmod 777 notifyServer.sh
  • use git xpush in the local branch folder to notify the local openhab server about changes
  • on openhab server in git repo create script pullUpdates.sh
#!/bin/bash
cd <openhab-repo>
git pull
EOF

I hope some people find this post usefull - let me know if you have suggestion for improvment :slight_smile:

Steps I might consider for the future:

  • Using scripts similiar to the ‘Pull on Commit’ section to automate merging changes to branch common back into my server branches.
  • Familiarize myself with the possibilities of GitLab and / or Gogs and running it in a container :thinking:

1. [More details in my request for help How to organize my openHAB setup with multiple git repos?]
2. [Generated with the following code:]

@startuml
scale 1.5
skinparam cloudBackgroundColor Red
skinparam rectangleBackgroundColor LightGreen
skinparam nodeBackgroundColor LightYellow
skinparam componentBackgroundColor LightBlue

cloud "Internet" as int {
    node "git" <<server>> as git {
        [A] <<branch>> as ba
        [B] <<branch>> as bb
        [common] <<branch>> as bc 
    }
}

rectangle "Home A" <<LAN>> {
    node "openHAB A" <<server>> as oha
    node "Mac" <<client>> as mac
}

rectangle "Home B" <<LAN>> {
    node "openHAB B" <<server>> as ohb
    node "Windows" <<client>> as win
}

note top of int
    1. clients pushes change to git server
    2. [if in the same Home] client sends info to openHAB server
       [otherwise] trigger pull manually via VPN
    3. openHAB server pulls branch change
end note

git <-down- mac : push\npull
git <-down- win : push\npull
ba <-right- oha : pull
bb <-left- ohb : pull
oha <.. mac : info\nafter push
ohb <.. win : info\nafter push

bc -[hidden]left-> ba
bc -[hidden]right-> bb
@enduml

3. [Tried that already earlier with a less comlex setup: Git based non public versioning and deploy workflow]
4. [I might be an IT specialist, but I’m neither a security specialist nor an Linux specialist]
5. [Details see this post at unixetc.co.uk]
6. [How to set up git on your client see my earlier post or Pro Git]
7. [Details see this post at raspberry.org]
8. [Details see this post at instructables.com]
9. [Possible alternative see this post at elektronik-kompendium.de (German)]
10. [Details see this post at zaiste.net]

3 Likes

Did you look at gogs? It looks very github-ish. And runs ina docker container. Has webhooks etc.

1 Like

Cool guide, a word of warning though, SD cards in Raspberry PI’s are not the most reliable storage types.
So I hope you’re using external USB storage?

You are right. I’m using a external SSD for my openHAB server for exactly that reason.
Having said that - I’m not using external storage for my git server. Since everyone of my clients has a copy of the repo it will not really matter if the SD card dies. I’ll simply follow my own guide and set up on a new SD card :blush: