HOWTO: Build a Jailed Git Repository

HOWTO: Build a Jailed Git Repository
Goals:
The goal of this HOWTO is to get a Git repository server running in a jailed environment. A jailed Git environment increases the security of the server and is the sort of setup you would find in a production environment. The goal for the user is if they want to build a production quality server for their company/commercial product/hobby/secure network/etc, the information here-in would help partially (not entirely!) in doing so.

I hope to share what I've learned when setting one up so others may use this if they find useful; furthermore, experts can way in any anything they might find helpful.

Pre-Requists:
I assume:
  • You are an intermediate UNIX user
  • You know how to use 'vi'
  • You know to boot/install/run FreeBSD
  • You know basics of networking, TCP/IP, firewalls, etc
  • You know basics of using 'git'
  • You have patients, a sense of humour and a drive to get this thing working!

[Server]
1) Install FreeBSD
I assume you can handle this. Here are some notes:
  • Ensure it's minimal as much as possible..
  • Include 'Ports' + 'Source'
  • Create "admin" user and make sure s/he belongs to "wheel" group
  • Ensure DHCP connects successfully.

2) Update Ports
Lets get the latest ports tree
Code:
# portsnap fetch
# portsnap extract
# portsnap update

3) Install + Setup + Config Jails Administration
We will be using 'EZJail-Administration' as a simple unified interface for doing jails administration
Code:
# cd /usr/ports/sysutils/ezjail
# make install clean
# rehash
# ezjail-admin install
# ezjail-admin update -b
We want to allow our jails environment(s) to access the LAN/WAN
Code:
 # echo 'security.jail.allow_raw_sockets=1' >> /etc/sysctl.conf
Let's modify the rc.conf file. Note, we will assign a static IP 192.168.0.238 to our jailed environment - Be sure to set an alias in your pfsense firewall.
Code:
# echo 'ezjail_enable="YES"' >> /etc/rc.conf                          
# echo 'ifconfig_re0_alias0="inet 192.168.0.238 netmask 255.255.255.0"  # jailed git repository server' ' >> /etc/rc.conf  
# reboot

Once we log on again, lets create our "git" jail
Code:
# ezjail-admin create git -f 192.168.0.238
# ezjail-admin console git

Setup ports system in our jailed environment.
Code:
# [Note: I'm assuming you're inside the git jail!]
# rm -R /usr/ports
# mkdir /usr/ports
# exit
# mount_nullfs /usr/ports /usr/jails/git/usr/ports

Lets log back into our new "git" jail and set it up!
Code:
# ezjail-admin console git
# vi /etc/rc.conf
Now that you have VI loaded, please add the following and replace 're0' with the ethernet interface you are currently using (em0, etc).

Code:
# No network interfaces in jails
network_interfaces="lo0 re0"

# Prevent rpc
rpcbind_enable="NO"

# Prevent loads of jails doing their cron jobs at the same time
cron_flags="$cron_flags -J 15"

# Prevent syslog to open sockets
syslogd_flags="-ss"

# Prevent sendmail to try to connect to localhost
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"

# Bring up sshd, it takes some time and uses some entropy on first startup
  sshd_enable="YES"

Now lets add the following to our resolv.conf. Please set the name to what you are currently using, and the ip of your firewall.
Code:
# vi /etc/resolv.conf
[Add the following:]
Code:
search          your_domain_etc_etc.com
nameserver      192.168.2.1

4) Installing + Configuring Git as remote repository.
Lets install our repository. Please note, the next set of instructions where 'more then inspired' from this article. Thanks!
Code:
# cd /usr/ports/devel/git && make install clean
Now lets set the name of the git repository
Code:
# git config --global user.name "Your Full Name"
# git config --global user.email Your_Email@company.com

Setup Git user + group
Code:
# pw groupadd -n git -g 9418
# pw useradd -n git -u 9418 -g git -c "Git User Account" -d /home/git \
	-s /usr/local/libexec/git-core/git-shell -h -

Setup Git user's password
Code:
# passwd git
<Change to what you want>

Setting up directory structure
Create the directories that will be keeping the private and public repositories and set proper permissions:
Code:
# mkdir -p /home/git/private
# mkdir -p /home/git/public
# chown -R git:git /home/git
# chmod -R 0755 /home/git

For every user that needs commit access to the remote repositories, collect their public SSH keys and put them to the authorized_keys file:
Code:
# mkdir -p /home/git/.ssh
# touch /home/git/.ssh/authorized_keys
# chown -R git:git /home/git/.ssh 
# chmod 0700 /home/git/.ssh
# chmod 0600 /home/git/.ssh/authorized_keys

Every new user that needs commit access you will need to get his/hers public key and then put it to /home/git/.ssh/authorized_keys file.

