diff --git a/modules/private/branch.go b/modules/private/branch.go
index faee1c918a..6b3b9170bb 100644
--- a/modules/private/branch.go
+++ b/modules/private/branch.go
@@ -5,7 +5,6 @@
 package private
 
 import (
-	"crypto/tls"
 	"encoding/json"
 	"fmt"
 
@@ -20,9 +19,7 @@ func GetProtectedBranchBy(repoID int64, branchName string) (*models.ProtectedBra
 	reqURL := setting.LocalURL + fmt.Sprintf("api/internal/branch/%d/%s", repoID, branchName)
 	log.GitLogger.Trace("GetProtectedBranchBy: %s", reqURL)
 
-	resp, err := newRequest(reqURL, "GET").SetTLSClientConfig(&tls.Config{
-		InsecureSkipVerify: true,
-	}).Response()
+	resp, err := newInternalRequest(reqURL, "GET").Response()
 	if err != nil {
 		return nil, err
 	}
diff --git a/modules/private/internal.go b/modules/private/internal.go
index fbf9d6a011..ac2fe56b87 100644
--- a/modules/private/internal.go
+++ b/modules/private/internal.go
@@ -8,6 +8,7 @@ import (
 	"crypto/tls"
 	"encoding/json"
 	"fmt"
+	"net"
 	"net/http"
 
 	"code.gitea.io/gitea/modules/httplib"
@@ -34,15 +35,27 @@ func decodeJSONError(resp *http.Response) *Response {
 	return &res
 }
 
+func newInternalRequest(url, method string) *httplib.Request {
+	req := newRequest(url, method).SetTLSClientConfig(&tls.Config{
+		InsecureSkipVerify: true,
+	})
+	if setting.Protocol == setting.UnixSocket {
+		req.SetTransport(&http.Transport{
+			Dial: func(_, _ string) (net.Conn, error) {
+				return net.Dial("unix", setting.HTTPAddr)
+			},
+		})
+	}
+	return req
+}
+
 // UpdatePublicKeyUpdated update publick key updates
 func UpdatePublicKeyUpdated(keyID int64) error {
 	// Ask for running deliver hook and test pull request tasks.
 	reqURL := setting.LocalURL + fmt.Sprintf("api/internal/ssh/%d/update", keyID)
 	log.GitLogger.Trace("UpdatePublicKeyUpdated: %s", reqURL)
 
-	resp, err := newRequest(reqURL, "POST").SetTLSClientConfig(&tls.Config{
-		InsecureSkipVerify: true,
-	}).Response()
+	resp, err := newInternalRequest(reqURL, "POST").Response()
 	if err != nil {
 		return err
 	}
diff --git a/modules/private/push_update.go b/modules/private/push_update.go
index 348a40e0a2..f3071b63ad 100644
--- a/modules/private/push_update.go
+++ b/modules/private/push_update.go
@@ -5,7 +5,6 @@
 package private
 
 import (
-	"crypto/tls"
 	"encoding/json"
 	"fmt"
 
@@ -25,9 +24,7 @@ func PushUpdate(opt models.PushUpdateOptions) error {
 		return err
 	}
 
-	resp, err := newRequest(reqURL, "POST").Body(body).SetTLSClientConfig(&tls.Config{
-		InsecureSkipVerify: true,
-	}).Response()
+	resp, err := newInternalRequest(reqURL, "POST").Body(body).Response()
 	if err != nil {
 		return err
 	}
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index 5bd2495287..8cd9fa6086 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -658,7 +658,22 @@ func NewContext() {
 	AppSubURL = strings.TrimSuffix(url.Path, "/")
 	AppSubURLDepth = strings.Count(AppSubURL, "/")
 
-	LocalURL = sec.Key("LOCAL_ROOT_URL").MustString(string(Protocol) + "://localhost:" + HTTPPort + "/")
+	var defaultLocalURL string
+	switch Protocol {
+	case UnixSocket:
+		defaultLocalURL = "http://unix/"
+	case FCGI:
+		defaultLocalURL = AppURL
+	default:
+		defaultLocalURL = string(Protocol) + "://"
+		if HTTPAddr == "0.0.0.0" {
+			defaultLocalURL += "localhost"
+		} else {
+			defaultLocalURL += HTTPAddr
+		}
+		defaultLocalURL += ":" + HTTPPort + "/"
+	}
+	LocalURL = sec.Key("LOCAL_ROOT_URL").MustString(defaultLocalURL)
 	OfflineMode = sec.Key("OFFLINE_MODE").MustBool()
 	DisableRouterLog = sec.Key("DISABLE_ROUTER_LOG").MustBool()
 	StaticRootPath = sec.Key("STATIC_ROOT_PATH").MustString(workDir)