2024-11-17 Setting Up a Git Server

In an earlier post I did a quick exercise on setting up a git server using SSH. While using GitHub private repos is convenient for many cases. When it comes to owning data and/or code, we should also consider adding some self-hosted git servers in the mix. Here I will try Forgejo to see if it fits.

As usual in setting up my initial home lab, I want open-source lightweight tools if they are also robust and well maintained. I was choosing between Soft Server, Gitea, and Forgejo, but since I can switch quickly, at least in the early stage, there won't be too much cost if I change my mind. So I start with Forgejo. I did use Gitlab before but it's too much to run on a VPS or even on my home machines.

Installation

Visit Forgejo, and look for Docker Compose installation guide. So we have a reference to get started:

mkdir forgejo
cd forgejo

Create the docker-compose.yaml:

networks:
  forgejo:
    external: false

services:
  forgejo:
    restart: unless-stopped
    image: codeberg.org/forgejo/forgejo:9
    container_name: forgejo
    environment:
      - USER_UID=1000
      - USER_GID=1000
    volumes:
      - ./data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - '192.168.x.x:2223:3000'
      - '192.168.x.x:2222:22'
    networks:
      - forgejo

Since I am getting used to using Nebula, in general I will choose to host services in the private network without creating domain names for them or serving them behind NPMs. I also assign "sticky" port numbers to different services so that they don't conflict on the same host or when migrating to other hosts. I will also try to use internal network when no other service, such as NPM, needs it. Later if I want the repo URLs to be stable and accessible easily from other machines or even globally for requirements in the future, I'll see how to migrate, if needed.

I disabled many options like self-registration and OIDC, and enter an administration account, and continue. The first two times I got a 500 page. No error logs so I tried again, waited for about a minute and got right into the home page logged in as the admin user:

I guess this will mark the beginning of the time I put "internal" projects into my own git server. I am wondering what will go there in near future.

The Pointegrity Landing Page

As mentioned earlier the post contains instructions to use only Git and SSH as a simple Git server. To check basic git operations with Forgejo, I'll create a new empty repo and copy the files from old project over, i.e. discarding the commit history. I will do some exercises on git migration later.

Suppose the server is named pigit, mapped to the IP 192.168.x.x specified in docker-compose.yaml, first

  • create a repo named pointegrity. It shows the HTTP URI as http://pigit:2223/jy/pointegrity.git, and SSH one as git@pigit:jy/pointegrity.git
  • On another machine A, try cloning the repo using SSH to see if it works:
    • git clone git@pigit:jy/pointegrity.git
  • It will probably ask for the login password for git, which does not seem right. We want immediate cloning without password prompts. So on the Forgejo site we need to add a key for machine A from its public key file (e.g. ~/.ssh/id_rsa.pub) for the user. Go to Settings then SSH / GPG Keys page to add it.
  • Further more, the SSH URI indicates git@pigit:jy/pointegrity.git, and there is nothing related to the port 2222. git will try to connect to port 22. So one preferred way to deal with it is to add an entry in ~/.ssh/config like this:
Host: pigit
  HostName: 192.168.x.x
  Name: jy
  Port: 2222
You can change the Host name to something, e.g. mygit, but the SSH URI will become git@mygit:jy/pointegrity.git "locally", not affecting what's on the server side.

Finally I can clone the empty repo:

$ git clone git@pigit:jy/pointegrity.git
git clone git@pigit:jy/pointegrity.git
Cloning into 'pointegrity'...
warning: You appear to have cloned an empty repository.

Copy the content from previous project folder (do not include .git subfolder there), add and commit them.

cd pointegrity
# cp -r .../pointegrity/* .../pointegrity/.gitignore .
git add .
git commit -m "copy files over"

Here you may be stopped, and asked to configure the email and user name for git. Do it and commit again.

git commit -m "copy files over"
git push

The Forgejo site should have new data now (it's day time now 😄)

Repo Migration

I can take this opportunity to try repo migration. There are a lot of info about this topics, such as this. First on some machine A, I make sure I can clone the project repo from the pervious Git SSH server, gits:

git clone --mirror ssh://git@gits/srv/git/pointegrity.git piwww
I happen to want to rename the repo from pointegrity to piwww.
$ cd piwww
$ git remote -v
origin	ssh://git@gits/srv/git/pointegrity.git (fetch)
origin	ssh://git@gits/srv/git/pointegrity.git (push)
$ git remote add new git@pigit:jy/piwww.git
new	git@pigit:jy/piwww.git (fetch)
new	git@pigit:jy/piwww.git (push)
origin	ssh://git@tok/srv/git/pointegrity.git (fetch)
origin	ssh://git@tok/srv/git/pointegrity.git (push)

Try to push to the new repo:

$ git push --mirror new
Forgejo: Push to create is not enabled for users.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Seems there are some settings need to be set. According to this and this, I need to change something in app.ini for Forgejo, which we can find in data/gitea/conf/app.ini. But make sure it is in [repository] section:

[repository]
...
ENABLE_PUSH_CREATE_USER=true
ENABLE_PUSH_CREATE_ORG=true
ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET=false
DEFAULT_PUSH_CREATE_PRIVATE = true

Restart Forgejo and we can finally push it.

$ git push --mirror new
Enumerating objects: 811, done.
Counting objects: 100% (811/811), done.
Delta compression using up to 8 threads
Compressing objects: 100% (524/524), done.
Writing objects: 100% (811/811), 2.77 MiB | 31.92 MiB/s, done.
Total 811 (delta 202), reused 811 (delta 202), pack-reused 0
remote: Resolving deltas: 100% (202/202), done.
To pigit:jy/piwww.git
 * [new branch]      main -> main

The site now has new repo:

Note that there are two remotes origin and new inside the folder. We can start over by cloning the new repo from Forgejo to another folder. Or you can follow the steps there to keep only origin with remote URI changed.