diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 3ca7a9edb..e3277625a 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -49,16 +49,6 @@ jobs:
             os: ubuntu-latest
             test_fuse: true
 
-          - job_name: Linux
-            go: 1.20.x
-            os: ubuntu-latest
-            test_fuse: true
-
-          - job_name: Linux
-            go: 1.19.x
-            os: ubuntu-latest
-            test_fuse: true
-
     name: ${{ matrix.job_name }} Go ${{ matrix.go }}
     runs-on: ${{ matrix.os }}
 
diff --git a/build.go b/build.go
index b3b7f5eee..5a4baf1c6 100644
--- a/build.go
+++ b/build.go
@@ -58,7 +58,7 @@ var config = Config{
 	Main:             "./cmd/restic",                           // package name for the main package
 	DefaultBuildTags: []string{"selfupdate"},                   // specify build tags which are always used
 	Tests:            []string{"./..."},                        // tests to run
-	MinVersion:       GoVersion{Major: 1, Minor: 18, Patch: 0}, // minimum Go version supported
+	MinVersion:       GoVersion{Major: 1, Minor: 21, Patch: 0}, // minimum Go version supported
 }
 
 // Config configures the build.
diff --git a/doc/020_installation.rst b/doc/020_installation.rst
index 17b581a87..8566c109e 100644
--- a/doc/020_installation.rst
+++ b/doc/020_installation.rst
@@ -284,8 +284,7 @@ From Source
 ***********
 
 restic is written in the Go programming language and you need at least
-Go version 1.19. Building for Solaris requires at least Go version 1.20.
-Building restic may also work with older versions of Go,
+Go version 1.21. Building restic may also work with older versions of Go,
 but that's not supported. See the `Getting
 started <https://go.dev/doc/install>`__ guide of the Go project for
 instructions how to install Go.
diff --git a/go.mod b/go.mod
index 366d89a7f..bf547299e 100644
--- a/go.mod
+++ b/go.mod
@@ -86,4 +86,4 @@ require (
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
 
-go 1.19
+go 1.21
diff --git a/internal/backend/rclone/backend.go b/internal/backend/rclone/backend.go
index 25082598f..8294aa8c4 100644
--- a/internal/backend/rclone/backend.go
+++ b/internal/backend/rclone/backend.go
@@ -94,7 +94,7 @@ func run(command string, args ...string) (*StdioConn, *sync.WaitGroup, chan stru
 		err = errW
 	}
 	if err != nil {
-		if util.IsErrDot(err) {
+		if errors.Is(err, exec.ErrDot) {
 			return nil, nil, nil, nil, errors.Errorf("cannot implicitly run relative executable %v found in current directory, use -o rclone.program=./<program> to override", cmd.Path)
 		}
 		return nil, nil, nil, nil, err
diff --git a/internal/backend/rest/rest_test.go b/internal/backend/rest/rest_test.go
index 93b9a103e..891f60a87 100644
--- a/internal/backend/rest/rest_test.go
+++ b/internal/backend/rest/rest_test.go
@@ -1,6 +1,3 @@
-//go:build go1.20
-// +build go1.20
-
 package rest_test
 
 import (
diff --git a/internal/backend/rest/rest_unix_test.go b/internal/backend/rest/rest_unix_test.go
index 85ef7a73d..c4f08df0e 100644
--- a/internal/backend/rest/rest_unix_test.go
+++ b/internal/backend/rest/rest_unix_test.go
@@ -1,5 +1,5 @@
-//go:build !windows && go1.20
-// +build !windows,go1.20
+//go:build !windows
+// +build !windows
 
 package rest_test
 
diff --git a/internal/backend/sftp/sftp.go b/internal/backend/sftp/sftp.go
index efbd0c8d5..d766591b7 100644
--- a/internal/backend/sftp/sftp.go
+++ b/internal/backend/sftp/sftp.go
@@ -88,7 +88,7 @@ func startClient(cfg Config) (*SFTP, error) {
 
 	bg, err := util.StartForeground(cmd)
 	if err != nil {
-		if util.IsErrDot(err) {
+		if errors.Is(err, exec.ErrDot) {
 			return nil, errors.Errorf("cannot implicitly run relative executable %v found in current directory, use -o sftp.command=./<command> to override", cmd.Path)
 		}
 		return nil, err
diff --git a/internal/backend/util/errdot_119.go b/internal/backend/util/errdot_119.go
deleted file mode 100644
index e20ed47b7..000000000
--- a/internal/backend/util/errdot_119.go
+++ /dev/null
@@ -1,20 +0,0 @@
-//go:build go1.19
-// +build go1.19
-
-// This file provides a function to check whether an error from cmd.Start() is
-//  exec.ErrDot which was introduced in Go 1.19.
-// This function is needed so that we can perform this check only for Go 1.19 and
-//  up, whereas for older versions we use a dummy/stub in the file errdot_old.go.
-// Once the minimum Go version restic supports is 1.19, remove this file and
-//  replace any calls to it with the corresponding code as per below.
-
-package util
-
-import (
-	"errors"
-	"os/exec"
-)
-
-func IsErrDot(err error) bool {
-	return errors.Is(err, exec.ErrDot)
-}
diff --git a/internal/backend/util/errdot_old.go b/internal/backend/util/errdot_old.go
deleted file mode 100644
index 4f7a0b40b..000000000
--- a/internal/backend/util/errdot_old.go
+++ /dev/null
@@ -1,13 +0,0 @@
-//go:build !go1.19
-// +build !go1.19
-
-// This file provides a stub for IsErrDot() for Go versions below 1.19.
-// See the corresponding file errdot_119.go for more information.
-// Once the minimum Go version restic supports is 1.19, remove this file
-//  and perform the actions listed in errdot_119.go.
-
-package util
-
-func IsErrDot(err error) bool {
-	return false
-}
diff --git a/internal/backend/util/foreground.go b/internal/backend/util/foreground.go
index 35cbada1a..477fc8900 100644
--- a/internal/backend/util/foreground.go
+++ b/internal/backend/util/foreground.go
@@ -11,6 +11,9 @@ import (
 // to the previous process group.
 //
 // The command's environment has all RESTIC_* variables removed.
+//
+// Return exec.ErrDot if it would implicitly run an executable from the current
+// directory.
 func StartForeground(cmd *exec.Cmd) (bg func() error, err error) {
 	env := os.Environ() // Returns a copy that we can modify.