diff --git a/.drone.yml b/.drone.yml
index a8fa7eba3687b..f9da8f9743807 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -25,7 +25,7 @@ steps:
       - make deps-frontend
 
   - name: deps-backend
-    image: golang:1.19
+    image: golang:1.20
     pull: always
     commands:
       - make deps-backend
@@ -88,7 +88,7 @@ steps:
     depends_on: [deps-frontend]
 
   - name: checks-backend
-    image: golang:1.19
+    image: golang:1.20
     commands:
       - make --always-make checks-backend # ensure the 'go-licenses' make target runs
     depends_on: [deps-backend]
@@ -109,7 +109,7 @@ steps:
     depends_on: [deps-frontend]
 
   - name: build-backend-no-gcc
-    image: golang:1.18 # this step is kept as the lowest version of golang that we support
+    image: golang:1.19 # this step is kept as the lowest version of golang that we support
     pull: always
     environment:
       GO111MODULE: on
@@ -122,7 +122,7 @@ steps:
         path: /go
 
   - name: build-backend-arm64
-    image: golang:1.19
+    image: golang:1.20
     environment:
       GO111MODULE: on
       GOPROXY: https://goproxy.io
@@ -138,7 +138,7 @@ steps:
         path: /go
 
   - name: build-backend-windows
-    image: golang:1.19
+    image: golang:1.20
     environment:
       GO111MODULE: on
       GOPROXY: https://goproxy.io
@@ -153,7 +153,7 @@ steps:
         path: /go
 
   - name: build-backend-386
-    image: golang:1.19
+    image: golang:1.20
     environment:
       GO111MODULE: on
       GOPROXY: https://goproxy.io
@@ -247,7 +247,7 @@ steps:
           - pull_request
 
   - name: deps-backend
-    image: golang:1.19
+    image: golang:1.20
     pull: always
     commands:
       - make deps-backend
@@ -364,7 +364,7 @@ steps:
         path: /go
 
   - name: generate-coverage
-    image: golang:1.19
+    image: golang:1.20
     commands:
       - make coverage
     environment:
@@ -440,7 +440,7 @@ steps:
           - pull_request
 
   - name: deps-backend
-    image: golang:1.19
+    image: golang:1.20
     pull: always
     commands:
       - make deps-backend
@@ -557,7 +557,7 @@ steps:
   - name: test-e2e
     image: mcr.microsoft.com/playwright:v1.29.2-focal
     commands:
-      - curl -sLO https://go.dev/dl/go1.19.linux-amd64.tar.gz && tar -C /usr/local -xzf go1.19.linux-amd64.tar.gz
+      - curl -sLO https://go.dev/dl/go1.20.linux-amd64.tar.gz && tar -C /usr/local -xzf go1.20.linux-amd64.tar.gz
       - groupadd --gid 1001 gitea && useradd -m --gid 1001 --uid 1001 gitea
       - apt-get -qq update && apt-get -qqy install build-essential
       - export TEST_PGSQL_SCHEMA=''
@@ -656,7 +656,7 @@ trigger:
 
 steps:
   - name: download
-    image: golang:1.19
+    image: golang:1.20
     pull: always
     commands:
       - timeout -s ABRT 40m make generate-license generate-gitignore
@@ -720,7 +720,7 @@ steps:
       - make deps-frontend
 
   - name: deps-backend
-    image: golang:1.19
+    image: golang:1.20
     pull: always
     commands:
       - make deps-backend
@@ -729,7 +729,7 @@ steps:
         path: /go
 
   - name: static
-    image: techknowlogick/xgo:go-1.19.x
+    image: techknowlogick/xgo:go-1.20.x
     pull: always
     commands:
       # Upgrade to node 18 once https://github.com/techknowlogick/xgo/issues/163 is resolved
@@ -841,7 +841,7 @@ steps:
       - make deps-frontend
 
   - name: deps-backend
-    image: golang:1.19
+    image: golang:1.20
     pull: always
     commands:
       - make deps-backend
@@ -850,7 +850,7 @@ steps:
         path: /go
 
   - name: static
-    image: techknowlogick/xgo:go-1.19.x
+    image: techknowlogick/xgo:go-1.20.x
     pull: always
     commands:
       # Upgrade to node 18 once https://github.com/techknowlogick/xgo/issues/163 is resolved
@@ -932,7 +932,7 @@ trigger:
 
 steps:
   - name: build-docs
