diff --git a/workhorse/Makefile b/workhorse/Makefile
index 1980db4ed486e4a5a97bb1b7616b44127c1e7eef..7d9a1b86c8bc6f20e43b3f9209ff996b50dec0d6 100644
--- a/workhorse/Makefile
+++ b/workhorse/Makefile
@@ -64,22 +64,13 @@ WITHOUT_BUILD_ID ?=
 .PHONY:	all
 all:	clean-build $(EXE_ALL)
 
-.PHONY: gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata
-gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata:
+.PHONY: gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata gitlab-workhorse
+gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata gitlab-workhorse:
 	$(call message,Building $@)
 	go build -ldflags "$(GO_BUILD_GENERIC_LDFLAGS)" -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)/cmd/$@
 ifndef WITHOUT_BUILD_ID
 	go build -ldflags "$(GO_BUILD_GENERIC_LDFLAGS) -B 0x$$(_support/make-gnu-build-id.sh $(BUILD_DIR)/$@)" -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)/cmd/$@
 endif
-
-.PHONY: gitlab-workhorse
-gitlab-workhorse:
-	$(call message,Building $@)
-	go build -ldflags "$(GO_BUILD_GENERIC_LDFLAGS)" -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)
-ifndef WITHOUT_BUILD_ID
-	go build -ldflags "$(GO_BUILD_GENERIC_LDFLAGS) -B 0x$$(_support/make-gnu-build-id.sh $(BUILD_DIR)/$@)" -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)
-endif
-
 .PHONY:	install
 install: $(EXE_ALL)
 	$(call message,$@)
