Gitea is an open-source GitHub clone. It forks from Gogs which has almost stopped development. Gitea is developed with Golang and is much lighter than GitLab while providing most useful functions. It also has a similar user experience as GitHub does.

Since Microsoft is acquiring GitHub, Gitea is a good choice for self-hosting lightweight solution.

Set Up Containers

Gitea could be easily setup by docker using its official image. Let's start with a docker-compose.yml:

version: '2'
services:
    code:
        image: 'gitea/gitea:latest'
        ports:
            - '$GIT_SSH_PORT:22'
            - '127.0.0.1:$WEB_PORT:3000'
        volumes:
            - ./code:/data
    restart: 'unless-stopped'

Then simply a docker-compose up -d would bring it up. Then we could configure a reverse proxy to it. Here is an example using nginx:

server {
    listen 80;
    listen [::]:80;
    server_name $DOMAIN;

    location / {
        return 301 https://$server_name$request_uri;
    }

    location /.well-known {
        root /var/www/html;
    }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name $DOMAIN;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem;
    include /etc/nginx/ssl.conf;

    client_max_body_size 10G;

    location / {
        proxy_pass http://localhost:$WEB_PORT;
        proxy_redirect off;
        proxy_set_header X-Scheme $scheme;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
    }
}

Now point your browser to $DOMAIN and you should see installation guide. Keeping everything as default and finishing the installation would be fine.

Sharing SSH with Host

With the above docker-compose.yml, Gitea will use $GIT_SSH_PORT to intereact with SSH clients. However there is a way to share port 22 between host and the container.
Let's start with how Gitea works. Checkout ~git/.authorized_keys in the container, we would see

# gitea public key
command="/usr/local/bin/gitea serv key-1 --config='/data/gitea/conf/app.ini'",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3N......
# gitea public key
command="/usr/local/bin/gitea serv key-2 --config='/data/gitea/conf/app.ini'",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3N......

and we could clearly see a command parameter. So the basic idea is to place a /usr/local/bin/gitea in the host which would pass all the parameters as-is to the container. The script will look like

#!/bin/sh
ssh -p $GIT_SSH_PORT -o StrictHostKeyChecking=no git@127.0.0.1 \
"SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $0 $@"
/usr/local/bin/gitea

Don't forget to chmod +x /usr/local/bin/gitea.

Then, create a git user on the host, and note down its $UID (997 here) and $GID (997 here). We should adjust our docker-compose.yml to let container and host share ~git/.ssh. The file now would be like

version: '2'
services:
    code:
        image: 'gitea/gitea:latest'
        ports:
            - '10022:22'
            - '127.0.0.1:10080:3000'
        volumes:
            - ./code:/data
            - /home/git/.ssh:/data/git/.ssh
    environment:
            - USER_UID=$UID
            - USER_GID=$GID
    restart: 'unless-stopped'

Finally, restart the container and add the SSH key of git@host to git@container. The simple way is

$ su git -c ssh-add-key git@localhost -p $GIT_SSH_PORT

And you will get things running now.

References

Installation with Docker - Docs