# Building Your Own Private Git Server With Gitolite


Some time ago, I wrote about [Building a Git over HTTPS Server with Caddy and Containers](../git-server). Since I had a more complex requirement—creating repositories on push—I needed a more flexible Git server, so I decided to explore Gitolite.

## Why Choose Gitolite?

Among the many Git service solutions, Gitolite stands out. It's not an "all-in-one" solution like GitLab, but rather a focused "permission manager."

- **Ultra-lightweight**: It's just a series of Perl scripts, requiring no database, no web server, with extremely low system resource consumption.
- **Security**: All users authenticate through SSH public keys, and they cannot gain shell access to the server.
- **Fine-grained permission control**: You can control who can read/write which branches of which repositories, and even prevent someone from force pushing or deleting branches.
- **Managing Git with Git**: All user, repository, and permission configurations are stored in a special Git repository called `gitolite-admin`. You just need to `git push` from your own computer to complete all management operations. Cool, right?

Ready? Let's get started!

---

## Server-side Initialization

This part of the operation is all done on your **server**, and only needs to be done once.

### Create a Dedicated `git` User

For security reasons, we never use the root user to run services. Creating a dedicated `git` user is a best practice.

```bash
# Create a user named 'git' and create a home directory for it
sudo useradd -m -s /bin/bash git

# If the git user already exists, use the following command to modify its home directory
# sudo mkdir -p /home/git # if the home directory doesn't exist
# sudo usermod -d /home/git -s /bin/bash git

# (Recommended) Lock the user's password, forcing all operations to go through SSH keys
sudo passwd -l git
```

### Install Gitolite and Upload Your Admin Public Key

I use Arch Linux and install using the `pacman` package manager. Please adjust the commands for other distributions. You can refer to the official documentation [Quick Install](https://gitolite.com/gitolite/quick_install.html).

```bash
# Update your package database and install gitolite
sudo pacman -Syu gitolite
```

Next, you need to set yourself as the supreme administrator of Gitolite. This is accomplished by uploading your SSH public key. There are many ways to upload files, choose according to your situation. The following example assumes the uploaded path is `/tmp/admin.pub`.

### Initialize Gitolite

This is the most critical step. We will use the public key we just uploaded to start the Gitolite service.

Run on your **server**:

```bash
# Switch to git user identity
sudo -u git -i

# Use your public key as administrator to initialize Gitolite
# Some distributions use gitolite3 instead of gitolite, please refer to the official documentation
gitolite setup -pk /tmp/admin.pub

# After seeing output similar to "Initialized...", exit the git user
exit
```

This command will automatically create the `~/repositories` and `~/.gitolite` directories, and configure the core `gitolite-admin` management repository. Most importantly, it will take over the `~git/.ssh/authorized_keys` file. **From now on, please do not manually edit this file!**

### Cleanup

After installation, the temporary public key file on the server is no longer needed.

```bash
sudo rm /tmp/admin.pub
```

At this point, the server is like a well-prepared precision machine, waiting for your commands.

---

## Managing Everything Locally

From now on, you'll experience the ingenious design of Gitolite. All management work is done on your own computer through Git commands.

### Clone the `gitolite-admin` Management Repository

This is your "central control room."

On your **local** machine, find a place to clone it:

```bash
# Replace YOUR_SERVER_IP with your server's IP address
git clone git@YOUR_SERVER_IP:gitolite-admin
```

After successful cloning, you'll see this clean structure:

```plaintext
gitolite-admin/
├── conf/
│   └── gitolite.conf  # Permission and repository definition file
└── keydir/
    └── admin.pub      # Storage location for all users' public keys
```

### Hands-on Practice: Adding New Users and Projects

Suppose a new team member `alice` joins your team, and you're starting an exciting new project `my-awesome-app`.

1. **Get the public key**: Have `alice` send you her SSH public key file (like `alice.pub`).
2. **Add user**: Copy the `alice.pub` file to your local `gitolite-admin/keydir/` directory.
3. **Configure permissions**: Open the `gitolite-admin/conf/gitolite.conf` file and add the following at the end:

```plaintext
# ... existing configuration ...

# Create a repository definition for the new project my-awesome-app
repo my-awesome-app
    # RW+ = read, write, force push permissions
    # Grant these permissions to user 'alice'
    RW+     =   alice

    # R = read-only permission
    # Administrator 'admin' has read-only permission (you can also give yourself RW+)
    R       =   admin
```

> **Tip**: Gitolite automatically recognizes filenames in the `keydir/` directory (minus the `.pub` suffix) as usernames.

### Commit and Push to Make Configuration Take Effect

It's time to work the magic. In the `gitolite-admin` repository directory, execute the standard Git workflow:

```bash
# Add all your changes to the staging area
git add .

# Commit with a clear commit message
git commit -m "Add user alice and create repo my-awesome-app"

# Push to the server!
git push
```

When you press enter, Gitolite's hook scripts will be triggered on the server, automatically creating the `my-awesome-app.git` bare repository and applying all the permission rules you just set. The entire process flows seamlessly.

### Notify Your New Colleague to Get Started

Now you can tell `alice` that her new project is ready. She just needs to run on her computer:

```bash
git clone git@YOUR_SERVER_IP:my-awesome-app
```

## Other Settings

### Migrating Existing Repositories

- Move repositories to the `/home/git/repositories` directory
  - Ensure they are all bare repositories
  - All repository names end with `.git`
  - All files and directories are owned and writable by git
  - No symbolic links are left behind, regardless of where the files came from
- Run the following three commands under git identity:

  ```bash
  gitolite compile
  gitolite setup --hooks-only
  gitolite trigger POST_COMPILE
  ```

- Edit the conf/gitolite.conf file to add new repositories to the gitolite.conf file

### Allow Users to Create Repositories on Push

Edit the conf/gitolite.conf file and add the following:

```plaintext
repo    [a-zA-Z0-9].*
    C       =   @all
    RW+     =   CREATOR
```

> **Tip**: You cannot use `.*` directly here, but need to use `[a-zA-Z0-9].*`.
> [Reference Documentation](https://gitolite.com/gitolite/wild.html#regex-pattern-versus-normal-repo)

## Common Issues

### Podman Group Permission Issue

Reference article: [Podman Rootless Trick: Using `--group-add keep-groups` to Solve Volume Group Permission Issues](../podman-group-share)


---

> Author: Nite  
> URL: https://www.nite07.com/en/posts/gitolite/  

