Computers & Electronics
80,355 views
31 min · 3 min read
9 steps
Advanced

How to create a private Git server for personal projects using Gitea and SSH access

This guide walks you through setting up a lightweight private Git server using Gitea with SSH access for your personal projects. It assumes a single machine (VPS or home server), basic Linux familiarity, and about 60–90 minutes to complete the initial install and configuration. Follow the steps to get a secure, fast, and self-hosted Git service you control.

Verified by pleasexplain editors
  1. Step 1: Prepare a Linux host

    Choose a stable Linux machine or VPS with at least 1 CPU, 1 GB RAM, and 10 GB disk. Update packages (apt update && apt upgrade -y or equivalent) and create a dedicated user account like 'git' for running Gitea and owning repositories to limit blast radius if something goes wrong.

    [Illustration: a terminal showing apt update and a new user creation command on a Linux server]

  2. Step 2: Install dependencies

    Install Git, a database (SQLite is fine for personal use; use MariaDB/PostgreSQL for more scale), and systemd tools. For example install git, wget, sqlite3, and nginx or Caddy for reverse proxy. These provide core features: Git operations, storage, and optional web access.

    [Illustration: package manager installing git, sqlite3, and nginx with progress bars on a console]

  3. Step 3: Download and install Gitea

    Fetch the latest Gitea binary for your CPU (wget or curl) and place it into /usr/local/bin/gitea with chmod +x. Create directories /var/lib/gitea and /etc/gitea and set ownership to the git user. This gives an isolated app binary and persistent data location.

    [Illustration: file saved as /usr/local/bin/gitea and directories under /var/lib/gitea with permission change commands]

  4. Step 4: Create systemd service

    Create a systemd unit file /etc/systemd/system/gitea.service to run Gitea as the git user and enable it to start at boot. Then run systemctl daemon-reload, systemctl enable --now gitea, and check status. Using systemd ensures automatic restart and simple process control.

    [Illustration: a systemctl enable gitea command with journalctl -u gitea -f tailing logs]

  5. Step 5: Configure reverse proxy and TLS

    Set up nginx or Caddy to reverse-proxy HTTP/HTTPS to Gitea's internal port (default 3000). Obtain a Let's Encrypt certificate automatically (Caddy) or via certbot (nginx). Use HTTP/2 and redirect HTTP to HTTPS for secure web access and Git-over-HTTPS if desired.

    [Illustration: nginx configuration file snippet mapping port 443 to localhost:3000 and certbot success message or Caddy auto TLS output]

  6. Step 6: Set up SSH for Git access

    On your workstation, generate a keypair with ssh-keygen -t ed25519 -C "your@email" and copy the public key into your Gitea account settings or into git user's authorized_keys if using bare SSH. Configure Gitea to accept SSH by setting the SSH server path (ssh command) and enabling SSH port 22 or a custom port to reduce noise.

    [Illustration: ssh-keygen output on a laptop and a browser showing Gitea profile SSH key paste field]

  7. Step 7: Create repos and test workflows

    Create a new private repository in Gitea via the web UI, clone it over SSH using git clone git@yourserver:username/repo.git, make commits, push, and pull. Run a quick push/pull cycle and test webhooks or CI integrations. This validates both SSH authentication and repository permissions.

    [Illustration: terminal with git clone, add, commit, push output and Gitea web UI showing the new repo]

  8. Step 8: Set up backups and maintenance

    Schedule automated backups of /var/lib/gitea and your database with cron or a system backup tool, keeping at least 7 days of snapshots and transferring them to offsite storage weekly. Also plan to update the Gitea binary monthly and monitor disk space with a simple alert script.

    [Illustration: crontab entry for nightly backup and an rsync command pushing backups to remote storage]

  9. Step 9: Harden security and access

    Limit SSH access by disabling password auth and allowing only key-based logins, optionally change the SSH port and enable Fail2ban. Keep the OS patched, use strong passwords for admin accounts, and audit user access every 30 days to remove stale keys and accounts.

    [Illustration: sshd_config showing PasswordAuthentication no and a fail2ban status screen]


  • Start with SQLite for simplicity; switch to MariaDB/PostgreSQL if you exceed ~100 repos or need concurrent writes.
  • Use ed25519 SSH keys for speed and smaller key files; they are widely supported and recommended over RSA for new keys.
  • Run Gitea behind a reverse proxy that also handles TLS to simplify certificate renewal and to support additional routing/virtual hosts.
  • Set a regular update cadence: check Gitea releases and OS updates once per month and apply on a maintenance window of 15–30 minutes.
  • Keep an offsite copy of backups (cloud object storage or another server) to recover from hardware failure or ransomware.
  • Use Gitea built-in organization and team features to separate personal experiments from long-term projects and to manage permissions easily.

  • Do not expose Gitea database ports (MariaDB/Postgres) to the public internet; allow access only from localhost or internal network IPs.
  • Avoid running services as root; always run Gitea and SSH under unprivileged accounts to reduce security risk.
  • If you enable password authentication for SSH or admin accounts, enforce strong passwords and consider two-factor authentication for the web UI to prevent brute-force compromise.
  • Regularly monitor disk usage; lack of free space can corrupt repositories. Keep at least 1–2 GB free on small servers and alert when usage exceeds 80%.

Was this guide helpful?