GICT knowledge base
Build Your Own GitHub in 10 Minutes: A Gitea VPS Setup That Actually Works
Published
GitHub and GitLab charge for private repositories on team plans. If you run even a small dev shop, you are bleeding money on plans you do not need. One Ubuntu VPS, Gitea, and about ten minutes gives you your own private GitHub. Zero monthly fees. Full control.
This is a step-by-step. I ran through every command below on a live VPS and it worked without surprises.
What You Need
A VPS with Ubuntu 22.04 or 24.04. SQLite is built into Gitea, so you do not need MySQL or PostgreSQL. 1GB RAM is enough for light use. 2GB is comfortable.
You also need a domain name. If you do not have one, read the next section. If you do have one, skip ahead.
No Domain? Use nip.io Instead
nip.io is a free wildcard DNS service. It takes any subdomain and resolves it to a given IP address. No account needed, no DNS management, no propagation waiting.
If your VPS IP is 1.2.3.4, then `git.1-2-3-4.nip.io` resolves to 1.2.3.4 automatically. Replace 1.2.3.4 with your actual VPS IP for the rest of this guide.
The nip.io domain works with Let’s Encrypt TLS certificates just like any regular domain. Your readers will see a normal HTTPS lock icon in the browser.
If you prefer to use your own domain instead, replace every `git.X-X-X-X.nip.io` reference below with your domain. The steps are identical.
Install the Binary
Gitea ships as a single binary. No database to install, no dependencies to fight with. Download the latest release from GitHub.
# Download Gitea 1.26.2 (check github.com/go-gitea/gitea/releases for latest)
cd /tmp
curl -L -o gitea https://github.com/go-gitea/gitea/releases/download/v1.26.2/gitea-1.26.2-linux-amd64
chmod +x gitea
sudo cp gitea /usr/local/bin/gitea
sudo chown root:root /usr/local/bin/gitea
Verify it works:
gitea --version
# Output: gitea version 1.26.2 built with go1.26.3-X:jsonv2 : bindata, sqlite, sqlite_unlock_notify
Create the Git User and Directories
Gitea should not run as root. Create a dedicated system user.
sudo useradd --system --comment "Gitea" --create-home --shell /bin/bash git
sudo mkdir -p /var/lib/gitea/{data,log,repositories}
sudo chown -R git:git /var/lib/gitea
sudo chmod -R 750 /var/lib/gitea
The data directory holds your SQLite database and all repository files. The repositories directory is where Git stores your actual code.
Configure Gitea
Gitea needs a config file before it starts. Create it at /etc/gitea/app.ini.
sudo mkdir -p /etc/gitea
sudo chown git:git /etc/gitea
sudo chmod 750 /etc/gitea
Write the config. Replace `git.YOUR_VPS_IP.nip.io` with your actual nip.io address.
APP_NAME = Gitea
RUN_MODE = prod
[server]
PROTOCOL = http
DOMAIN = git.YOUR_VPS_IP.nip.io
ROOT_URL = https://git.YOUR_VPS_IP.nip.io/
HTTP_PORT = 3000
DISABLE_SSH = true
SSH_PORT = 22
START_SSH_SERVER = false
LFS_START_SERVER = true
APP_DATA_PATH = /var/lib/gitea/data
[database]
DB_TYPE = sqlite3
PATH = /var/lib/gitea/data/gitea.db
[security]
INSTALL_LOCK = false
SECRET_KEY = CHANGEME-replace-with-random-secret
INTERNAL_TOKEN = CHANGEME-replace-with-random-token
PASSWORD_HASH_ALGO = pbkdf2
MIN_PASSWORD_LENGTH = 8
[log]
MODE = console
LEVEL = info
ROOT_PATH = /var/lib/gitea/log
Generate random secrets with:
openssl rand -hex 32
Copy the output into SECRET_KEY and INTERNAL_TOKEN.
Set Up the Systemd Service
Systemd keeps Gitea running and starts it on boot. Create the service file:
sudo nano /etc/systemd/system/gitea.service
Paste this:
[Unit]
Description=Gitea (Git with a cup of tea)
After=network.target
[Service]
Type=simple
User=git
Group=git
WorkingDirectory=/var/lib/gitea
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
Restart=always
RestartSec=2
[Install]
WantedBy=multi-user.target
Enable and start it:
sudo systemctl daemon-reload
sudo systemctl enable gitea
sudo systemctl start gitea
Check it is running:
sudo systemctl status gitea --no-pager
Look for “active (running)” in the output. If it failed, check the logs with:
sudo journalctl -u gitea --no-pager -n 30
The most common failure is port 3000 already in use or permission denied on the data directories. Both are in the troubleshooting section at the end.
Run the Web Installer
Open your browser and go to http://YOUR_VPS_IP:3000/. You see the Gitea installation wizard. Fill in these fields:
- Database Type: SQLite3 (default, no setup needed)
- Repository Root Path: /var/lib/gitea/repositories
- Run As Username: git (pre-filled, do not change)
- Domain: git.YOUR_VPS_IP.nip.io (your nip.io address)
- HTTP Port: 3000
- Application URL: https://git.YOUR_VPS_IP.nip.io/
- Administrator Username: pick a username for your admin account
- Administrator Password: strong password, minimum 8 characters
- Administrator Email: [email protected]
Click “Install Gitea”. It takes about 30 seconds. When it finishes you land on the login page. Log in with the admin account you just created.
The installer sets INSTALL_LOCK to true in your app.ini. After this the installer is disabled and only the admin can change settings through the UI.
Set Up HTTPS with nginx and Let’s Encrypt
Set up nginx as a reverse proxy first:
sudo nano /etc/nginx/sites-available/gitea
Paste this, replacing `git.YOUR_VPS_IP.nip.io` with your nip.io address:
server {
listen 80;
server_name git.YOUR_VPS_IP.nip.io;
location / {
proxy_pass http://127.0.0.1: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;
}
}
Enable the site and reload nginx:
sudo ln -sf /etc/nginx/sites-available/gitea /etc/nginx/sites-enabled/gitea
sudo nginx -t
sudo systemctl reload nginx
Now get a free TLS certificate from Let’s Encrypt:
sudo certbot --nginx -d git.YOUR_VPS_IP.nip.io
Certbot reads the nginx config, adds the certificate, and updates it to HTTPS. All HTTP traffic redirects to HTTPS automatically. Your Gitea instance is now served over TLS with a valid certificate that renews automatically. On a VPS with 1GB RAM, the first certbot run takes about 30 seconds.
Create Your First Repository
After logging in, click the plus icon in the top right corner and select “New Repository”.
Fill in:
- Repository Name: my-project
- Private: check this if you do not want it public
- Initialize Repository: check this to add a README
- GitIgnore: select your language (e.g. Go, Python, Node)
Click “Create Repository”. You now have a working Git server.
Clone and Push Code
On your local machine, find the HTTPS clone URL on your repository page. It looks like:
https://git.YOUR_VPS_IP.nip.io/your-username/my-project.git
Cloning prompts for your Gitea username and password. Enter them and the repository clones.
For a smoother experience, configure Git to remember your password for one hour:
git config --global credential.helper cache --timeout=3600
Enter your credentials once and Git caches them for the session. No more typing your password on every push.
For permanent storage, use the store helper instead:
git config --global credential.helper store
echo "https://your-username:[email protected]_VPS_IP.nip.io" >> ~/.git-credentials
chmod 600 ~/.git-credentials
Replace your-username and your-password with your actual Gitea credentials. This file is plain text so keep it protected.
Once credentials are set up, cloning and pushing work exactly like GitHub:
git clone https://git.YOUR_VPS_IP.nip.io/your-username/my-project.git
cd my-project
echo "Hello world" > README.md
git add README.md
git commit -m "first commit"
git push origin main
If you see “fatal: could not read Username for ‘https://git.YOUR_VPS_IP.nip.io’: No such device or address” when pushing, your credentials are not saved. Run the credential.helper store commands above to fix this.
Back Up Your Data
Gitea stores everything in /var/lib/gitea. The SQLite database, repository files, and attachments are all in there. Back up the entire directory:
sudo tar -czf gitea-backup-$(date +%Y%m%d).tar.gz /var/lib/gitea
sudo chown $USER:$USER gitea-backup-*.tar.gz
Run this daily with a cron job:
sudo crontab -e
Add this line:
0 3 * * * tar -czf /root/gitea-backup-$(date +\%Y\%m\%d).tar.gz /var/lib/gitea
This runs the backup at 3am every day. Copy the backups off the VPS regularly.
Troubleshooting
Gitea will not start. Run:
sudo journalctl -u gitea --no-pager -n 50
The most common issue is port 3000 already in use. Stop whatever is on that port or change HTTP_PORT in app.ini to 3001.
Permission denied on data directories. Verify the git user owns /var/lib/gitea:
sudo chown -R git:git /var/lib/gitea
Push asks for username and password and fails. Your credentials are not saved. Run:
git config --global credential.helper store
# Then enter this line with your actual credentials:
echo "https://username:[email protected]_VPS_IP.nip.io" >> ~/.git-credentials
chmod 600 ~/.git-credentials
Let’s Encrypt fails to issue a certificate. Verify the nip.io domain resolves to your VPS IP:
ping git.YOUR_VPS_IP.nip.io
If ping resolves to your VPS IP, nginx is proxying correctly and certbot should work. If you see a different IP, your VPS IP in the nip.io address is wrong. Check your VPS public IP with:
curl ifconfig.me
Ready to own your code? InterServer VPS plans starting at $3/month with full root access. No panel fees, no limits on repositories.
Related guides
How to Use Git for Version Control
Learn how to effectively use Git for version control with this comprehensive guide covering installation, setup, branching, merging, and best practices.
GitHow to install and use Git Desktop in Windows
Github provides a Desktop app for Windows. Follow this tutorial to learn How to download, install and use Github Desktop in Windows.
