How to Deploy Gitea – Self-Hosted Git Platform
How to Deploy Gitea – Self-Hosted Git Platform
Deploy Gitea with Docker Compose and Traefik for secure, lightweight self-hosted Git hosting.

Gitea is a lightweight, self-hosted Git service that offers features such as repository hosting, pull requests, issues, SSH/HTTPS access, a built-in web editor, and CI integrations. You can run Gitea on any Linux server and access it securely via web browser.
This article demonstrates how to deploy Gitea on Ubuntu 24.04 using Docker Compose and secure it with HTTPS via a Traefik reverse proxy.
Prerequisites
Before you begin:
- Have access to an Ubuntu 24.04 server as a non-root user with sudo privileges.
- Install Docker and Docker Compose.
- Configure a domain name, such as
gitea.example.com, to point to your server’s public IP address.
Set Up the Directory Structure and Env Variables
Set up the project directory to store persistent Gitea, MariaDB, and Let’s Encrypt files.
- Create folders to store Gitea data, database files, and Let’s Encrypt certificates.
console
$ mkdir -p ~/gitea/{data,db,letsencrypt}
data– Gitea repositories, configs, SSH keys.db– MariaDB database files.letsencrypt– Traefik ACME certificates.
- Navigate to the root Gitea directory.
console
$ cd ~/gitea
- Create a
.envfile to store environment variables.console$ nano .envAdd these values:
iniGITEA_DB_USER=gitea GITEA_DB_PASS=STRONG_APP_PASSWORD MYSQL_ROOT_PASS=STRONG_MYSQL_ROOT_PASSWORD GITEA_DB_NAME=giteadb GITEA_DOMAIN=gitea.example.com LETSENCRYPT_EMAIL=admin@example.com
In the above file, replace:
STRONG_APP_PASSWORDwith a secure password for the Gitea DB user.STRONG_MYSQL_ROOT_PASSWORDwith a secure password for the MySQL root user.gitea.example.comwith your domain.admin@example.comwith your email.
Save and close the file.
Deploy with Docker Compose
Deploy Gitea with Docker Compose, Traefik as reverse proxy, and MariaDB for storage.
- Add your user account to the docker user group.
console
$ sudo usermod -aG docker $USER
- Apply new group membership.
console
$ newgrp docker - Create and edit a Docker Compose manifest file.
console
$ nano docker-compose.yml - Add the following contents:
yaml
services: traefik: image: traefik:latest container_name: traefik restart: unless-stopped environment: DOCKER_API_VERSION: "1.44" command: - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" - "--entrypoints.web.http.redirections.entrypoint.to=websecure" - "--entrypoints.web.http.redirections.entrypoint.scheme=https" - "--certificatesresolvers.le.acme.httpchallenge=true" - "--certificatesresolvers.le.acme.httpchallenge.entrypoint=web" - "--certificatesresolvers.le.acme.email=${LETSENCRYPT_EMAIL}" - "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json" ports: - "80:80" - "443:443" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./letsencrypt:/letsencrypt db: image: mariadb:latest container_name: gitea-db restart: unless-stopped environment: - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASS} - MYSQL_DATABASE=${GITEA_DB_NAME} - MYSQL_USER=${GITEA_DB_USER} - MYSQL_PASSWORD=${GITEA_DB_PASS} volumes: - ./db:/var/lib/mysql gitea: image: gitea/gitea:latest container_name: gitea restart: unless-stopped depends_on: - db environment: - USER_UID=1000 - USER_GID=1000 - DB_TYPE=mysql - DB_HOST=db:3306 - DB_NAME=${GITEA_DB_NAME} - DB_USER=${GITEA_DB_USER} - DB_PASSWD=${GITEA_DB_PASS} - ROOT_URL=https://${GITEA_DOMAIN} volumes: - ./data:/data labels: - "traefik.enable=true" - "traefik.http.routers.gitea.rule=Host(`${GITEA_DOMAIN}`)" - "traefik.http.routers.gitea.entrypoints=websecure" - "traefik.http.routers.gitea.tls=true" - "traefik.http.routers.gitea.tls.certresolver=le" - "traefik.http.services.gitea.loadbalancer.server.port=3000"
Save and close the file.
This Docker Compose file deploys Gitea behind Traefik, enabling secure HTTPS access using Let’s Encrypt. Each service has a specific purpose:
- gitea service
- Runs the Gitea application container, providing the Git hosting interface.
- Stores repositories, SSH keys, and config in the
./datadirectory. - Connects to MariaDB using database credentials from your
.envfile. - Advertises itself to Traefik using labels so Traefik can route traffic for your domain to the Gitea web interface over HTTPS.
- Exposes its internal port 3000 for the web UI.
- db service (MariaDB)
- Stores all Gitea metadata such as users, repositories, issues, and pull requests.
- Uses the
./dbdirectory for persistent data. - Initializes the database using values provided in the
.envfile.
- traefik service
- Listens on ports 80 and 443 and handles all incoming traffic.
- Automatically provisions and renews SSL certificates via Let’s Encrypt using the ACME HTTP-01 challenge.
- Reads labels from the Gitea container to route traffic to it securely.
- Stores certificate data in the
./letsencryptdirectory.
- gitea service
- Start all services in detached mode.
console
$ docker compose up -d - Check container status.
console
$ docker compose psYou should see
gitea,gitea-db, andtraefiklisted as “Up”.NoteFor more information on managing a Docker Compose stack, see the How To Use Docker Compose article.
Access and Configure Gitea
- Open your browser and visit your Gitea domain
https://gitea.example.com.

You should see the Initial Configuration page. Leave the Database settings to their default values.
2.Scroll down to the Optional Settings section, and expand the Administrator Account Settings. Fill in the values to create an Administrator user.

3.Click the Install Gitea button to finish the installation process. After installation, the dashboard loads. You now have a fully functional and secure Gitea installation.
Conclusion
By following this article, you successfully deployed Gitea on Ubuntu 24.04 using Docker Compose and secured it with Traefik. Your Git service now supports HTTPS, automatic TLS renewal, repository hosting, and all Gitea’s built-in features. For more details, visit the Gitea documentation.