GitHub is an amazing platform. It has completely revolutionized the way developers work together on software and has inspired countless individuals and organizations to open-source their code for a more transparent, collaborative development world. It encourages developers to work according to best practices and renowned coding styles, making it easier for people to work together on projects, and boosting overall developer proficiency.
I adore GitHub. Every time I start working on a personal project in my own free time, I can't wait for the exciting moment when I finally share it with the world by typing
git push origin master, hoping that someone stumbles upon it someday. That's usually not the case though, as most of my projects go unnoticed due to the vast number of GitHub repositories. But hopefully, when someone Googles a specific need that I have managed to answer with one of my projects, they'll be able to find it and complain about something not working as it should. =)
What about projects that you are not yet ready to share with the world? Maybe your code isn't perfect yet, or maybe it contains sensitive database credentials or secret API keys that you definitely don't want out there in the open? Maybe you're behind a corporate firewall and can't host your code on cloud services like GitHub? Or maybe you think you built a project that won't benefit anyone else, ever? Maybe, just maybe, you don't want to host your sensitive private repositories on a shared cloud with other people's code, having it sit there, waiting until someone finds a way in, as this talented gentleman did?
GitHub's private repository plan for individuals starts at $7/month. I think that's a bit expensive -- people working on their personal pet projects should be able to create a few private repositories for free. A $7/month fee can get expensive if you plan to have your projects hosted privately on GitHub for years to come. And this doesn't change the fact that your code is sitting in a shared cloud, targeted by many skilled individuals.
How about hosting the repositories on your own servers? There are several host-it-yourself git services, but some of them are extremely complicated to set up, requiring you to sift through slow and complicated installation steps that don't always go as planned, others are quite ugly, and some are simply limited. Luckily, I found Gogs, and it is the easiest of them all to setup and feature-rich, delivering the closest experience to GitHub than any other self-hosted git service!
Gogs lets you host your own private GitHub on your own servers. Literally. It's a very detailed clone of GitHub, both in design and features. It's built in Go and works really, really fast! Check out the live demo here. The fact that it's a GitHub clone makes it really easy to use if you're already used to GitHub's clean interface.
Let's go ahead and set up Gogs on a freshly-spun Ubuntu 14.04 EC2 instance on Amazon Web Services! You can also perform these steps on any other cloud provider, if you're not into AWS for some weird reason that is beyond me.
Launch an Instance
Let's spin-up a new EC2 instance by heading over to the EC2 launch wizard on AWS. Make sure to select Ubuntu Server 14.04 LTS (HVM), as the following installation guide is tailored to debian-based distros, specifically Ubuntu.
If you intend to be the only one accessing Gogs, Amazon's new
t2.nano instance class will definitely suffice. I'd recommend assigning an Elastic IP to your instance and exposing ports
22 (preferably only to your IP) and an additional port that Gogs will listen on, port number
1337, because we're cool. =)
If you happen to own a domain name, I'd highly recommend creating an
A Record at your DNS provider and pointing it at the EC2 server's Elastic IP so that you'll be able to access Gogs via a human-friendly URL, e.g. http://gogs.example.com:1337. This is a requirement if you wish to use Gogs over HTTPS.
Go ahead and grab a cup of coffee while your instance is spinning up.
SSH into the instance and run the following command to update your repository cache and install some basic dependencies for Gogs:
sudo apt-get update sudo apt-get install -y wget unzip git
Let's go ahead and create a new user called
git that will run Gogs and have full ownership over its files:
sudo useradd --system --create-home git
This will create a system user for Gogs and a home directory in
Switch the shell over to the git user and head over to its home directory:
sudo su git cd ~
Grab the latest Gogs version as a
.zip archive from here -- you'll probably need the
amd64 archive since your instance is 64-bit (check with
uname -a, look for
At the time of writing, the latest version is v0.9.13. Let's grab it by using
wget https://dl.gogs.io/gogs_v0.9.13_linux_amd64.zip unzip gogs*.zip rm -rf gogs*.zip
This will download and unzip Gogs for you into the
Run the Binary
Gogs is extremely easy to run -- the archive includes a binary called
gogs that you can invoke directly to run the service, specifying the port as an argument:
cd gogs ./gogs web --port=1337
Look for the
Listen: http://0.0.0.0:1337 log message to verify that everything is working as expected. If so, go ahead and browse to the hostname pointing to your EC2 server, e.g. http://gogs.example.com:1337.
You should be able to see the following installation screen:
If not, you try accessing your server via its Elastic IP, e.g. http://188.8.131.52:1337, and if that still doesn't work, you most likely didn't configure your EC2 security group correctly. Make sure any IP address can access port
1337 in the EC2 server's security group.
Make sure to select SQLite3 as the database type, as it requires no configuration at all. The rest of the configuration is up to you, go crazy!
Be sure to update the Domain and Application URL in the Application General Settings section to point to your subdomain or Elastic IP address. Be sure to use
https:// as the protocol if you wish to set up HTTPS to access Gogs.
This one's important: Make sure to tick Disable Self-registration and Enable Require Sign In to View Pages in the Optional Settings section so Gogs operates in private mode.
Also, set up an account for yourself under Admin Account Settings.
Go ahead and click Install Gogs when you're done. You'll now be presented with a friendly message and a sign-in screen.
After signing in, you'll be able to create repositories, clone, push, and whatever else your heart desires.
That's all, folks!
Just kidding! What about HTTPS encryption? How about setting up a daemon to make sure it runs forever, even if the server reboots? Let's get to it!
Set Up the Gogs Daemon
Gogs provides a daemon script that we can use to have the system automatically run Gogs for us when it boots.
Kill the running Gogs instance, log out of the
git user's shell and back into
ubuntu, and then run the following commands to download the Gogs
init.d script and make it executable:
cd /etc/init.d sudo wget https://raw.githubusercontent.com/gogits/gogs/master/scripts/init/debian/gogs sudo chmod +x gogs
Now all we need to do is edit the init script to add our port to the
gogs binary argument string. Using
sed we can automatically find and replace within the
gogs daemon file without opening it, using the following command:
sudo sed -i -e 's/DAEMON_ARGS="web"/DAEMON_ARGS="web --port 1337"/g' gogs
Let's try running the service now:
sudo service gogs start
If all is well, you should be able to browse to your Gogs instance at http://gogs.example.com:1337.
Let's configure Ubuntu to start Gogs automatically after booting:
sudo update-rc.d gogs defaults sudo update-rc.d gogs enable
You can make sure this actually works by rebooting the system:
Gogs should be accessible automatically after reboot completes.
I'd strongly advise against using Gogs without HTTPS encryption, as your credentials will then be exposed to eavesdroppers using a very simple man-in-the-middle attack whenever you connect via a public Wi-Fi hotspot.
Luckily, setting up HTTPS is dead-simple and free, thanks to Amazon's new AWS Certificate Manager. All you need is a domain name!
Request an ACM Certificate
Follow this tutorial I posted a month ago to generate a wildcard ACM certificate for your domain. Once that's done, all that's left is to set up an Elastic Load Balancer to handle the HTTPS connection on behalf of Gogs.
Set Up an Elastic Load Balancer
Head over to the ELB creation wizard. Specify a name for your Elastic Load Balancer and set the following port forwarding configuration to forward incoming HTTPS traffic at port
1337 to your instance's port
1337 as HTTP traffic:
Create a new security group for your ELB, specifying the following rule to allow anyone to access port 1337 on your ELB:
Finally, choose your generated ACM certificate by selecting Choose an existing certificate from AWS Certificate Manager (ACM):
You can leave the Predefined Security Policy intact -- AWS already selected the most up-to-date policy available.
For the ELB's health check, configure it to ping the
/user/login path, which always returns
200 OK if Gogs is currently running:
Finally, select your EC2 instance and create the ELB!
Point Your Subdomain to the ELB
Now, all that's left is to modify your DNS configuration, changing the
A Record you created before to a
CNAME record, setting the value to your Load Balancer's DNS Name, which you can retrieve by going to the Load Balancers page.
Once the DNS change propagates through the Internet, you'll be able to access Gogs securely through encrypted HTTPS via the same hostname and port:
I'm serious this time. You've successfully set up a persistent, self-hosted, secure, and private Git service! Now get back to working on your personal projects!