diff --git a/build/generate-bindata.go b/build/generate-bindata.go
index efd172f779..477139d67b 100644
--- a/build/generate-bindata.go
+++ b/build/generate-bindata.go
@@ -11,7 +11,6 @@ import (
 	"bytes"
 	"crypto/sha1"
 	"fmt"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"os"
@@ -28,7 +27,7 @@ func needsUpdate(dir string, filename string) (bool, []byte) {
 		needRegen = true
 	}
 
-	oldHash, err := ioutil.ReadFile(filename + ".hash")
+	oldHash, err := os.ReadFile(filename + ".hash")
 	if err != nil {
 		oldHash = []byte{}
 	}
@@ -83,5 +82,5 @@ func main() {
 	if err != nil {
 		log.Fatalf("%v\n", err)
 	}
-	_ = ioutil.WriteFile(filename+".hash", newHash, 0666)
+	_ = os.WriteFile(filename+".hash", newHash, 0666)
 }
diff --git a/build/generate-emoji.go b/build/generate-emoji.go
index da4e12373c..aa56d45f74 100644
--- a/build/generate-emoji.go
+++ b/build/generate-emoji.go
@@ -12,9 +12,10 @@ import (
 	"flag"
 	"fmt"
 	"go/format"
-	"io/ioutil"
+	"io"
 	"log"
 	"net/http"
+	"os"
 	"regexp"
 	"sort"
 	"strconv"
@@ -67,7 +68,7 @@ func main() {
 	}
 
 	// write
-	err = ioutil.WriteFile(*flagOut, buf, 0644)
+	err = os.WriteFile(*flagOut, buf, 0644)
 	if err != nil {
 		log.Fatal(err)
 	}
@@ -96,7 +97,7 @@ func generate() ([]byte, error) {
 	defer res.Body.Close()
 
 	// read all
-	body, err := ioutil.ReadAll(res.Body)
+	body, err := io.ReadAll(res.Body)
 	if err != nil {
 		return nil, err
 	}
@@ -157,7 +158,7 @@ func generate() ([]byte, error) {
 
 	// write a JSON file to use with tribute (write before adding skin tones since we can't support them there yet)
 	file, _ := json.Marshal(data)
-	_ = ioutil.WriteFile("assets/emoji.json", file, 0644)
+	_ = os.WriteFile("assets/emoji.json", file, 0644)
 
 	// Add skin tones to emoji that support it
 	var (
diff --git a/build/generate-gitignores.go b/build/generate-gitignores.go
index d0b972e803..811953ee4a 100644
--- a/build/generate-gitignores.go
+++ b/build/generate-gitignores.go
@@ -9,7 +9,6 @@ import (
 	"flag"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"os"
@@ -34,7 +33,7 @@ func main() {
 	flag.StringVar(&githubApiToken, "token", "", "github api token")
 	flag.Parse()
 
-	file, err := ioutil.TempFile(os.TempDir(), prefix)
+	file, err := os.CreateTemp(os.TempDir(), prefix)
 
 	if err != nil {
 		log.Fatalf("Failed to create temp file. %s", err)
@@ -114,13 +113,13 @@ func main() {
 	for dst, src := range filesToCopy {
 		// Read all content of src to data
 		src = path.Join(destination, src)
-		data, err := ioutil.ReadFile(src)
+		data, err := os.ReadFile(src)
 		if err != nil {
 			log.Fatalf("Failed to read src file. %s", err)
 		}
 		// Write data to dst
 		dst = path.Join(destination, dst)
-		err = ioutil.WriteFile(dst, data, 0644)
+		err = os.WriteFile(dst, data, 0644)
 		if err != nil {
 			log.Fatalf("Failed to write new file. %s", err)
 		}
diff --git a/build/generate-licenses.go b/build/generate-licenses.go
index 4009a0351d..75fb7cc810 100644
--- a/build/generate-licenses.go
+++ b/build/generate-licenses.go
@@ -9,7 +9,6 @@ import (
 	"flag"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"os"
@@ -34,7 +33,7 @@ func main() {
 	flag.StringVar(&githubApiToken, "token", "", "github api token")
 	flag.Parse()
 
-	file, err := ioutil.TempFile(os.TempDir(), prefix)
+	file, err := os.CreateTemp(os.TempDir(), prefix)
 
 	if err != nil {
 		log.Fatalf("Failed to create temp file. %s", err)
diff --git a/cmd/dump.go b/cmd/dump.go
index 5be77d6348..fd89eb89f9 100644
--- a/cmd/dump.go
+++ b/cmd/dump.go
@@ -7,7 +7,6 @@ package cmd
 
 import (
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path"
 	"path/filepath"
@@ -247,7 +246,7 @@ func runDump(ctx *cli.Context) error {
 		fatal("Path does not exist: %s", tmpDir)
 	}
 
-	dbDump, err := ioutil.TempFile(tmpDir, "gitea-db.sql")
+	dbDump, err := os.CreateTemp(tmpDir, "gitea-db.sql")
 	if err != nil {
 		fatal("Failed to create tmp file: %v", err)
 	}
diff --git a/contrib/fixtures/fixture_generation.go b/contrib/fixtures/fixture_generation.go
index 1665dab643..5408a005c6 100644
--- a/contrib/fixtures/fixture_generation.go
+++ b/contrib/fixtures/fixture_generation.go
@@ -6,7 +6,6 @@ package main
 
 import (
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 
@@ -65,7 +64,7 @@ func generate(name string) error {
 				return err
 			}
 			path := filepath.Join(fixturesDir, name+".yml")
-			if err := ioutil.WriteFile(path, []byte(data), 0644); err != nil {
+			if err := os.WriteFile(path, []byte(data), 0644); err != nil {
 				return fmt.Errorf("%s: %+v", path, err)
 			}
 			fmt.Printf("%s created.\n", path)
diff --git a/contrib/pr/checkout.go b/contrib/pr/checkout.go
index 44c3fd5176..cba6d4d372 100644
--- a/contrib/pr/checkout.go
+++ b/contrib/pr/checkout.go
@@ -12,7 +12,6 @@ import (
 	"context"
 	"flag"
 	"fmt"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"net/url"
@@ -52,11 +51,11 @@ func runPR() {
 	setting.SetCustomPathAndConf("", "", "")
 	setting.NewContext()
 
-	setting.RepoRootPath, err = ioutil.TempDir(os.TempDir(), "repos")
+	setting.RepoRootPath, err = os.MkdirTemp(os.TempDir(), "repos")
 	if err != nil {
 		log.Fatalf("TempDir: %v\n", err)
 	}
-	setting.AppDataPath, err = ioutil.TempDir(os.TempDir(), "appdata")
+	setting.AppDataPath, err = os.MkdirTemp(os.TempDir(), "appdata")
 	if err != nil {
 		log.Fatalf("TempDir: %v\n", err)
 	}
@@ -181,7 +180,7 @@ func main() {
 	codeFilePath = filepath.FromSlash(codeFilePath) //Convert to running OS
 
 	//Copy this file if it will not exist in the PR branch
-	dat, err := ioutil.ReadFile(codeFilePath)
+	dat, err := os.ReadFile(codeFilePath)
 	if err != nil {
 		log.Fatalf("Failed to cache this code file : %v", err)
 	}
@@ -245,7 +244,7 @@ func main() {
 		if err != nil {
 			log.Fatalf("Failed to duplicate this code file in PR : %v", err)
 		}
-		err = ioutil.WriteFile(codeFilePath, dat, 0644)
+		err = os.WriteFile(codeFilePath, dat, 0644)
 		if err != nil {
 			log.Fatalf("Failed to duplicate this code file in PR : %v", err)
 		}
diff --git a/integrations/api_helper_for_declarative_test.go b/integrations/api_helper_for_declarative_test.go
index 5d44cde5bf..8745ada96d 100644
--- a/integrations/api_helper_for_declarative_test.go
+++ b/integrations/api_helper_for_declarative_test.go
@@ -7,9 +7,9 @@ package integrations
 import (
 	"context"
 	"fmt"
-	"io/ioutil"
 	"net/http"
 	"net/url"
+	"os"
 	"testing"
 	"time"
 
@@ -163,7 +163,7 @@ func doAPICreateUserKey(ctx APITestContext, keyname, keyFile string, callback ..
 	return func(t *testing.T) {
 		urlStr := fmt.Sprintf("/api/v1/user/keys?token=%s", ctx.Token)
 
-		dataPubKey, err := ioutil.ReadFile(keyFile + ".pub")
+		dataPubKey, err := os.ReadFile(keyFile + ".pub")
 		assert.NoError(t, err)
 		req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateKeyOption{
 			Title: keyname,
@@ -199,7 +199,7 @@ func doAPICreateDeployKey(ctx APITestContext, keyname, keyFile string, readOnly
 	return func(t *testing.T) {
 		urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/keys?token=%s", ctx.Username, ctx.Reponame, ctx.Token)
 
-		dataPubKey, err := ioutil.ReadFile(keyFile + ".pub")
+		dataPubKey, err := os.ReadFile(keyFile + ".pub")
 		assert.NoError(t, err)
 		req := NewRequestWithJSON(t, "POST", urlStr, api.CreateKeyOption{
 			Title:    keyname,
diff --git a/integrations/api_repo_test.go b/integrations/api_repo_test.go
index 63da373827..b93319be33 100644
--- a/integrations/api_repo_test.go
+++ b/integrations/api_repo_test.go
@@ -6,9 +6,9 @@ package integrations
 
 import (
 	"fmt"
-	"io/ioutil"
 	"net/http"
 	"net/url"
+	"os"
 	"testing"
 
 	"code.gitea.io/gitea/models"
@@ -356,7 +356,7 @@ func testAPIRepoMigrateConflict(t *testing.T, u *url.URL) {
 		httpContext := baseAPITestContext
 
 		httpContext.Reponame = "repo-tmp-17"
-		dstPath, err := ioutil.TempDir("", httpContext.Reponame)
+		dstPath, err := os.MkdirTemp("", httpContext.Reponame)
 		assert.NoError(t, err)
 		defer util.RemoveAll(dstPath)
 		t.Run("CreateRepo", doAPICreateRepository(httpContext, false))
@@ -419,7 +419,7 @@ func testAPIRepoCreateConflict(t *testing.T, u *url.URL) {
 		httpContext := baseAPITestContext
 
 		httpContext.Reponame = "repo-tmp-17"
-		dstPath, err := ioutil.TempDir("", httpContext.Reponame)
+		dstPath, err := os.MkdirTemp("", httpContext.Reponame)
 		assert.NoError(t, err)
 		defer util.RemoveAll(dstPath)
 		t.Run("CreateRepo", doAPICreateRepository(httpContext, false))
diff --git a/integrations/create_no_session_test.go b/integrations/create_no_session_test.go
index d6b3634268..a76ff1eaaf 100644
--- a/integrations/create_no_session_test.go
+++ b/integrations/create_no_session_test.go
@@ -5,7 +5,6 @@
 package integrations
 
 import (
-	"io/ioutil"
 	"net/http"
 	"net/http/httptest"
 	"os"
@@ -69,7 +68,7 @@ func TestSessionFileCreation(t *testing.T) {
 	config.Provider = "file"
 
 	// Now create a temporaryDirectory
-	tmpDir, err := ioutil.TempDir("", "sessions")
+	tmpDir, err := os.MkdirTemp("", "sessions")
 	assert.NoError(t, err)
 	defer func() {
 		if _, err := os.Stat(tmpDir); !os.IsNotExist(err) {
diff --git a/integrations/git_clone_wiki_test.go b/integrations/git_clone_wiki_test.go
index 4e48df69f5..2139ce5fe0 100644
--- a/integrations/git_clone_wiki_test.go
+++ b/integrations/git_clone_wiki_test.go
@@ -7,8 +7,8 @@ package integrations
 import (
 	"context"
 	"fmt"
-	"io/ioutil"
 	"net/url"
+	"os"
 	"path/filepath"
 	"testing"
 
@@ -24,7 +24,7 @@ func assertFileExist(t *testing.T, p string) {
 }
 
 func assertFileEqual(t *testing.T, p string, content []byte) {
-	bs, err := ioutil.ReadFile(p)
+	bs, err := os.ReadFile(p)
 	assert.NoError(t, err)
 	assert.EqualValues(t, content, bs)
 }
@@ -33,7 +33,7 @@ func TestRepoCloneWiki(t *testing.T) {
 	onGiteaRun(t, func(t *testing.T, u *url.URL) {
 		defer prepareTestEnv(t)()
 
-		dstPath, err := ioutil.TempDir("", "clone_wiki")
+		dstPath, err := os.MkdirTemp("", "clone_wiki")
 		assert.NoError(t, err)
 
 		r := fmt.Sprintf("%suser2/repo1.wiki.git", u.String())
diff --git a/integrations/git_helper_for_declarative_test.go b/integrations/git_helper_for_declarative_test.go
index 5a5b1314c6..9da5c05f94 100644
--- a/integrations/git_helper_for_declarative_test.go
+++ b/integrations/git_helper_for_declarative_test.go
@@ -7,7 +7,6 @@ package integrations
 import (
 	"context"
 	"fmt"
-	"io/ioutil"
 	"net"
 	"net/http"
 	"net/url"
@@ -28,7 +27,7 @@ import (
 
 func withKeyFile(t *testing.T, keyname string, callback func(string)) {
 
-	tmpDir, err := ioutil.TempDir("", "key-file")
+	tmpDir, err := os.MkdirTemp("", "key-file")
 	assert.NoError(t, err)
 	defer util.RemoveAll(tmpDir)
 
@@ -39,7 +38,7 @@ func withKeyFile(t *testing.T, keyname string, callback func(string)) {
 	err = ssh.GenKeyPair(keyFile)
 	assert.NoError(t, err)
 
-	err = ioutil.WriteFile(path.Join(tmpDir, "ssh"), []byte("#!/bin/bash\n"+
+	err = os.WriteFile(path.Join(tmpDir, "ssh"), []byte("#!/bin/bash\n"+
 		"ssh -o \"UserKnownHostsFile=/dev/null\" -o \"StrictHostKeyChecking=no\" -o \"IdentitiesOnly=yes\" -i \""+keyFile+"\" \"$@\""), 0700)
 	assert.NoError(t, err)
 
@@ -125,7 +124,7 @@ func doGitClone(dstLocalPath string, u *url.URL) func(*testing.T) {
 
 func doGitCloneFail(u *url.URL) func(*testing.T) {
 	return func(t *testing.T) {
-		tmpDir, err := ioutil.TempDir("", "doGitCloneFail")
+		tmpDir, err := os.MkdirTemp("", "doGitCloneFail")
 		assert.NoError(t, err)
 		defer util.RemoveAll(tmpDir)
 		assert.Error(t, git.Clone(u.String(), tmpDir, git.CloneRepoOptions{}))
@@ -139,7 +138,7 @@ func doGitInitTestRepository(dstPath string) func(*testing.T) {
 	return func(t *testing.T) {
 		// Init repository in dstPath
 		assert.NoError(t, git.InitRepository(dstPath, false))
-		assert.NoError(t, ioutil.WriteFile(filepath.Join(dstPath, "README.md"), []byte(fmt.Sprintf("# Testing Repository\n\nOriginally created in: %s", dstPath)), 0644))
+		assert.NoError(t, os.WriteFile(filepath.Join(dstPath, "README.md"), []byte(fmt.Sprintf("# Testing Repository\n\nOriginally created in: %s", dstPath)), 0644))
 		assert.NoError(t, git.AddChanges(dstPath, true))
 		signature := git.Signature{
 			Email: "test@example.com",
diff --git a/integrations/git_smart_http_test.go b/integrations/git_smart_http_test.go
index 9a4e3689c1..c049f71c30 100644
--- a/integrations/git_smart_http_test.go
+++ b/integrations/git_smart_http_test.go
@@ -5,7 +5,7 @@
 package integrations
 
 import (
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/url"
 	"testing"
@@ -62,7 +62,7 @@ func testGitSmartHTTP(t *testing.T, u *url.URL) {
 			assert.NoError(t, err)
 			defer resp.Body.Close()
 			assert.EqualValues(t, kase.code, resp.StatusCode)
-			_, err = ioutil.ReadAll(resp.Body)
+			_, err = io.ReadAll(resp.Body)
 			assert.NoError(t, err)
 		})
 	}
diff --git a/integrations/git_test.go b/integrations/git_test.go
index 72e01d3753..9a264c9448 100644
--- a/integrations/git_test.go
+++ b/integrations/git_test.go
@@ -7,10 +7,10 @@ package integrations
 import (
 	"encoding/hex"
 	"fmt"
-	"io/ioutil"
 	"math/rand"
 	"net/http"
 	"net/url"
+	"os"
 	"path"
 	"path/filepath"
 	"strconv"
@@ -52,7 +52,7 @@ func testGit(t *testing.T, u *url.URL) {
 		httpContext.Reponame = "repo-tmp-17"
 		forkedUserCtx.Reponame = httpContext.Reponame
 
-		dstPath, err := ioutil.TempDir("", httpContext.Reponame)
+		dstPath, err := os.MkdirTemp("", httpContext.Reponame)
 		assert.NoError(t, err)
 		defer util.RemoveAll(dstPath)
 
@@ -102,7 +102,7 @@ func testGit(t *testing.T, u *url.URL) {
 			sshURL := createSSHUrl(sshContext.GitPath(), u)
 
 			//Setup clone folder
-			dstPath, err := ioutil.TempDir("", sshContext.Reponame)
+			dstPath, err := os.MkdirTemp("", sshContext.Reponame)
 			assert.NoError(t, err)
 			defer util.RemoveAll(dstPath)
 
@@ -128,7 +128,7 @@ func testGit(t *testing.T, u *url.URL) {
 }
 
 func ensureAnonymousClone(t *testing.T, u *url.URL) {
-	dstLocalPath, err := ioutil.TempDir("", "repo1")
+	dstLocalPath, err := os.MkdirTemp("", "repo1")
 	assert.NoError(t, err)
 	defer util.RemoveAll(dstLocalPath)
 	t.Run("CloneAnonymous", doGitClone(dstLocalPath, u))
@@ -311,7 +311,7 @@ func generateCommitWithNewData(size int, repoPath, email, fullName, prefix strin
 
 	buffer := make([]byte, bufSize)
 
-	tmpFile, err := ioutil.TempFile(repoPath, prefix)
+	tmpFile, err := os.CreateTemp(repoPath, prefix)
 	if err != nil {
 		return "", err
 	}
@@ -558,7 +558,7 @@ func doPushCreate(ctx APITestContext, u *url.URL) func(t *testing.T) {
 		u.Path = ctx.GitPath()
 
 		// Create a temporary directory
-		tmpDir, err := ioutil.TempDir("", ctx.Reponame)
+		tmpDir, err := os.MkdirTemp("", ctx.Reponame)
 		assert.NoError(t, err)
 		defer util.RemoveAll(tmpDir)
 
@@ -636,7 +636,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, baseBranch, headB
 		t.Run("CreateHeadBranch", doGitCreateBranch(dstPath, headBranch))
 
 		t.Run("AddCommit", func(t *testing.T) {
-			err := ioutil.WriteFile(path.Join(dstPath, "test_file"), []byte("## test content"), 0666)
+			err := os.WriteFile(path.Join(dstPath, "test_file"), []byte("## test content"), 0666)
 			if !assert.NoError(t, err) {
 				return
 			}
@@ -710,7 +710,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, baseBranch, headB
 		}
 
 		t.Run("AddCommit2", func(t *testing.T) {
-			err := ioutil.WriteFile(path.Join(dstPath, "test_file"), []byte("## test content \n ## test content 2"), 0666)
+			err := os.WriteFile(path.Join(dstPath, "test_file"), []byte("## test content \n ## test content 2"), 0666)
 			if !assert.NoError(t, err) {
 				return
 			}
diff --git a/integrations/gpg_git_test.go b/integrations/gpg_git_test.go
index 11d9a0e2a5..2cfb883fd9 100644
--- a/integrations/gpg_git_test.go
+++ b/integrations/gpg_git_test.go
@@ -7,7 +7,6 @@ package integrations
 import (
 	"encoding/base64"
 	"fmt"
-	"io/ioutil"
 	"net/url"
 	"os"
 	"testing"
@@ -28,7 +27,7 @@ func TestGPGGit(t *testing.T) {
 	username := "user2"
 
 	// OK Set a new GPG home
-	tmpDir, err := ioutil.TempDir("", "temp-gpg")
+	tmpDir, err := os.MkdirTemp("", "temp-gpg")
 	assert.NoError(t, err)
 	defer util.RemoveAll(tmpDir)
 
diff --git a/integrations/lfs_getobject_test.go b/integrations/lfs_getobject_test.go
index 063f72b25c..d179428c6d 100644
--- a/integrations/lfs_getobject_test.go
+++ b/integrations/lfs_getobject_test.go
@@ -7,7 +7,7 @@ package integrations
 import (
 	"archive/zip"
 	"bytes"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/http/httptest"
 	"testing"
@@ -74,7 +74,7 @@ func checkResponseTestContentEncoding(t *testing.T, content *[]byte, resp *httpt
 		assert.Contains(t, contentEncoding, "gzip")
 		gzippReader, err := gzipp.NewReader(resp.Body)
 		assert.NoError(t, err)
-		result, err := ioutil.ReadAll(gzippReader)
+		result, err := io.ReadAll(gzippReader)
 		assert.NoError(t, err)
 		assert.Equal(t, *content, result)
 	}
diff --git a/integrations/lfs_local_endpoint_test.go b/integrations/lfs_local_endpoint_test.go
index eda418c429..7e0166b381 100644
--- a/integrations/lfs_local_endpoint_test.go
+++ b/integrations/lfs_local_endpoint_test.go
@@ -6,7 +6,6 @@ package integrations
 
 import (
 	"fmt"
-	"io/ioutil"
 	"net/url"
 	"os"
 	"path/filepath"
@@ -25,14 +24,14 @@ func str2url(raw string) *url.URL {
 func TestDetermineLocalEndpoint(t *testing.T) {
 	defer prepareTestEnv(t)()
 
-	root, _ := ioutil.TempDir("", "lfs_test")
+	root, _ := os.MkdirTemp("", "lfs_test")
 	defer os.RemoveAll(root)
 
-	rootdotgit, _ := ioutil.TempDir("", "lfs_test")
+	rootdotgit, _ := os.MkdirTemp("", "lfs_test")
 	defer os.RemoveAll(rootdotgit)
 	os.Mkdir(filepath.Join(rootdotgit, ".git"), 0700)
 
-	lfsroot, _ := ioutil.TempDir("", "lfs_test")
+	lfsroot, _ := os.MkdirTemp("", "lfs_test")
 	defer os.RemoveAll(lfsroot)
 
 	// Test cases
diff --git a/integrations/migrate_test.go b/integrations/migrate_test.go
index e79be238d5..c0d5d4fc75 100644
--- a/integrations/migrate_test.go
+++ b/integrations/migrate_test.go
@@ -5,7 +5,6 @@
 package integrations
 
 import (
-	"io/ioutil"
 	"os"
 	"testing"
 
@@ -25,14 +24,14 @@ func TestMigrateLocalPath(t *testing.T) {
 	old := setting.ImportLocalPaths
 	setting.ImportLocalPaths = true
 
-	lowercasePath, err := ioutil.TempDir("", "lowercase") // may not be lowercase because TempDir creates a random directory name which may be mixedcase
+	lowercasePath, err := os.MkdirTemp("", "lowercase") // may not be lowercase because MkdirTemp creates a random directory name which may be mixedcase
 	assert.NoError(t, err)
 	defer os.RemoveAll(lowercasePath)
 
 	err = migrations.IsMigrateURLAllowed(lowercasePath, adminUser)
 	assert.NoError(t, err, "case lowercase path")
 
-	mixedcasePath, err := ioutil.TempDir("", "mIxeDCaSe")
+	mixedcasePath, err := os.MkdirTemp("", "mIxeDCaSe")
 	assert.NoError(t, err)
 	defer os.RemoveAll(mixedcasePath)
 
diff --git a/integrations/migration-test/migration_test.go b/integrations/migration-test/migration_test.go
index 66aca0ef70..43dc2a8348 100644
--- a/integrations/migration-test/migration_test.go
+++ b/integrations/migration-test/migration_test.go
@@ -9,7 +9,7 @@ import (
 	"context"
 	"database/sql"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"os"
 	"path"
 	"path/filepath"
@@ -113,7 +113,7 @@ func readSQLFromFile(version string) (string, error) {
 	}
 	defer gr.Close()
 
-	bytes, err := ioutil.ReadAll(gr)
+	bytes, err := io.ReadAll(gr)
 	if err != nil {
 		return "", err
 	}
diff --git a/integrations/oauth_test.go b/integrations/oauth_test.go
index c97db777be..c36aab652b 100644
--- a/integrations/oauth_test.go
+++ b/integrations/oauth_test.go
@@ -6,7 +6,7 @@ package integrations
 
 import (
 	"bytes"
-	"io/ioutil"
+	"io"
 	"testing"
 
 	"code.gitea.io/gitea/modules/json"
@@ -240,20 +240,20 @@ func TestRefreshTokenInvalidation(t *testing.T) {
 		"refresh_token": parsed.RefreshToken,
 	})
 
-	bs, err := ioutil.ReadAll(refreshReq.Body)
+	bs, err := io.ReadAll(refreshReq.Body)
 	assert.NoError(t, err)
 
-	refreshReq.Body = ioutil.NopCloser(bytes.NewReader(bs))
+	refreshReq.Body = io.NopCloser(bytes.NewReader(bs))
 	MakeRequest(t, refreshReq, 200)
 
-	refreshReq.Body = ioutil.NopCloser(bytes.NewReader(bs))
+	refreshReq.Body = io.NopCloser(bytes.NewReader(bs))
 	MakeRequest(t, refreshReq, 200)
 
 	// test with invalidation
 	setting.OAuth2.InvalidateRefreshTokens = true
-	refreshReq.Body = ioutil.NopCloser(bytes.NewReader(bs))
+	refreshReq.Body = io.NopCloser(bytes.NewReader(bs))
 	MakeRequest(t, refreshReq, 200)
 
-	refreshReq.Body = ioutil.NopCloser(bytes.NewReader(bs))
+	refreshReq.Body = io.NopCloser(bytes.NewReader(bs))
 	MakeRequest(t, refreshReq, 400)
 }
diff --git a/integrations/repo_tag_test.go b/integrations/repo_tag_test.go
index 05505a644d..abbc2c02fc 100644
--- a/integrations/repo_tag_test.go
+++ b/integrations/repo_tag_test.go
@@ -5,8 +5,8 @@
 package integrations
 
 import (
-	"io/ioutil"
 	"net/url"
+	"os"
 	"testing"
 
 	"code.gitea.io/gitea/models"
@@ -55,7 +55,7 @@ func TestCreateNewTagProtected(t *testing.T) {
 			username := "user2"
 			httpContext := NewAPITestContext(t, username, "repo1")
 
-			dstPath, err := ioutil.TempDir("", httpContext.Reponame)
+			dstPath, err := os.MkdirTemp("", httpContext.Reponame)
 			assert.NoError(t, err)
 			defer util.RemoveAll(dstPath)
 
diff --git a/integrations/ssh_key_test.go b/integrations/ssh_key_test.go
index 91774f6335..f9c807413a 100644
--- a/integrations/ssh_key_test.go
+++ b/integrations/ssh_key_test.go
@@ -6,9 +6,9 @@ package integrations
 
 import (
 	"fmt"
-	"io/ioutil"
 	"net/http"
 	"net/url"
+	"os"
 	"path/filepath"
 	"testing"
 	"time"
@@ -28,7 +28,7 @@ func doCheckRepositoryEmptyStatus(ctx APITestContext, isEmpty bool) func(*testin
 
 func doAddChangesToCheckout(dstPath, filename string) func(*testing.T) {
 	return func(t *testing.T) {
-		assert.NoError(t, ioutil.WriteFile(filepath.Join(dstPath, filename), []byte(fmt.Sprintf("# Testing Repository\n\nOriginally created in: %s at time: %v", dstPath, time.Now())), 0644))
+		assert.NoError(t, os.WriteFile(filepath.Join(dstPath, filename), []byte(fmt.Sprintf("# Testing Repository\n\nOriginally created in: %s at time: %v", dstPath, time.Now())), 0644))
 		assert.NoError(t, git.AddChanges(dstPath, true))
 		signature := git.Signature{
 			Email: "test@example.com",
@@ -61,7 +61,7 @@ func testPushDeployKeyOnEmptyRepo(t *testing.T, u *url.URL) {
 		t.Run("CreatePushDeployKey", doAPICreateDeployKey(ctx, keyname, keyFile, false))
 
 		// Setup the testing repository
-		dstPath, err := ioutil.TempDir("", "repo-tmp-deploy-key-empty-repo-1")
+		dstPath, err := os.MkdirTemp("", "repo-tmp-deploy-key-empty-repo-1")
 		assert.NoError(t, err)
 		defer util.RemoveAll(dstPath)
 
@@ -107,7 +107,7 @@ func testKeyOnlyOneType(t *testing.T, u *url.URL) {
 	withKeyFile(t, keyname, func(keyFile string) {
 		var userKeyPublicKeyID int64
 		t.Run("KeyCanOnlyBeUser", func(t *testing.T) {
-			dstPath, err := ioutil.TempDir("", ctx.Reponame)
+			dstPath, err := os.MkdirTemp("", ctx.Reponame)
 			assert.NoError(t, err)
 			defer util.RemoveAll(dstPath)
 
@@ -133,7 +133,7 @@ func testKeyOnlyOneType(t *testing.T, u *url.URL) {
 		})
 
 		t.Run("KeyCanBeAnyDeployButNotUserAswell", func(t *testing.T) {
-			dstPath, err := ioutil.TempDir("", ctx.Reponame)
+			dstPath, err := os.MkdirTemp("", ctx.Reponame)
 			assert.NoError(t, err)
 			defer util.RemoveAll(dstPath)
 
@@ -151,7 +151,7 @@ func testKeyOnlyOneType(t *testing.T, u *url.URL) {
 			t.Run("FailToPush", doGitPushTestRepositoryFail(dstPath, "origin", "master"))
 
 			otherSSHURL := createSSHUrl(otherCtx.GitPath(), u)
-			dstOtherPath, err := ioutil.TempDir("", otherCtx.Reponame)
+			dstOtherPath, err := os.MkdirTemp("", otherCtx.Reponame)
 			assert.NoError(t, err)
 			defer util.RemoveAll(dstOtherPath)
 
@@ -168,7 +168,7 @@ func testKeyOnlyOneType(t *testing.T, u *url.URL) {
 
 		t.Run("DeleteRepositoryShouldReleaseKey", func(t *testing.T) {
 			otherSSHURL := createSSHUrl(otherCtx.GitPath(), u)
-			dstOtherPath, err := ioutil.TempDir("", otherCtx.Reponame)
+			dstOtherPath, err := os.MkdirTemp("", otherCtx.Reponame)
 			assert.NoError(t, err)
 			defer util.RemoveAll(dstOtherPath)
 
@@ -190,7 +190,7 @@ func testKeyOnlyOneType(t *testing.T, u *url.URL) {
 				userKeyPublicKeyID = publicKey.ID
 			}))
 
-			dstPath, err := ioutil.TempDir("", ctx.Reponame)
+			dstPath, err := os.MkdirTemp("", ctx.Reponame)
 			assert.NoError(t, err)
 			defer util.RemoveAll(dstPath)
 
diff --git a/models/db/unit_tests.go b/models/db/unit_tests.go
index 8d834fe118..0540c9ba8a 100644
--- a/models/db/unit_tests.go
+++ b/models/db/unit_tests.go
@@ -6,7 +6,6 @@ package db
 
 import (
 	"fmt"
-	"io/ioutil"
 	"math"
 	"net/url"
 	"os"
@@ -57,11 +56,11 @@ func MainTest(m *testing.M, pathToGiteaRoot string) {
 	setting.SSH.Port = 3000
 	setting.SSH.Domain = "try.gitea.io"
 	setting.Database.UseSQLite3 = true
-	setting.RepoRootPath, err = ioutil.TempDir(os.TempDir(), "repos")
+	setting.RepoRootPath, err = os.MkdirTemp(os.TempDir(), "repos")
 	if err != nil {
 		fatalTestError("TempDir: %v\n", err)
 	}
-	setting.AppDataPath, err = ioutil.TempDir(os.TempDir(), "appdata")
+	setting.AppDataPath, err = os.MkdirTemp(os.TempDir(), "appdata")
 	if err != nil {
 		fatalTestError("TempDir: %v\n", err)
 	}
diff --git a/models/engine_test.go b/models/engine_test.go
index 2c93667511..66e3ef099f 100644
--- a/models/engine_test.go
+++ b/models/engine_test.go
@@ -5,7 +5,6 @@
 package models
 
 import (
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"testing"
@@ -19,7 +18,7 @@ import (
 func TestDumpDatabase(t *testing.T) {
 	assert.NoError(t, db.PrepareTestDatabase())
 
-	dir, err := ioutil.TempDir(os.TempDir(), "dump")
+	dir, err := os.MkdirTemp(os.TempDir(), "dump")
 	assert.NoError(t, err)
 
 	type Version struct {
diff --git a/models/fixture_test.go b/models/fixture_test.go
index 387ee8ff57..3c6ebc0685 100644
--- a/models/fixture_test.go
+++ b/models/fixture_test.go
@@ -5,7 +5,7 @@
 package models
 
 import (
-	"io/ioutil"
+	"os"
 	"path/filepath"
 	"testing"
 
@@ -23,7 +23,7 @@ func TestFixtureGeneration(t *testing.T) {
 		if !assert.NoError(t, err) {
 			return
 		}
-		bytes, err := ioutil.ReadFile(filepath.Join(db.FixturesDir(), name+".yml"))
+		bytes, err := os.ReadFile(filepath.Join(db.FixturesDir(), name+".yml"))
 		if !assert.NoError(t, err) {
 			return
 		}
diff --git a/models/helper_directory.go b/models/helper_directory.go
index aed2dbcf9b..10114959ef 100644
--- a/models/helper_directory.go
+++ b/models/helper_directory.go
@@ -6,7 +6,6 @@ package models
 
 import (
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path"
 	"path/filepath"
@@ -30,7 +29,7 @@ func CreateTemporaryPath(prefix string) (string, error) {
 		log.Error("Unable to create localcopypath directory: %s (%v)", LocalCopyPath(), err)
 		return "", fmt.Errorf("Failed to create localcopypath directory %s: %v", LocalCopyPath(), err)
 	}
-	basePath, err := ioutil.TempDir(LocalCopyPath(), prefix+".git")
+	basePath, err := os.MkdirTemp(LocalCopyPath(), prefix+".git")
 	if err != nil {
 		log.Error("Unable to create temporary directory: %s-*.git (%v)", prefix, err)
 		return "", fmt.Errorf("Failed to create dir %s-*.git: %v", prefix, err)
diff --git a/models/migrations/v115.go b/models/migrations/v115.go
index 8222a8ceea..7708ed5e28 100644
--- a/models/migrations/v115.go
+++ b/models/migrations/v115.go
@@ -7,7 +7,7 @@ package migrations
 import (
 	"crypto/md5"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"math"
 	"os"
 	"path/filepath"
@@ -141,9 +141,9 @@ func copyOldAvatarToNewLocation(userID int64, oldAvatar string) (string, error)
 	}
 	defer fr.Close()
 
-	data, err := ioutil.ReadAll(fr)
+	data, err := io.ReadAll(fr)
 	if err != nil {
-		return "", fmt.Errorf("ioutil.ReadAll: %v", err)
+		return "", fmt.Errorf("io.ReadAll: %v", err)
 	}
 
 	newAvatar := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%x", userID, md5.Sum(data)))))
@@ -151,8 +151,8 @@ func copyOldAvatarToNewLocation(userID int64, oldAvatar string) (string, error)
 		return newAvatar, nil
 	}
 
-	if err := ioutil.WriteFile(filepath.Join(setting.Avatar.Path, newAvatar), data, 0o666); err != nil {
-		return "", fmt.Errorf("ioutil.WriteFile: %v", err)
+	if err := os.WriteFile(filepath.Join(setting.Avatar.Path, newAvatar), data, 0o666); err != nil {
+		return "", fmt.Errorf("os.WriteFile: %v", err)
 	}
 
 	return newAvatar, nil
diff --git a/models/repo.go b/models/repo.go
index 914001191a..39e5a089eb 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -10,11 +10,7 @@ import (
 	"errors"
 	"fmt"
 	"html/template"
-	"unicode/utf8"
-
-	// Needed for jpeg support
-	_ "image/jpeg"
-	"io/ioutil"
+	_ "image/jpeg" // Needed for jpeg support
 	"net"
 	"net/url"
 	"os"
@@ -24,6 +20,7 @@ import (
 	"strconv"
 	"strings"
 	"time"
+	"unicode/utf8"
 
 	"code.gitea.io/gitea/models/db"
 	"code.gitea.io/gitea/modules/lfs"
@@ -1013,7 +1010,7 @@ func GetRepoInitFile(tp, name string) ([]byte, error) {
 		log.Error("Unable to check if %s is a file. Error: %v", customPath, err)
 	}
 	if isFile {
-		return ioutil.ReadFile(customPath)
+		return os.ReadFile(customPath)
 	}
 
 	switch tp {
diff --git a/models/ssh_key_parse.go b/models/ssh_key_parse.go
index a86b7de02a..d2c24b0a2a 100644
--- a/models/ssh_key_parse.go
+++ b/models/ssh_key_parse.go
@@ -13,8 +13,8 @@ import (
 	"encoding/pem"
 	"errors"
 	"fmt"
-	"io/ioutil"
 	"math/big"
+	"os"
 	"strconv"
 	"strings"
 
@@ -263,7 +263,7 @@ func SSHNativeParsePublicKey(keyLine string) (string, int, error) {
 // writeTmpKeyFile writes key content to a temporary file
 // and returns the name of that file, along with any possible errors.
 func writeTmpKeyFile(content string) (string, error) {
-	tmpFile, err := ioutil.TempFile(setting.SSH.KeyTestPath, "gitea_keytest")
+	tmpFile, err := os.CreateTemp(setting.SSH.KeyTestPath, "gitea_keytest")
 	if err != nil {
 		return "", fmt.Errorf("TempFile: %v", err)
 	}
diff --git a/modules/avatar/avatar_test.go b/modules/avatar/avatar_test.go
index f48266c858..b958a9e236 100644
--- a/modules/avatar/avatar_test.go
+++ b/modules/avatar/avatar_test.go
@@ -5,7 +5,7 @@
 package avatar
 
 import (
-	"io/ioutil"
+	"os"
 	"testing"
 
 	"code.gitea.io/gitea/modules/setting"
@@ -30,7 +30,7 @@ func Test_PrepareWithPNG(t *testing.T) {
 	setting.Avatar.MaxWidth = 4096
 	setting.Avatar.MaxHeight = 4096
 
-	data, err := ioutil.ReadFile("testdata/avatar.png")
+	data, err := os.ReadFile("testdata/avatar.png")
 	assert.NoError(t, err)
 
 	imgPtr, err := Prepare(data)
@@ -44,7 +44,7 @@ func Test_PrepareWithJPEG(t *testing.T) {
 	setting.Avatar.MaxWidth = 4096
 	setting.Avatar.MaxHeight = 4096
 
-	data, err := ioutil.ReadFile("testdata/avatar.jpeg")
+	data, err := os.ReadFile("testdata/avatar.jpeg")
 	assert.NoError(t, err)
 
 	imgPtr, err := Prepare(data)
@@ -65,7 +65,7 @@ func Test_PrepareWithInvalidImageSize(t *testing.T) {
 	setting.Avatar.MaxWidth = 5
 	setting.Avatar.MaxHeight = 5
 
-	data, err := ioutil.ReadFile("testdata/avatar.png")
+	data, err := os.ReadFile("testdata/avatar.png")
 	assert.NoError(t, err)
 
 	_, err = Prepare(data)
diff --git a/modules/charset/charset.go b/modules/charset/charset.go
index 3000864c2e..47906e2638 100644
--- a/modules/charset/charset.go
+++ b/modules/charset/charset.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"strings"
 	"unicode/utf8"
 
@@ -78,7 +77,7 @@ func ToUTF8WithErr(content []byte) (string, error) {
 
 // ToUTF8WithFallback detects the encoding of content and coverts to UTF-8 if possible
 func ToUTF8WithFallback(content []byte) []byte {
-	bs, _ := ioutil.ReadAll(ToUTF8WithFallbackReader(bytes.NewReader(content)))
+	bs, _ := io.ReadAll(ToUTF8WithFallbackReader(bytes.NewReader(content)))
 	return bs
 }
 
diff --git a/modules/context/repo.go b/modules/context/repo.go
index 89ff890cc3..eceefd9e59 100644
--- a/modules/context/repo.go
+++ b/modules/context/repo.go
@@ -8,7 +8,7 @@ package context
 import (
 	"context"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/url"
 	"path"
 	"strings"
@@ -915,7 +915,7 @@ func (ctx *Context) IssueTemplatesFromDefaultBranch() []api.IssueTemplate {
 						_ = r.Close()
 					}
 				}()
-				data, err := ioutil.ReadAll(r)
+				data, err := io.ReadAll(r)
 				if err != nil {
 					log.Debug("ReadAll: %v", err)
 					continue
diff --git a/modules/doctor/paths.go b/modules/doctor/paths.go
index 53409b5fa4..88172d3150 100644
--- a/modules/doctor/paths.go
+++ b/modules/doctor/paths.go
@@ -6,7 +6,6 @@ package doctor
 
 import (
 	"fmt"
-	"io/ioutil"
 	"os"
 
 	"code.gitea.io/gitea/modules/log"
@@ -102,7 +101,7 @@ func isWritableDir(path string) error {
 	// There's no platform-independent way of checking if a directory is writable
 	// https://stackoverflow.com/questions/20026320/how-to-tell-if-folder-exists-and-is-writable
 
-	tmpFile, err := ioutil.TempFile(path, "doctors-order")
+	tmpFile, err := os.CreateTemp(path, "doctors-order")
 	if err != nil {
 		return err
 	}
diff --git a/modules/git/blame_test.go b/modules/git/blame_test.go
index 734d63ee14..4bee8cd27a 100644
--- a/modules/git/blame_test.go
+++ b/modules/git/blame_test.go
@@ -6,7 +6,7 @@ package git
 
 import (
 	"context"
-	"io/ioutil"
+	"os"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
@@ -84,7 +84,7 @@ e2aa991e10ffd924a828ec149951f2f20eecead2 7 7
 `
 
 func TestReadingBlameOutput(t *testing.T) {
-	tempFile, err := ioutil.TempFile("", ".txt")
+	tempFile, err := os.CreateTemp("", ".txt")
 	if err != nil {
 		panic(err)
 	}
diff --git a/modules/git/blob.go b/modules/git/blob.go
index 5831bc3735..c7919f3c41 100644
--- a/modules/git/blob.go
+++ b/modules/git/blob.go
@@ -9,7 +9,6 @@ import (
 	"bytes"
 	"encoding/base64"
 	"io"
-	"io/ioutil"
 
 	"code.gitea.io/gitea/modules/typesniffer"
 )
@@ -83,7 +82,7 @@ func (b *Blob) GetBlobContentBase64() (string, error) {
 		}
 	}()
 
-	out, err := ioutil.ReadAll(pr)
+	out, err := io.ReadAll(pr)
 	if err != nil {
 		return "", err
 	}
diff --git a/modules/git/blob_nogogit.go b/modules/git/blob_nogogit.go
index 3391bc3931..65a73ebc52 100644
--- a/modules/git/blob_nogogit.go
+++ b/modules/git/blob_nogogit.go
@@ -11,7 +11,6 @@ import (
 	"bufio"
 	"bytes"
 	"io"
-	"io/ioutil"
 	"math"
 
 	"code.gitea.io/gitea/modules/log"
@@ -46,13 +45,13 @@ func (b *Blob) DataAsync() (io.ReadCloser, error) {
 	b.size = size
 
 	if size < 4096 {
-		bs, err := ioutil.ReadAll(io.LimitReader(rd, size))
+		bs, err := io.ReadAll(io.LimitReader(rd, size))
 		defer cancel()
 		if err != nil {
 			return nil, err
 		}
 		_, err = rd.Discard(1)
-		return ioutil.NopCloser(bytes.NewReader(bs)), err
+		return io.NopCloser(bytes.NewReader(bs)), err
 	}
 
 	return &blobReader{
diff --git a/modules/git/blob_test.go b/modules/git/blob_test.go
index 2ceda6c4ef..34d8054d1e 100644
--- a/modules/git/blob_test.go
+++ b/modules/git/blob_test.go
@@ -6,7 +6,7 @@
 package git
 
 import (
-	"io/ioutil"
+	"io"
 	"path/filepath"
 	"testing"
 
@@ -30,7 +30,7 @@ func TestBlob_Data(t *testing.T) {
 	assert.NoError(t, err)
 	require.NotNil(t, r)
 
-	data, err := ioutil.ReadAll(r)
+	data, err := io.ReadAll(r)
 	assert.NoError(t, r.Close())
 
 	assert.NoError(t, err)
@@ -55,7 +55,7 @@ func Benchmark_Blob_Data(b *testing.B) {
 		if err != nil {
 			b.Fatal(err)
 		}
-		ioutil.ReadAll(r)
+		io.ReadAll(r)
 		_ = r.Close()
 	}
 }
diff --git a/modules/git/hook.go b/modules/git/hook.go
index 7007d23be2..ecd2db3cc3 100644
--- a/modules/git/hook.go
+++ b/modules/git/hook.go
@@ -7,7 +7,6 @@ package git
 
 import (
 	"errors"
-	"io/ioutil"
 	"os"
 	"path"
 	"path/filepath"
@@ -59,14 +58,14 @@ func GetHook(repoPath, name string) (*Hook, error) {
 	}
 	samplePath := filepath.Join(repoPath, "hooks", name+".sample")
 	if isFile(h.path) {
-		data, err := ioutil.ReadFile(h.path)
+		data, err := os.ReadFile(h.path)
 		if err != nil {
 			return nil, err
 		}
 		h.IsActive = true
 		h.Content = string(data)
 	} else if isFile(samplePath) {
-		data, err := ioutil.ReadFile(samplePath)
+		data, err := os.ReadFile(samplePath)
 		if err != nil {
 			return nil, err
 		}
@@ -97,7 +96,7 @@ func (h *Hook) Update() error {
 		return err
 	}
 
-	err := ioutil.WriteFile(h.path, []byte(strings.ReplaceAll(h.Content, "\r", "")), os.ModePerm)
+	err := os.WriteFile(h.path, []byte(strings.ReplaceAll(h.Content, "\r", "")), os.ModePerm)
 	if err != nil {
 		return err
 	}
@@ -143,5 +142,5 @@ func SetUpdateHook(repoPath, content string) (err error) {
 	if err != nil {
 		return err
 	}
-	return ioutil.WriteFile(hookPath, []byte(content), 0777)
+	return os.WriteFile(hookPath, []byte(content), 0777)
 }
diff --git a/modules/git/notes_gogit.go b/modules/git/notes_gogit.go
index 84f66d86bf..28dbbc0ee5 100644
--- a/modules/git/notes_gogit.go
+++ b/modules/git/notes_gogit.go
@@ -9,7 +9,7 @@ package git
 
 import (
 	"context"
-	"io/ioutil"
+	"io"
 
 	"code.gitea.io/gitea/modules/log"
 
@@ -58,7 +58,7 @@ func GetNote(ctx context.Context, repo *Repository, commitID string, note *Note)
 	}
 
 	defer dataRc.Close()
-	d, err := ioutil.ReadAll(dataRc)
+	d, err := io.ReadAll(dataRc)
 	if err != nil {
 		log.Error("Unable to read blob with ID %q. Error: %v", blob.ID, err)
 		return err
diff --git a/modules/git/notes_nogogit.go b/modules/git/notes_nogogit.go
index 9a54b48106..5afe8d4614 100644
--- a/modules/git/notes_nogogit.go
+++ b/modules/git/notes_nogogit.go
@@ -9,7 +9,7 @@ package git
 
 import (
 	"context"
-	"io/ioutil"
+	"io"
 	"strings"
 
 	"code.gitea.io/gitea/modules/log"
@@ -60,7 +60,7 @@ func GetNote(ctx context.Context, repo *Repository, commitID string, note *Note)
 			_ = dataRc.Close()
 		}
 	}()
-	d, err := ioutil.ReadAll(dataRc)
+	d, err := io.ReadAll(dataRc)
 	if err != nil {
 		log.Error("Unable to read blob with ID %q. Error: %v", blob.ID, err)
 		return err
diff --git a/modules/git/repo_blob_test.go b/modules/git/repo_blob_test.go
index ccf418b305..132a3fa50c 100644
--- a/modules/git/repo_blob_test.go
+++ b/modules/git/repo_blob_test.go
@@ -6,7 +6,7 @@ package git
 
 import (
 	"fmt"
-	"io/ioutil"
+	"io"
 	"path/filepath"
 	"testing"
 
@@ -34,7 +34,7 @@ func TestRepository_GetBlob_Found(t *testing.T) {
 		dataReader, err := blob.DataAsync()
 		assert.NoError(t, err)
 
-		data, err := ioutil.ReadAll(dataReader)
+		data, err := io.ReadAll(dataReader)
 		assert.NoError(t, dataReader.Close())
 		assert.NoError(t, err)
 		assert.Equal(t, testCase.Data, data)
diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go
index e456f04e87..25060f56da 100644
--- a/modules/git/repo_commit.go
+++ b/modules/git/repo_commit.go
@@ -8,7 +8,6 @@ package git
 import (
 	"bytes"
 	"io"
-	"io/ioutil"
 	"strconv"
 	"strings"
 
@@ -222,7 +221,7 @@ func (repo *Repository) CommitsByFileAndRange(revision, file string, page int) (
 	}()
 
 	if skip > 0 {
-		_, err := io.CopyN(ioutil.Discard, stdoutReader, int64(skip*41))
+		_, err := io.CopyN(io.Discard, stdoutReader, int64(skip*41))
 		if err != nil {
 			if err == io.EOF {
 				return []*Commit{}, nil
@@ -232,7 +231,7 @@ func (repo *Repository) CommitsByFileAndRange(revision, file string, page int) (
 		}
 	}
 
-	stdout, err := ioutil.ReadAll(stdoutReader)
+	stdout, err := io.ReadAll(stdoutReader)
 	if err != nil {
 		return nil, err
 	}
diff --git a/modules/git/repo_commit_nogogit.go b/modules/git/repo_commit_nogogit.go
index b7e49a6501..8bfc953759 100644
--- a/modules/git/repo_commit_nogogit.go
+++ b/modules/git/repo_commit_nogogit.go
@@ -11,7 +11,6 @@ import (
 	"bufio"
 	"errors"
 	"io"
-	"io/ioutil"
 	"strings"
 
 	"code.gitea.io/gitea/modules/log"
@@ -77,7 +76,7 @@ func (repo *Repository) getCommitFromBatchReader(rd *bufio.Reader, id SHA1) (*Co
 	case "tag":
 		// then we need to parse the tag
 		// and load the commit
-		data, err := ioutil.ReadAll(io.LimitReader(rd, size))
+		data, err := io.ReadAll(io.LimitReader(rd, size))
 		if err != nil {
 			return nil, err
 		}
diff --git a/modules/git/repo_compare_test.go b/modules/git/repo_compare_test.go
index f0e20838f4..3a6cda955c 100644
--- a/modules/git/repo_compare_test.go
+++ b/modules/git/repo_compare_test.go
@@ -6,7 +6,7 @@ package git
 
 import (
 	"bytes"
-	"io/ioutil"
+	"io"
 	"path/filepath"
 	"testing"
 
@@ -25,7 +25,7 @@ func TestGetFormatPatch(t *testing.T) {
 	rd := &bytes.Buffer{}
 	err = repo.GetPatch("8d92fc95^", "8d92fc95", rd)
 	assert.NoError(t, err)
-	patchb, err := ioutil.ReadAll(rd)
+	patchb, err := io.ReadAll(rd)
 	assert.NoError(t, err)
 	patch := string(patchb)
 	assert.Regexp(t, "^From 8d92fc95", patch)
diff --git a/modules/git/repo_index.go b/modules/git/repo_index.go
index b301ff2437..27cb7fbebe 100644
--- a/modules/git/repo_index.go
+++ b/modules/git/repo_index.go
@@ -7,7 +7,6 @@ package git
 import (
 	"bytes"
 	"context"
-	"io/ioutil"
 	"os"
 	"strings"
 
@@ -47,7 +46,7 @@ func (repo *Repository) readTreeToIndex(id SHA1, indexFilename ...string) error
 
 // ReadTreeToTemporaryIndex reads a treeish to a temporary index file
 func (repo *Repository) ReadTreeToTemporaryIndex(treeish string) (filename string, cancel context.CancelFunc, err error) {
-	tmpIndex, err := ioutil.TempFile("", "index")
+	tmpIndex, err := os.CreateTemp("", "index")
 	if err != nil {
 		return
 	}
diff --git a/modules/git/repo_language_stats_gogit.go b/modules/git/repo_language_stats_gogit.go
index 1f2738a5a8..d37827c3de 100644
--- a/modules/git/repo_language_stats_gogit.go
+++ b/modules/git/repo_language_stats_gogit.go
@@ -11,7 +11,7 @@ import (
 	"bytes"
 	"context"
 	"io"
-	"io/ioutil"
+	"os"
 
 	"code.gitea.io/gitea/modules/analyze"
 	"code.gitea.io/gitea/modules/log"
@@ -51,7 +51,7 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
 		indexFilename, deleteTemporaryFile, err := repo.ReadTreeToTemporaryIndex(commitID)
 		if err == nil {
 			defer deleteTemporaryFile()
-			tmpWorkTree, err := ioutil.TempDir("", "empty-work-dir")
+			tmpWorkTree, err := os.MkdirTemp("", "empty-work-dir")
 			if err == nil {
 				defer func() {
 					_ = util.RemoveAll(tmpWorkTree)
@@ -174,7 +174,7 @@ func readFile(f *object.File, limit int64) ([]byte, error) {
 	defer r.Close()
 
 	if limit <= 0 {
-		return ioutil.ReadAll(r)
+		return io.ReadAll(r)
 	}
 
 	size := f.Size
diff --git a/modules/git/repo_language_stats_nogogit.go b/modules/git/repo_language_stats_nogogit.go
index 8e9a3d6bcd..06269a466c 100644
--- a/modules/git/repo_language_stats_nogogit.go
+++ b/modules/git/repo_language_stats_nogogit.go
@@ -12,8 +12,8 @@ import (
 	"bytes"
 	"context"
 	"io"
-	"io/ioutil"
 	"math"
+	"os"
 
 	"code.gitea.io/gitea/modules/analyze"
 	"code.gitea.io/gitea/modules/log"
@@ -71,7 +71,7 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
 		indexFilename, deleteTemporaryFile, err := repo.ReadTreeToTemporaryIndex(commitID)
 		if err == nil {
 			defer deleteTemporaryFile()
-			tmpWorkTree, err := ioutil.TempDir("", "empty-work-dir")
+			tmpWorkTree, err := os.MkdirTemp("", "empty-work-dir")
 			if err == nil {
 				defer func() {
 					_ = util.RemoveAll(tmpWorkTree)
diff --git a/modules/git/repo_tree_nogogit.go b/modules/git/repo_tree_nogogit.go
index 9d4268b13a..b27abb6e02 100644
--- a/modules/git/repo_tree_nogogit.go
+++ b/modules/git/repo_tree_nogogit.go
@@ -9,7 +9,6 @@ package git
 
 import (
 	"io"
-	"io/ioutil"
 )
 
 func (repo *Repository) getTree(id SHA1) (*Tree, error) {
@@ -27,7 +26,7 @@ func (repo *Repository) getTree(id SHA1) (*Tree, error) {
 	switch typ {
 	case "tag":
 		resolvedID := id
-		data, err := ioutil.ReadAll(io.LimitReader(rd, size))
+		data, err := io.ReadAll(io.LimitReader(rd, size))
 		if err != nil {
 			return nil, err
 		}
diff --git a/modules/graceful/server.go b/modules/graceful/server.go
index 6b7d4a1a97..23eb821c8c 100644
--- a/modules/graceful/server.go
+++ b/modules/graceful/server.go
@@ -7,7 +7,6 @@ package graceful
 
 import (
 	"crypto/tls"
-	"io/ioutil"
 	"net"
 	"os"
 	"strings"
@@ -111,13 +110,13 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string, serve ServeFuncti
 
 	config.Certificates = make([]tls.Certificate, 1)
 
-	certPEMBlock, err := ioutil.ReadFile(certFile)
+	certPEMBlock, err := os.ReadFile(certFile)
 	if err != nil {
 		log.Error("Failed to load https cert file %s for %s:%s: %v", certFile, srv.network, srv.address, err)
 		return err
 	}
 
-	keyPEMBlock, err := ioutil.ReadFile(keyFile)
+	keyPEMBlock, err := os.ReadFile(keyFile)
 	if err != nil {
 		log.Error("Failed to load https key file %s for %s:%s: %v", keyFile, srv.network, srv.address, err)
 		return err
diff --git a/modules/httplib/httplib.go b/modules/httplib/httplib.go
index aecdd4346c..ad3b7462e9 100644
--- a/modules/httplib/httplib.go
+++ b/modules/httplib/httplib.go
@@ -11,7 +11,6 @@ import (
 	"crypto/tls"
 	"encoding/xml"
 	"io"
-	"io/ioutil"
 	"log"
 	"mime/multipart"
 	"net"
@@ -243,11 +242,11 @@ func (r *Request) Body(data interface{}) *Request {
 	switch t := data.(type) {
 	case string:
 		bf := bytes.NewBufferString(t)
-		r.req.Body = ioutil.NopCloser(bf)
+		r.req.Body = io.NopCloser(bf)
 		r.req.ContentLength = int64(len(t))
 	case []byte:
 		bf := bytes.NewBuffer(t)
-		r.req.Body = ioutil.NopCloser(bf)
+		r.req.Body = io.NopCloser(bf)
 		r.req.ContentLength = int64(len(t))
 	}
 	return r
@@ -307,7 +306,7 @@ func (r *Request) getResponse() (*http.Response, error) {
 				_ = pw.Close()
 			}()
 			r.Header("Content-Type", bodyWriter.FormDataContentType())
-			r.req.Body = ioutil.NopCloser(pr)
+			r.req.Body = io.NopCloser(pr)
 		} else if len(paramBody) > 0 {
 			r.Header("Content-Type", "application/x-www-form-urlencoded")
 			r.Body(paramBody)
@@ -407,7 +406,7 @@ func (r *Request) Bytes() ([]byte, error) {
 		return nil, nil
 	}
 	defer resp.Body.Close()
-	data, err := ioutil.ReadAll(resp.Body)
+	data, err := io.ReadAll(resp.Body)
 	if err != nil {
 		return nil, err
 	}
diff --git a/modules/indexer/code/bleve.go b/modules/indexer/code/bleve.go
index fc5c602dbe..8e5df34e60 100644
--- a/modules/indexer/code/bleve.go
+++ b/modules/indexer/code/bleve.go
@@ -8,7 +8,6 @@ import (
 	"bufio"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"os"
 	"strconv"
 	"strings"
@@ -210,7 +209,7 @@ func (b *BleveIndexer) addUpdate(batchWriter git.WriteCloserError, batchReader *
 		return err
 	}
 
-	fileContents, err := ioutil.ReadAll(io.LimitReader(batchReader, size))
+	fileContents, err := io.ReadAll(io.LimitReader(batchReader, size))
 	if err != nil {
 		return err
 	} else if !typesniffer.DetectContentType(fileContents).IsText() {
diff --git a/modules/indexer/code/bleve_test.go b/modules/indexer/code/bleve_test.go
index 1199dc98a0..3d97e312f9 100644
--- a/modules/indexer/code/bleve_test.go
+++ b/modules/indexer/code/bleve_test.go
@@ -5,7 +5,7 @@
 package code
 
 import (
-	"io/ioutil"
+	"os"
 	"testing"
 
 	"code.gitea.io/gitea/models/db"
@@ -17,7 +17,7 @@ import (
 func TestBleveIndexAndSearch(t *testing.T) {
 	db.PrepareTestEnv(t)
 
-	dir, err := ioutil.TempDir("", "bleve.index")
+	dir, err := os.MkdirTemp("", "bleve.index")
 	assert.NoError(t, err)
 	if err != nil {
 		assert.Fail(t, "Unable to create temporary directory")
diff --git a/modules/indexer/code/elastic_search.go b/modules/indexer/code/elastic_search.go
index a7a243e24e..49633c3191 100644
--- a/modules/indexer/code/elastic_search.go
+++ b/modules/indexer/code/elastic_search.go
@@ -9,7 +9,6 @@ import (
 	"context"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"strconv"
 	"strings"
 	"time"
@@ -207,7 +206,7 @@ func (b *ElasticSearchIndexer) addUpdate(batchWriter git.WriteCloserError, batch
 		return nil, err
 	}
 
-	fileContents, err := ioutil.ReadAll(io.LimitReader(batchReader, size))
+	fileContents, err := io.ReadAll(io.LimitReader(batchReader, size))
 	if err != nil {
 		return nil, err
 	} else if !typesniffer.DetectContentType(fileContents).IsText() {
diff --git a/modules/indexer/issues/bleve_test.go b/modules/indexer/issues/bleve_test.go
index 2a8ed15d82..70a9582e1d 100644
--- a/modules/indexer/issues/bleve_test.go
+++ b/modules/indexer/issues/bleve_test.go
@@ -5,7 +5,7 @@
 package issues
 
 import (
-	"io/ioutil"
+	"os"
 	"testing"
 
 	"code.gitea.io/gitea/modules/util"
@@ -13,7 +13,7 @@ import (
 )
 
 func TestBleveIndexAndSearch(t *testing.T) {
-	dir, err := ioutil.TempDir("", "bleve.index")
+	dir, err := os.MkdirTemp("", "bleve.index")
 	assert.NoError(t, err)
 	if err != nil {
 		assert.Fail(t, "Unable to create temporary directory")
diff --git a/modules/indexer/issues/indexer_test.go b/modules/indexer/issues/indexer_test.go
index 1431115b8e..561f357f4d 100644
--- a/modules/indexer/issues/indexer_test.go
+++ b/modules/indexer/issues/indexer_test.go
@@ -5,7 +5,7 @@
 package issues
 
 import (
-	"io/ioutil"
+	"os"
 	"path"
 	"path/filepath"
 	"testing"
@@ -28,7 +28,7 @@ func TestBleveSearchIssues(t *testing.T) {
 	assert.NoError(t, db.PrepareTestDatabase())
 	setting.Cfg = ini.Empty()
 
-	tmpIndexerDir, err := ioutil.TempDir("", "issues-indexer")
+	tmpIndexerDir, err := os.MkdirTemp("", "issues-indexer")
 	if err != nil {
 		assert.Fail(t, "Unable to create temporary directory: %v", err)
 		return
diff --git a/modules/lfs/http_client_test.go b/modules/lfs/http_client_test.go
index 589773e45b..5b514a1230 100644
--- a/modules/lfs/http_client_test.go
+++ b/modules/lfs/http_client_test.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"context"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"strings"
 	"testing"
@@ -32,7 +31,7 @@ func (a *DummyTransferAdapter) Name() string {
 }
 
 func (a *DummyTransferAdapter) Download(ctx context.Context, l *Link) (io.ReadCloser, error) {
-	return ioutil.NopCloser(bytes.NewBufferString("dummy")), nil
+	return io.NopCloser(bytes.NewBufferString("dummy")), nil
 }
 
 func (a *DummyTransferAdapter) Upload(ctx context.Context, l *Link, p Pointer, r io.Reader) error {
@@ -50,7 +49,7 @@ func lfsTestRoundtripHandler(req *http.Request) *http.Response {
 	if strings.Contains(url, "status-not-ok") {
 		return &http.Response{StatusCode: http.StatusBadRequest}
 	} else if strings.Contains(url, "invalid-json-response") {
-		return &http.Response{StatusCode: http.StatusOK, Body: ioutil.NopCloser(bytes.NewBufferString("invalid json"))}
+		return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewBufferString("invalid json"))}
 	} else if strings.Contains(url, "valid-batch-request-download") {
 		batchResponse = &BatchResponse{
 			Transfer: "dummy",
@@ -149,7 +148,7 @@ func lfsTestRoundtripHandler(req *http.Request) *http.Response {
 	payload := new(bytes.Buffer)
 	json.NewEncoder(payload).Encode(batchResponse)
 
-	return &http.Response{StatusCode: http.StatusOK, Body: ioutil.NopCloser(payload)}
+	return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(payload)}
 }
 
 func TestHTTPClientDownload(t *testing.T) {
@@ -350,7 +349,7 @@ func TestHTTPClientUpload(t *testing.T) {
 		client.transfers["dummy"] = dummy
 
 		err := client.Upload(context.Background(), []Pointer{p}, func(p Pointer, objectError error) (io.ReadCloser, error) {
-			return ioutil.NopCloser(new(bytes.Buffer)), objectError
+			return io.NopCloser(new(bytes.Buffer)), objectError
 		})
 		if len(c.expectederror) > 0 {
 			assert.True(t, strings.Contains(err.Error(), c.expectederror), "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
diff --git a/modules/lfs/transferadapter_test.go b/modules/lfs/transferadapter_test.go
index 9192b486ed..b26d516c68 100644
--- a/modules/lfs/transferadapter_test.go
+++ b/modules/lfs/transferadapter_test.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"context"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"strings"
 	"testing"
@@ -35,7 +34,7 @@ func TestBasicTransferAdapter(t *testing.T) {
 		if strings.Contains(url, "download-request") {
 			assert.Equal(t, "GET", req.Method)
 
-			return &http.Response{StatusCode: http.StatusOK, Body: ioutil.NopCloser(bytes.NewBufferString("dummy"))}
+			return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewBufferString("dummy"))}
 		} else if strings.Contains(url, "upload-request") {
 			assert.Equal(t, "PUT", req.Method)
 			assert.Equal(t, "application/octet-stream", req.Header.Get("Content-Type"))
@@ -63,7 +62,7 @@ func TestBasicTransferAdapter(t *testing.T) {
 			payload := new(bytes.Buffer)
 			json.NewEncoder(payload).Encode(er)
 
-			return &http.Response{StatusCode: http.StatusNotFound, Body: ioutil.NopCloser(payload)}
+			return &http.Response{StatusCode: http.StatusNotFound, Body: io.NopCloser(payload)}
 		} else {
 			t.Errorf("Unknown test case: %s", url)
 			return nil
diff --git a/modules/log/conn_test.go b/modules/log/conn_test.go
index dc5de732f4..158a8ca6ce 100644
--- a/modules/log/conn_test.go
+++ b/modules/log/conn_test.go
@@ -6,7 +6,7 @@ package log
 
 import (
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net"
 	"strings"
 	"sync"
@@ -20,7 +20,7 @@ func listenReadAndClose(t *testing.T, l net.Listener, expected string) {
 	conn, err := l.Accept()
 	assert.NoError(t, err)
 	defer conn.Close()
-	written, err := ioutil.ReadAll(conn)
+	written, err := io.ReadAll(conn)
 
 	assert.NoError(t, err)
 	assert.Equal(t, expected, string(written))
diff --git a/modules/log/file_test.go b/modules/log/file_test.go
index 7bc5f90037..39d2467a1f 100644
--- a/modules/log/file_test.go
+++ b/modules/log/file_test.go
@@ -7,7 +7,7 @@ package log
 import (
 	"compress/gzip"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"os"
 	"path/filepath"
 	"strings"
@@ -19,7 +19,7 @@ import (
 )
 
 func TestFileLoggerFails(t *testing.T) {
-	tmpDir, err := ioutil.TempDir("", "TestFileLogger")
+	tmpDir, err := os.MkdirTemp("", "TestFileLogger")
 	assert.NoError(t, err)
 	defer util.RemoveAll(tmpDir)
 
@@ -47,7 +47,7 @@ func TestFileLoggerFails(t *testing.T) {
 }
 
 func TestFileLogger(t *testing.T) {
-	tmpDir, err := ioutil.TempDir("", "TestFileLogger")
+	tmpDir, err := os.MkdirTemp("", "TestFileLogger")
 	assert.NoError(t, err)
 	defer util.RemoveAll(tmpDir)
 
@@ -85,21 +85,21 @@ func TestFileLogger(t *testing.T) {
 
 	fileLogger.LogEvent(&event)
 	fileLogger.Flush()
-	logData, err := ioutil.ReadFile(filename)
+	logData, err := os.ReadFile(filename)
 	assert.NoError(t, err)
 	assert.Equal(t, expected, string(logData))
 
 	event.level = DEBUG
 	fileLogger.LogEvent(&event)
 	fileLogger.Flush()
-	logData, err = ioutil.ReadFile(filename)
+	logData, err = os.ReadFile(filename)
 	assert.NoError(t, err)
 	assert.Equal(t, expected, string(logData))
 
 	event.level = TRACE
 	fileLogger.LogEvent(&event)
 	fileLogger.Flush()
-	logData, err = ioutil.ReadFile(filename)
+	logData, err = os.ReadFile(filename)
 	assert.NoError(t, err)
 	assert.Equal(t, expected, string(logData))
 
@@ -107,18 +107,18 @@ func TestFileLogger(t *testing.T) {
 	expected += fmt.Sprintf("%s%s %s:%d:%s [%c] %s\n", prefix, dateString, event.filename, event.line, event.caller, strings.ToUpper(event.level.String())[0], event.msg)
 	fileLogger.LogEvent(&event)
 	fileLogger.Flush()
-	logData, err = ioutil.ReadFile(filename)
+	logData, err = os.ReadFile(filename)
 	assert.NoError(t, err)
 	assert.Equal(t, expected, string(logData))
 
 	// Should rotate
 	fileLogger.LogEvent(&event)
 	fileLogger.Flush()
-	logData, err = ioutil.ReadFile(filename + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), 1))
+	logData, err = os.ReadFile(filename + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), 1))
 	assert.NoError(t, err)
 	assert.Equal(t, expected, string(logData))
 
-	logData, err = ioutil.ReadFile(filename)
+	logData, err = os.ReadFile(filename)
 	assert.NoError(t, err)
 	expected = fmt.Sprintf("%s%s %s:%d:%s [%c] %s\n", prefix, dateString, event.filename, event.line, event.caller, strings.ToUpper(event.level.String())[0], event.msg)
 	assert.Equal(t, expected, string(logData))
@@ -134,7 +134,7 @@ func TestFileLogger(t *testing.T) {
 	expected += fmt.Sprintf("%s%s %s:%d:%s [%c] %s\n", prefix, dateString, event.filename, event.line, event.caller, strings.ToUpper(event.level.String())[0], event.msg)
 	fileLogger.LogEvent(&event)
 	fileLogger.Flush()
-	logData, err = ioutil.ReadFile(filename)
+	logData, err = os.ReadFile(filename)
 	assert.NoError(t, err)
 	assert.Equal(t, expected, string(logData))
 
@@ -142,7 +142,7 @@ func TestFileLogger(t *testing.T) {
 	expected += fmt.Sprintf("%s%s %s:%d:%s [%c] %s\n", prefix, dateString, event.filename, event.line, event.caller, strings.ToUpper(event.level.String())[0], event.msg)
 	fileLogger.LogEvent(&event)
 	fileLogger.Flush()
-	logData, err = ioutil.ReadFile(filename)
+	logData, err = os.ReadFile(filename)
 	assert.NoError(t, err)
 	assert.Equal(t, expected, string(logData))
 
@@ -150,7 +150,7 @@ func TestFileLogger(t *testing.T) {
 }
 
 func TestCompressFileLogger(t *testing.T) {
-	tmpDir, err := ioutil.TempDir("", "TestFileLogger")
+	tmpDir, err := os.MkdirTemp("", "TestFileLogger")
 	assert.NoError(t, err)
 	defer util.RemoveAll(tmpDir)
 
@@ -184,7 +184,7 @@ func TestCompressFileLogger(t *testing.T) {
 
 	fileLogger.LogEvent(&event)
 	fileLogger.Flush()
-	logData, err := ioutil.ReadFile(filename)
+	logData, err := os.ReadFile(filename)
 	assert.NoError(t, err)
 	assert.Equal(t, expected, string(logData))
 
@@ -192,7 +192,7 @@ func TestCompressFileLogger(t *testing.T) {
 	expected += fmt.Sprintf("%s%s %s:%d:%s [%c] %s\n", prefix, dateString, event.filename, event.line, event.caller, strings.ToUpper(event.level.String())[0], event.msg)
 	fileLogger.LogEvent(&event)
 	fileLogger.Flush()
-	logData, err = ioutil.ReadFile(filename)
+	logData, err = os.ReadFile(filename)
 	assert.NoError(t, err)
 	assert.Equal(t, expected, string(logData))
 
@@ -210,7 +210,7 @@ func TestCompressFileLogger(t *testing.T) {
 }
 
 func TestCompressOldFile(t *testing.T) {
-	tmpDir, err := ioutil.TempDir("", "TestFileLogger")
+	tmpDir, err := os.MkdirTemp("", "TestFileLogger")
 	assert.NoError(t, err)
 	defer util.RemoveAll(tmpDir)
 	fname := filepath.Join(tmpDir, "test")
@@ -238,9 +238,9 @@ func TestCompressOldFile(t *testing.T) {
 	assert.NoError(t, err)
 	zr, err := gzip.NewReader(f)
 	assert.NoError(t, err)
-	data, err := ioutil.ReadAll(zr)
+	data, err := io.ReadAll(zr)
 	assert.NoError(t, err)
-	original, err := ioutil.ReadFile(nonGzip)
+	original, err := os.ReadFile(nonGzip)
 	assert.NoError(t, err)
 	assert.Equal(t, original, data)
 }
diff --git a/modules/log/stack.go b/modules/log/stack.go
index 568c10cd00..8fc3f35421 100644
--- a/modules/log/stack.go
+++ b/modules/log/stack.go
@@ -7,7 +7,7 @@ package log
 import (
 	"bytes"
 	"fmt"
-	"io/ioutil"
+	"os"
 	"runtime"
 )
 
@@ -38,7 +38,7 @@ func Stack(skip int) string {
 		fmt.Fprintf(buf, "%s:%d (0x%x)\n", filename, lineNumber, programCounter)
 		// Now try to print the offending line
 		if filename != lastFilename {
-			data, err := ioutil.ReadFile(filename)
+			data, err := os.ReadFile(filename)
 			if err != nil {
 				// can't read this sourcefile
 				// likely we don't have the sourcecode available
diff --git a/modules/markup/csv/csv.go b/modules/markup/csv/csv.go
index 8a4df89511..e4b423d4f0 100644
--- a/modules/markup/csv/csv.go
+++ b/modules/markup/csv/csv.go
@@ -9,7 +9,6 @@ import (
 	"bytes"
 	"html"
 	"io"
-	"io/ioutil"
 	"regexp"
 	"strconv"
 
@@ -87,7 +86,7 @@ func (Renderer) Render(ctx *markup.RenderContext, input io.Reader, output io.Wri
 	var tmpBlock = bufio.NewWriter(output)
 
 	// FIXME: don't read all to memory
-	rawBytes, err := ioutil.ReadAll(input)
+	rawBytes, err := io.ReadAll(input)
 	if err != nil {
 		return err
 	}
diff --git a/modules/markup/external/external.go b/modules/markup/external/external.go
index f7be06dbe9..36cbd69f92 100644
--- a/modules/markup/external/external.go
+++ b/modules/markup/external/external.go
@@ -8,7 +8,6 @@ import (
 	"context"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"os"
 	"os/exec"
 	"runtime"
@@ -75,7 +74,7 @@ func (p *Renderer) Render(ctx *markup.RenderContext, input io.Reader, output io.
 
 	if p.IsInputFile {
 		// write to temp file
-		f, err := ioutil.TempFile("", "gitea_input")
+		f, err := os.CreateTemp("", "gitea_input")
 		if err != nil {
 			return fmt.Errorf("%s create temp file when rendering %s failed: %v", p.Name(), p.Command, err)
 		}
diff --git a/modules/markup/html.go b/modules/markup/html.go
index 4d6574a596..d5ae237b5b 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -7,7 +7,6 @@ package markup
 import (
 	"bytes"
 	"io"
-	"io/ioutil"
 	"net/url"
 	"path"
 	"path/filepath"
@@ -290,7 +289,7 @@ var nulCleaner = strings.NewReplacer("\000", "")
 func postProcess(ctx *RenderContext, procs []processor, input io.Reader, output io.Writer) error {
 	defer ctx.Cancel()
 	// FIXME: don't read all content to memory
-	rawHTML, err := ioutil.ReadAll(input)
+	rawHTML, err := io.ReadAll(input)
 	if err != nil {
 		return err
 	}
diff --git a/modules/markup/markdown/markdown.go b/modules/markup/markdown/markdown.go
index ab026dd1b8..554ee0d4be 100644
--- a/modules/markup/markdown/markdown.go
+++ b/modules/markup/markdown/markdown.go
@@ -8,7 +8,6 @@ package markdown
 import (
 	"fmt"
 	"io"
-	"io/ioutil"
 	"strings"
 	"sync"
 
@@ -189,7 +188,7 @@ func actualRender(ctx *markup.RenderContext, input io.Reader, output io.Writer)
 
 		// FIXME: Don't read all to memory, but goldmark doesn't support
 		pc := newParserContext(ctx)
-		buf, err := ioutil.ReadAll(input)
+		buf, err := io.ReadAll(input)
 		if err != nil {
 			log.Error("Unable to ReadAll: %v", err)
 			return
diff --git a/modules/migrations/restore.go b/modules/migrations/restore.go
index 6287d601c2..5fddf7b505 100644
--- a/modules/migrations/restore.go
+++ b/modules/migrations/restore.go
@@ -7,7 +7,6 @@ package migrations
 import (
 	"context"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"strconv"
@@ -55,7 +54,7 @@ func (r *RepositoryRestorer) SetContext(ctx context.Context) {
 
 func (r *RepositoryRestorer) getRepoOptions() (map[string]string, error) {
 	p := filepath.Join(r.baseDir, "repo.yml")
-	bs, err := ioutil.ReadFile(p)
+	bs, err := os.ReadFile(p)
 	if err != nil {
 		return nil, err
 	}
@@ -96,7 +95,7 @@ func (r *RepositoryRestorer) GetTopics() ([]string, error) {
 		Topics []string `yaml:"topics"`
 	}{}
 
-	bs, err := ioutil.ReadFile(p)
+	bs, err := os.ReadFile(p)
 	if err != nil {
 		return nil, err
 	}
@@ -120,7 +119,7 @@ func (r *RepositoryRestorer) GetMilestones() ([]*base.Milestone, error) {
 		return nil, err
 	}
 
-	bs, err := ioutil.ReadFile(p)
+	bs, err := os.ReadFile(p)
 	if err != nil {
 		return nil, err
 	}
@@ -144,7 +143,7 @@ func (r *RepositoryRestorer) GetReleases() ([]*base.Release, error) {
 		return nil, err
 	}
 
-	bs, err := ioutil.ReadFile(p)
+	bs, err := os.ReadFile(p)
 	if err != nil {
 		return nil, err
 	}
@@ -175,7 +174,7 @@ func (r *RepositoryRestorer) GetLabels() ([]*base.Label, error) {
 		return nil, err
 	}
 
-	bs, err := ioutil.ReadFile(p)
+	bs, err := os.ReadFile(p)
 	if err != nil {
 		return nil, err
 	}
@@ -199,7 +198,7 @@ func (r *RepositoryRestorer) GetIssues(page, perPage int) ([]*base.Issue, bool,
 		return nil, false, err
 	}
 
-	bs, err := ioutil.ReadFile(p)
+	bs, err := os.ReadFile(p)
 	if err != nil {
 		return nil, false, err
 	}
@@ -226,7 +225,7 @@ func (r *RepositoryRestorer) GetComments(opts base.GetCommentOptions) ([]*base.C
 		return nil, false, err
 	}
 
-	bs, err := ioutil.ReadFile(p)
+	bs, err := os.ReadFile(p)
 	if err != nil {
 		return nil, false, err
 	}
@@ -250,7 +249,7 @@ func (r *RepositoryRestorer) GetPullRequests(page, perPage int) ([]*base.PullReq
 		return nil, false, err
 	}
 
-	bs, err := ioutil.ReadFile(p)
+	bs, err := os.ReadFile(p)
 	if err != nil {
 		return nil, false, err
 	}
@@ -278,7 +277,7 @@ func (r *RepositoryRestorer) GetReviews(context base.IssueContext) ([]*base.Revi
 		return nil, err
 	}
 
-	bs, err := ioutil.ReadFile(p)
+	bs, err := os.ReadFile(p)
 	if err != nil {
 		return nil, err
 	}
diff --git a/modules/options/dynamic.go b/modules/options/dynamic.go
index 13fa5d6aa7..78b0450d9b 100644
--- a/modules/options/dynamic.go
+++ b/modules/options/dynamic.go
@@ -9,7 +9,7 @@ package options
 
 import (
 	"fmt"
-	"io/ioutil"
+	"os"
 	"path"
 
 	"code.gitea.io/gitea/modules/log"
@@ -100,7 +100,7 @@ func fileFromDir(name string) ([]byte, error) {
 		log.Error("Unable to check if %s is a file. Error: %v", customPath, err)
 	}
 	if isFile {
-		return ioutil.ReadFile(customPath)
+		return os.ReadFile(customPath)
 	}
 
 	staticPath := path.Join(setting.StaticRootPath, "options", name)
@@ -110,7 +110,7 @@ func fileFromDir(name string) ([]byte, error) {
 		log.Error("Unable to check if %s is a file. Error: %v", staticPath, err)
 	}
 	if isFile {
-		return ioutil.ReadFile(staticPath)
+		return os.ReadFile(staticPath)
 	}
 
 	return []byte{}, fmt.Errorf("Asset file does not exist: %s", name)
diff --git a/modules/options/static.go b/modules/options/static.go
index 49e8445cd5..afe32216d3 100644
--- a/modules/options/static.go
+++ b/modules/options/static.go
@@ -9,7 +9,8 @@ package options
 
 import (
 	"fmt"
-	"io/ioutil"
+	"io"
+	"os"
 	"path"
 
 	"code.gitea.io/gitea/modules/log"
@@ -109,7 +110,7 @@ func fileFromDir(name string) ([]byte, error) {
 		log.Error("Unable to check if %s is a file. Error: %v", customPath, err)
 	}
 	if isFile {
-		return ioutil.ReadFile(customPath)
+		return os.ReadFile(customPath)
 	}
 
 	f, err := Assets.Open(name)
@@ -118,7 +119,7 @@ func fileFromDir(name string) ([]byte, error) {
 	}
 	defer f.Close()
 
-	return ioutil.ReadAll(f)
+	return io.ReadAll(f)
 }
 
 func Asset(name string) ([]byte, error) {
@@ -127,7 +128,7 @@ func Asset(name string) ([]byte, error) {
 		return nil, err
 	}
 	defer f.Close()
-	return ioutil.ReadAll(f)
+	return io.ReadAll(f)
 }
 
 func AssetNames() []string {
diff --git a/modules/pprof/pprof.go b/modules/pprof/pprof.go
index 80ad67be3a..f080728766 100644
--- a/modules/pprof/pprof.go
+++ b/modules/pprof/pprof.go
@@ -6,7 +6,7 @@ package pprof
 
 import (
 	"fmt"
-	"io/ioutil"
+	"os"
 	"runtime"
 	"runtime/pprof"
 
@@ -15,7 +15,7 @@ import (
 
 // DumpMemProfileForUsername dumps a memory profile at pprofDataPath as memprofile_<username>_<temporary id>
 func DumpMemProfileForUsername(pprofDataPath, username string) error {
-	f, err := ioutil.TempFile(pprofDataPath, fmt.Sprintf("memprofile_%s_", username))
+	f, err := os.CreateTemp(pprofDataPath, fmt.Sprintf("memprofile_%s_", username))
 	if err != nil {
 		return err
 	}
@@ -27,7 +27,7 @@ func DumpMemProfileForUsername(pprofDataPath, username string) error {
 // DumpCPUProfileForUsername dumps a CPU profile at pprofDataPath as cpuprofile_<username>_<temporary id>
 //  it returns the stop function which stops, writes and closes the CPU profile file
 func DumpCPUProfileForUsername(pprofDataPath, username string) (func(), error) {
-	f, err := ioutil.TempFile(pprofDataPath, fmt.Sprintf("cpuprofile_%s_", username))
+	f, err := os.CreateTemp(pprofDataPath, fmt.Sprintf("cpuprofile_%s_", username))
 	if err != nil {
 		return nil, err
 	}
diff --git a/modules/private/key.go b/modules/private/key.go
index d0b11a96e7..8dfd82a6d6 100644
--- a/modules/private/key.go
+++ b/modules/private/key.go
@@ -7,7 +7,7 @@ package private
 import (
 	"context"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 
 	"code.gitea.io/gitea/modules/setting"
@@ -49,7 +49,7 @@ func AuthorizedPublicKeyByContent(ctx context.Context, content string) (string,
 	if resp.StatusCode != http.StatusOK {
 		return "", fmt.Errorf("Failed to update public key: %s", decodeJSONError(resp).Err)
 	}
-	bs, err := ioutil.ReadAll(resp.Body)
+	bs, err := io.ReadAll(resp.Body)
 
 	return string(bs), err
 }
diff --git a/modules/private/mail.go b/modules/private/mail.go
index 7e229396e3..bcf601b029 100644
--- a/modules/private/mail.go
+++ b/modules/private/mail.go
@@ -7,7 +7,7 @@ package private
 import (
 	"context"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 
 	"code.gitea.io/gitea/modules/json"
@@ -45,7 +45,7 @@ func SendEmail(ctx context.Context, subject, message string, to []string) (int,
 	}
 	defer resp.Body.Close()
 
-	body, err := ioutil.ReadAll(resp.Body)
+	body, err := io.ReadAll(resp.Body)
 	if err != nil {
 		return http.StatusInternalServerError, fmt.Sprintf("Response body error: %v", err.Error())
 	}
diff --git a/modules/private/restore_repo.go b/modules/private/restore_repo.go
index b5592278ab..6ebf4c63d5 100644
--- a/modules/private/restore_repo.go
+++ b/modules/private/restore_repo.go
@@ -7,7 +7,7 @@ package private
 import (
 	"context"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"time"
 
@@ -47,7 +47,7 @@ func RestoreRepo(ctx context.Context, repoDir, ownerName, repoName string, units
 		var ret = struct {
 			Err string `json:"err"`
 		}{}
-		body, err := ioutil.ReadAll(resp.Body)
+		body, err := io.ReadAll(resp.Body)
 		if err != nil {
 			return http.StatusInternalServerError, fmt.Sprintf("Response body error: %v", err.Error())
 		}
diff --git a/modules/public/static.go b/modules/public/static.go
index 6994ed6508..32ba0fe258 100644
--- a/modules/public/static.go
+++ b/modules/public/static.go
@@ -11,7 +11,6 @@ import (
 	"bytes"
 	"compress/gzip"
 	"io"
-	"io/ioutil"
 	"mime"
 	"net/http"
 	"os"
@@ -31,7 +30,7 @@ func Asset(name string) ([]byte, error) {
 		return nil, err
 	}
 	defer f.Close()
-	return ioutil.ReadAll(f)
+	return io.ReadAll(f)
 }
 
 func AssetNames() []string {
diff --git a/modules/queue/queue_disk_channel_test.go b/modules/queue/queue_disk_channel_test.go
index 06cb7a7a96..99fb65934e 100644
--- a/modules/queue/queue_disk_channel_test.go
+++ b/modules/queue/queue_disk_channel_test.go
@@ -5,7 +5,7 @@
 package queue
 
 import (
-	"io/ioutil"
+	"os"
 	"sync"
 	"testing"
 
@@ -26,7 +26,7 @@ func TestPersistableChannelQueue(t *testing.T) {
 	queueShutdown := []func(){}
 	queueTerminate := []func(){}
 
-	tmpDir, err := ioutil.TempDir("", "persistable-channel-queue-test-data")
+	tmpDir, err := os.MkdirTemp("", "persistable-channel-queue-test-data")
 	assert.NoError(t, err)
 	defer util.RemoveAll(tmpDir)
 
diff --git a/modules/queue/queue_disk_test.go b/modules/queue/queue_disk_test.go
index 1f884d4f8d..549a04104e 100644
--- a/modules/queue/queue_disk_test.go
+++ b/modules/queue/queue_disk_test.go
@@ -5,7 +5,7 @@
 package queue
 
 import (
-	"io/ioutil"
+	"os"
 	"sync"
 	"testing"
 	"time"
@@ -28,7 +28,7 @@ func TestLevelQueue(t *testing.T) {
 	queueShutdown := []func(){}
 	queueTerminate := []func(){}
 
-	tmpDir, err := ioutil.TempDir("", "level-queue-test-data")
+	tmpDir, err := os.MkdirTemp("", "level-queue-test-data")
 	assert.NoError(t, err)
 	defer util.RemoveAll(tmpDir)
 
diff --git a/modules/recaptcha/recaptcha.go b/modules/recaptcha/recaptcha.go
index e0f5ee2e07..c6798f7117 100644
--- a/modules/recaptcha/recaptcha.go
+++ b/modules/recaptcha/recaptcha.go
@@ -7,7 +7,7 @@ package recaptcha
 import (
 	"context"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/url"
 	"strings"
@@ -46,7 +46,7 @@ func Verify(ctx context.Context, response string) (bool, error) {
 		return false, fmt.Errorf("Failed to send CAPTCHA response: %s", err)
 	}
 	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
+	body, err := io.ReadAll(resp.Body)
 	if err != nil {
 		return false, fmt.Errorf("Failed to read CAPTCHA response: %s", err)
 	}
diff --git a/modules/repository/generate.go b/modules/repository/generate.go
index 6ac2a3051c..8ab518add5 100644
--- a/modules/repository/generate.go
+++ b/modules/repository/generate.go
@@ -6,7 +6,6 @@ package repository
 
 import (
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path"
 	"path/filepath"
@@ -85,7 +84,7 @@ func checkGiteaTemplate(tmpDir string) (*models.GiteaTemplate, error) {
 		return nil, err
 	}
 
-	content, err := ioutil.ReadFile(gtPath)
+	content, err := os.ReadFile(gtPath)
 	if err != nil {
 		return nil, err
 	}
@@ -151,12 +150,12 @@ func generateRepoCommit(repo, templateRepo, generateRepo *models.Repository, tmp
 				base := strings.TrimPrefix(filepath.ToSlash(path), tmpDirSlash)
 				for _, g := range gt.Globs() {
 					if g.Match(base) {
-						content, err := ioutil.ReadFile(path)
+						content, err := os.ReadFile(path)
 						if err != nil {
 							return err
 						}
 
-						if err := ioutil.WriteFile(path,
+						if err := os.WriteFile(path,
 							[]byte(generateExpansion(string(content), templateRepo, generateRepo)),
 							0644); err != nil {
 							return err
@@ -187,7 +186,7 @@ func generateRepoCommit(repo, templateRepo, generateRepo *models.Repository, tmp
 }
 
 func generateGitContent(ctx *db.Context, repo, templateRepo, generateRepo *models.Repository) (err error) {
-	tmpDir, err := ioutil.TempDir(os.TempDir(), "gitea-"+repo.Name)
+	tmpDir, err := os.MkdirTemp(os.TempDir(), "gitea-"+repo.Name)
 	if err != nil {
 		return fmt.Errorf("Failed to create temp dir for repository %s: %v", repo.RepoPath(), err)
 	}
diff --git a/modules/repository/hooks.go b/modules/repository/hooks.go
index de5df591f0..e219903f75 100644
--- a/modules/repository/hooks.go
+++ b/modules/repository/hooks.go
@@ -7,7 +7,6 @@ package repository
 import (
 	"context"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 
@@ -110,7 +109,7 @@ func createDelegateHooks(repoPath string) (err error) {
 		if err = util.Remove(oldHookPath); err != nil && !os.IsNotExist(err) {
 			return fmt.Errorf("unable to pre-remove old hook file '%s' prior to rewriting: %v ", oldHookPath, err)
 		}
-		if err = ioutil.WriteFile(oldHookPath, []byte(hookTpls[i]), 0777); err != nil {
+		if err = os.WriteFile(oldHookPath, []byte(hookTpls[i]), 0777); err != nil {
 			return fmt.Errorf("write old hook file '%s': %v", oldHookPath, err)
 		}
 
@@ -121,7 +120,7 @@ func createDelegateHooks(repoPath string) (err error) {
 		if err = util.Remove(newHookPath); err != nil && !os.IsNotExist(err) {
 			return fmt.Errorf("unable to pre-remove new hook file '%s' prior to rewriting: %v", newHookPath, err)
 		}
-		if err = ioutil.WriteFile(newHookPath, []byte(giteaHookTpls[i]), 0777); err != nil {
+		if err = os.WriteFile(newHookPath, []byte(giteaHookTpls[i]), 0777); err != nil {
 			return fmt.Errorf("write new hook file '%s': %v", newHookPath, err)
 		}
 
@@ -192,7 +191,7 @@ func CheckDelegateHooks(repoPath string) ([]string, error) {
 		if cont {
 			continue
 		}
-		contents, err := ioutil.ReadFile(oldHookPath)
+		contents, err := os.ReadFile(oldHookPath)
 		if err != nil {
 			return results, err
 		}
@@ -202,7 +201,7 @@ func CheckDelegateHooks(repoPath string) ([]string, error) {
 		if !checkExecutable(oldHookPath) {
 			results = append(results, fmt.Sprintf("old hook file %s is not executable", oldHookPath))
 		}
-		contents, err = ioutil.ReadFile(newHookPath)
+		contents, err = os.ReadFile(newHookPath)
 		if err != nil {
 			return results, err
 		}
diff --git a/modules/repository/init.go b/modules/repository/init.go
index e42d35a971..2a86e964ca 100644
--- a/modules/repository/init.go
+++ b/modules/repository/init.go
@@ -7,7 +7,6 @@ package repository
 import (
 	"bytes"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"strings"
@@ -59,7 +58,7 @@ func prepareRepoCommit(ctx *db.Context, repo *models.Repository, tmpDir, repoPat
 		"CloneURL.HTTPS": cloneLink.HTTPS,
 		"OwnerName":      repo.OwnerName,
 	}
-	if err = ioutil.WriteFile(filepath.Join(tmpDir, "README.md"),
+	if err = os.WriteFile(filepath.Join(tmpDir, "README.md"),
 		[]byte(com.Expand(string(data), match)), 0644); err != nil {
 		return fmt.Errorf("write README.md: %v", err)
 	}
@@ -79,7 +78,7 @@ func prepareRepoCommit(ctx *db.Context, repo *models.Repository, tmpDir, repoPat
 		}
 
 		if buf.Len() > 0 {
-			if err = ioutil.WriteFile(filepath.Join(tmpDir, ".gitignore"), buf.Bytes(), 0644); err != nil {
+			if err = os.WriteFile(filepath.Join(tmpDir, ".gitignore"), buf.Bytes(), 0644); err != nil {
 				return fmt.Errorf("write .gitignore: %v", err)
 			}
 		}
@@ -92,7 +91,7 @@ func prepareRepoCommit(ctx *db.Context, repo *models.Repository, tmpDir, repoPat
 			return fmt.Errorf("GetRepoInitFile[%s]: %v", opts.License, err)
 		}
 
-		if err = ioutil.WriteFile(filepath.Join(tmpDir, "LICENSE"), data, 0644); err != nil {
+		if err = os.WriteFile(filepath.Join(tmpDir, "LICENSE"), data, 0644); err != nil {
 			return fmt.Errorf("write LICENSE: %v", err)
 		}
 	}
@@ -291,7 +290,7 @@ func initRepository(ctx *db.Context, repoPath string, u *models.User, repo *mode
 
 	// Initialize repository according to user's choice.
 	if opts.AutoInit {
-		tmpDir, err := ioutil.TempDir(os.TempDir(), "gitea-"+repo.Name)
+		tmpDir, err := os.MkdirTemp(os.TempDir(), "gitea-"+repo.Name)
 		if err != nil {
 			return fmt.Errorf("Failed to create temp dir for repository %s: %v", repo.RepoPath(), err)
 		}
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index 02f5cd8548..b054f27c59 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -9,7 +9,6 @@ import (
 	"encoding/base64"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"math"
 	"net"
 	"net/url"
@@ -764,7 +763,7 @@ func NewContext() {
 
 		if len(trustedUserCaKeys) > 0 && SSH.AuthorizedPrincipalsEnabled {
 			fname := sec.Key("SSH_TRUSTED_USER_CA_KEYS_FILENAME").MustString(filepath.Join(SSH.RootPath, "gitea-trusted-user-ca-keys.pem"))
-			if err := ioutil.WriteFile(fname,
+			if err := os.WriteFile(fname,
 				[]byte(strings.Join(trustedUserCaKeys, "\n")), 0600); err != nil {
 				log.Fatal("Failed to create '%s': %v", fname, err)
 			}
@@ -1030,7 +1029,7 @@ func loadInternalToken(sec *ini.Section) string {
 		}
 		defer fp.Close()
 
-		buf, err := ioutil.ReadAll(fp)
+		buf, err := io.ReadAll(fp)
 		if err != nil {
 			log.Fatal("Failed to read InternalTokenURI (%s): %v", uri, err)
 		}
diff --git a/modules/storage/local.go b/modules/storage/local.go
index 1329f722c2..54e0d0563d 100644
--- a/modules/storage/local.go
+++ b/modules/storage/local.go
@@ -7,7 +7,6 @@ package storage
 import (
 	"context"
 	"io"
-	"io/ioutil"
 	"net/url"
 	"os"
 	"path/filepath"
@@ -76,7 +75,7 @@ func (l *LocalStorage) Save(path string, r io.Reader, size int64) (int64, error)
 	if err := os.MkdirAll(l.tmpdir, os.ModePerm); err != nil {
 		return 0, err
 	}
-	tmp, err := ioutil.TempFile(l.tmpdir, "upload-*")
+	tmp, err := os.CreateTemp(l.tmpdir, "upload-*")
 	if err != nil {
 		return 0, err
 	}
diff --git a/modules/svg/discover_nobindata.go b/modules/svg/discover_nobindata.go
index 8d857551dc..e3f13ddf6c 100644
--- a/modules/svg/discover_nobindata.go
+++ b/modules/svg/discover_nobindata.go
@@ -8,7 +8,7 @@
 package svg
 
 import (
-	"io/ioutil"
+	"os"
 	"path/filepath"
 
 	"code.gitea.io/gitea/modules/setting"
@@ -20,7 +20,7 @@ func Discover() map[string]string {
 
 	files, _ := filepath.Glob(filepath.Join(setting.StaticRootPath, "public", "img", "svg", "*.svg"))
 	for _, file := range files {
-		content, err := ioutil.ReadFile(file)
+		content, err := os.ReadFile(file)
 		if err == nil {
 			filename := filepath.Base(file)
 			svgs[filename[:len(filename)-4]] = string(content)
diff --git a/modules/templates/dynamic.go b/modules/templates/dynamic.go
index 4732fce421..fde58a4a70 100644
--- a/modules/templates/dynamic.go
+++ b/modules/templates/dynamic.go
@@ -9,7 +9,6 @@ package templates
 
 import (
 	"html/template"
-	"io/ioutil"
 	"os"
 	"path"
 	"path/filepath"
@@ -28,14 +27,14 @@ var (
 
 // GetAsset returns asset content via name
 func GetAsset(name string) ([]byte, error) {
-	bs, err := ioutil.ReadFile(filepath.Join(setting.CustomPath, name))
+	bs, err := os.ReadFile(filepath.Join(setting.CustomPath, name))
 	if err != nil && !os.IsNotExist(err) {
 		return nil, err
 	} else if err == nil {
 		return bs, nil
 	}
 
-	return ioutil.ReadFile(filepath.Join(setting.StaticRootPath, name))
+	return os.ReadFile(filepath.Join(setting.StaticRootPath, name))
 }
 
 // GetAssetNames returns assets list
@@ -71,7 +70,7 @@ func Mailer() (*texttmpl.Template, *template.Template) {
 					continue
 				}
 
-				content, err := ioutil.ReadFile(path.Join(staticDir, filePath))
+				content, err := os.ReadFile(path.Join(staticDir, filePath))
 
 				if err != nil {
 					log.Warn("Failed to read static %s template. %v", filePath, err)
@@ -100,7 +99,7 @@ func Mailer() (*texttmpl.Template, *template.Template) {
 					continue
 				}
 
-				content, err := ioutil.ReadFile(path.Join(customDir, filePath))
+				content, err := os.ReadFile(path.Join(customDir, filePath))
 
 				if err != nil {
 					log.Warn("Failed to read custom %s template. %v", filePath, err)
diff --git a/modules/templates/static.go b/modules/templates/static.go
index ee20b2af3b..fdd68c1e6a 100644
--- a/modules/templates/static.go
+++ b/modules/templates/static.go
@@ -9,7 +9,7 @@ package templates
 
 import (
 	"html/template"
-	"io/ioutil"
+	"io"
 	"os"
 	"path"
 	"path/filepath"
@@ -28,7 +28,7 @@ var (
 
 // GetAsset get a special asset, only for chi
 func GetAsset(name string) ([]byte, error) {
-	bs, err := ioutil.ReadFile(filepath.Join(setting.CustomPath, name))
+	bs, err := os.ReadFile(filepath.Join(setting.CustomPath, name))
 	if err != nil && !os.IsNotExist(err) {
 		return nil, err
 	} else if err == nil {
@@ -103,7 +103,7 @@ func Mailer() (*texttmpl.Template, *template.Template) {
 					continue
 				}
 
-				content, err := ioutil.ReadFile(path.Join(customDir, filePath))
+				content, err := os.ReadFile(path.Join(customDir, filePath))
 
 				if err != nil {
 					log.Warn("Failed to read custom %s template. %v", filePath, err)
@@ -130,7 +130,7 @@ func Asset(name string) ([]byte, error) {
 		return nil, err
 	}
 	defer f.Close()
-	return ioutil.ReadAll(f)
+	return io.ReadAll(f)
 }
 
 func AssetNames() []string {
diff --git a/routers/api/v1/misc/markdown_test.go b/routers/api/v1/misc/markdown_test.go
index 3ae3165fd3..dc6762c4cf 100644
--- a/routers/api/v1/misc/markdown_test.go
+++ b/routers/api/v1/misc/markdown_test.go
@@ -5,7 +5,7 @@
 package misc
 
 import (
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/http/httptest"
 	"net/url"
@@ -172,7 +172,7 @@ func TestAPI_RenderRaw(t *testing.T) {
 	ctx := wrap(m)
 
 	for i := 0; i < len(simpleCases); i += 2 {
-		ctx.Req.Body = ioutil.NopCloser(strings.NewReader(simpleCases[i]))
+		ctx.Req.Body = io.NopCloser(strings.NewReader(simpleCases[i]))
 		MarkdownRaw(ctx)
 		assert.Equal(t, simpleCases[i+1], resp.Body.String())
 		resp.Body.Reset()
diff --git a/routers/private/restore_repo.go b/routers/private/restore_repo.go
index 87d60537cd..b7f7ed176f 100644
--- a/routers/private/restore_repo.go
+++ b/routers/private/restore_repo.go
@@ -5,7 +5,7 @@
 package private
 
 import (
-	"io/ioutil"
+	"io"
 	"net/http"
 
 	myCtx "code.gitea.io/gitea/modules/context"
@@ -16,7 +16,7 @@ import (
 
 // RestoreRepo restore a repository from data
 func RestoreRepo(ctx *myCtx.PrivateContext) {
-	bs, err := ioutil.ReadAll(ctx.Req.Body)
+	bs, err := io.ReadAll(ctx.Req.Body)
 	if err != nil {
 		ctx.JSON(http.StatusInternalServerError, private.Response{
 			Err: err.Error(),
diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go
index a99c1c7c61..1d18bfe9a9 100644
--- a/routers/web/repo/editor.go
+++ b/routers/web/repo/editor.go
@@ -6,7 +6,7 @@ package repo
 
 import (
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"path"
 	"strings"
@@ -127,7 +127,7 @@ func editFile(ctx *context.Context, isNewFile bool) {
 			return
 		}
 
-		d, _ := ioutil.ReadAll(dataRc)
+		d, _ := io.ReadAll(dataRc)
 		if err := dataRc.Close(); err != nil {
 			log.Error("Error whilst closing blob data: %v", err)
 		}
diff --git a/routers/web/repo/http.go b/routers/web/repo/http.go
index 6078d764b6..fbd1e19a82 100644
--- a/routers/web/repo/http.go
+++ b/routers/web/repo/http.go
@@ -10,7 +10,6 @@ import (
 	"compress/gzip"
 	gocontext "context"
 	"fmt"
-	"io/ioutil"
 	"net/http"
 	"os"
 	"os/exec"
@@ -308,7 +307,7 @@ var (
 
 func dummyInfoRefs(ctx *context.Context) {
 	infoRefsOnce.Do(func() {
-		tmpDir, err := ioutil.TempDir(os.TempDir(), "gitea-info-refs-cache")
+		tmpDir, err := os.MkdirTemp(os.TempDir(), "gitea-info-refs-cache")
 		if err != nil {
 			log.Error("Failed to create temp dir for git-receive-pack cache: %v", err)
 			return
diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go
index bb3a0c8a9c..013286f2de 100644
--- a/routers/web/repo/issue.go
+++ b/routers/web/repo/issue.go
@@ -9,7 +9,7 @@ import (
 	"bytes"
 	"errors"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"path"
 	"strconv"
@@ -707,7 +707,7 @@ func getFileContentFromDefaultBranch(ctx *context.Context, filename string) (str
 		return "", false
 	}
 	defer r.Close()
-	bytes, err = ioutil.ReadAll(r)
+	bytes, err = io.ReadAll(r)
 	if err != nil {
 		return "", false
 	}
diff --git a/routers/web/repo/lfs.go b/routers/web/repo/lfs.go
index e524a9209a..271c638553 100644
--- a/routers/web/repo/lfs.go
+++ b/routers/web/repo/lfs.go
@@ -9,7 +9,6 @@ import (
 	"fmt"
 	gotemplate "html/template"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"path"
 	"strconv"
@@ -300,7 +299,7 @@ func LFSFileGet(ctx *context.Context) {
 		buf := charset.ToUTF8WithFallbackReader(io.MultiReader(bytes.NewReader(buf), dataRc))
 
 		// Building code view blocks with line number on server side.
-		fileContent, _ := ioutil.ReadAll(buf)
+		fileContent, _ := io.ReadAll(buf)
 
 		var output bytes.Buffer
 		lines := strings.Split(string(fileContent), "\n")
diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go
index ad7a330381..ed82c2eeb5 100644
--- a/routers/web/repo/setting.go
+++ b/routers/web/repo/setting.go
@@ -8,7 +8,7 @@ package repo
 import (
 	"errors"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"strconv"
 	"strings"
@@ -1126,9 +1126,9 @@ func UpdateAvatarSetting(ctx *context.Context, form forms.AvatarForm) error {
 		return errors.New(ctx.Tr("settings.uploaded_avatar_is_too_big"))
 	}
 
-	data, err := ioutil.ReadAll(r)
+	data, err := io.ReadAll(r)
 	if err != nil {
-		return fmt.Errorf("ioutil.ReadAll: %v", err)
+		return fmt.Errorf("io.ReadAll: %v", err)
 	}
 	st := typesniffer.DetectContentType(data)
 	if !(st.IsImage() && !st.IsSvgImage()) {
diff --git a/routers/web/repo/settings_test.go b/routers/web/repo/settings_test.go
index f9986e44ed..a3ed271cce 100644
--- a/routers/web/repo/settings_test.go
+++ b/routers/web/repo/settings_test.go
@@ -5,8 +5,8 @@
 package repo
 
 import (
-	"io/ioutil"
 	"net/http"
+	"os"
 	"testing"
 
 	"code.gitea.io/gitea/models"
@@ -22,7 +22,7 @@ import (
 )
 
 func createSSHAuthorizedKeysTmpPath(t *testing.T) func() {
-	tmpDir, err := ioutil.TempDir("", "tmp-ssh")
+	tmpDir, err := os.MkdirTemp("", "tmp-ssh")
 	if err != nil {
 		assert.Fail(t, "Unable to create temporary directory: %v", err)
 		return nil
diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go
index c71562f271..addde15de1 100644
--- a/routers/web/repo/view.go
+++ b/routers/web/repo/view.go
@@ -11,7 +11,6 @@ import (
 	"fmt"
 	gotemplate "html/template"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"net/url"
 	"path"
@@ -344,7 +343,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
 					}, rd, &result)
 					if err != nil {
 						log.Error("Render failed: %v then fallback", err)
-						bs, _ := ioutil.ReadAll(rd)
+						bs, _ := io.ReadAll(rd)
 						ctx.Data["FileContent"] = strings.ReplaceAll(
 							gotemplate.HTMLEscapeString(string(bs)), "\n", `<br>`,
 						)
@@ -353,7 +352,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
 					}
 				} else {
 					ctx.Data["IsRenderedHTML"] = true
-					buf, err = ioutil.ReadAll(rd)
+					buf, err = io.ReadAll(rd)
 					if err != nil {
 						log.Error("ReadAll failed: %v", err)
 					}
@@ -528,13 +527,13 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
 			}
 			ctx.Data["FileContent"] = result.String()
 		} else if readmeExist {
-			buf, _ := ioutil.ReadAll(rd)
+			buf, _ := io.ReadAll(rd)
 			ctx.Data["IsRenderedHTML"] = true
 			ctx.Data["FileContent"] = strings.ReplaceAll(
 				gotemplate.HTMLEscapeString(string(buf)), "\n", `<br>`,
 			)
 		} else {
-			buf, _ := ioutil.ReadAll(rd)
+			buf, _ := io.ReadAll(rd)
 			lineNums := linesBytesCount(buf)
 			ctx.Data["NumLines"] = strconv.Itoa(lineNums)
 			ctx.Data["NumLinesSet"] = true
diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go
index f0b91aae99..a571c46fd7 100644
--- a/routers/web/repo/wiki.go
+++ b/routers/web/repo/wiki.go
@@ -8,7 +8,7 @@ package repo
 import (
 	"bytes"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/url"
 	"path/filepath"
@@ -110,7 +110,7 @@ func wikiContentsByEntry(ctx *context.Context, entry *git.TreeEntry) []byte {
 		return nil
 	}
 	defer reader.Close()
-	content, err := ioutil.ReadAll(reader)
+	content, err := io.ReadAll(reader)
 	if err != nil {
 		ctx.ServerError("ReadAll", err)
 		return nil
diff --git a/routers/web/repo/wiki_test.go b/routers/web/repo/wiki_test.go
index df565487f1..14cb893d46 100644
--- a/routers/web/repo/wiki_test.go
+++ b/routers/web/repo/wiki_test.go
@@ -5,7 +5,7 @@
 package repo
 
 import (
-	"io/ioutil"
+	"io"
 	"net/http"
 	"testing"
 
@@ -47,7 +47,7 @@ func wikiContent(t *testing.T, repo *models.Repository, wikiName string) string
 	reader, err := entry.Blob().DataAsync()
 	assert.NoError(t, err)
 	defer reader.Close()
-	bytes, err := ioutil.ReadAll(reader)
+	bytes, err := io.ReadAll(reader)
 	assert.NoError(t, err)
 	return string(bytes)
 }
diff --git a/routers/web/user/auth.go b/routers/web/user/auth.go
index b4c52675fd..9785ca68d5 100644
--- a/routers/web/user/auth.go
+++ b/routers/web/user/auth.go
@@ -9,7 +9,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"strings"
 
@@ -704,7 +703,7 @@ func updateAvatarIfNeed(url string, u *models.User) {
 		}
 		// ignore any error
 		if err == nil && resp.StatusCode == http.StatusOK {
-			data, err := ioutil.ReadAll(io.LimitReader(resp.Body, setting.Avatar.MaxFileSize+1))
+			data, err := io.ReadAll(io.LimitReader(resp.Body, setting.Avatar.MaxFileSize+1))
 			if err == nil && int64(len(data)) <= setting.Avatar.MaxFileSize {
 				_ = u.UploadAvatar(data)
 			}
diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go
index 15c08856b4..bd967af32b 100644
--- a/routers/web/user/setting/profile.go
+++ b/routers/web/user/setting/profile.go
@@ -8,7 +8,7 @@ package setting
 import (
 	"errors"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"os"
 	"path/filepath"
@@ -167,9 +167,9 @@ func UpdateAvatarSetting(ctx *context.Context, form *forms.AvatarForm, ctxUser *
 			return errors.New(ctx.Tr("settings.uploaded_avatar_is_too_big"))
 		}
 
-		data, err := ioutil.ReadAll(fr)
+		data, err := io.ReadAll(fr)
 		if err != nil {
-			return fmt.Errorf("ioutil.ReadAll: %v", err)
+			return fmt.Errorf("io.ReadAll: %v", err)
 		}
 
 		st := typesniffer.DetectContentType(data)
diff --git a/services/auth/source/oauth2/jwtsigningkey.go b/services/auth/source/oauth2/jwtsigningkey.go
index 720a9a33f7..3102be5f14 100644
--- a/services/auth/source/oauth2/jwtsigningkey.go
+++ b/services/auth/source/oauth2/jwtsigningkey.go
@@ -15,7 +15,6 @@ import (
 	"encoding/base64"
 	"encoding/pem"
 	"fmt"
-	"io/ioutil"
 	"math/big"
 	"os"
 	"path/filepath"
@@ -429,7 +428,7 @@ func loadOrCreateAsymmetricKey() (interface{}, error) {
 		}
 	}
 
-	bytes, err := ioutil.ReadFile(keyPath)
+	bytes, err := os.ReadFile(keyPath)
 	if err != nil {
 		return nil, err
 	}
diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go
index 239358789a..ac5e947d15 100644
--- a/services/gitdiff/gitdiff.go
+++ b/services/gitdiff/gitdiff.go
@@ -13,7 +13,6 @@ import (
 	"html"
 	"html/template"
 	"io"
-	"io/ioutil"
 	"net/url"
 	"os"
 	"os/exec"
@@ -721,7 +720,7 @@ parsingLoop:
 		// TODO: Handle skipping first n files
 		if len(diff.Files) >= maxFiles {
 			diff.IsIncomplete = true
-			_, err := io.Copy(ioutil.Discard, reader)
+			_, err := io.Copy(io.Discard, reader)
 			if err != nil {
 				// By the definition of io.Copy this never returns io.EOF
 				return diff, fmt.Errorf("Copy: %v", err)
@@ -1280,7 +1279,7 @@ func GetDiffRangeWithWhitespaceBehavior(gitRepo *git.Repository, beforeCommitID,
 		indexFilename, deleteTemporaryFile, err := gitRepo.ReadTreeToTemporaryIndex(afterCommitID)
 		if err == nil {
 			defer deleteTemporaryFile()
-			workdir, err := ioutil.TempDir("", "empty-work-dir")
+			workdir, err := os.MkdirTemp("", "empty-work-dir")
 			if err != nil {
 				log.Error("Unable to create temporary directory: %v", err)
 				return nil, err
diff --git a/services/pull/check.go b/services/pull/check.go
index 1e757ef28b..e819b09cf3 100644
--- a/services/pull/check.go
+++ b/services/pull/check.go
@@ -8,7 +8,6 @@ package pull
 import (
 	"context"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"strconv"
 	"strings"
@@ -75,7 +74,7 @@ func getMergeCommit(pr *models.PullRequest) (*git.Commit, error) {
 		}
 	}
 
-	indexTmpPath, err := ioutil.TempDir(os.TempDir(), "gitea-"+pr.BaseRepo.Name)
+	indexTmpPath, err := os.MkdirTemp(os.TempDir(), "gitea-"+pr.BaseRepo.Name)
 	if err != nil {
 		return nil, fmt.Errorf("Failed to create temp dir for repository %s: %v", pr.BaseRepo.RepoPath(), err)
 	}
@@ -98,7 +97,7 @@ func getMergeCommit(pr *models.PullRequest) (*git.Commit, error) {
 		return nil, fmt.Errorf("git merge-base --is-ancestor: %v", err)
 	}
 
-	commitIDBytes, err := ioutil.ReadFile(pr.BaseRepo.RepoPath() + "/" + headFile)
+	commitIDBytes, err := os.ReadFile(pr.BaseRepo.RepoPath() + "/" + headFile)
 	if err != nil {
 		return nil, fmt.Errorf("ReadFile(%s): %v", headFile, err)
 	}
diff --git a/services/pull/merge.go b/services/pull/merge.go
index ef797e1ca4..4d4a64e984 100644
--- a/services/pull/merge.go
+++ b/services/pull/merge.go
@@ -9,7 +9,6 @@ import (
 	"bufio"
 	"bytes"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"regexp"
@@ -149,7 +148,7 @@ func rawMerge(pr *models.PullRequest, doer *models.User, mergeStyle models.Merge
 	}
 
 	sparseCheckoutListPath := filepath.Join(infoPath, "sparse-checkout")
-	if err := ioutil.WriteFile(sparseCheckoutListPath, []byte(sparseCheckoutList), 0600); err != nil {
+	if err := os.WriteFile(sparseCheckoutListPath, []byte(sparseCheckoutList), 0600); err != nil {
 		log.Error("Unable to write .git/info/sparse-checkout file in %s: %v", tmpBasePath, err)
 		return "", fmt.Errorf("Unable to write .git/info/sparse-checkout file in tmpBasePath: %v", err)
 	}
@@ -276,7 +275,7 @@ func rawMerge(pr *models.PullRequest, doer *models.User, mergeStyle models.Merge
 				}
 				for _, failingCommitPath := range failingCommitPaths {
 					if _, statErr := os.Stat(filepath.Join(failingCommitPath)); statErr == nil {
-						commitShaBytes, readErr := ioutil.ReadFile(filepath.Join(failingCommitPath))
+						commitShaBytes, readErr := os.ReadFile(filepath.Join(failingCommitPath))
 						if readErr != nil {
 							// Abandon this attempt to handle the error
 							log.Error("git rebase staging on to base [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
diff --git a/services/pull/patch.go b/services/pull/patch.go
index 73b979f647..184da9f659 100644
--- a/services/pull/patch.go
+++ b/services/pull/patch.go
@@ -10,7 +10,6 @@ import (
 	"context"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"os"
 	"strings"
 
@@ -100,7 +99,7 @@ func TestPatch(pr *models.PullRequest) error {
 
 func checkConflicts(pr *models.PullRequest, gitRepo *git.Repository, tmpBasePath string) (bool, error) {
 	// 1. Create a plain patch from head to base
-	tmpPatchFile, err := ioutil.TempFile("", "patch")
+	tmpPatchFile, err := os.CreateTemp("", "patch")
 	if err != nil {
 		log.Error("Unable to create temporary patch file! Error: %v", err)
 		return false, fmt.Errorf("Unable to create temporary patch file! Error: %v", err)
diff --git a/services/webhook/deliver.go b/services/webhook/deliver.go
index d0e115b136..abdbed0d5f 100644
--- a/services/webhook/deliver.go
+++ b/services/webhook/deliver.go
@@ -13,7 +13,6 @@ import (
 	"encoding/hex"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net"
 	"net/http"
 	"net/url"
@@ -181,7 +180,7 @@ func Deliver(t *models.HookTask) error {
 		t.ResponseInfo.Headers[k] = strings.Join(vals, ",")
 	}
 
-	p, err := ioutil.ReadAll(resp.Body)
+	p, err := io.ReadAll(resp.Body)
 	if err != nil {
 		t.ResponseInfo.Body = fmt.Sprintf("read body: %s", err)
 		return err
diff --git a/services/wiki/wiki_test.go b/services/wiki/wiki_test.go
index ff4dcf334b..d6a65cc23a 100644
--- a/services/wiki/wiki_test.go
+++ b/services/wiki/wiki_test.go
@@ -5,7 +5,6 @@
 package wiki
 
 import (
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"testing"
@@ -271,7 +270,7 @@ func TestPrepareWikiFileName_FirstPage(t *testing.T) {
 	db.PrepareTestEnv(t)
 
 	// Now create a temporaryDirectory
-	tmpDir, err := ioutil.TempDir("", "empty-wiki")
+	tmpDir, err := os.MkdirTemp("", "empty-wiki")
 	assert.NoError(t, err)
 	defer func() {
 		if _, err := os.Stat(tmpDir); !os.IsNotExist(err) {