Install Gitea on Raspberry Pi
Why Gitea on a Pi
Gitea is one of the lightest self-hosted git platforms available. It idles at ~100 MB RAM and runs natively on ARM64, making the Raspberry Pi 4 (even the 1 GB model) a viable git server for personal projects or small teams. If you want to own your code without renting a VPS, a Pi in your closet does the job.
Prerequisites
- Raspberry Pi 4 (1 GB+) or Pi 5 running 64-bit Raspberry Pi OS (Bookworm)
- Docker and Docker Compose installed (guide)
- MicroSD card (minimum) or USB SSD (recommended for active repos)
- Ethernet connection recommended (more stable than Wi-Fi for git operations)
- 10 GB free disk space minimum
Storage: SD Card vs USB SSD
An SD card works for small personal repos, but active development with frequent pushes and CI will wear it out. For anything beyond casual use, attach a USB SSD:
# Identify the SSD
lsblk
# Format and mount (assuming /dev/sda1)
sudo mkfs.ext4 /dev/sda1
sudo mkdir -p /mnt/ssd
sudo mount /dev/sda1 /mnt/ssd
# Add to /etc/fstab for auto-mount
echo "/dev/sda1 /mnt/ssd ext4 defaults,noatime 0 2" | sudo tee -a /etc/fstab
Then point your Docker volumes to /mnt/ssd/gitea/ instead of using named volumes.
Install Docker on Raspberry Pi OS
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
Log out and back in, then verify:
docker run --rm hello-world
Docker Compose Configuration
Create the project directory:
mkdir -p ~/gitea && cd ~/gitea
Create docker-compose.yml:
services:
gitea:
image: gitea/gitea:1.25.4
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=change_this_password # Change this
- GITEA__server__ROOT_URL=http://gitea.local:3000/
- GITEA__server__SSH_PORT=2222
- GITEA__server__SSH_DOMAIN=gitea.local # Your Pi's hostname or IP
restart: unless-stopped
volumes:
- gitea_data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "2222:22"
depends_on:
db:
condition: service_healthy
networks:
- gitea-net
db:
image: postgres:16-alpine
container_name: gitea-db
restart: unless-stopped
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=change_this_password # Must match GITEA__database__PASSWD
- POSTGRES_DB=gitea
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "gitea"]
interval: 10s
timeout: 5s
retries: 5
networks:
- gitea-net
# Tune PostgreSQL for limited Pi RAM
command: >
postgres
-c shared_buffers=128MB
-c effective_cache_size=256MB
-c work_mem=4MB
-c maintenance_work_mem=64MB
-c max_connections=20
volumes:
gitea_data:
postgres_data:
networks:
gitea-net:
Using a USB SSD for Storage
Replace the named volumes with bind mounts to your SSD:
volumes:
- /mnt/ssd/gitea/data:/data
# ...
# And for PostgreSQL:
volumes:
- /mnt/ssd/gitea/postgres:/var/lib/postgresql/data
ARM64 Image Compatibility
The gitea/gitea:1.25.4 and postgres:16-alpine images both publish ARM64 variants. Docker automatically pulls the correct architecture — no special flags needed.
Start the stack:
docker compose up -d
First startup takes 30-60 seconds on a Pi 4 as PostgreSQL initializes. Check progress:
docker compose logs -f
First-Time Setup
Open http://<pi-ip>:3000 in your browser. On the initial configuration page:
- Database settings are pre-filled from environment variables — verify they match
- Set Server Domain to your Pi’s IP or hostname
- Set SSH Server Port to
2222 - Set Gitea Base URL to
http://<pi-ip>:3000/ - Create an admin account at the bottom of the page
- Click Install Gitea
SSH for Git Operations
Add your SSH public key to your Gitea profile under Settings > SSH / GPG Keys.
Clone repos using the SSH port:
git clone ssh://git@<pi-ip>:2222/username/repo.git
Or configure ~/.ssh/config on your client machine for cleaner commands:
Host gitea-pi
HostName 192.168.1.100
Port 2222
User git
IdentityFile ~/.ssh/id_ed25519
Then clone with:
git clone gitea-pi:username/repo.git
Pi-Specific Optimization
Reduce Memory Pressure
On a 1 GB Pi, Gitea + PostgreSQL use ~250-350 MB combined, leaving room for the OS but not much else. If memory is tight:
# Add to gitea service environment
- GITEA__cache__ADAPTER=memory
- GITEA__cache__ITEM_TTL=16h
- GITEA__session__PROVIDER=memory
This avoids additional memory overhead from external cache services.
Disable Unused Features
If you do not need the built-in CI (Gitea Actions), disable it to save resources:
- GITEA__actions__ENABLED=false
Git LFS on Limited Storage
Git LFS stores large files outside the main git database. On a Pi with limited storage, either disable it or point LFS storage to an external drive:
- GITEA__server__LFS_START_SERVER=true
- GITEA__lfs__PATH=/data/lfs
If using LFS, a USB SSD is essential. LFS objects on an SD card will cause significant wear.
Temperature Monitoring
The Pi throttles CPU under sustained load (large git pushes, repo migrations). Keep an eye on temperature:
vcgencmd measure_temp
Use a heatsink or active cooling case if running Gitea alongside other services. Throttling starts at 80C.
Backup
#!/bin/bash
# backup-gitea-pi.sh
BACKUP_DIR="/mnt/ssd/backups/gitea/$(date +%Y-%m-%d)"
mkdir -p "$BACKUP_DIR"
# Database
docker exec gitea-db pg_dump -U gitea gitea > "$BACKUP_DIR/db.sql"
# Gitea data
docker run --rm -v gitea_gitea_data:/data -v "$BACKUP_DIR":/backup alpine \
tar czf /backup/gitea-data.tar.gz /data
echo "Backup saved to $BACKUP_DIR"
If you only have an SD card, back up to a network share or external USB drive. Never keep your only backup on the same SD card. See Backup Strategy.
Troubleshooting
Container Fails to Start on Pi 3
Symptom: exec format error or container exits immediately.
Fix: Gitea’s Docker image requires 64-bit ARM (ARM64/aarch64). The Pi 3 runs 32-bit by default. Reflash with 64-bit Raspberry Pi OS, or use a Pi 4/5.
Out of Memory Kills
Symptom: Gitea or PostgreSQL is killed by the OOM killer. Check with dmesg | grep -i oom.
Fix: On a 1 GB Pi, reduce PostgreSQL memory usage further:
-c shared_buffers=64MB
-c effective_cache_size=128MB
-c max_connections=10
And increase swap:
sudo dphys-swapfile swapoff
sudo sed -i 's/CONF_SWAPSIZE=.*/CONF_SWAPSIZE=1024/' /etc/dphys-swapfile
sudo dphys-swapfile setup
sudo dphys-swapfile swapon
Slow Git Push for Large Repos
Symptom: Pushing a large repo takes significantly longer than expected.
Fix: The Pi’s CPU and I/O are the bottleneck during git pack operations. There is no configuration fix — this is a hardware limitation. For repos over 1 GB, consider a more powerful server. For moderate repos, patience is the answer.
SD Card Corruption After Power Loss
Symptom: Gitea data or PostgreSQL is corrupted after an unexpected shutdown.
Fix: PostgreSQL’s WAL provides crash recovery for the database, but repeated hard power-offs degrade SD cards. Use a UPS or at minimum a clean shutdown script. Move to USB SSD for reliability.
SSH Connection Refused
Symptom: ssh: connect to host <ip> port 2222: Connection refused.
Fix: Check the container is running (docker compose ps). Verify port 2222 is open on the Pi’s firewall if using ufw or iptables. Check the Pi’s IP has not changed (assign a static IP or DHCP reservation).
Resource Requirements
- RAM: ~100 MB idle (Gitea) + ~80 MB (PostgreSQL) = ~180 MB total
- CPU: Low for typical use. Spikes during git pack/clone of large repos
- Disk: 300 MB for the application, plus repository storage
- Recommended Pi: Pi 4 (1 GB minimum, 2 GB comfortable), Pi 5 (any model)
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments