Sunday, June 24

Here’s, which is (provisionally) where I’m planning to host my own projects from here on out. This was precipitated by the Microsoft-eating-GitHub thing, but now that I have it feels like something I should have set up a while ago.

For the moment, it’s running Gitea, a sort of GitHub-lite in terms of interface, which is written in Go and distributed as a single binary. This feels like a good piece of software in many ways, although some of the decisions to straightforwardly copy GitHub features feel kind of arbitrary. It’s talking to a local PostgreSQL instance, although it’s also capable of using SQLite. At the volume of traffic I’m likely to get, SQLite would probably be fine.

I decided to put Gitea in a subdirectory and write a minimal front page for the site, so as to avoid locking myself into one piece of third-party tooling. I’ll experiment with other ways to view the repositories stored there, and probably with other version control systems, like the SQLite-backed Fossil. is a $5/month DigitalOcean droplet with a gig of memory and 25 gigs of storage, running Debian 9.4.

I’m using Nginx to serve the front page, and as a reverse proxy for the Gitea installation, with the following configuration:

server {
  root /var/www/html;

  # Add index.php to the list if you are using PHP
  index index.html index.htm index.nginx-debian.html;
  server_name; # managed by Certbot

  listen [::]:443 ssl ipv6only=on; # managed by Certbot
  listen 443 ssl; # managed by Certbot
  ssl_certificate /etc/letsencrypt/live/; # managed by Certbot
  ssl_certificate_key /etc/letsencrypt/live/; # managed by Certbot
  include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

  location / {
    ssi on;

  location /gitea/ {
    proxy_pass http://localhost:3000/;

server {
  if ($host = {
    return 301 https://$host$request_uri;
  } # managed by Certbot

  listen 80 ;
  listen [::]:80 ;
  return 404; # managed by Certbot

You can see source for the front page in the p1k3 repo.

I used Let’s Encrypt / Certbot to get a certificate for the site (note all the # managed by Certbot comments above). I still have not set up a cron job to renew the cert.

For copying repos over from GitHub, I used Jonas Franz’s gitea-github-migrator, with a command like the following:

gitea-github-migrator migrate-all \
    --gh-user brennen \
    --gh-token $GH_TOKEN \
    --url \
    --token $GITEA_TOKEN \
    --owner 1

On GitHub, you can get an API token under Settings / Developer Settings / Personal access tokens, and on a Gitea installation under Your Settings / Applications.

I’m not sure whether I’m going to continue mirroring existing repos to GitHub or not. In terms of discoverability, archival resilience, and continuity for anyone who has something cloned from there, it makes sense. On the other hand, it continues lending force to GitHub’s near-monopoly. Maybe I’ll just add some disclaimers to READMEs.

Fortunately, no one actually uses any of my code, so it’s all kind of academic.

The above is a pretty haphazard writeup, and it’s missing a bunch of detail about installing golang and configuring Gitea. As I refine the setup, I’ll try to document the whole thing more effectively in code, so that it can be mostly reproduced by running a script or something.