Gitea Version
1.27.0
What happened?
After upgrading from Gitea v1.26.4 to v1.27.0, all clients using SSH Keys were no longer able to git pull/push. It also happens when upgrading to v1.27.1.
This had previously been functioning OK for a long time, possibly back to v1.8 in 2019.
I have resolved this after finding a somewhat similar problem mentioned in #35776 and using their diagnostic steps, but wanted to create this issue for:
- Improving search results for users who might find the same errors in the future
- Getting feedback on changes in v1.27 that might have caused the changed behavior
Symptom
Clients get an "error: Internal Server Connection Error" when doing git clone / push / pull to Gitea 1.27. All clients using SSH Key for authentication were impacted. ex:
git clone ssh://git@sub.example.com:11/sshtest/myrepo.git
Cloning into 'myrepo'...
error:
error: Internal Server Connection Error
error:
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
$ git remote -v
origin ssh://git@sub.example.com:11/domain.tld/container-tools.git (fetch)
origin ssh://git@sub.example.com:11/domain.tld/container-tools.git (push)
$ git pull
error:
error: Internal Server Connection Error
error:
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
Note: I also run SSH on a custom port for legacy reasons (SSH_PORT = 11), so was also considering if something about the syntax for cloning repos from other ports was involved...
Investigation
Connection with the SSH Key succeeds at the OS level, but fails from Gitea. This confirms that the authorized_keys file is working & has correct permissions, but something specific to Gitea config/access is causing the problem.
Creating a new client with a new SSH Key did not make any difference
$ ssh -v -T -p 11 git@sub.example.com
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Connecting to sub.example.com [nnn.nnn.nnn.nnn] port 11.
debug1: Connection established.
# [...]
debug1: Offering public key: /home/sshtest/.ssh/id_ed25519 ED25519 SHA256:<<removed>>
debug1: Server accepts key: /home/sshtest/.ssh/id_ed25519 ED25519 SHA256:<<removed>>
Authenticated to sub.example.com ([nnn.nnn.nnn.nnn]:11) using "publickey".
# [...]
debug1: Remote: /home/git/.ssh/authorized_keys:46: key options: command
error:
error: Key check failed
error:
Running the check from gitea binary locally also fails with no additional information
git@sub.example.com:~$ /usr/local/bin/gitea --config=/etc/gitea/app.ini serv key-50
error:
error: Key check failed
error:
Each time the connection with SSH Key is attempted, a pair of TLS errors is visible in the Gitea log, ex:
2026/08/12 23:01:34 modules/log/misc.go:72:(*loggerToWriter).Write() [I] http: TLS handshake error from 127.0.0.1:51922: no certificate available for '127.0.0.1'
2026/08/12 23:01:34 modules/log/misc.go:72:(*loggerToWriter).Write() [I] http: TLS handshake error from 127.0.0.1:51930: no certificate available for '127.0.0.1'
This hints that the SSH Key validation does something in the API internally, but wasn't sure yet what/why it is doing.
From the comments on the other Issue, set RUN_MODE = dev, and tried the tests again. Now, the URL triggering the TLS error is visible.
git@sub.example.com:~$ /usr/local/bin/gitea --config=/etc/gitea/app.ini serv key-50
error:
error: Key check failed
error:
Gitea: Failed to check provided key: unable to contact gitea "GET https://0.0.0.0:443/api/internal/serv/none/50": Get "https://0.0.0.0:443/api/internal/serv/none/50": remote error: tls: internal error
Checking with curl, Gitea is indeed unable to serve HTTPS for 0.0.0.0. This makes some sense, as only the real URL is included in ACME certs / SNI would not be functional for the wrong host.
$ curl -vkI https://0.0.0.0:443
* Trying 0.0.0.0:443...
* Connected to 0.0.0.0 (127.0.0.1) port 443
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS alert, internal error (592):
* OpenSSL/3.0.13: error:0A000438:SSL routines::tlsv1 alert internal error
* Closing connection
curl: (35) OpenSSL/3.0.13: error:0A000438:SSL routines::tlsv1 alert internal error
Inside app.ini, the LOCAL_ROOT_URL defines that URL where the 0.0.0.0 is coming unexpectedly - I don't remember why I have specifically configured this, but I think it matches the Gitea Cheat Sheet anyway...
[server]
ROOT_URL = https://sub.example.com
PROTOCOL = https
HTTP_PORT = 443
SSL_MIN_VERSION = TLSv1.2
REDIRECT_OTHER_PORT = true
PORT_TO_REDIRECT = 80
DOMAIN = sub.example.com
LOCAL_ROOT_URL = %(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/
DISABLE_SSH = false
SSH_PORT = 11
# [...]
I do not set HTTP_ADDR and the Cheat Sheet suggests is defaults to 0.0.0.0. However I think that using it in LOCAL_ROOT_URL causes some internal logic to be overridden, as the Cheat Sheet also says that it defaults to localhost when listen on 0.0.0.0
Removing the LOCAL_ROOT_URL from app.ini also causes a failure, but this time the failing URL is for https://localhost:443
error:
error: Key check failed
error:
Gitea: Failed to check provided key: unable to contact gitea "GET https://localhost:443/api/internal/serv/none/50": Get "https://localhost:443/api/internal/serv/none/50": remote error: tls: internal error
Setting the LOCAL_ROOT_URL using my actual domain name instead of HTTP_ADDR fixes the problem.
Key Findings
Some of the error messages and diagnostic steps were not immediately helpful, but I found these to be the most important points
- The SSH Key is accepted by the OS but rejected by Gitea
- Each time the SSH Key access is attempted, a TLS error is visible in the gitea logs
- With gitea in
RUN_MODE = dev, the URL triggering the TLS error is shown in the gitea serv key-## output
- The URL showing in the
gitea serv key-## error is from LOCAL_ROOT_URL in app.ini
Resolution
Change the LOCAL_ROOT_URL to use the actual domain name (prevent using 0.0.0.0 or localhost)
[server]
DOMAIN = sub.example.com
#LOCAL_ROOT_URL = %(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/
LOCAL_ROOT_URL = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/
# or
LOCAL_ROOT_URL = %(PROTOCOL)s://sub.example.com:%(HTTP_PORT)s/
Root Cause
How are you running Gitea?
Manual binary install
Ubuntu 24.04 (systemd service)
PosgreSQL 16(?)
Gitea Version
1.27.0
What happened?
After upgrading from Gitea v1.26.4 to v1.27.0, all clients using SSH Keys were no longer able to git pull/push. It also happens when upgrading to v1.27.1.
This had previously been functioning OK for a long time, possibly back to v1.8 in 2019.
I have resolved this after finding a somewhat similar problem mentioned in #35776 and using their diagnostic steps, but wanted to create this issue for:
Symptom
Clients get an "error: Internal Server Connection Error" when doing git clone / push / pull to Gitea 1.27. All clients using SSH Key for authentication were impacted. ex:
Note: I also run SSH on a custom port for legacy reasons (
SSH_PORT = 11), so was also considering if something about the syntax for cloning repos from other ports was involved...Investigation
Connection with the SSH Key succeeds at the OS level, but fails from Gitea. This confirms that the
authorized_keysfile is working & has correct permissions, but something specific to Gitea config/access is causing the problem.Creating a new client with a new SSH Key did not make any difference
Running the check from gitea binary locally also fails with no additional information
git@sub.example.com:~$ /usr/local/bin/gitea --config=/etc/gitea/app.ini serv key-50 error: error: Key check failed error:Each time the connection with SSH Key is attempted, a pair of TLS errors is visible in the Gitea log, ex:
This hints that the SSH Key validation does something in the API internally, but wasn't sure yet what/why it is doing.
From the comments on the other Issue, set
RUN_MODE = dev, and tried the tests again. Now, the URL triggering the TLS error is visible.Checking with
curl, Gitea is indeed unable to serve HTTPS for 0.0.0.0. This makes some sense, as only the real URL is included in ACME certs / SNI would not be functional for the wrong host.Inside
app.ini, theLOCAL_ROOT_URLdefines that URL where the 0.0.0.0 is coming unexpectedly - I don't remember why I have specifically configured this, but I think it matches the Gitea Cheat Sheet anyway...I do not set
HTTP_ADDRand the Cheat Sheet suggests is defaults to0.0.0.0. However I think that using it inLOCAL_ROOT_URLcauses some internal logic to be overridden, as the Cheat Sheet also says that it defaults tolocalhostwhen listen on 0.0.0.0Removing the
LOCAL_ROOT_URLfromapp.inialso causes a failure, but this time the failing URL is for https://localhost:443Setting the
LOCAL_ROOT_URLusing my actual domain name instead ofHTTP_ADDRfixes the problem.Key Findings
Some of the error messages and diagnostic steps were not immediately helpful, but I found these to be the most important points
RUN_MODE = dev, the URL triggering the TLS error is shown in thegitea serv key-##outputgitea serv key-##error is fromLOCAL_ROOT_URLinapp.iniResolution
Change the
LOCAL_ROOT_URLto use the actual domain name (prevent using 0.0.0.0 or localhost)Root Cause
LOCAL_ROOT_URLinapp.iniHow are you running Gitea?
Manual binary install
Ubuntu 24.04 (systemd service)
PosgreSQL 16(?)