[CLIENT]
5) Setting up Public keys
The next step is to be done on the client. This can be done on any UNIX-like computer in your network (ex. Mac).]
Go to the ssh folder and generate a key, choose whatever password you set for git
Code:
# cd ~/.ssh
# ssh-keygen
< use same password as git user password >
# vi id_rsa.pub    
<Copy the data into clipboard>

Now go back to the server and add the ssh rsa pub key
Code:
# cd /home/git/.ssh
# vi authorized_keys
<Paste the data from clipboard into this file and save>

[SERVER]
6) Creating the Git Repositories
Now, let's create some Git repositories for our system.
Code:
mkdir -p /home/git/private/test-repo.git

Now, lets initialize them - make them ready for push/pull
Code:
cd /home/git/private/test-repo.git && git init --bare --shared

Now, let's export these repos and set proper permissions, so we can clone and fetch from them:
Code:
touch /home/git/private/test-repo.git/git-daemon-export-ok

Finalize by setting every folder/file inside to be owned by the 'git' user.
Code:
# chown -R git:git /home/git

7) Starting git-daemon
In order the clients to be able to pull and fetch from the repos we will use the git-daemon(1). Add these lines at the end of your rc.conf file, so that git-daemon is started during boot-time:
Code:
# vi /etc/rc.conf
[Insert the following]
Code:
# Enable git-daemon
git_daemon_enable="YES"
git_daemon_directory="/home/git"
git_daemon_flags="--syslog --base-path=/home/git --export-all --reuseaddr --detach"

Now during boot-time the git-daemon will be started as well. To start git-daemon, without rebooting, execute the following command:
Code:
# /usr/local/etc/rc.d/git_daemon start

[CLIENT]
8) Pushing content to the repositories
This is to be done on the client side.
Suppose you are a commiter and want to add some files to the already existing and still empty repositories. You will then create a local directory, git-init(1) it, add the files to the index, commit and push them to the remote repo. Note, that this operations requires that your public SSH key is already present in the authorized_keys file on the remote server:
Code:
$ mkdir ~/my-git-repo
$ cd ~/my-git-repo && git init

Initialized empty Git repository in /home/user/my-git-repo/
Code:
$ git remote add origin git@192.168.0.238:/home/git/private/test-repo.git
# echo foo > bar
# git add .
# git commit -m 'initial commit'
# git push origin master

9) Cloning the repositories
Now that you want to clone and track the remote repository what you do is this:
Code:
$ git clone git://git.your_domain.com/private/test-repo.git
 
torr_from_fallout2 said:
Code:
 # echo 'security.jail.allow_raw_sockets=1' >> /etc/sysctl.conf
IMHO you don't need raw sockets for git.
Raw sockets needed to be allowed if you want to ping from inside of the jail to the outside LAN. Only my nagios jail has raw_sockets enabled, all others (including the git jail) have raw_sockets disabled.


torr_from_fallout2 said:
Let's modify the rc.conf file. Note, we will assign a static IP 192.168.0.238 to our jailed environment - Be sure to set an alias in your pfsense firewall.
Code:
# echo 'ezjail_enable="YES"' >> /etc/rc.conf                          
# echo 'ifconfig_re0_alias0="inet 192.168.0.238 netmask 255.255.255.0"' >> /etc/rc.conf  
# reboot
I use a netmask of 255.255.255.255 for all aliased jail interfaces.
I just can't remember where I got this from. Howtos on the internet differ with /24 and /32 netmasks.


torr_from_fallout2 said:
Code:
# [Note: I'm assuming you're inside the git jail!]
# rm -R /usr/ports
# mkdir /usr/ports
# exit
# mount_nullfs /usr/ports /usr/jails/git/usr/ports

I edited the /etc/fstab.[jailname] on the host-system (NOT in the jail) to automatically mount the nullfs into the corresponding jail once it is started.

In your case this would be an additional line in /etc/fstab.git:
Code:
/usr/ports           /usr/jails/git/usr/ports     nullfs ro 0 0


Thanks for a nice HowTo!
 
Thanks for this tutorial, helped me :)

I also set git-shell as the default login shell for user 'git' and deactivated the git-daemon (do not need it). So that I can use just SSH for commits. This suits more my needs ;)
 
Addendum
Client
Xcode + Git Integration
Now that you have your server running from this tutorial, to integrate it with Xcode 5.x.x++, do the following.

1) Load up Xcode
2) Go to "Preferences"
3) Go to "Accounts"
4) Click "+" (plus) add symbol.
5) Enter:
Code:
git.your_domain.com/private/test-repo.git

Now you are able to easily checkout you iOS / OSX projections from your FreeBSD Jailed Git Server! Simply go to 'Repository' menu and you can access your projects from those submenus.

Enjoy the FreeBSD journey :beer
 
Back
Top