Skip to main content

Build a personal Git server with Gogs and Podman

Use a personal git server to save and manage your own code, to share code across different machines in your network, or to share with a small team.

Sometimes we want to manage source code or configuration files for small projects or laboratories with a Git server, but we don't want to use any of the hosted services available on the Internet, either due to privacy reasons, or to work on a disconnected environment.

Gogs is a self-hosted Git server written in Go that provides many of the same features you find in cloud-based Git services such as GitLab or GitHub. For more information about this project check the official GitHub repository. Gogs allows you to deploy a local Git server for a single machine or a small network. It lets you clone and push code using HTTP and SSH protocols, and provides a nice web UI with common features such as Pull Requests and Issues.

In this tutorial, you use Podman to run a local Gogs server using containers. By deploying Gogs in a container, you don't need to worry about downloading and compiling the code. It also allows you to manage the entire configuration with a single directory that is shared with the container. Finally, it permits easy upgrades by running the latest versions of the container image.

Let's start by installing Podman.

Install Podman

In Red Hat Enterprise Linux (RHEL) 8, deploy Podman by installing the container-tools module. List the available versions with the following command:

$ sudo dnf module list container-tools
Name                        Stream                Profiles               Summary
container-tools             rhel8 [d]             common [d]             Common tools and dependencies for container runtimes
container-tools             1.0                   common [d]             Common tools and dependencies for container runtimes
container-tools             2.0                   common [d]             Common tools and dependencies for container runtimes

Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled

Install the default stream for this module:

$ sudo dnf module install -y container-tools

Wait until the installation finishes and test Podman by running:

$ podman run --rm busybox echo hello world
Trying to pull
Getting image source signatures
Copying blob 91f30d776fb2 done
Copying config c7c37e472d done
Writing manifest to image destination
Storing signatures
hello world

In Red Hat Enterprise Linux (RHEL) 8, Podman is already configured to run "rootless" containers.

For more information about installing and configuring Podman in RHEL8, consult the product documentation.

For general information about Podman and installation instructions for other Linux distributions, consult the project page.

Now that Podman is installed, let's start the Gogs container.

Start the Gogs container

By default, data in the container is ephemeral and is deleted when the container is removed. That is fine for temporary data or if we can quickly re-create the environment. Since we're deploying a Git server that we may want to use for a long time, we need to ensure data persists across containers and system restarts. Otherwise, we would have to re-deploy the Gogs server every time.

The Gogs container supports custom data in the /data directory. To ensure data persists, we map that directory in the container to a local directory using the -v option with the podman run command. First, create the local directory. For this example, we use $HOME/var/gogs, but you can use any directory for which you have write permissions. Here is the command:

$ mkdir -p $HOME/var/gogs
$ ls -ld $HOME/var/gogs
drwxrwxr-x. 2 ricardo ricardo 6 Aug  1 18:26 /home/ricardo/var/gogs

The Gogs container uses two TCP ports for external communications: Port 22 for SSH communication and port 3000 for HTTP. Because you're running this container in "rootless" mode, you cannot use port 22. It would conflict with the machine's SSH service. In this case, we'll map this port to port 10022. Users can access Gogs via SSH through this port. We'll also expose the HTTP port as 10080, so it's close to the SSH port. This makes it easier to find grouped entries in case you decide to run several instances of Gogs in the same machine.

Now that you defined the volume and the required ports, use these values to start the Gogs container, like this:

$ podman run -d --name gogs01 -p 10022:22 -p 10080:3000 -v /home/ricardo/var/gogs:/data:Z gogs/gogs

This command returns the container ID for the running container. Your ID will be different from this example.

Note that we used the option :Z when mounting the local volume. This is necessary on RHEL8 to allow Podman to create the volume with the correct SELinux permissions. You can omit this option when running this example in a system that does not use SELinux.

Verify that the container is running with podman ps -l to list the most recently started container:

$ podman ps -l
CONTAINER ID  IMAGE                       COMMAND               CREATED         STATUS             PORTS                                           NAMES
e884b6dfc319  /bin/s6-svscan /a...  2 minutes ago   Up 2 minutes ago>22/tcp,>3000/tcp  gogs01

You can also list the persistent directory content using ls -lZ to ensure the sub-directories were created with the correct SELinux label `container_file_t`:

$ ls -lZ $HOME/var/gogs
total 0
drwxr-xr-x. 3 100999 100999 system_u:object_r:container_file_t:s0:c355,c706  18 Aug  1 18:36 git
drwxr-xr-x. 5 100999 100999 system_u:object_r:container_file_t:s0:c355,c706  41 Aug  1 18:36 gogs
drwx------. 2 100999 100999 system_u:object_r:container_file_t:s0:c355,c706 226 Aug  1 18:36 ssh

Now that the Gogs container is up and running let's configure it for remote access.

[ Getting started with containers? Check out this free course. Deploying containerized applications: A technical overview. ]

Configure Gogs

If you want to use this container locally, you can access it directly using the hostname localhost. For this example, we'll assume that we want to access it remotely so we can push code from other machines in the same network.

First, add the exposed ports to the firewall to allow remote access. In RHEL8, use firewall-cmd for that:

$ sudo firewall-cmd --add-port=10080/tcp --add-port=10022/tcp
$ sudo firewall-cmd --add-port=10080/tcp --add-port=10022/tcp --permanent 

Now list the enabled ports to ensure they are configured correctly:

$ sudo firewall-cmd --list-ports 
10080/tcp 10022/tcp

Then, use a browser to access the Gogs server. Use the appropriate hostname or IP address for your machine. For this example, the hostname of this machine is rh8vm02 so we can access it by browsing to http://rh8vm02:10080/.

The first time you access it, Gogs presents the configuration page where you define its main settings. First, select the database to store Gogs data. Gogs supports several databases, including Postgres, MySQL, and SQLite3. Since we're running a personal server, let's use SQLite3, a local database stored in a single file in the data directory. By using SQLite3, you don't need to manage another database instance. Leave the database file path as is: data/gogs.db.

Next, set the domain value to the hostname of the machine running the Gogs container. In this case, rh8vm02. Set the SSH port to the exposed port value: 10022.

Finally, set the application URL to match your server's hostname and the exposed HTTP port. In this example, http://rh8vm02:10080/:

Gogs-config: install steps for first-time run

When you're done with the settings, click on "Install Gogs" to complete the setup:

Gogs-config: Optional settings

Next, create the admin user for Gogs. The first account that you register automatically becomes the admin user. Click on the button "Register" on the top right corner and fill in the details. You can choose any name. For this example, we're using gogs-admin. Fill in the user email address, password, and complete the captcha. Then click on "Create New Account" to create the user:

Gogs-config: Sign up dialog box to create a user and password

Gogs created the admin user. Next, log in with your new user and password to access the Gogs dashboard and configure an SSH key.

Log into Gogs and configure an SSH key

You can use SSH keys with Gogs to clone and push code to your Git repositories. This allows automatic authentication without prompting for a password all the time. If you don't have an SSH key, create one in Linux using the command ssh-keygen:

$ ssh-keygen -t rsa
Generating public/private RSA key pair.
Enter file in which to save the key (/home/ricardo/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/ricardo/.ssh/id_rsa.
Your public key has been saved in /home/ricardo/.ssh/
The key fingerprint is:
SHA256:n8gKxhDCPPLfuFb9z5J9CmQedI6Wrw32vc6WtOh60uc ricardo@rh8vm02.localdomain
The key's randomart image is:
+---[RSA 3072]----+
|                 |
|o                |
|o+.       . .    |
|.o..     . =     |
|  o    .S B .    |
|   + o...B +  .  |
|    *.. o.B+.o o |
|   ..o . .=B=o*  |
|   .. .   oBBBE. |

Then, copy the public key and add it to Gogs. By default the ssh-keygen command generates the public key in $HOME/.ssh/

$ cat .ssh/ 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDWj/xcXVmRKkLAUZPk9ReFQ8kvT76mtrFeGKiZ+anHU2C9UEDdbcPNNJdSWQyq7J6NObmc+LV7ozCdjA6oPaSPQ8pVX1BLpxdiOT1cSeV21BPvmtM/Kzut9P39GDx9Nvi3POyDRmwAXceE+MlUvPLtLzqLq7Y0UTWTOmBeRJU3QVFw5fNOeCkl3KgCMseVew8q6UY/mSaMtxKsJCMYA5NJb00tBKtY7iQ+mKr2Yk99nsMQjqySqPvzMHepDP9s6qayNv51qSW8TxT/dkGZMOipMDmvZk3kv0mMW9iAst66kmCGBwnxj3EkMv5nz4JuOsaDQcCN49eHnCz1eL8TKtncApuIoUI3qs9h6X/r2i765b+tvGYXXfOChbrQ6vmL+aPzVk3sQIen7BoUkjrG5TKbIBC9tvdc7lDCuLMYDBfHirN8yjDDn6R4d/hd5ZdqGXiaN8XERWItc47OsmK94RDVMNX3rLEE7OkvBVBQ1cyOHub9Y6RUdl3p4kAIbXsiSB8= ricardo@rh8vm02.localdomain

Note: Never share the private key with anyone. By default the private key is in $HOME/.ssh/id_rsa.

Now, log in to the Gogs UI by clicking on "Sign In" in the Gogs home page using your browser. Use the admin user and password you created earlier.

Gogs Sign in dialog box

You see the user's dashboard. For now, it is empty, since we have not created any repositories yet.

Gogs admin dashboard

To add the SSH key, expand the user profile drop-down on the top right corner, and click on "Your Settings."

Gogs user settings menu

Next, click on "SSH Keys" on the "Settings" menu to the left and the "Add Key" button on the right corner. Give the key a name, such as "Admin Public Key," and paste the public key you copied earlier into the "Content" field. When done, click on the "Add Key" button at the bottom of the screen to create the key:

Gogs interface, paste in SSH public key

You will see a message confirming the key was added: New SSH key Admin Public Key has been added successfully!

Now that you added your SSH key to Gogs let's create a repository and push some code into it.

Creating a new repository and pushing code

In this final step, create a new repository in Gogs to manage source code. Click on the + icon drop-down and "New Repository" to add a new repository:

Gogs create a new repository

Fill in the details about the new repository. For example, set the name to test-repo01, and add a description Test Repository. Initialize the repository with an MIT License and a Default ReadMe file. Then click on "Create Repository" button to create the repository:

Gogs new repository settings box

Next, clone this repository on your machine to add code to it:

$ git clone ssh://git@rh8vm02:10022/gogs-admin/test-repo01.git
Cloning into 'test-repo01'...
The authenticity of host '[rh8vm02]:10022 ([]:10022)' can't be established.
ECDSA key fingerprint is SHA256:sKixNIbH5mtFmsd8EeMTTtrTwE57+grnm+LhUUBieHM.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[rh8vm02]:10022,[]:10022' (ECDSA) to the list of known hosts.
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (4/4), done.

Change into the created directory test-repo01 and update the file:

$ vi
# test-repo01

Test Repository

This is just a test repository!

Save and close the file. Now commit the changes using Git:

$ git add 
$ git commit -m "Updated"
[master ddf4545] Updated
 1 file changed, 4 insertions(+), 1 deletion(-)

Finally, push the code back to Gogs using git push. Because you configured your SSH key, there's no need to authenticate explicitly.

$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 333 bytes | 333.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To ssh://rh8vm02:10022/gogs-admin/test-repo01.git
   5fd0fde..ddf4545  master -> master

You can see the changes you made to the file using Gogs web UI:

Gogs interface displays new repository

What's next?

You have your own containerized Git server using Gogs. You can use it to save and manage your own code, or to share code across different machines in your network or with a small team. This personal Git server is also useful to support a small lab. You can use it to manage your Ansible projects and synchronize them with Ansible Tower without using a cloud-based solution. Finally, you can also use it to manage and build your applications with OpenShift.

[ Are you a current RHCSA looking to learn more about working with containers? RHCSAs are eligible for 50% off online containers, Kubernetes, and Red Hat OpenShift training through the end of 2020. ]

Topics:   Git   Podman   Networking   Web servers  
Author’s photo

Ricardo Gerardi

Ricardo Gerardi is Technical Community Advocate for Enable Sysadmin and Enable Architect. He was previously a senior consultant at Red Hat Canada, where he specialized in IT automation with Ansible and OpenShift.  More about me

Try Red Hat Enterprise Linux

Download it at no charge from the Red Hat Developer program.