diff --git a/workhorse/authorization_test.go b/workhorse/cmd/gitlab-workhorse/authorization_test.go
similarity index 100%
rename from workhorse/authorization_test.go
rename to workhorse/cmd/gitlab-workhorse/authorization_test.go
diff --git a/workhorse/backend.go b/workhorse/cmd/gitlab-workhorse/backend.go
similarity index 100%
rename from workhorse/backend.go
rename to workhorse/cmd/gitlab-workhorse/backend.go
diff --git a/workhorse/backend_test.go b/workhorse/cmd/gitlab-workhorse/backend_test.go
similarity index 100%
rename from workhorse/backend_test.go
rename to workhorse/cmd/gitlab-workhorse/backend_test.go
diff --git a/workhorse/cable_test.go b/workhorse/cmd/gitlab-workhorse/cable_test.go
similarity index 100%
rename from workhorse/cable_test.go
rename to workhorse/cmd/gitlab-workhorse/cable_test.go
diff --git a/workhorse/channel_test.go b/workhorse/cmd/gitlab-workhorse/channel_test.go
similarity index 100%
rename from workhorse/channel_test.go
rename to workhorse/cmd/gitlab-workhorse/channel_test.go
diff --git a/workhorse/config_test.go b/workhorse/cmd/gitlab-workhorse/config_test.go
similarity index 100%
rename from workhorse/config_test.go
rename to workhorse/cmd/gitlab-workhorse/config_test.go
diff --git a/workhorse/gitaly_integration_test.go b/workhorse/cmd/gitlab-workhorse/gitaly_integration_test.go
similarity index 100%
rename from workhorse/gitaly_integration_test.go
rename to workhorse/cmd/gitlab-workhorse/gitaly_integration_test.go
diff --git a/workhorse/gitaly_test.go b/workhorse/cmd/gitlab-workhorse/gitaly_test.go
similarity index 100%
rename from workhorse/gitaly_test.go
rename to workhorse/cmd/gitlab-workhorse/gitaly_test.go
diff --git a/workhorse/jobs_test.go b/workhorse/cmd/gitlab-workhorse/jobs_test.go
similarity index 100%
rename from workhorse/jobs_test.go
rename to workhorse/cmd/gitlab-workhorse/jobs_test.go
diff --git a/workhorse/listener.go b/workhorse/cmd/gitlab-workhorse/listener.go
similarity index 100%
rename from workhorse/listener.go
rename to workhorse/cmd/gitlab-workhorse/listener.go
diff --git a/workhorse/listener_test.go b/workhorse/cmd/gitlab-workhorse/listener_test.go
similarity index 93%
rename from workhorse/listener_test.go
rename to workhorse/cmd/gitlab-workhorse/listener_test.go
index 26b5535af09f00daeec08d0bf2c56513e1426e70..fac3fc3576fb1bab335522a77475567cc58a8ddb 100644
--- a/workhorse/listener_test.go
+++ b/workhorse/cmd/gitlab-workhorse/listener_test.go
@@ -14,7 +14,7 @@ import (
 )
 
 func TestNewListener(t *testing.T) {
-	const unixSocket = "testdata/sock"
+	const unixSocket = "../../testdata/sock"
 
 	require.NoError(t, os.RemoveAll(unixSocket))
 
@@ -61,8 +61,8 @@ func pingClient(t *testing.T, c net.Conn) {
 
 func TestNewListener_TLS(t *testing.T) {
 	const (
-		certFile = "testdata/localhost.crt"
-		keyFile  = "testdata/localhost.key"
+		certFile = "../../testdata/localhost.crt"
+		keyFile  = "../../testdata/localhost.key"
 	)
 
 	cfg := config.ListenerConfig{Addr: "127.0.0.1:0",
diff --git a/workhorse/logging.go b/workhorse/cmd/gitlab-workhorse/logging.go
similarity index 100%
rename from workhorse/logging.go
rename to workhorse/cmd/gitlab-workhorse/logging.go
diff --git a/workhorse/main.go b/workhorse/cmd/gitlab-workhorse/main.go
similarity index 100%
rename from workhorse/main.go
rename to workhorse/cmd/gitlab-workhorse/main.go
diff --git a/workhorse/main_test.go b/workhorse/cmd/gitlab-workhorse/main_test.go
similarity index 99%
rename from workhorse/main_test.go
rename to workhorse/cmd/gitlab-workhorse/main_test.go
index c3a0156f3c88d63984cd0e2d7a7c5d785451db23..5a1bc8ad9a60a2a47d475d163113a39acbe81437 100644
--- a/workhorse/main_test.go
+++ b/workhorse/cmd/gitlab-workhorse/main_test.go
@@ -35,9 +35,9 @@ import (
 	"gitlab.com/gitlab-org/gitlab/workhorse/internal/upstream"
 )
 
-const testRepoRoot = "testdata/repo"
-const testDocumentRoot = "testdata/public"
-const testAltDocumentRoot = "testdata/alt-public"
+const testRepoRoot = "../../testdata/repo"
+const testDocumentRoot = "../../testdata/public"
+const testAltDocumentRoot = "../../testdata/alt-public"
 
 var absDocumentRoot string
 
@@ -405,7 +405,7 @@ func doSendDataRequest(t *testing.T, path string, command, literalJSON string) (
 
 func TestArtifactsGetSingleFile(t *testing.T) {
 	// We manually created this zip file in the gitlab-workhorse Git repository
-	archivePath := `testdata/artifacts-archive.zip`
+	archivePath := `../../testdata/artifacts-archive.zip`
 	fileName := "myfile"
 	fileContents := "MY FILE"
 	resourcePath := `/namespace/project/builds/123/artifacts/file/` + fileName
@@ -421,7 +421,7 @@ func TestArtifactsGetSingleFile(t *testing.T) {
 }
 
 func TestImageResizing(t *testing.T) {
-	imageLocation := `testdata/image.png`
+	imageLocation := `../../testdata/image.png`
 	requestedWidth := 40
 	imageFormat := "image/png"
 	jsonParams := fmt.Sprintf(`{"Location":"%s","Width":%d, "ContentType":"%s"}`, imageLocation, requestedWidth, imageFormat)
diff --git a/workhorse/proxy_test.go b/workhorse/cmd/gitlab-workhorse/proxy_test.go
similarity index 100%
rename from workhorse/proxy_test.go
rename to workhorse/cmd/gitlab-workhorse/proxy_test.go
diff --git a/workhorse/raven.go b/workhorse/cmd/gitlab-workhorse/raven.go
similarity index 100%
rename from workhorse/raven.go
rename to workhorse/cmd/gitlab-workhorse/raven.go
diff --git a/workhorse/sendfile_test.go b/workhorse/cmd/gitlab-workhorse/sendfile_test.go
similarity index 100%
rename from workhorse/sendfile_test.go
rename to workhorse/cmd/gitlab-workhorse/sendfile_test.go
diff --git a/workhorse/tools.go b/workhorse/cmd/gitlab-workhorse/tools.go
similarity index 100%
rename from workhorse/tools.go
rename to workhorse/cmd/gitlab-workhorse/tools.go
diff --git a/workhorse/upload_test.go b/workhorse/cmd/gitlab-workhorse/upload_test.go
similarity index 100%
rename from workhorse/upload_test.go
rename to workhorse/cmd/gitlab-workhorse/upload_test.go