How to Install Gitea Code Hosting using Docker on Rocky Linux 8
Gitea is a self-hosted code hosting service similar to Github, Bitbucket, and Gitlab. It is written in Go language and can be installed on multiple operating systems, including Linux, macOS, Windows, and architectures like amd64, i386, ARM, and others. Being a lightweight application, it can be installed with minimal hardware requirements. It includes a repository file editor, OpenSSH server, issue tracking, pull requests, user management, notifications, built-in wiki, LFS support, Git hooks, and much more.
In this article, you will learn to install Gitea using Docker on a Rocky Linux 8 server.
Prerequisites
-
A Server running Rocky Linux 8.5.
-
A non-root user with sudo privileges.
-
Disable SELinux.
-
Update everything.
$ sudo dnf update
-
Install essential packages.
$ sudo dnf install yum-utils nano curl
-
A fully qualified domain name(FQDN) pointing to the server like
gitea.example.com.
Step 1 - Configure Firewall
The first step is to configure the firewall. Rocky Linux uses Firewalld Firewall. Check the firewall's status.
$ sudo firewall-cmd --state running
The firewall works with different zones, and the public zone is the default one that we will use. List all the services and ports active on the firewall.
$ sudo firewall-cmd --permanent --list-services
It should show the following output.
cockpit dhcpv6-client ssh
Allow HTTP and HTTPS ports.
$ sudo firewall-cmd --permanent --add-service=http $ sudo firewall-cmd --permanent --add-service=https
Open port 2221 for SSH.
$ sudo firewall-cmd --permanent --add-port=2221/tcp
List all the services being enabled by the firewall.
$ sudo firewall-cmd --permanent --list-all
You should see a similar output.
public target: default icmp-block-inversion: no interfaces: sources: services: cockpit dhcpv6-client http https ssh ports: 2221/tcp protocols: forward: no masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
Reload the firewall to enable the changes.
$ sudo firewall-cmd --reload
Step 2 - Install Docker
Rocky Linux ships with an older version of Docker. To install the latest version, first, install the official Docker repository.
$ sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
Install the latest version of Docker.
$ sudo dnf install docker-ce docker-ce-cli containerd.io
Enable and run the Docker daemon.
$ sudo systemctl enable docker --now
Verify that it is running.
? docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since Sat 2022-04-02 13:26:08 UTC; 2s ago
Docs: https://docs.docker.com
Main PID: 21152 (dockerd)
Tasks: 7
Memory: 30.9M
CGroup: /system.slice/docker.service
??21152 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
...
By default, Docker requires root privileges. If you want to avoid using sudo every time you run the docker command, add your username to the docker group.
$ sudo usermod -aG docker $(whoami)
You will need to log out of the server and back in as the same user to enable this change.
Step 3 - Install Docker Compose
Download the latest stable release of Docker Compose.
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
Apply executable permissions to the Docker Compose binary file.
$ sudo chmod +x /usr/local/bin/docker-compose
Test the installation.
$ docker-compose --version docker-compose version 1.29.2, build 5becea4c
Install the Docker-compose Bash Completion script.
$ sudo curl \
-L https://raw.githubusercontent.com/docker/compose/1.29.2/contrib/completion/bash/docker-compose \
-o /etc/bash_completion.d/docker-compose
Reload your profile settings to make the bash-completion work.
$ source ~/.bashrc
Step 4 - Configure and Install Gitea
Configure System Timezone
You can check your system's current timezone by the following command.
$ timedatectl
Local time: Mon 2022-05-02 06:38:36 UTC
Universal time: Mon 2022-05-02 06:38:36 UTC
RTC time: Mon 2022-05-02 06:38:36
Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
You can see that the system is set to GMT or UTC timezone. If you live in an area with a different timezone or want to change it, use the following command to do that.
$ sudo timedatectl set-timezone Asia/Kolkata
Check the timezone again.
$ timedatectl
Local time: Mon 2022-05-02 12:09:23 IST
Universal time: Mon 2022-05-02 06:39:23 UTC
RTC time: Mon 2022-05-02 06:39:22
Time zone: Asia/Kolkata (IST, +0530)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
You can see that the timezone has been updated to IST, which is GMT+5:30.
Create Gitea Directories
Create the directory for Gitea.
$ mkdir ~/gitea-docker
Switch to the Gitea directory.
$ cd ~/gitea-docker
Create directories for storing Gitea data and PostgreSQL databases.
$ mkdir {gitea,postgres}
Configure Gitea Docker Compose File
Get the UID (User Identifier) and GID (Group Identifier) values for the currently logged-in user. The first command generates the UID, while the second one generates the GID. Copy both the values as they will be required to configure the Docker compose file.
$ echo $(id -u) 1000 $ echo $(id -g) 1000
Create and open the Docker Compose file for editing.
$ nano docker-compose.yml
Paste the following code in it. Paste the UID and GID values generated earlier.
version: "3"
networks:
gitea:
external: false
services:
server:
image: gitea/gitea:1.16.6
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=db:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=gitea
restart: always
networks:
- gitea
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "2221:22"
depends_on:
- db
db:
image: postgres:14
restart: always
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=gitea
- POSTGRES_DB=gitea
networks:
- gitea
volumes:
- ./postgres:/var/lib/postgresql/data
Save the file by pressing Ctrl + X and entering Y when prompted.
The above Docker Compose file deploys two containers - one for Gitea and one for PostgreSQL. We have added a few environment variables to configure the database details. To connect the PostgreSQL database to the Gitea container, we have specified the host as the name of the PostgreSQL service in the file.
The port parameters "3000:3000" and "2221:22" specifies the port mapping where the left port denotes the host port and the right port denotes the container port. Gitea uses port 3000 for its web service, which is what we have exposed to the server too. For SSH, our system is already using port 22 for logging purposes. Therefore, we specify a custom port to perform SSH operations. In our case, we are using port 2221. This port also needs to be opened via your firewall, which we already did in step 1 of this tutorial.
Both, Gitea and the PostgreSQL containers are connected via a common internal Docker network named gitea. The volume mounts will automatically create gitea and postgres directories in the current folder when you start your Docker installation. The user ID specified in the compose file is what the Gitea container will use to create the gitea directory. On the other hand, the PostgreSQL container will be managed by the user systemd-coredump which is the default behavior. You can change that behavior, but it is not necessary.
Customize your Gitea Installation
You can customize your Gitea installation by adding an app.ini file to the ~/gitea-docker/gitea/gitea/conf directory. After the installation, this file can be edited from inside the container from the /data/gitea/conf/app.ini location. You can use the sample ini file from Gitea's Github repository for reference.
Install Gitea
Run the following command to launch Gitea containers.
$ docker-compose up -d
Check the status of the containers to ensure they are running properly.
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES bd06e370c46b gitea/gitea:1.16.6 "/usr/bin/entrypoint…" 19 minutes ago Up 19 minutes 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp, 0.0.0.0:2221->22/tcp, :::2221->22/tcp gitea 3fc6c4bce810 postgres:14 "docker-entrypoint.s…" 19 minutes ago Up 19 minutes 5432/tcp gitea_db_1
You can also use the following command to check the status.
$ docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------------------------------------------------ gitea /usr/bin/entrypoint /bin/s ... Up 0.0.0.0:2221->22/tcp,:::2221->22/tcp, 0.0.0.0:3000->3000/tcp,:::3000->3000/tcp gitea_db_1 docker-entrypoint.sh postgres Up 5432/tcp
Step 5 - Install SSL
To install an SSL certificate using Let's Encrypt, we need to install the Certbot tool.
Firstly, you need to download and install the EPEL repository.
$ sudo dnf install epel-release
Run the following commands to install Certbot.
$ sudo dnf install certbot
Generate the SSL certificate.
$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d gitea.example.com
The above command will download a certificate to the /etc/letsencrypt/live/gitea.example.com directory on your server.
Generate a Diffie-Hellman group certificate.
$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
Create a challenge web root directory for Let's Encrypt auto-renewal.
$ sudo mkdir -p /var/lib/letsencrypt
Create a Cron Job to renew the SSL. It will run every day to check the certificate and renew it if needed. For that, first, create the file /etc/cron.daily/certbot-renew and open it for editing.
$ sudo nano /etc/cron.daily/certbot-renew
Paste the following code.
#!/bin/sh certbot renew --cert-name gitea.example.com --webroot -w /var/lib/letsencrypt/ --post-hook "systemctl reload nginx"
Save the file by pressing Ctrl + X and entering Y when prompted.
Change the permissions on the task file to make it executable.
$ sudo chmod +x /etc/cron.daily/certbot-renew
Step 6 - Install Nginx
We will be installing the latest version of Nginx. Create and open the file /etc/yum.repos.d/nginx.repo for editing.
$ sudo nano /etc/yum.repos.d/nginx.repo
Paste the following lines in it.
[nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key module_hotfixes=true [nginx-mainline] name=nginx mainline repo baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/ gpgcheck=1 enabled=0 gpgkey=https://nginx.org/keys/nginx_signing.key module_hotfixes=true
Save the file by pressing Ctrl + X and entering Y when prompted.
Install Nginx.
$ sudo dnf install nginx
Verify the installation.
$ nginx -v nginx version: nginx/1.20.2
Enable and start the Nginx service.
$ sudo systemctl enable nginx --now
Create and open the file /etc/nginx/conf.d/gitea.conf for editing.
$ sudo nano /etc/nginx/conf.d/gitea.conf
Paste the following code in it.
# Redirect all non-encrypted to encrypted
server {
listen 80;
listen [::]:80;
server_name gitea.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name gitea.example.com;
ssl_certificate /etc/letsencrypt/live/gitea.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gitea.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/gitea.example.com/chain.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
access_log /var/log/nginx/gitea.example.com.access.log main;
error_log /var/log/nginx/gitea.example.com.error.log;
location / {
client_max_body_size 100M;
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Once finished, save the file by pressing Ctrl + X and entering Y when prompted. The above configuration allows Nginx to act as a proxy server and bind to the port 3000 on localhost. To enable the uploading of large files for Git LFS, you can change the value of the client_max_body_size variable as per requirement. For our tutorial, we are using 100 MB as the limit.
Open the file /etc/nginx/nginx.conf for editing.
$ sudo nano /etc/nginx/nginx.conf
Add the following line before the line include /etc/nginx/conf.d/*.conf;.
server_names_hash_bucket_size 64;
Save the file by pressing Ctrl + X and entering Y when prompted.
Verify the Nginx configuration file syntax.
$ sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Restart the Nginx service to enable the new configuration.
$ sudo systemctl restart nginx
Step 7 - Access and Set up Gitea
Visit the URL https://gitea.example.com in your browser, and the following installation screen shall appear.

Most of the fields will be pre-filled for you based on the values from the Docker compose file.

Enter gitea.example.com as the Server Domain and https://gitea.example.com as the Gitea Base URL. Change the value for the SSH Server Port from 22 to 2221. Leave the remaining settings as it is.
If you want to use mail features, you can add your SMTP server details. Expand the Email Settings section of the page and enter values as shown in the screenshot. Make sure to include your SMTP port with the hostname as shown. For our tutorial, we are using the Amazon SES service. You can use any SMTP service of your choice.

There are a few more settings you should check out before installing. To change them, expand the Server and Third-Party Service Settings section of the page.