Github at Home

But Why Though?

If you are already an avid self-hoster or more interested in the tutorial here feel free to skip this section, but I wanted to take a moment to outline some of the reasons having a self hosted Github like CI/CD at home can be important.

GitHub Can Take Down Your Code Without Notice.

There have been many stories over the last few years of projects disappearing from GitHub for various legal reasons. The unfortunately part about relying on GitHub to host source control is that pretty much any DMCA takedown request must be immediately followed by action. It is not up to GitHub to determine validity, as such companies have and do make incorrect DMCA requests which could result in your code being removed without due cause.

This has happened to both youtube-dl and SymPy. Although in the end the two repositories made it back up, it's important to note that you're using GitHub at the behest of Microsoft, and that can change at any time.

DockerHub Has Very Limited Support for Free Private Images

DockerHub has always had a limited free tier which limits how useful their hosting may be for individuals. I do however believe that this is the right choice. DockerHub is an invaluable part of the developer landscape in 2022 and it's only going to become more used as time goes on. Finding a sustainable model for running their service is important. However, for an individual who wants to host 4-5 images for their own private use, self-hosting provides a better solution in most cases.

Tutorial

Summary

We're going to use Docker as an infrastructure base to build our own GitHub alternative with a reproducible deployment method using docker-compose on a Ubuntu 20.04 system. While this was tested on Ubuntu 20.04, it should work for nearly any other distro that supports docker.

Software To Deploy

  1. Gitea
  2. Drone.io
  3. Docker Registry

This stack uses minimal resources at idle , and should be able to be run on a fairly resource limited machine. The contains themselves idle less than 100mb on my machine, but your mileage may vary.

We'll also be using Traefik to provide HTTPS certifications and a reverse proxy for our services, but you can substitute those sections for a proxy of your own choosing.

I'll also briefly talk about running CI/CD for an Mkdocs Wiki and an Ansible Playbook.

Alternatives Considered

GitLabI did try GitLab. I found it difficult to deploy and not very straight forward on how to manage it longer term. Also it was very slow to start and fairly resource intensive

OneDevThis is a good alternative for those looking for a GitLab like solution, it's less resource intensive than GitLab, but still uses more than what we'll be deploying today. It's also not super widely used so you may find limited support if you encounter a problem. I deployed it for a few days and found it usable, but too different from GitHub (what I'm used to). Additionally, I also have an unfounded hate for Java applications.

Step 1: Infrastructure / Servers

First and foremost you'll need a server setup for docker. The best way to do this is to follow the official guide. You'll need docker and docker-compose. Follow these links and come back when you have them installed.

Install Docker

Install Docker Compose

Step 2: Gitea

Gitea is a community managed lightweight code hosting solution written in Go. It is published under the MIT license. It is one of the most popular options for self-hosting a git server.

Step 3: Drone.io

Step 4: Docker Registry

References

Gitea / Drone Docker-Compose

---version: "3.7"services:  gitea:    image: gitea/gitea:1.15.4    container_name: gitea    networks:      - web      - gitea    volumes:      - /home/hayden/docker/gitea/gitea:/data      - /home/hayden/docker/gitea/gitea/public/css:/data/gitea/public/css      - /etc/timezone:/etc/timezone:ro      - /etc/localtime:/etc/localtime:ro    ports:      - "3000:3000"      - "2222:22"    environment:      - USER_UID=1101      - USER_GID=1101      - DISABLE_REGISTRATION=true      - ROOT_URL={{ ROOT_URL }}      - GITEA__database__DB_TYPE=postgres      - GITEA__database__HOST=gitea-postgres:5432      - GITEA__database__NAME=gitea      - GITEA__database__USER=gitea      - GITEA__database__PASSWD={{ DATABASE_PASSWORD}}      - GITEA__ui__THEMES=auto,gitea,arc-green,gitea-modern    depends_on:      - gitea-postgres    restart: unless-stopped  gitea-postgres:    image: postgres:13    container_name: gitea-postgres    networks:      - gitea    volumes:      - /var/run/docker.sock:/var/run/docker.sock    environment:      - DRONE_RPC_PROTO=http      - DRONE_RPC_HOST=drone:80      - DRONE_RPC_SECRET={{ RPC_SECRET }}      - DRONE_RUNNER_CAPACITY=2      - DRONE_RUNNER_NAME=drone-runner    restart: alwaysnetworks:  web:    external: True  gitea:    external: False

Docker Registry UI Docker-Compose

# Ansible managed---version: "3.7"services:  docker-registry:    image: registry:2.7    container_name: docker-registry    networks:      - docker-registry    volumes:      - /opt/docker-registry:/var/lib/registry    environment:      - REGISTRY_HTTP_SECRET=my_registry_secret      - REGISTRY_STORAGE_DELETE_ENABLED=true  docker-registry-ui:    image: joxit/docker-registry-ui:latest    container_name: docker-registry-ui    networks:      - web      - docker-registry    ports:      - "80:80"    environment:      - DELETE_IMAGES=true      - REGISTRY_TITLE=Home Lab Registry      - NGINX_PROXY_PASS_URL=http://docker-registry:5000      - SINGLE_REGISTRY=true    depends_on:      - docker-registry    restart: unless-stoppednetworks:  web:    external: True  docker-registry:    external: False