Self-host Git with Gitea on Debian

Last update: Sep 18, 2021

We use SQLite as database in this example tutorial.

apt update 
apt install sqlite3 git -y

Create a user for Gitea

adduser --system --shell /bin/bash --group  --disabled-password --home /root/gitea-repositories gitea

Download Gitea binary file

## Download Gitea 

export VERSION=1.15.3 && wget -O /tmp/gitea https://dl.gitea.io/gitea/${VERSION}/gitea-${VERSION}-linux-amd64 && mv /tmp/gitea /usr/local/bin && chmod +x /usr/local/bin/gitea
## Create gitea directory

mkdir -p /var/lib/gitea/{custom,data,log}
chown gitea:gitea /var/lib/gitea/{custom,data,log}
chmod 750 /var/lib/gitea/{data,log}

Gitea Systemd startup

nano /etc/systemd/system/gitea.service

## Paste following lines 

[Unit]
Description=Gitea (Git with a cup of tea)
After=syslog.target
After=network.target

[Service]
# Modify these two values and uncomment them if you have
# repos with lots of files and get an HTTP error 500 because
# of that

#LimitMEMLOCK=infinity
#LimitNOFILE=65535
RestartSec=2s
Type=simple
User=root
Group=root
WorkingDirectory=/var/lib/gitea/

ExecStart=/usr/local/bin/gitea -p 3001 --config /var/lib/gitea/custom/conf/app.ini
Restart=always
Environment=USER=root HOME=/root/gitea-repositories GITEA_WORK_DIR=/var/lib/gitea

# If you want to bind Gitea to a port below 1024, uncomment
# the two values below, or use socket activation to pass Gitea its ports as above

#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
#AmbientCapabilities=CAP_NET_BIND_SERVICE
###

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now gitea.service

The default startup port is 3000, if you wanna change it, ensure modify gitea.service with additional option -p 3001

Example:

ExecStart=/usr/local/bin/gitea -p 3001 --config /var/lib/gitea/conf/app.ini

Nginx as reverse proxy with SSL

server {
  listen 80;
  listen [::]:80;
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  ssl_certificate /root/.acme.sh/xxx.cer;
  ssl_certificate_key /root/.acme.sh/xxx.key;
  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
  ssl_prefer_server_ciphers on;
  ssl_session_timeout 10m;
  ssl_session_cache builtin:1000 shared:SSL:10m;
  ssl_buffer_size 1400;
  add_header Strict-Transport-Security max-age=15768000;
  ssl_stapling on;
  ssl_stapling_verify on;
  server_name xxx;
  access_log off;
  # index index.html index.htm index.php;

  if ($ssl_protocol = "") { return 301 https://$host$request_uri; }

  location / {
    proxy_pass http://127.0.0.1:3001;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    client_max_body_size 0;
    proxy_max_temp_file_size 0;
    proxy_redirect off;
    proxy_read_timeout 120;
    add_header Pragma "no-cache";
    add_header Cache-Control "no-cache";
  }

}
  

Backup and migration

# Backup and migration with rclone.org

nano /root/backup-git.sh

## Paste following line

## Gitea configuration store in /var/lib/gitea/custom, data, log
## Gitea git repo store at /root/gitea-repositories

rm /root/backup-git-*

rm -rf /root/backup-git

mkdir /root/backup-git
zip -r data.zip /var/lib/gitea/ /etc/systemd/system/gitea.service
zip -r /root/backup-git/gitea.zip /root/gitea-repositories
zip -r "/root/backup-git-$(date '+%Y-%m-%d-%H-%M').zip" /root/backup-git

echo "Backup git"
rclone copy /root/backup-git-* xxxx:/ -c -v

rm /root/backup-git-*

exit 0