# How I Set Up Gitea on a Google Cloud VM This repository documents how I deployed a small self-hosted Gitea instance at: ```text https://git.low-level-guy.com ``` The setup uses: - Google Compute Engine - Ubuntu Server 26.04 LTS - Docker Compose - Gitea - PostgreSQL - Nginx as a reverse proxy - Let's Encrypt HTTPS certificates through Certbot - Gitea SSH on port `2222` This is meant as a practical guide for deploying Gitea the same way I did. It is not a hardened production checklist. ## Deployment Overview The VM runs Nginx directly on the host. Nginx terminates HTTPS and proxies web traffic to the Gitea container on port `3000`. Gitea and PostgreSQL run in Docker. Gitea also exposes SSH on host port `2222`, so repositories can be cloned over SSH without conflicting with the VM's normal SSH service on port `22`. ```text Internet | | HTTPS 443 v Nginx on VM | | HTTP 3000 v Gitea container | | PostgreSQL 5432 v Postgres container ``` ## 1. Create the VM Create a Google Compute Engine VM. The instance I used: - Machine type: `e2-small` - Boot disk: `10 GB` - OS: Ubuntu Server 26.04 LTS - External IP: static or at least stable enough to point DNS at it A larger disk is a good idea if you expect many repositories, users, packages, or large Git history. ## 2. Configure the Firewall Allow these TCP ports to reach the VM: ```text 22 VM administration over SSH 80 HTTP for Let's Encrypt validation and redirect 443 HTTPS for the Gitea web UI 2222 Git over SSH through Gitea ``` In Google Cloud, this is configured under: ```text VPC network -> Firewall -> Create firewall rule ``` ## 3. Point DNS to the VM Create an `A` record for the Gitea subdomain: ```text A git.low-level-guy.com ``` Wait for DNS propagation before requesting the HTTPS certificate. ## 4. Install Docker SSH into the VM and install Docker from Docker's Ubuntu repository: ```bash sudo apt update sudo apt install -y \ ca-certificates \ curl \ gnupg curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker.gpg] \ https://download.docker.com/linux/ubuntu noble stable" \ | sudo tee /etc/apt/sources.list.d/docker.list sudo apt update sudo apt install -y \ docker-ce \ docker-ce-cli \ containerd.io \ docker-compose-plugin ``` Verify the install: ```bash sudo docker --version sudo docker compose version ``` I did not add my user to the `docker` group, so the Docker commands in this guide use `sudo`. ## 5. Install Nginx ```bash sudo apt install -y nginx sudo systemctl enable nginx sudo systemctl start nginx ``` ## 6. Install Certbot ```bash sudo apt install -y certbot python3-certbot-nginx ``` ## 7. Create the Gitea Directory Create a working directory for the Compose project: ```bash mkdir -p ~/gitea cd ~/gitea ``` ## 8. Add the Compose File Use the [`compose.yaml`](./compose.yaml) file from this repository. Copy it to the VM inside `~/gitea`: ```bash cd ~/gitea nano compose.yaml ``` Paste the contents of this repo's `compose.yaml`. The password values in the repo are placeholders. Change them before using this on a real server: ```yaml POSTGRES_PASSWORD: gitea GITEA__database__PASSWD=gitea ``` Both values must match because Gitea uses that password to connect to PostgreSQL. ## 9. Start Gitea and PostgreSQL From `~/gitea`, start the containers: ```bash sudo docker compose up -d ``` Check that both containers are running: ```bash sudo docker ps ``` You should see containers for: - `gitea` - `gitea-postgres` ## 10. Configure Nginx Create an Nginx site config: ```bash sudo nano /etc/nginx/sites-available/gitea ``` Use this config: ```nginx server { listen 80; server_name git.low-level-guy.com; 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: ```bash sudo ln -s /etc/nginx/sites-available/gitea /etc/nginx/sites-enabled/gitea ``` Remove the default site if it is still enabled: ```bash sudo rm /etc/nginx/sites-enabled/default ``` Test and reload Nginx: ```bash sudo nginx -t sudo systemctl reload nginx ``` ## 11. Enable HTTPS Request a Let's Encrypt certificate for the real domain: ```bash sudo certbot --nginx -d git.low-level-guy.com ``` When Certbot asks, choose the option to redirect HTTP traffic to HTTPS. After this, the site should be available at: ```text https://git.low-level-guy.com ``` ## 12. Complete the Gitea Setup Wizard Open the site in a browser: ```text https://git.low-level-guy.com ``` Use PostgreSQL as the database: ```text Database type: PostgreSQL Host: postgres:5432 Database name: gitea Username: gitea Password: ``` Use the public domain for the server settings: ```text Server domain: git.low-level-guy.com Gitea base URL: https://git.low-level-guy.com/ SSH server domain: git.low-level-guy.com SSH port: 2222 ``` During this step, create the initial administrator account. ## 13. Test Git over SSH After the setup wizard completes, test the Gitea SSH endpoint: ```bash ssh -p 2222 git@git.low-level-guy.com ``` Once your SSH key is added to your Gitea account, a successful connection should authenticate against Gitea instead of the VM's normal SSH service. Repository clone URLs should look like this: ```bash git clone ssh://git@git.low-level-guy.com:2222/username/repository.git ``` HTTPS clone URLs should look like this: ```bash git clone https://git.low-level-guy.com/username/repository.git ```