diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini
index ecd7febeb..e4d0d4d1f 100644
--- a/custom/conf/app.example.ini
+++ b/custom/conf/app.example.ini
@@ -892,6 +892,9 @@ ROUTER = console
 ;; Allow deletion of unadopted repositories
 ;ALLOW_DELETION_OF_UNADOPTED_REPOSITORIES = false
 
+;; Don't allow download source archive files from UI
+;DISABLE_DOWNLOAD_SOURCE_ARCHIVES = false
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;[repository.editor]
diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md
index ca756c2e6..f59465ce2 100644
--- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md
+++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md
@@ -78,6 +78,7 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
 - `DEFAULT_BRANCH`: **main**: Default branch name of all repositories.
 - `ALLOW_ADOPTION_OF_UNADOPTED_REPOSITORIES`: **false**: Allow non-admin users to adopt unadopted repositories
 - `ALLOW_DELETION_OF_UNADOPTED_REPOSITORIES`: **false**: Allow non-admin users to delete unadopted repositories
+- `DISABLE_DOWNLOAD_SOURCE_ARCHIVES`: **false**: Don't allow download source archive files from UI
 
 ### Repository - Editor (`repository.editor`)
 
diff --git a/modules/context/context.go b/modules/context/context.go
index a19972119..d34dbb5e6 100644
--- a/modules/context/context.go
+++ b/modules/context/context.go
@@ -224,7 +224,7 @@ func (ctx *Context) HTML(status int, name base.TplName) {
 	ctx.Data["TemplateLoadTimes"] = func() string {
 		return strconv.FormatInt(time.Since(tmplStartTime).Nanoseconds()/1e6, 10) + "ms"
 	}
-	if err := ctx.Render.HTML(ctx.Resp, status, string(name), ctx.Data); err != nil {
+	if err := ctx.Render.HTML(ctx.Resp, status, string(name), templates.BaseVars().Merge(ctx.Data)); err != nil {
 		if status == http.StatusInternalServerError && name == base.TplName("status/500") {
 			ctx.PlainText(http.StatusInternalServerError, "Unable to find status/500 template")
 			return
diff --git a/modules/setting/repository.go b/modules/setting/repository.go
index 733bc6d90..d0406dbf9 100644
--- a/modules/setting/repository.go
+++ b/modules/setting/repository.go
@@ -48,6 +48,7 @@ var (
 		DefaultBranch                           string
 		AllowAdoptionOfUnadoptedRepositories    bool
 		AllowDeleteOfUnadoptedRepositories      bool
+		DisableDownloadSourceArchives           bool
 
 		// Repository editor settings
 		Editor struct {
diff --git a/modules/templates/base.go b/modules/templates/base.go
index 282019f82..9563650e1 100644
--- a/modules/templates/base.go
+++ b/modules/templates/base.go
@@ -35,10 +35,11 @@ func BaseVars() Vars {
 		"IsLandingPageExplore":       setting.LandingPageURL == setting.LandingPageExplore,
 		"IsLandingPageOrganizations": setting.LandingPageURL == setting.LandingPageOrganizations,
 
-		"ShowRegistrationButton":      setting.Service.ShowRegistrationButton,
-		"ShowMilestonesDashboardPage": setting.Service.ShowMilestonesDashboardPage,
-		"ShowFooterBranding":          setting.ShowFooterBranding,
-		"ShowFooterVersion":           setting.ShowFooterVersion,
+		"ShowRegistrationButton":        setting.Service.ShowRegistrationButton,
+		"ShowMilestonesDashboardPage":   setting.Service.ShowMilestonesDashboardPage,
+		"ShowFooterBranding":            setting.ShowFooterBranding,
+		"ShowFooterVersion":             setting.ShowFooterVersion,
+		"DisableDownloadSourceArchives": setting.Repository.DisableDownloadSourceArchives,
 
 		"EnableSwagger":      setting.API.EnableSwagger,
 		"EnableOpenIDSignIn": setting.Service.EnableOpenIDSignIn,
diff --git a/routers/web/web.go b/routers/web/web.go
index d594caf64..b60433771 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -289,6 +289,13 @@ func RegisterRoutes(m *web.Route) {
 		}
 	}
 
+	dlSourceEnabled := func(ctx *context.Context) {
+		if setting.Repository.DisableDownloadSourceArchives {
+			ctx.Error(http.StatusNotFound)
+			return
+		}
+	}
+
 	// FIXME: not all routes need go through same middleware.
 	// Especially some AJAX requests, we can reduce middleware number to improve performance.
 	// Routers.
@@ -1096,7 +1103,7 @@ func RegisterRoutes(m *web.Route) {
 		m.Group("/archive", func() {
 			m.Get("/*", repo.Download)
 			m.Post("/*", repo.InitiateDownload)
-		}, repo.MustBeNotEmpty, reqRepoCodeReader)
+		}, repo.MustBeNotEmpty, dlSourceEnabled, reqRepoCodeReader)
 
 		m.Group("/branches", func() {
 			m.Get("", repo.Branches)
diff --git a/templates/mail/release.tmpl b/templates/mail/release.tmpl
index 813aba556..c5c718548 100644
--- a/templates/mail/release.tmpl
+++ b/templates/mail/release.tmpl
@@ -31,12 +31,14 @@
 		
 		{{.i18n.Tr "mail.release.downloads"}}