The way to an own clowd - Part 11
The Way to Your Own Cloud (Part 11) – Run your own GitHub
GitHub, GitLab or Bitbucket – convenient, but all hosted elsewhere. If you truly want independence, you should also host your source code repositories yourself.
With Gitea you get a lightweight, fast, and flexible Git web interface. It offers everything you know: issues, pull requests, wikis, organizations – and all of it open source.
Setup
Gitea supports PostgreSQL. So first, create a user and a database:
sudo -u postgres psql
Inside the psql
shell, execute the following statements:
CREATE USER giteauser WITH PASSWORD '<STRONG-PASSWORD>';
CREATE DATABASE giteadb WITH OWNER giteauser;
GRANT ALL PRIVILEGES ON DATABASE giteadb TO giteauser;
Exit the tool with \\q
or exit
.
The service will run under the directory /opt/gitea
:
sudo mkdir -p /opt/gitea
cd /opt/gitea
Create the file docker-compose.yaml there:
services:
gitea:
image: localhost:5000/gitea/gitea:latest
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=host.docker.internal:5432
- GITEA__database__NAME=giteadb
- GITEA__database__USER=giteauser
- GITEA__database__PASSWD=<STRONG-PASSWORD>
volumes:
- ./data:/data
ports:
- "4000:3000"
- "2222:22"
restart: unless-stopped
extra_hosts:
- "host.docker.internal:host-gateway"
Next, host the underlying image from the official hub locally:
docker pull gitea/gitea:latest
docker tag gitea/gitea:latest localhost:5000/gitea/gitea:latest
docker push localhost:5000/gitea/gitea:latest
Now start the service:
docker compose up -d
For security reasons, create a random port:
echo $(shuf -i 1024-65535 -n 1)
For external communication, NGINX requires an additional configuration in the file /etc/nginx/sites-available/gitea:
server {
listen <RANDOM-PORT> ssl;
server_name <CLOUD-DOMAIN>;
ssl_certificate /etc/letsencrypt/live/<CLOUD-DOMAIN>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<CLOUD-DOMAIN>/privkey.pem;
location / {
proxy_pass http://localhost:4000;
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;
}
}
Activate and reload with:
sudo ln -s /etc/nginx/sites-available/gitea /etc/nginx/sites-enabled/
sudo systemctl restart nginx
Finally, open the port in the firewall:
sudo ufw allow <RANDOM-PORT>
sudo ufw reload
Now Gitea should be available at https://<CLOUD-DOMAIN>:<RANDOM-PORT>
.
Backups
Gitea can also be integrated into the central backup system. Just create a file named /opt/backup/plugins/gitea.sh with the following content:
#!/bin/bash
PLUGIN_OUTPUT_DIR="$1"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S.%3N')] $*"
}
FILES_BACKUP="$PLUGIN_OUTPUT_DIR/files_$(date '+%Y-%m-%d').tar.gz"
log "[INFO] Start backup of files in $GITEA_DATA_DIR ..."
tar -czf "$FILES_BACKUP" -C "$GITEA_DATA_DIR" .
if [ $? -eq 0 ]; then
log "[INFO] Backup of files was successful: $FILES_BACKUP"
else
log "[ERROR] Backup of files failed!"
fi
Then make it executable:
chmod +x /opt/backup/plugins/gitea.sh
Conclusion
With Gitea you run a lean, fast, and secure alternative to GitHub & Co. Repositories, issues, and wikis remain fully under your own control – perfect for small teams, projects, or as your personal GitHub at home.
Quick & Dirty
DB_PASS='STRONG_PASSWORD'
DOMAIN='cloud.example.com'
PORT=$(shuf -i 1024-65535 -n 1)
sudo -u postgres psql <<EOF
CREATE USER giteauser WITH PASSWORD '$DB_PASS';
CREATE DATABASE giteadb WITH OWNER giteauser;
GRANT ALL PRIVILEGES ON DATABASE giteadb TO giteauser;
\\q
EOF
sudo mkdir -p /opt/gitea
cd /opt/gitea
cat <<EOF > docker-compose.yaml
services:
gitea:
image: localhost:5000/gitea/gitea:latest
container_name: gitea
environment:
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=host.docker.internal:5432
- GITEA__database__NAME=giteadb
- GITEA__database__USER=giteauser
- GITEA__database__PASSWD=$DB_PASS
volumes:
- ./data:/data
ports:
- "3000:3000"
- "2222:22"
restart: unless-stopped
extra_hosts:
- "host.docker.internal:host-gateway"
EOF
docker pull gitea/gitea:latest
docker tag gitea/gitea:latest localhost:5000/gitea/gitea:latest
docker push localhost:5000/gitea/gitea:latest
docker compose up -d
sudo tee /etc/nginx/sites-available/gitea >/dev/null <<EONGX
server {
listen $PORT ssl;
server_name $DOMAIN;
ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem;
location / {
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;
}
}
EONGX
sudo ln -sf /etc/nginx/sites-available/gitea /etc/nginx/sites-enabled/
sudo systemctl restart nginx
sudo ufw allow $PORT && sudo ufw reload
cat <<'EOF' > /opt/backup/plugins/gitea.sh
#!/bin/bash
PLUGIN_OUTPUT_DIR="$1"
GITEA_DATA_DIR="/opt/gitea/data"
tar -czf "$PLUGIN_OUTPUT_DIR/files_$(date '+%Y-%m-%d').tar.gz" -C "$GITEA_DATA_DIR" .
EOF
chmod +x /opt/backup/plugins/gitea.sh