diff --git a/.forgejo/workflows/compliance.yml b/.forgejo/workflows/compliance.yml
new file mode 100644
index 0000000000..3e50ae7038
--- /dev/null
+++ b/.forgejo/workflows/compliance.yml
@@ -0,0 +1,32 @@
+name: compliance
+
+on:
+  pull_request:
+  push:
+    branches:
+      - 'forgejo*'
+      - 'v*/forgejo*'
+
+jobs:
+  lint-backend:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: https://code.forgejo.org/actions/checkout@v3
+      - uses: https://code.forgejo.org/actions/setup-go@v4
+        with:
+          go-version: ">=1.20"
+          check-latest: true
+      - run: make deps-backend deps-tools
+      - run: make lint-backend
+        env:
+          TAGS: bindata sqlite sqlite_unlock_notify
+  checks-backend:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: https://code.forgejo.org/actions/checkout@v3
+      - uses: https://code.forgejo.org/actions/setup-go@v4
+        with:
+          go-version: ">=1.20"
+          check-latest: true
+      - run: make deps-backend deps-tools
+      - run: make --always-make checks-backend # ensure the "go-licenses" make target runs
diff --git a/.forgejo/workflows/testing-mysql.yml b/.forgejo/workflows/testing-mysql.yml
new file mode 100644
index 0000000000..d2d4f420f8
--- /dev/null
+++ b/.forgejo/workflows/testing-mysql.yml
@@ -0,0 +1,42 @@
+name: testing MySQL
+
+on:
+  pull_request:
+  push:
+    branches:
+      - 'forgejo*'
+      - 'v*/forgejo*'
+
+jobs:
+  test-mysql:
+    runs-on: ubuntu-latest
+    container:
+      image: codeberg.org/forgejo/test_env:main
+    services:
+      mysql8:
+        image: mysql:8
+        env:
+          MYSQL_ALLOW_EMPTY_PASSWORD: yes
+          MYSQL_DATABASE: testgitea
+        ports:
+          - "3306:3306"
+    steps:
+      - uses: https://code.forgejo.org/actions/checkout@v3
+      - uses: https://code.forgejo.org/actions/setup-go@v4
+        with:
+          go-version: ">=1.20.0"
+      - run: |
+          git config --add safe.directory '*'
+          chown -R gitea:gitea . /go
+      - run: |
+          su gitea -c 'make deps-backend'
+      - run: |
+          su gitea -c 'make backend'
+        env:
+          TAGS: bindata
+      - run: |
+          su gitea -c 'make test-mysql8-migration test-mysql8'
+        timeout-minutes: 50
+        env:
+          TAGS: bindata
+          USE_REPO_TEST_DIR: 1
diff --git a/.forgejo/workflows/testing-psql.yml b/.forgejo/workflows/testing-psql.yml
new file mode 100644
index 0000000000..7e6361bca4
--- /dev/null
+++ b/.forgejo/workflows/testing-psql.yml
@@ -0,0 +1,44 @@
+name: testing PostgreSQL
+
+on:
+  pull_request:
+  push:
+    branches:
+      - 'forgejo*'
+      - 'v*/forgejo*'
+
+jobs:
+  test-pgsql:
+    runs-on: ubuntu-latest
+    container:
+      image: codeberg.org/forgejo/test_env:main
+    services:
+      pgsql:
+        image: postgres:15
+        env:
+          POSTGRES_DB: test
+          POSTGRES_PASSWORD: postgres
+        ports:
+          - "5432:5432"
+    steps:
+      - uses: https://code.forgejo.org/actions/checkout@v3
+      - uses: https://code.forgejo.org/actions/setup-go@v4
+        with:
+          go-version: ">=1.20.0"
+      - run: |
+          git config --add safe.directory '*'
+          chown -R gitea:gitea . /go
+      - run: |
+          su gitea -c 'make deps-backend'
+      - run: |
+          su gitea -c 'make backend'
+        env:
+          TAGS: bindata
+      - run: |
+          su gitea -c 'make test-pgsql-migration test-pgsql'
+        timeout-minutes: 50
+        env:
+          TAGS: bindata gogit
+          RACE_ENABLED: true
+          TEST_TAGS: gogit
+          USE_REPO_TEST_DIR: 1
diff --git a/.forgejo/workflows/testing-sqlite.yml b/.forgejo/workflows/testing-sqlite.yml
new file mode 100644
index 0000000000..858fce371b
--- /dev/null
+++ b/.forgejo/workflows/testing-sqlite.yml
@@ -0,0 +1,36 @@
+name: testing SQLite
+
+on:
+  pull_request:
+  push:
+    branches:
+      - 'forgejo*'
+      - 'v*/forgejo*'
+
+jobs:
+  test-sqlite:
+    runs-on: ubuntu-latest
+    container:
+      image: codeberg.org/forgejo/test_env:main
+    steps:
+      - uses: https://code.forgejo.org/actions/checkout@v3
+      - uses: https://code.forgejo.org/actions/setup-go@v4
+        with:
+          go-version: ">=1.20.0"
+      - run: |
+          git config --add safe.directory '*'
+          chown -R gitea:gitea . /go
+      - run: |
+          su gitea -c 'make deps-backend'
+      - run: |
+          su gitea -c 'make backend'
+        env:
+          TAGS: bindata gogit sqlite sqlite_unlock_notify
+      - run: |
+          su gitea -c 'make test-sqlite-migration test-sqlite'
+        timeout-minutes: 50
+        env:
+          TAGS: bindata gogit sqlite sqlite_unlock_notify
+          RACE_ENABLED: true
+          TEST_TAGS: gogit sqlite sqlite_unlock_notify
+          USE_REPO_TEST_DIR: 1
diff --git a/.forgejo/workflows/testing-unit.yml b/.forgejo/workflows/testing-unit.yml
new file mode 100644
index 0000000000..a17c73d4f8
--- /dev/null
+++ b/.forgejo/workflows/testing-unit.yml
@@ -0,0 +1,34 @@
+name: testing unit
+
+on:
+  pull_request:
+  push:
+    branches:
+      - 'forgejo*'
+      - 'v*/forgejo*'
+
+jobs:
+  test-unit:
+    runs-on: ubuntu-latest
+    container:
+      image: codeberg.org/forgejo/test_env:main
+    steps:
+      - uses: https://code.forgejo.org/actions/checkout@v3
+      - uses: https://code.forgejo.org/actions/setup-go@v4
+        with:
+          go-version: ">=1.20.0"
+      - run: |
+          git config --add safe.directory '*'
+          chown -R gitea:gitea . /go
+      - run: |
+          su gitea -c 'make deps-backend'
+      - run: |
+          su gitea -c 'make backend'
+        env:
+          TAGS: bindata
+      - run: |
+          su gitea -c 'make unit-test-coverage test-check'
+        timeout-minutes: 50
+        env:
+          RACE_ENABLED: 'true'
+          TAGS: bindata