diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8e8499ec2d3b7d3e7a7c91b965a816996ab006e1..0ea0331e30bc29d9361e4189752478a6dd9b9057 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -86,11 +86,13 @@ docker_build_image_all:
     - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh grafana latest
     - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh jupyter latest
     - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh apsct-sim latest
+    - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh ccd-sim latest
     - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh apspu-sim latest
     - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh recv-sim latest
     - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh sdptr-sim latest
     - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh unb2-sim latest
     - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-apsct latest
+    - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-ccd latest
     - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-apspu latest
     - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-tilebeam latest
     - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-beamlet latest
@@ -191,6 +193,17 @@ docker_build_image_apsct_sim:
   script:
 #    Do not remove 'bash' or statement will be ignored by primitive docker shell
     - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh apsct-sim $tag
+docker_build_image_ccd_sim:
+  extends: .base_docker_images_except
+  only:
+    refs:
+      - merge_requests
+    changes:
+      - docker-compose/ccd-sim.yml
+      - docker-compose/pypcc-sim-base/*
+  script:
+#    Do not remove 'bash' or statement will be ignored by primitive docker shell
+    - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh ccd-sim $tag
 docker_build_image_apspu_sim:
   extends: .base_docker_images_except
   only:
@@ -246,6 +259,17 @@ docker_build_image_device_apsct:
   script:
 #    Do not remove 'bash' or statement will be ignored by primitive docker shell
     - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-aspct $tag
+docker_build_image_device_ccd:
+  extends: .base_docker_images_except
+  only:
+    refs:
+      - merge_requests
+    changes:
+      - docker-compose/device-ccd.yml
+      - docker-compose/lofar-device-base/*
+  script:
+#    Do not remove 'bash' or statement will be ignored by primitive docker shell
+    - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-ccd $tag
 docker_build_image_device_apspu:
   extends: .base_docker_images_except
   only:
diff --git a/docker-compose/ccd-sim.yml b/docker-compose/ccd-sim.yml
new file mode 100644
index 0000000000000000000000000000000000000000..0ceac9c2e0023e1dc184a8a898c5a70f42884ac5
--- /dev/null
+++ b/docker-compose/ccd-sim.yml
@@ -0,0 +1,25 @@
+#
+# Docker compose file that launches an APSCT simulator
+#
+# Defines:
+#   - apsct-sim
+#
+version: '2.1'
+
+services:
+  ccd-sim:
+    build:
+        context: pypcc-sim-base
+        args:
+         - LOCAL_DOCKER_REGISTRY_HOST=${LOCAL_DOCKER_REGISTRY_HOST}
+         - LOCAL_DOCKER_REGISTRY_LOFAR=${LOCAL_DOCKER_REGISTRY_LOFAR}
+    container_name: ${CONTAINER_NAME_PREFIX}ccd-sim
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "100m"
+        max-file: "10"
+    networks:
+      - control
+    entrypoint: hwtr --simulator --port 4843 --config CCDTR
+    restart: on-failure
diff --git a/docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py b/docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py
index af329f05b03ae4bdc3b10542e96949c2f5e2b604..350ecb1e87f4829ddd60698831bbf75d941782a9 100644
--- a/docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py
+++ b/docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py
@@ -1,5 +1,6 @@
 # Create shortcuts for our devices
 apsct = DeviceProxy("STAT/APSCT/1")
+ccd = DeviceProxy("STAT/CCD/1")
 apspu = DeviceProxy("STAT/APSPU/1")
 recv = DeviceProxy("STAT/RECV/1")
 sdp = DeviceProxy("STAT/SDP/1")
@@ -17,4 +18,4 @@ docker = DeviceProxy("STAT/Docker/1")
 temperaturemanager = DeviceProxy("STAT/TemperatureManager/1")
 
 # Put them in a list in case one wants to iterate
-devices = [apsct, apspu, recv, sdp, bst, sst, xst, unb2, boot, tilebeam, beamlet, digitalbeam, antennafield, temperaturemanager, docker]
+devices = [apsct, ccd, apspu, recv, sdp, bst, sst, xst, unb2, boot, tilebeam, beamlet, digitalbeam, antennafield, temperaturemanager, docker]
diff --git a/docker-compose/tango-prometheus-exporter/lofar2-policy.json b/docker-compose/tango-prometheus-exporter/lofar2-policy.json
index e7da467993c3fed8f4fef44c107bbc8f0608d072..bfc07e87704a9350098981ff3094b2591a752cf3 100644
--- a/docker-compose/tango-prometheus-exporter/lofar2-policy.json
+++ b/docker-compose/tango-prometheus-exporter/lofar2-policy.json
@@ -15,6 +15,8 @@
         },
         "stat/apsct/1": {
         },
+        "stat/ccd/1": {
+        },
         "stat/apspu/1": {
         },
         "stat/beamlet/1": {
diff --git a/tangostationcontrol/tangostationcontrol/devices/boot.py b/tangostationcontrol/tangostationcontrol/devices/boot.py
index cb172c34d3b4249691518609f18bd5a7ceced613..8d51d269f3e83eb2eb0a45442cec4209e00ecf13 100644
--- a/tangostationcontrol/tangostationcontrol/devices/boot.py
+++ b/tangostationcontrol/tangostationcontrol/devices/boot.py
@@ -238,6 +238,7 @@ class Boot(lofar_device):
                        "STAT/PCON/1",  # PCON boot early because it is responsible for power delivery.
                        "STAT/APSPU/1",  # APS Power Units control other hardware we want to initialise
                        "STAT/APSCT/1",
+                       "STAT/CCD/1",
                        "STAT/RECV/1",   # RCUs are input for SDP, so initialise them first
                        "STAT/UNB2/1",   # Uniboards host SDP, so initialise them first
                        "STAT/SDP/1",    # SDP controls the mask for SST/XST/BST/Beamlet, so initialise it first