-    image: golang:1.19
+    image: golang:1.20
     commands:
       - cd docs
       - make trans-copy clean build
diff --git a/.golangci.yml b/.golangci.yml
index 7635e83a37260..caa237370e375 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -28,7 +28,7 @@ linters:
   fast: false
 
 run:
-  go: 1.19
+  go: 1.20
   timeout: 10m
   skip-dirs:
     - node_modules
@@ -74,7 +74,7 @@ linters-settings:
       - name: modifies-value-receiver
   gofumpt:
     extra-rules: true
-    lang-version: "1.19"
+    lang-version: "1.20"
   depguard:
     list-type: denylist
     # Check the list against standard lib.
diff --git a/Dockerfile b/Dockerfile
index 3ee474bb3425b..89f000882c57a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
 #Build stage
-FROM golang:1.19-alpine3.17 AS build-env
+FROM golang:1.20-alpine3.17 AS build-env
 
 ARG GOPROXY
 ENV GOPROXY ${GOPROXY:-direct}
diff --git a/Dockerfile.rootless b/Dockerfile.rootless
index a43a63fa10c78..e92ce857d3cd3 100644
--- a/Dockerfile.rootless
+++ b/Dockerfile.rootless
@@ -1,5 +1,5 @@
 #Build stage
-FROM golang:1.19-alpine3.17 AS build-env
+FROM golang:1.20-alpine3.17 AS build-env
 
 ARG GOPROXY
 ENV GOPROXY ${GOPROXY:-direct}
diff --git a/Makefile b/Makefile
index 4d7c507875529..717d7cafc660b 100644
--- a/Makefile
+++ b/Makefile
@@ -23,13 +23,13 @@ SHASUM ?= shasum -a 256
 HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" )
 COMMA := ,
 
-XGO_VERSION := go-1.19.x
+XGO_VERSION := go-1.20.x
 
 AIR_PACKAGE ?= github.com/cosmtrek/air@v1.40.4
 EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.6.0
 ERRCHECK_PACKAGE ?= github.com/kisielk/errcheck@v1.6.2
 GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.4.0
-GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.50.1
+GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.0
 GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10
 MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4
 SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.3
diff --git a/docs/config.yaml b/docs/config.yaml
index 0b47c0ffd83f5..0a6d5d13f23a9 100644
--- a/docs/config.yaml
+++ b/docs/config.yaml
@@ -19,8 +19,8 @@ params:
   author: The Gitea Authors
   website: https://docs.gitea.io
   version: 1.18.1
-  minGoVersion: 1.18
-  goVersion: 1.19
+  minGoVersion: 1.19
+  goVersion: 1.20
   minNodeVersion: 16
   search: nav
   repo: "https://github.com/go-gitea/gitea"
diff --git a/go.mod b/go.mod
index a929508e0de0d..eb23bd9e32a17 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module code.gitea.io/gitea
 
-go 1.18
+go 1.19
 
 require (
 	code.gitea.io/actions-proto-go v0.2.0
diff --git a/models/db/sql_postgres_with_schema.go b/models/db/sql_postgres_with_schema.go
index ec63447f6f6f3..c2694b37bb934 100644
--- a/models/db/sql_postgres_with_schema.go
+++ b/models/db/sql_postgres_with_schema.go
@@ -37,9 +37,7 @@ func (d *postgresSchemaDriver) Open(name string) (driver.Conn, error) {
 	}
 	schemaValue, _ := driver.String.ConvertValue(setting.Database.Schema)
 
-	// golangci lint is incorrect here - there is no benefit to using driver.ExecerContext here
-	// and in any case pq does not implement it
-	if execer, ok := conn.(driver.Execer); ok { //nolint
+	if execer, ok := conn.(driver.Execer); ok {
 		_, err := execer.Exec(`SELECT set_config(
 			'search_path',
 			$1 || ',' || current_setting('search_path'),
@@ -63,8 +61,7 @@ func (d *postgresSchemaDriver) Open(name string) (driver.Conn, error) {
 
 	// driver.String.ConvertValue will never return err for string
 
-	// golangci lint is incorrect here - there is no benefit to using stmt.ExecWithContext here
-	_, err = stmt.Exec([]driver.Value{schemaValue}) //nolint
+	_, err = stmt.Exec([]driver.Value{schemaValue})
 	if err != nil {
 		_ = conn.Close()
 		return nil, err