The git server I installed way back in November 2013 is still going strong. I upgraded it to Ubuntu Server 14.04 at some point, and now that is reaching end of life and it's time to upgrade. This time I've decided to install on a tiny little Intel NUC. The server is currently using all of 8.3GB worth of space, so a NUC with a 64GB SSD is actually overkill.
First, I grabbed the ISO that I wanted to use. I went with Ubuntu Server 18.04.x. This will be supported until April 2023.
I used mkusb to create a bootable flash drive from the Ubuntu .iso file. mkusb74 is the version I usually use.
The USB install was ok, although it did require a little babysitting as it would ask various questions along the way. It's a text mode interface, and the final install is about 5.7GB.
In the past, I've tried LVM (Logical Volume Manager) and was irritated by the fact that the boot directory is on a rather small partition that fills up as new kernels come out. This time I skipped LVM.
The install offered an "Install OpenSSH Server" option. I selected it, and it installed it for me. If you forget, you can always install it later:
This time around I used Ethernet and it was automatically detected and configured.
If you go the wireless route, you may need to add the appropriate lines to /etc/network/interfaces. In the past, my entries have looked something like this:
Put your wireless router SSID (name) where you see "WirelessRouterName" and your WPA2 passphrase where you see "passphrase". This assumes you are using WPA2 and PSK mode. See the man page for wpa_supplicant.conf(5) for the details on each of the above fields.
Next you'll want to configure the firewall. I used ufw, which is probably not a good idea for a server that isn't protected by another hardware firewall. Setting up ufw is very easy:
Use apt and install the latest updates.
Use one of the following (or try all of them) to see what servers are running and listening on ports. Ubuntu tends to have almost nothing running after a clean install. Very nice.
Using git through ssh is simple and secure, so I decided to go with that approach. My main concern was securing ssh so that it would be very difficult to hack. These steps are probably not complete, so I recommend that you check other sources to find out how to secure a ssh server.
Make sure the admin account has an ssh key so that we can get back in after we lock things down. If you are working from the console, this might not be a big deal, but it will probably make your life a lot easier.
The /etc/ssh/sshd_config file has all the settings for sshd that you can use to make it more secure. In no particular order...
Restrict the encryption ciphers to the best by adding this line to sshd_config:
Pick a random port number between 10000 and 65535 (see random.org) and move the server to that port. Add or adjust the following line in sshd_config, replace "port" with the port number you've picked:
Restrict authentication so that only public/private key authentication is allowed. Add or adjust the following lines in sshd_config:
Turn off tcp tunneling so your users can't use your server to bounce around the Internet and cause trouble. Add or adjust this line in sshd_config:
Note that this is pretty extreme as it blocks tunneling even to other ports on the server. If you want to selectively allow connections, e.g. to 192.168.1.200:3000 only, do this:
Finally, once you've made all your changes, ask sshd to reload the config file (this sends it a good ol' SIGHUP):
So that ssh traffic can get in through the random port we picked above, we'll need to poke a hole through the server's firewall. With ufw (replace "port" with the random port number we selected for sshd):
Now we can test ssh from the local network. From another computer on the network, try logging into the server with ssh. (Replace "port" with the random port number we selected for sshd.):
Some additional ssh security tips to try:
For 18.04, this is already installed.
Set up a "git" group. Members of this group will be able to push to the repo. Everyone else will be able to fetch only.
Then add your user to that group so that you can test. Change "ted" to your userid on the server.
Now we need to create the /srv/git directory and set it up properly. (Be sure to replace "ted" with your server userid. "root" is probably ok too.)
Tell git that we want to do sharing with the git group. This should preserve the "git" group on all files along with the setgid bit on all directories. We'll double-check later just in case.
Now you can clone your first repo into the /srv/git directory. One way is to clone from a repo in another directory. In this example, we assume the repo is in a directory called "source-repo-dir". Replace "projectname" with an appropriate name for the git project.
Setting core.sharedRepository to "group" should have ensured that the group and setgid bits were handled properly when we did the clone. Check to make sure this is the case. Go through the new repo and make sure all files and directories belong to the "git" group and that the setgid bit is on for all directories. If this isn't the case, fix up the permissions with chown and chmod:
Now we can test git from another machine on the network. Clone the repo and see if it works. Replace "user" with your server userid, "host" with the IP or hostname of the server, and "port" with the random sshd port we selected. Also replace "projectname" with the name of the project.
Set up a hole in your Internet firewall so that people outside of the local network can get to your git server. If you have a dynamic IP, set up Dynamic DNS so that others can find you. With my Asus router, this was built-in and very easy to set up. Next, poke a hole through your firewall to allow data for the sshd port we selected above to get to the server. E.g. if the port we picked was 2222, and the server was at 192.168.5.15, set up port forwarding on the firewall to send connections for port 2222 to 192.168.5.15:2222.
Once this is set up, try testing from the outside. Or test from the inside with the dynamic DNS name. This should be almost as good.
To add a user to the server:
Optionally, add them to the "git" group if you want them to be able to push:
For the git-shell to work, you must create a git-shell-commands directory. Not sure why, but if you don't, you'll get errors that it is missing.
Ask them to generate a public key for you with ssh-keygen and email it to you. Append their public key to their authorized_keys file.
And finally, for good measure, normalize the owner/group:
Now they should be able to clone from their machine:
To troubleshoot, the user can use ssh to connect and they should get a "git>" prompt if all is configured properly. "quit" will exit.
See Ubuntu LTS Server Guide: Automatic Updates.
Turns out this is already installed on Ubuntu 18.04 server.
The default configuration stays on top of security updates only. You can change that in
/etc/apt/apt.conf.d/50unattended-upgrades. You can also configure autoremove and reboots when required in that file.
Git repos occasionally need garbage collection. You can set up a weekly script to do this. If you don't, I suspect that git itself will periodically garbage collect your repos anyway, so no big deal. Here's my git garbage collection script, git-gc. You'll need to tweak "projectname.git" for your needs. Plus, you might need to gc multiple repos.
A server that is exposed to the public Internet needs to be monitored to make sure it continues to be secure. There are many ways to check this. This is definitely not an exhaustive checklist. In fact, it's a pretty lousy one based on a few things I've researched. I highly recommend looking elsewhere for advice on this.
The /var/log/auth.log file shows attempted ssh logins. You can monitor this to detect attempted break-ins.
denyhosts is a program that will watch for excessive login failures and ban the host that is causing them. This should block attackers before they get in by brute-force.
Use lsof -i to make sure no unexpected servers are running.
"logcheck" is a program that might be useful, but I've not looked into it.
An Intrustion Detection System like tripwire is also a good idea. It will detect modifications to the system that might be an indication of a break-in.
If you want to keep up with the latest releases of Git, but still run the LTS version of Ubuntu, you'll need to download the Git source and build it.
First, you'll need to install some software to do the build:
You can find the Git source on github. The tags on the Git project have .tar.gz files with the source:
You can use wget to download the file you want. Or you can use the text browser "w3m" to find and download the latest version:
Move the cursor on top of a link and hit enter to download. Press q to exit out of w3m.
Expand the code archive with tar:
Within the git source directory, you will find an INSTALL file with instructions on how to build and install. For 22.214.171.124 the "configure" set of steps seemed to work best:
And you've got the latest Git.
I've been trying to get NUT to monitor my UPS and shutdown the server when the UPS runs out of power. Click here for details.
Ubuntu Server Guide 12.04
How to Deploy a Server - From Linux Journal. Walks through the various options for automating server setup: by hand, images, post-install script, central CM (e.g. Puppet and Chef). Might be worth looking into so that I can migrate the server easily.
The Git Book
Git Conflict Resolution - My article walking through one of the trickier aspects of git.
Copyright (C) 2012-2020, Ted Felix
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. See http://www.gnu.org/licenses/fdl.html for the full text of this license.
<- Back to my software page.