A synchronizer for establishing a connection to a Generic Git host in order to update the list of repositories from Gitea to Sourcegraph
Gitea is a cross-platform software development service (similar to GitHub, Bitbucket, and GitLab) that combines ease of use with low resource consumption.
Sourcegraph is a Code Intelligence platform that deeply analyzes your code—regardless of its size or hosting location—while providing a modern user interface. It is a powerful and feature-rich tool for code analysis and reuse.
This repository contains a working solution for:
- Creating a connection between Gitea and Sourcegraph (if one does not already exist);
- Automatically retrieving the list of repositories via the Gitea API;
- Automatically adding these repositories to the created connection.
🌟🌟🌟 HELP CALL 🌟🌟🌟
▶ APP_LANG=en ./gitea_2_sourcegraph_sync.py -h
2025-08-22 18:31:24 [info ] *** Application gitea_2_sourcegraph_sync.py started *** func_name=<module> lineno=40
2025-08-22 18:31:24 [info ] *** Help called for arguments ***
usage: ./gitea_2_sourcegraph_sync.py [-h] [-s PATH] [-i] [-y] [-u SEC] [-r SEC] [-c N] [-t]
Script to update the list of Gitea repositories in Sourcegraph.
Supports input parameters via UPPER env variables (overriding default
when defining argument). For example, these commands are equivalent:
LOG_LEVEL=INFO ./gitea_2_sourcegraph_sync.py -u 60 -y
LOG_LEVEL=INFO UPDATE_TIMEOUT=60 ALWAYS_YES=TRUE ./gitea_2_sourcegraph_sync.py
For more transparency (e.g., running manually inside a Docker container),
env variable support can be disabled:
IGNORE_ENV=TRUE ./gitea_2_sourcegraph_sync.py
Logging level LOG_LEVEL (DEFAULT="INFO") is set only via env.
Supported values: "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL".
Changing the APP_LANG locale is only done via environment variables.
Supported values: "en", "ru". For example:
APP_LANG=ru ./gitea_2_sourcegraph_sync.py -y
optional arguments:
-h, --help show this help message and exit
Recommended parameters:
-s PATH, --settings PATH
Path to the YAML file that defines script settings
DEFAULT=sync_settings.yml
Optional parameters:
-i, --interactive Show interactive input prompt in case of problems
-y, --always_yes Always answer YES to interactive boolean questions
-u SEC, --update_timeout SEC
How often to update git connection status
DEFAULT=600 (every 10 minutes)
-r SEC, --retry_timeout SEC
Next git connection retry interval in case of error
DEFAULT=30 (every 30 seconds)
-c N, --retry_count N
Number of retries for git connection on network errors
DEFAULT=3 (number of attempts = retries + 1)
-t, --no_term Do not terminate the application in case of network errors
that may be caused by incorrect values in the --settings
configuration file (e.g., invalid domain, token, or
insufficient permissions)
Adminka-root 2025. https://github.com/adminka-rootAttention! This repository has been tested only with the following versions:
- Docker version 24.0.5, build ced0996
- Python 3.8 / Python 3.11
- Gitea v1.22.1
- Sourcegraph v6.6.868
Compatibility with other versions is not guaranteed due to possible API changes.
Bug reports are welcome!Pull requests are also welcome. Feel free to use
git rebase -ibefore submitting your changes. Please follow the atomic commits practice:
- each commit should represent a logically complete change (feature, fix, refactoring);
- the commit should clearly show what was changed and why;
- the history should remain readable and linear.
The synchronizer setup is divided into two levels:
- External services — configuring Gitea and Sourcegraph (setting up SSH, obtaining tokens, etc.);
- Internal environment — launching and managing via Docker Compose.
These variables will be used in the following instructions. Make sure to adjust them according to your needs and export them in your terminal session. They are provided here for convenience in the README, but failing to initialize them in the terminal before executing further bash commands may cause issues.
gitea_domain=gitea.local
gitea_username_or_group=adminka # for git commands (<gitea_username_or_group>/repo)
sg_repo_dest_dir="$HOME/.local/share/my_sg_dir"
sg_domain=sourcegraph.localSetting up the integration between Gitea and Sourcegraph is primarily the responsibility of Sourcegraph developers. Unfortunately, there is no detailed documentation on this topic. Therefore, I will describe how I configured Gitea + Sourcegraph. Please note that this guide:
- reflects my personal experience and settings, and is not the "ultimate truth";
- assumes that you have a configured Gitea with SSH support (otherwise, welcome to the excellent and detailed Gitea documentation).
We follow the official deployment recommendations to set up Sourcegraph:
🌟🌟🌟 BASH 🌟🌟🌟
cd /tmp
# Clone the repository structure (git, without project data)
git clone --bare https://github.com/sourcegraph/deploy-sourcegraph-docker/
# Push to our private repository
cd deploy-sourcegraph-docker.git
git push --mirror git@${gitea_domain}:${gitea_username_or_group}/sourcegraph.git
# Remove the local clone
cd ..
rm -rf deploy-sourcegraph-docker.git
mkdir -p "${sg_repo_dest_dir}" && cd "${sg_repo_dest_dir}"
# Clone the pushed mirror repository locally
git clone git@${gitea_domain}:${gitea_username_or_group}/sourcegraph.git
# Add upstream to synchronize our clone with the original repository in the future
cd sourcegraph/
git remote add upstream https://github.com/sourcegraph/deploy-sourcegraph-docker
# Specify the version we want to install (see available branches/tags)
export SOURCEGRAPH_VERSION=v6.6.868
# Create our private branch pointing to $SOURCEGRAPH_VERSION
git checkout $SOURCEGRAPH_VERSION -b releaseNext, the developers recommend configuring a docker-compose.override.yaml file, which would layer on top of the standard configuration. However, my final Sourcegraph setup contains too many custom modifications. Therefore, I preferred a more transparent approach: creating a separate file, which I ran as follows:
cd "${sg_repo_dest_dir}/sourcegraph/docker-compose"
docker compose -f my-docker-compose.yaml up
# docker compose -f my-docker-compose.yaml downThe content of my-docker-compose.yaml is not provided because it is highly context-specific for my setup. You can review Sourcegraph service architecture on an unofficial resource to determine for yourself what is needed and in what form.
Connecting Gitea to Sourcegraph involves:
- Creating a shared Docker network and attaching both Gitea and Sourcegraph to it;
- Generating SSH keys and integrating them into Gitea and the Sourcegraph container;
- Defining the code host connection (Gitea) within Sourcegraph.
Create the shared network:
docker network create --driver bridge --subnet 172.23.0.0/16 gitea_localDefine the shared network in the corresponding Docker Compose files for Gitea and Sourcegraph:
networks: # network definition
gitea_local:
external: true
name: gitea_localAttach all Gitea and Sourcegraph services to the network:
networks: ['gitea_local']We define an alias for Gitea, where gitea.local is your echo ${gitea_domain}:
networks:
gitea_local: { 'aliases': ['gitea.local'] }When creating my-docker-compose.yaml for Sourcegraph, I decided not to use Caddy and explicitly map the internal 3080 port of the sourcegraph-frontend-0 service to the host. Therefore, the alias is defined specifically on sourcegraph-frontend-0:
networks:
gitea_local: { 'aliases': ['sourcegraph.local'] }where sourcegraph.local is your echo ${sg_domain}.
Generate the SSH keys and add them to Gitea:
cd "${sg_repo_dest_dir}" && mkdir -p gitserver && cd gitserver
ssh-keygen -t ecdsa -b 521 -C "sourcegraph@gitea.access" -f "./sourcegraph_gitea"
cat "./sourcegraph_gitea.pub"
# Copy the stdout output into the corresponding field at:
echo "https://${gitea_domain}/user/settings/keys"Integration into Sourcegraph. Prepare the config file to connect to Gitea:
cat <<EOF > "${sg_repo_dest_dir}/gitserver/config"
Host ${gitea_domain}
PreferredAuthentications publickey
IdentityFile ~/.ssh/sourcegraph_gitea
StrictHostKeyChecking accept-new
Port 22
EOFChanging the entrypoint and some service settings:
🌟🌟🌟 YAML 🌟🌟🌟
services:
# ... (other service definitions)
gitserver-0:
container_name: gitserver-0
image: 'index.docker.io/sourcegraph/gitserver:6.6.868@sha256:304800860a46f22dafa63730e5d16c114f857a9c21353bfaf5d64a2f0502f34a'
cpus: 1
mem_limit: '1.5g'
environment:
- 'SRC_FRONTEND_INTERNAL=sourcegraph-frontend-internal:3090'
- 'static_dir=/STATIC'
- 'user_name=sourcegraph'
volumes:
- 'gitserver-0:/data/repos'
- '../../gitserver/gitserver:/STATIC:rw'
- '../../gitserver/su-exec.py:/usr/local/bin/su-exec:ro'
networks:
- gitea_local
restart: always
hostname: gitserver-0
user: root
tty: true
entrypoint: ["/sbin/tini", "--", "/STATIC/entry.sh"]I am not providing my custom entrypoint, but the concept is presented in the additional/gitserver folder. Review it and configure it before proceeding further.
The next step is connection testing. Verify the functionality of git clone inside the gitserver-0 container and SSH access.
🌟🌟🌟 For example 🌟🌟🌟
docker exec -it gitserver-0 su sourcegraph -c "ssh git@${gitea_domain}"
Warning: Permanently added 'gitea.local' (ED25519) to the list of known hosts.
PTY allocation request failed on channel 0
Hi there, adminka! You've successfully authenticated with the key named sourcegraph_gitea, but Gitea does not provide shell access.
If this is unexpected, please log in with password and setup Gitea under another user.
Connection to gitea.local closed.
docker exec -it gitserver-0 su sourcegraph -c "git clone git@${gitea_domain}:${gitea_username_or_group}/sourcegraph.git /tmp/sourcegraph"
Cloning into '/tmp/sourcegraph'...
remote: Enumerating objects: 12892, done.
remote: Counting objects: 100% (12892/12892), done.
remote: Compressing objects: 100% (3187/3187), done.
remote: Total 12892 (delta 9531), reused 12577 (delta 9323), pack-reused 0 (from 0)
Receiving objects: 100% (12892/12892), 2.92 MiB | 12.62 MiB/s, done.
Resolving deltas: 100% (9531/9531), done.This will not be covered in this guide, as the gitea_2_sourcegraph_sync.py script will create it automatically after execution.
Tokens are required for the synchronizer to read the list of repositories from Gitea and update the list in Sourcegraph.
Links to create tokens in the web application will likely look like:
cat <<EOF
Gitea: https://${gitea_domain:-?????}/user/settings/applications
Sourcegraph: https://${sg_domain:-?????}/users/adminka/settings/tokens/new
EOFClone this repository:
cd "$HOME/.local/share" && git clone git@github.com:adminka-root/gitea_2_sourcegraph_sync.gitBuild the Docker image locally if you don't want to pull it from GitHub Container Registry.
cd ~/.local/share/gitea_2_sourcegraph_sync
docker build -t gitea_2_sourcegraph_sync:latest -f ./Dockerfile .
Based on docker-compose.example.yml, create your own docker-compose.yml in the same directory (the repository root).
Set the required environment variables for:
- Gitea connection:
GITEA_URL,GITEA_API_TOKEN,GIT_SSH_URL; - Sourcegraph connection:
SRC_ENDPOINT,SRC_ACCESS_TOKEN; - Defining the target host connection name in Sourcegraph:
EXTERNAL_DISPLAY_NAME.
Based on sync_settings.example.yml, create your own sync_settings.yml in the same directory (docker_static/).
This file is required to adjust the list of repositories sent to Sourcegraph during synchronization: RULE_LIST_POLICY, INCLUDE_LIST – whitelist, EXCLUDE_LIST – blacklist.
🌟🌟🌟 Running the synchronizer and example output (without variables) 🌟🌟🌟
cd ~/.local/share/gitea_2_sourcegraph_sync
▶ docker compose up
[+] Running 1/0
✔ Container sg_sync Created 0.0s
Attaching to sg_sync
sg_sync | Start time: 2025-08-23 06:17:04
sg_sync | The current image is based on Debian GNU/Linux 12 (bookworm)
sg_sync | Python version: 3.11.13
sg_sync | src: Current version: 6.7.0
sg_sync | Recommended version: 6.5.0 or later
sg_sync |
sg_sync | INFO Set uid to user 0 succeeded
sg_sync | INFO supervisord started with pid 1
sg_sync | INFO spawned: 'gitea_2_sourcegraph_sync' with pid 19
sg_sync | [info ] *** Application gitea_2_sourcegraph_sync.py started ***
sg_sync | [info ] Additional parameter validation check
sg_sync | [info ] Settings normalized
sg_sync | [info ] [START] Synchronizing repository list...
sg_sync | [info ] Successfully retrieved external services list
sg_sync | [warning ] Target git source not found in Sourcegraph matching EXTERNAL_DISPLAY_NAME
sg_sync | [info ] Created git repository connection
sg_sync | [info ] Selected git source in Sourcegraph
sg_sync | [info ] Successfully retrieved repositories from Gitea
sg_sync | [info ] Filtered repository list received
sg_sync | [info ] Updated git repository connection
sg_sync | [info ] [START END] Resynchronization in {update_timeout} seconds update_timeout=600Check that the connection has been created and configured at the link:
echo https://${sg_domain}/site-admin/external-services