diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 283a70e6c24eccbbdd5ce2f6b4ec70dcb4f2f95e..132bd9b2cdea9df2eab811227d131ad13314d882 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,8 +1,10 @@
 default:
-  image: $CI_REGISTRY/lofar2.0/attributewrapper/ci_python37:$CI_COMMIT_SHORT_SHA # minimum supported version
+  image: $CI_REGISTRY/lofar2.0/attributewrapper/ci_python38:$CI_COMMIT_SHORT_SHA # minimum supported version
   # Make sure each step is executed in a virtual environment with some basic dependencies present
   before_script:
     - python --version # For debugging
+    - tox --version
+    - pip --version
   cache:
     paths:
       - .cache/pip
@@ -10,8 +12,6 @@ default:
 stages:
   - image
   - lint
-  # check if this needs to be a separate step
-  # - build_extensions
   - test
   - package
   - integration
@@ -21,7 +21,7 @@ stages:
 variables:
   PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
 
-build_test_image_python37:
+build_test_image_python38:
   stage: image
   image: docker
   services:
@@ -31,8 +31,8 @@ build_test_image_python37:
   before_script:
     - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
   script:
-    - docker build -t $CI_REGISTRY/lofar2.0/attributewrapper/ci_python37:$CI_COMMIT_SHORT_SHA -f docker/Dockerfile.ci_python37 docker
-    - docker push $CI_REGISTRY/lofar2.0/attributewrapper/ci_python37:$CI_COMMIT_SHORT_SHA
+    - docker build -t $CI_REGISTRY/lofar2.0/attributewrapper/ci_python38:$CI_COMMIT_SHORT_SHA -f docker/Dockerfile.ci_python38 docker
+    - docker push $CI_REGISTRY/lofar2.0/attributewrapper/ci_python38:$CI_COMMIT_SHORT_SHA
 
 run_black:
   stage: lint
@@ -50,11 +50,6 @@ run_pylint:
     - tox -e pylint
   allow_failure: true
 
-# build_extensions:
-#   stage: build_extensions
-#   script:
-#     - echo "build fortran/c/cpp extension source code"
-
 run_unit_tests_coverage:
   stage: test
   script:
@@ -67,11 +62,11 @@ run_unit_tests_coverage:
     paths:
       - htmlcov/*
 
-run_unit_tests_py37:
+run_unit_tests_py38:
   stage: test
   script:
     - echo "run python3.7 unit tests /w coverage"
-    - tox -e py37
+    - tox -e py38
 
 .run_unit_tests_pyXX:
   # installs the prerequisites explicitly, instead of piggy backing
@@ -79,29 +74,22 @@ run_unit_tests_py37:
   # images with different python versions.
   stage: test
   before_script:
-    - apt-get update -y && DEBIAN_FRONTEND=noninteractive apt-get install -y git python3-pip libboost-python-dev libtango-dev # Needed to install pytango
+    - apt-get update -y && DEBIAN_FRONTEND=noninteractive apt-get install -y git python3-pip
     - python3 -m pip install --upgrade pip
     - pip install --upgrade tox
 
-run_unit_tests_py38:
-  extends: .run_unit_tests_pyXX
-  image: python:3.8-buster
-  script:
-    - echo "run python3.8 unit tests /w coverage"
-    - tox -e py38
-
 run_unit_tests_py39:
   extends: .run_unit_tests_pyXX
   image: python:3.9-bullseye
   script:
-    - echo "run python3.9 unit tests /w coverage"
+    - echo "run python3.8 unit tests /w coverage"
     - tox -e py39
 
 run_unit_tests_py310:
   extends: .run_unit_tests_pyXX
   image: ubuntu:jammy
   script:
-    - echo "run python3.10 unit tests /w coverage"
+    - echo "run python3.9 unit tests /w coverage"
     - tox -e py310
 
 run_unit_tests_py311:
@@ -114,6 +102,16 @@ run_unit_tests_py311:
     - echo "run python3.11 unit tests /w coverage"
     - tox -e py311
 
+run_unit_tests_py312:
+  extends: .run_unit_tests_pyXX
+  image: python:3.12-bullseye
+  script:
+    # Debian Bullseye ships with libboost-python linked to Python 3.9. Use the one from Debian Sid instead.
+    - echo 'deb http://deb.debian.org/debian sid main' >> /etc/apt/sources.list
+    - apt-get update -y && DEBIAN_FRONTEND=noninteractive apt-get install -y libboost-python1.74-dev
+    - echo "run python3.12 unit tests /w coverage"
+    - tox -e py312
+
 package_files:
   stage: package
   artifacts:
@@ -125,21 +123,25 @@ package_files:
 
 package_docs:
   stage: package
+  allow_failure: true
   artifacts:
     expire_in: 1w
     paths:
       - docs/* # update path to match the dest dir for documentation
   script:
     - echo "build and collect docs"
+    - exit 1
 
 run_integration_tests:
   stage: integration
+  allow_failure: true
   needs:
     - package_files
   script:
     - echo "make sure to move out of source dir"
     - echo "install package from filesystem (or use the artefact)"
     - echo "run against foreign systems (e.g. databases, cwl etc.)"
+    - exit 1
 
 publish_on_gitlab:
   stage: publish
@@ -193,6 +195,7 @@ publish_on_pypi:
 
 publish_to_readthedocs:
   stage: publish
+  allow_failure: true
   environment: readthedocs
   needs:
     - package_docs
@@ -201,3 +204,4 @@ publish_to_readthedocs:
     - if: $CI_COMMIT_TAG
   script:
     - echo "scp docs/* ???"
+    - exit 1
diff --git a/README.md b/README.md
index 1cbc13ab1e0301e95c3d58febbac060f015f5677..8ed6a9d6a9574fa30acf02b20c13c19c9e7d1df9 100644
--- a/README.md
+++ b/README.md
@@ -43,4 +43,5 @@ This project is licensed under the Apache License Version 2.0
 
 ## Releases
 
-- 0.1 - Initial release from separating into own repository
\ No newline at end of file
+- 0.2 - Ensure requirements.txt dependencies are installed
+- 0.1 - Initial release from separating into own repository
diff --git a/docker/Dockerfile.ci_python37 b/docker/Dockerfile.ci_python38
similarity index 79%
rename from docker/Dockerfile.ci_python37
rename to docker/Dockerfile.ci_python38
index c1caab8127c615af1b8862be65f38a50ac48d823..e454417bd312db7b42339cd91812f16b7838f9d3 100644
--- a/docker/Dockerfile.ci_python37
+++ b/docker/Dockerfile.ci_python38
@@ -1,8 +1,8 @@
-FROM python:3.7-buster
+FROM python:3.8-buster
 
 # Install PyTango dependencies
 RUN apt-get update -y
-RUN DEBIAN_FRONTEND=noninteractive apt-get install -y git python3-pip libboost-python-dev libtango-dev
+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y git python3-pip
 
 # Make sure we have the latest tooling for our tests
 RUN python -m pip install --upgrade pip
diff --git a/pyproject.toml b/pyproject.toml
index 68345be2dfa069a838a63baec39c584a34c9cdde..b6e0be7c6b54a4b4b3afd739493924a48a5a98de 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [build-system]
 requires = [
-    "setuptools>=45",
+    "setuptools>=62.6",
     "setuptools_scm[toml]>=6.2",
     "wheel"
 ]
diff --git a/requirements.txt b/requirements.txt
index 198420c501fa4141aa9ea95e436929b88744f586..2ef853cd1156c1aece86c1f89b885871b4e1d209 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,9 @@
-numpy >= 1.19.5 # BSD
-stestr>=3.0.0 # Apache-2.0
-testscenarios>=0.5.0 # Apache-2.0/BSD
-testtools>=2.4.0 # MIT
+importlib-metadata>=0.12; python_version<"3.8"
+pip >= 1.5
+pytango >= 9.4.0
+numpy >= 1.19.3; python_version >"3.9" and python_version <"3.10" # BSD
+numpy >= 1.21.6; python_version >"3.10" and python_version <"3.11" # BSD
+numpy >= 1.23.2; python_version >"3.11" and python_version <"3.12" # BSD
+stestr >= 3.0.0 # Apache-2.0
+testscenarios >= 0.5.0 # Apache-2.0/BSD
+testtools >= 2.4.0 # MIT
diff --git a/setup.cfg b/setup.cfg
index edd47152b0578893e2300197ff0e8ac0a57fb1d5..a56b8243081daf5671b3fcb15cfe8595f7f4756c 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -29,9 +29,7 @@ classifiers =
 include_package_data = true
 packages = find:
 python_requires = >=3.7
-install_requires =
-    importlib-metadata>=0.12;python_version<"3.8"
-    pip >= 1.5
+install_requires = file: requirements.txt
 
 [flake8]
 max-line-length = 88
diff --git a/tox.ini b/tox.ini
index 621d91400e6e930470cbfd07d577ff1bde78c17f..a2899d8d3a56c93b399afb24c56597770f49241b 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,7 +1,7 @@
 [tox]
 # Generative environment list to test all supported Python versions
 envlist = py3{7,8,9,10,11},black,pep8,pylint
-minversion = 3.28.0
+minversion = 4.3.3
 
 [testenv]
 usedevelop = True
@@ -14,10 +14,6 @@ setenv =
 deps =
     -r{toxinidir}/requirements.txt
     -r{toxinidir}/tests/requirements.txt
-commands_pre =
-    # required until https://gitlab.com/tango-controls/pytango/-/issues/468 is resolved
-    pip install 'numpy>=1.19.5'
-    pip install --no-cache 'PyTango>=9.3.6,<9.4.0'
 commands =
     {envpython} --version
     {envpython} -m pytest {posargs}