diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 2a4a6bce..217c065f 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -33,9 +33,19 @@ jobs:
           go mod download
 
       - name: Build
+        env:
+          CGO_ENABLED: "0"
         run: |
           go build -v .
 
+      - name: Run integration test
+        timeout-minutes: 10
+        env:
+          CODER_IMAGE: "ghcr.io/coder/coder"
+          CODER_VERSION: "latest"
+        run: |
+          go test -v ./integration
+
   # run acceptance tests in a matrix with Terraform core versions
   test:
     name: Matrix Test
diff --git a/integration/integration_test.go b/integration/integration_test.go
index f2c55ed8..1c2046be 100644
--- a/integration/integration_test.go
+++ b/integration/integration_test.go
@@ -5,6 +5,7 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
+	"io"
 	"os"
 	"path/filepath"
 	"runtime"
@@ -15,6 +16,7 @@ import (
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/container"
+	"github.com/docker/docker/api/types/image"
 	"github.com/docker/docker/client"
 	"github.com/docker/docker/pkg/stdcopy"
 	"github.com/stretchr/testify/assert"
@@ -44,17 +46,14 @@ func TestIntegration(t *testing.T) {
 	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeoutMins)*time.Minute)
 	t.Cleanup(cancel)
 
-	// Given: we have an existing Coder deployment running locally
-	ctrID := setup(ctx, t)
-
 	for _, tt := range []struct {
 		// Name of the folder under `integration/` containing a test template
-		templateName string
+		name string
 		// map of string to regex to be passed to assertOutput()
 		expectedOutput map[string]string
 	}{
 		{
-			templateName: "test-data-source",
+			name: "test-data-source",
 			expectedOutput: map[string]string{
 				"provisioner.arch":                  runtime.GOARCH,
 				"provisioner.id":                    `[a-zA-Z0-9-]+`,
@@ -82,20 +81,22 @@ func TestIntegration(t *testing.T) {
 				"workspace_owner.name":              `testing`,
 				"workspace_owner.oidc_access_token": `^$`, // TODO: test OIDC integration
 				"workspace_owner.session_token":     `.+`,
-				"workspace_owner.ssh_private_key":   `^$`, // Depends on coder/coder#13366
-				"workspace_owner.ssh_public_key":    `^$`, // Depends on coder/coder#13366
+				"workspace_owner.ssh_private_key":   `(?s)^.+?BEGIN OPENSSH PRIVATE KEY.+?END OPENSSH PRIVATE KEY.+?$`,
+				"workspace_owner.ssh_public_key":    `(?s)^ssh-ed25519.+$`,
 			},
 		},
 	} {
-		t.Run(tt.templateName, func(t *testing.T) {
+		t.Run(tt.name, func(t *testing.T) {
+			// Given: we have an existing Coder deployment running locally
+			ctrID := setup(ctx, t, tt.name)
 			// Import named template
-			_, rc := execContainer(ctx, t, ctrID, fmt.Sprintf(`coder templates push %s --directory /src/integration/%s --var output_path=/tmp/%s.json --yes`, tt.templateName, tt.templateName, tt.templateName))
+			_, rc := execContainer(ctx, t, ctrID, fmt.Sprintf(`coder templates push %s --directory /src/integration/%s --var output_path=/tmp/%s.json --yes`, tt.name, tt.name, tt.name))
 			require.Equal(t, 0, rc)
 			// Create a workspace
-			_, rc = execContainer(ctx, t, ctrID, fmt.Sprintf(`coder create %s -t %s --yes`, tt.templateName, tt.templateName))
+			_, rc = execContainer(ctx, t, ctrID, fmt.Sprintf(`coder create %s -t %s --yes`, tt.name, tt.name))
 			require.Equal(t, 0, rc)
 			// Fetch the output created by the template
-			out, rc := execContainer(ctx, t, ctrID, fmt.Sprintf(`cat /tmp/%s.json`, tt.templateName))
+			out, rc := execContainer(ctx, t, ctrID, fmt.Sprintf(`cat /tmp/%s.json`, tt.name))
 			require.Equal(t, 0, rc)
 			actual := make(map[string]string)
 			require.NoError(t, json.NewDecoder(strings.NewReader(out)).Decode(&actual))
@@ -104,7 +105,7 @@ func TestIntegration(t *testing.T) {
 	}
 }
 
-func setup(ctx context.Context, t *testing.T) string {
+func setup(ctx context.Context, t *testing.T, name string) string {
 	var (
 		// For this test to work, we pass in a custom terraformrc to use
 		// the locally built version of the provider.
@@ -148,9 +149,17 @@ func setup(ctx context.Context, t *testing.T) string {
 	require.NoError(t, err, "get abs path of parent")
 	t.Logf("src path is %s\n", srcPath)
 
+	// Ensure the image is available locally.
+	refStr := coderImg + ":" + coderVersion
+	t.Logf("ensuring image %q", refStr)
+	resp, err := cli.ImagePull(ctx, refStr, image.PullOptions{})
+	require.NoError(t, err)
+	_, err = io.ReadAll(resp)
+	require.NoError(t, err)
+
 	// Stand up a temporary Coder instance
 	ctr, err := cli.ContainerCreate(ctx, &container.Config{
-		Image: coderImg + ":" + coderVersion,
+		Image: refStr,
 		Env: []string{
 			"CODER_ACCESS_URL=" + localURL,             // Set explicitly to avoid creating try.coder.app URLs.
 			"CODER_IN_MEMORY=true",                     // We don't necessarily care about real persistence here.
@@ -163,7 +172,7 @@ func setup(ctx context.Context, t *testing.T) string {
 			tfrcPath + ":/tmp/integration.tfrc", // Custom tfrc from above.
 			srcPath + ":/src",                   // Bind-mount in the repo with the built binary and templates.
 		},
-	}, nil, nil, "")
+	}, nil, nil, "terraform-provider-coder-integration-"+name)
 	require.NoError(t, err, "create test deployment")
 
 	t.Logf("created container %s\n", ctr.ID)