How to host a git service using Gitea on Debian Buster
Table of Contents
A self-hosted git service gives full control over source repositories. Compared with Gitlab, a popular alternative to Github, Gitea is memory friendly and easier to setup. According to the official documentation, pre-built binaries are not recommended for production environment, so we turn to source-based installation method instead.

Install build dependencies
Make sure backports are enabled as described in here. After that, run the following commands to install necessary dependencies:
apt install build-essential
apt install -t buster-backports golang npm
With pam
support:
apt install libpam0g-dev
Build from source
Clone the source repository from Github: 😥
cd /usr/src
git clone https://github.com/go-gitea/gitea
Checkout the latest stable release:
git checkout v1.12.2
Change the default working directory via LDFLAGS
:
export LDFLAGS="-X \"code.gitea.io/gitea/modules/setting.AppWorkPath=/var/lib/gitea/\""
Run make
to automate build process:
TAGS="pam" make build
Verify that the compiled binary works:
./gitea help
Manual installation
Feel free to replace /usr/local
with another prefix.
Install the binary:
install gitea /usr/local/bin
Copy static assets:
mkdir -p /usr/local/share/gitea
cp -r {options,public,templates} /usr/local/share/gitea
Copy the default configuration:
mkdir -p /usr/local/etc/gitea
cp custom/conf/app.ini.sample /usr/local/etc/gitea/app.ini
Prepare database
Visit Database preparation for more information.
Edit configuration file
First create an unprivileged user for Gitea:
useradd gitea -c "Gitea" -m -d /var/lib/gitea -s /bin/bash
Assign write permission to the user:
chgrp gitea /usr/local/etc/gitea/app.ini
chmod g+w /usr/local/etc/gitea/app.ini
Then change the runtime user:
;RUN_USER = git
RUN_USER = gitea
…and change some default paths:
[repository]
ROOT = /var/lib/gitea/repos
[server]
STATIC_ROOT_PATH = /usr/local/share/gitea
Use domain socket for better performance:
[server]
;PROTOCOL = http
PROTOCOL = unix
;HTTP_ADDR = 0.0.0.0
HTTP_ADDR = /run/gitea/gitea.socket
To enable logging:
[log]
ROOT_PATH = /var/log/gitea
;MODE = console
MODE = console, file
More options can be found in the cheat sheet.
Create systemd service
Modification is based on Arch patch.
[Unit]
Description=Gitea (Git with a cup of tea)
After=syslog.target
After=network.target
# uncomment as needed
#After=mysqld.service
#After=postgresql.service
#After=memcached.service
#After=redis.service
[Service]
User=gitea
Group=gitea
Type=simple
WorkingDirectory=~
RuntimeDirectory=gitea
# uncomment if enabled logging
#LogsDirectory=gitea
StateDirectory=gitea
Environment=USER=gitea HOME=/var/lib/gitea GITEA_WORK_DIR=/var/lib/gitea
ExecStart=/usr/local/bin/gitea web -c /usr/local/etc/gitea/app.ini
Restart=always
RestartSec=2s
# security hardening
CapabilityBoundingSet=
NoNewPrivileges=True
PrivateUsers=true
PrivateDevices=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ProtectControlGroups=yes
ProtectKernelTunables=true
ProtectKernelModules=yes
ReadWritePaths=/usr/local/etc/gitea/app.ini
LockPersonality=true
MemoryDenyWriteExecute=true
RestrictRealtime=true
SystemCallArchitectures=native
SystemCallFilter=@system-service
[Install]
WantedBy=multi-user.target
Save as /etc/systemd/system/gitea.service
and reload systemd to take effect.
Running behind Nginx
Nginx can serve static resources directly.
server {
listen 80;
server_name git.example.com;
location / {
proxy_pass http://unix:/run/gitea/gitea.socket;
}
location /_/static {
access_log off;
log_not_found off;
alias /usr/local/share/gitea/public;
}
}
In the configuration file, remember to set STATIC_URL_PREFIX = /_/static
.
Complete setup
Start the service and navigate to git.example.com/install. Done.