From 9e5cc5d926e4c16b1b41e345c1e8a245ceda2004 Mon Sep 17 00:00:00 2001 From: Dusty <24461751+ploparmor@users.noreply.github.com> Date: Thu, 19 Sep 2019 12:07:42 -0500 Subject: [PATCH 1/8] Update README.md --- README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 8d2852b..f0bda2c 100755 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## Overview -SCADA sensor networks are ubiquitous in industry and notoriously difficult to secure effectively. This simulator generates network traffic in a virtual environment and allows students the opportunity to view and work with modbus traffic, the protocol used by SCADA systems. This system fully encompasses a basic SCADA network and allows 1 to N PLC devices attached to HMIs that feed into a central historian. The topology is controled by a single json configuration file, allowing for simple or complex sensor networks. +SCADA sensor networks are ubiquitous in industry and notoriously difficult to secure effectively. This simulator generates network traffic in a virtual environment and allows students the opportunity to view and work with modbus traffic, the protocol used by SCADA systems. This system fully encompasses a basic SCADA network and allows 1 to N PLC devices attached to HMIs that feed into a central historian. The topology is controlled by a single json configuration file, allowing for simple or complex sensor networks. ## Getting Started @@ -11,8 +11,8 @@ The SCADA simulator requires at least three different systems: A historian, one #
Table of Contents
1. [Check out SCADA code](#Pull-SCADA-Source-Code) 2. [Install Dependencies](#Install-Dependencies) -3. [Setup Postgres DB](#Setup-Postgres-DB-for-Deployment) -4. [Initilize SCADA](#Initilize-SCADA) +3. [Setup Postgres Database](#Setup-Postgres-DB-for-Deployment) +4. [Initialize SCADA](#Initialize-SCADA) 5. [Local Deployment](#Local-Deployment) 6. [Historian Deployment](#Historian-Deployment) 7. [HMI Deployment](#HMI-Deployment) @@ -46,7 +46,7 @@ $ systemctl start postgresql && systemctl enable postgresql ```bash $ python ./init.py --help # Help CLI arguments $ python ./init.py -f path/to/config.json -u -d -w # Local -$ python ./init.py -s -f path/to/config.json -u -d -w # Distrobuted +$ python ./init.py -s -f path/to/config.json -u -d -w # Distributed ``` Troubleshoot 1: Make sure if you have a distributed SCADA network that you can connect to HMIs defined in the configuration file. @@ -112,13 +112,13 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config ``` ## 9. Configuration File Standard -* 9a. This project simulates a SCADA system that has three unique parts: Histoian, HMI, and PLC. The Historian is the central repository for all of the Human-Managment Interfaces. The Historian poles the HMIs to gather a historiacal picture of what the HMIs are seeing. The default poling interval is 30 seconds, if the poling interval should be larger or shorter then the sleep time in HMI_Server.py/historina_handler can be changed up or down. The HMIs are a real time view of the PLC devices readings. This allows users to identify real time issues associated with each individual PLC devices. The HMI unlike the Historian only maintains records of the last 1000 readings pulled from the PLC devices. Finally the PLC devices are modled off of the arduino controller archetecture. Each ardunino has its own unique IP address and allows two way communication. These modules are comprised of actuators and sensors with the actuators having direct relationship with the sesnors, meaning if a heater actuator is turned up the temperture sensor will start rising in value. The next couple of sections will walk you through how to properly configure the json configuration file in order to correctly map your SCADA System. +* 9a. This project simulates a SCADA system that has three unique parts: Historian, HMI, and PLC. The Historian is the central repository for all of the Human-Managment Interfaces. The Historian polls the HMIs to gather a historical picture of what the HMIs are seeing. The default polling interval is 30 seconds, if the polling interval should be larger or shorter then the sleep time in HMI_Server.py/historian_handler can be changed up or down. The HMIs are a real time view of the PLC devices readings. This allows users to identify real time issues associated with each individual PLC devices. The HMI unlike the Historian only maintains records of the last 1000 readings pulled from the PLC devices. Finally the PLC devices are modeled off of the arduino controller architecture. Each arduino has its own unique IP address and allows two way communication. These modules are comprised of actuators and sensors with the actuators having direct relationship with the sensors, meaning if a heater actuator is turned up the temperture sensor will start rising in value. The next couple of sections will walk you through how to properly configure the json configuration file in order to correctly map your SCADA System. * **9b. Historian** * 9b.1 The required keys are: name_system, name, location, actuators, and sub_devices. The default IP address is 127.0.0.1 and listening port is 5020 - * 9b.2 Sub Devices are HMIs or Controllers(PLC Device) the Historian cannot have any controller devices and must have atleaset one HMI - * 9b.3 The "Status" Actuator is required for all devices this allows users to turn on and off services that the device provides as well as all services dependant on the device ex: if the Historian is disabled then all HMIs will be disabled and all PLC devices relying on the HMI. + * 9b.2 Sub Devices are HMIs or Controllers(PLC Device) the Historian cannot have any controller devices and must have atleast one HMI + * 9b.3 The "Status" Actuator is required for all devices this allows users to turn on and off services that the device provides as well as all services dependent on the device ex: if the Historian is disabled then all HMIs will be disabled and all PLC devices relying on the HMI. * 9b.4 The Historian only has one Actuator and cannot have any additional sensors or actuators. - * 9b.5 Below is an example of the Hisorian Configuration: + * 9b.5 Below is an example of the Historian Configuration:
**Example Historian Configuration**
```json @@ -168,8 +168,8 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config ``` * **9d. Controller** * 9d.1 The required keys are: name_system, name, location, and sub_devices. - * 9d.2 The IP address will be assigned during the initilization phase of deployment - * 9d.3 The controller can have as many actuators and sensors necessary but, must have atleaset one actuator or sensor. + * 9d.2 The IP address will be assigned during the initialization phase of deployment + * 9d.3 The controller can have as many actuators and sensors necessary but, must have atleast one actuator or sensor. * 9d.4 The PLC Identifier is a unique string that identifies the HMI. This is what will be used to bind PLC devices to the HMI and can be any unique string
**Example Controller Configuration**
@@ -186,7 +186,7 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config ``` * **9e. Sensor** * 9e.1 The required keys are: type, units, initial_value, and variability. - * 9e.2 The variability is the how far +- the sensor readings will flucuate from the current_value + * 9e.2 The variability is the how far +- the sensor readings will fluctuate from the current_value * 9e.3 The valid types are: "locked", "enabled", "open", "temperature", "pressure", "humidity", "flow", "live-stream", "speed", "rotation", "power", "motion" * 9e.4 The threshold is optional if not defined the PLC will only fail if the controller tells it to fail. Otherwise the Sensors Controller will fail/shutoff if the sensor reads below the min or above the max @@ -202,14 +202,14 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config ``` * **9f. Actuator** * 9f.1 The required keys are: type, and initial_value. - * 9f.2 The relationship can be as follows: positive - The value increases, negative - The value decreases, and variable - The value can both increase or decrease according to the current value (0 OFF 1 Decrease 2 Maintian 3 Increase) + * 9f.2 The relationship can be as follows: positive - The value increases, negative - The value decreases, and variable - The value can both increase or decrease according to the current value (0 OFF 1 Decrease 2 Maintain 3 Increase) * 9f.3 The valid types are: "locked", "enabled", "live-stream", "variable", "relational" with locked, enabled and live-stream will have sensors the reflect the actuator current value * 9f.4 Type with Variable will have a relationship of positive or negative while relational will have a relationship of variable * 9f.5 The master field must have the sensor identifier of which sensor that will reflect the changes spawned from the actuator
**Example Actuator Configuration**
```json -: { +: { "type": , "initial_value": , "master" : , @@ -328,6 +328,6 @@ $ sudo systemctl enable docker.service $ sudo systemctl start docker.service ``` -
**Prepare docker image for ardunio engine**
+
**Prepare docker image for arduino engine**
```bash ``` From c9a9ae439bc4dd533940e40ebf0c4994c8ecd6c7 Mon Sep 17 00:00:00 2001 From: Dusty <24461751+ploparmor@users.noreply.github.com> Date: Thu, 19 Sep 2019 12:59:20 -0500 Subject: [PATCH 2/8] Update README.md --- README.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index f0bda2c..efe9ca4 100755 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Troubleshoot 1: Make sure if you have a distributed SCADA network that you can c Troubleshoot 2: Ensure the postgres service is on and the pg_hba.conf file allows for users to connect remotely to the defined HMIs. ## 5. Local Deployment - Open three terminals and navigate to the SCADA home directory -
**Data Server - Terminal 1**
+**Data Server - Terminal 1** ```bash $ python ./dataserver.py --help # Help CLI arguments $ python ./dataserver.py -u -d -w @@ -61,7 +61,7 @@ Open browser and go to http://localhost:5000 Troubleshoot 1: Default port is port 5000 ensure that the firewall allows communication over port 5000. -
**HMI Server - Terminal 2**
+**HMI Server - Terminal 2** ```bash $ python ./HMI_Server.py --help # Help CLI arguments $ python ./HMI_Server.py -p 5001 -u -d -w @@ -70,7 +70,7 @@ Troubleshoot 1: Ensure that the Data Server is started and currently running. Troubleshoot 2: Ensure firewall allows communication over port 5001 local -
**PLC Engine - Terminal 3**
+**PLC Engine - Terminal 3** ```bash $ python ./PLC_manager.py --help # Help CLI arguments $ python ./PLC_manager.py -f path/to/config.json @@ -81,7 +81,7 @@ Troubleshoot 2: Ensure firewall allows communication over port 5001 local. ## 6. Historian Deployment - Only the Data Server is required for the historian -
**Data Server - Terminal 1**
+**Data Server - Terminal 1** ```bash $ python ./dataserver.py --help # Help CLI arguments $ python ./dataserver.py -i -p -u -d -w @@ -89,13 +89,13 @@ $ python ./dataserver.py -i -p -u -d HMI Deployment - Open two terminals and navigate to JASPR home directory. -
**Data Server - Terminal 1**
+**Data Server - Terminal 1** ```bash $ python ./dataserver.py --help # Help CLI arguments $ python ./dataserver.py -i -p -u -d -w ``` Troubleshoot 1: Ensure that the firewall allows communication over the defined port. If the port number is low then sudo may be required. -
**7b. HMI Server - Terminal 2**
+**7b. HMI Server - Terminal 2** ```bash $ python ./HMI_Server.py --help # Help CLI arguments $ python ./HMI_Server.py -i -p -u -d -w @@ -120,11 +120,11 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config * 9b.4 The Historian only has one Actuator and cannot have any additional sensors or actuators. * 9b.5 Below is an example of the Historian Configuration: -
**Example Historian Configuration**
-```json +**Example Historian Configuration** +``` { "Historian": { - "name_system": , + "name_system": , "name": , "location": , "device_type": "Historian", @@ -146,8 +146,8 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config * 9c.3 The HMI only has one Actuator and cannot have any additional sensors or actuators. * 9c.4 The HMI Identifier is a unique string that identifies the HMI. This is what will be used to bind PLC devices to the HMI and can be any unique string -
**Example HMI Configuration**
-```json +**Example HMI Configuration** +``` : { "name_system": , "name": , @@ -172,8 +172,8 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config * 9d.3 The controller can have as many actuators and sensors necessary but, must have atleast one actuator or sensor. * 9d.4 The PLC Identifier is a unique string that identifies the HMI. This is what will be used to bind PLC devices to the HMI and can be any unique string -
**Example Controller Configuration**
-```json +**Example Controller Configuration** +``` : { "name_system": , "name": , @@ -190,8 +190,8 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config * 9e.3 The valid types are: "locked", "enabled", "open", "temperature", "pressure", "humidity", "flow", "live-stream", "speed", "rotation", "power", "motion" * 9e.4 The threshold is optional if not defined the PLC will only fail if the controller tells it to fail. Otherwise the Sensors Controller will fail/shutoff if the sensor reads below the min or above the max -
**Example Sensor Configuration**
-```json +**Example Sensor Configuration** +``` : { "type": , "units": , @@ -207,8 +207,8 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config * 9f.4 Type with Variable will have a relationship of positive or negative while relational will have a relationship of variable * 9f.5 The master field must have the sensor identifier of which sensor that will reflect the changes spawned from the actuator -
**Example Actuator Configuration**
-```json +**Example Actuator Configuration** +``` : { "type": , "initial_value": , @@ -218,8 +218,8 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config ``` * **9e. Complete Example:** -
**Example**
-```json +**Example** +``` { "Historian": { "name_system": "SCADA System", @@ -320,7 +320,7 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config ## 10. Install and Configure Docker To install Docker on your PLC Box follow the instructions in the following Link: https://docs.docker.com/engine/installation/, however this guide will be going over how to install on a CentOS 5 or above. -
**Download and Install Docker (you must be in the scada home directory)**
+**Download and Install Docker (you must be in the scada home directory)** ```bash $ cp ./docker.repo /etc/yum.repos.d $ sudo yum update && sudo yum install docker-engine @@ -328,6 +328,6 @@ $ sudo systemctl enable docker.service $ sudo systemctl start docker.service ``` -
**Prepare docker image for arduino engine**
+**Prepare docker image for arduino engine** ```bash ``` From df774c93057b9cc42a45df0d4e7145c126cdd7f4 Mon Sep 17 00:00:00 2001 From: Dusty <24461751+ploparmor@users.noreply.github.com> Date: Thu, 19 Sep 2019 13:11:49 -0500 Subject: [PATCH 3/8] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index efe9ca4..b62fdf0 100755 --- a/README.md +++ b/README.md @@ -320,7 +320,7 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config ## 10. Install and Configure Docker To install Docker on your PLC Box follow the instructions in the following Link: https://docs.docker.com/engine/installation/, however this guide will be going over how to install on a CentOS 5 or above. -**Download and Install Docker (you must be in the scada home directory)** +**

Download and Install Docker (you must be in the scada home directory)

** ```bash $ cp ./docker.repo /etc/yum.repos.d $ sudo yum update && sudo yum install docker-engine From 18363a4f8c3047315632cda552cc0d6e0cbddf46 Mon Sep 17 00:00:00 2001 From: Dusty <24461751+ploparmor@users.noreply.github.com> Date: Thu, 19 Sep 2019 13:16:46 -0500 Subject: [PATCH 4/8] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b62fdf0..efe9ca4 100755 --- a/README.md +++ b/README.md @@ -320,7 +320,7 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config ## 10. Install and Configure Docker To install Docker on your PLC Box follow the instructions in the following Link: https://docs.docker.com/engine/installation/, however this guide will be going over how to install on a CentOS 5 or above. -**

Download and Install Docker (you must be in the scada home directory)

** +**Download and Install Docker (you must be in the scada home directory)** ```bash $ cp ./docker.repo /etc/yum.repos.d $ sudo yum update && sudo yum install docker-engine From 023c242afd3b3f7ea2806a4aceb104c25490df43 Mon Sep 17 00:00:00 2001 From: Dusty <24461751+ploparmor@users.noreply.github.com> Date: Thu, 19 Sep 2019 13:47:45 -0500 Subject: [PATCH 5/8] Update README.md --- README.md | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index efe9ca4..6b3c0bf 100755 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ SCADA sensor networks are ubiquitous in industry and notoriously difficult to se The SCADA simulator requires at least three different systems: A historian, one or more HMIs, and a PLC. Each component can run on an independent Ubuntu virtual machine. -#
Table of Contents
+# Table of Contents 1. [Check out SCADA code](#Pull-SCADA-Source-Code) 2. [Install Dependencies](#Install-Dependencies) 3. [Setup Postgres Database](#Setup-Postgres-DB-for-Deployment) @@ -118,9 +118,7 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config * 9b.2 Sub Devices are HMIs or Controllers(PLC Device) the Historian cannot have any controller devices and must have atleast one HMI * 9b.3 The "Status" Actuator is required for all devices this allows users to turn on and off services that the device provides as well as all services dependent on the device ex: if the Historian is disabled then all HMIs will be disabled and all PLC devices relying on the HMI. * 9b.4 The Historian only has one Actuator and cannot have any additional sensors or actuators. - * 9b.5 Below is an example of the Historian Configuration: - -**Example Historian Configuration** + * 9b.5 **Example of Historian Configuration:** ``` { "Historian": { @@ -145,8 +143,7 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config * 9c.2 The Host IP address is the web page front end for the HMI while the HMI IP address is the interface communicating with the PLC devices * 9c.3 The HMI only has one Actuator and cannot have any additional sensors or actuators. * 9c.4 The HMI Identifier is a unique string that identifies the HMI. This is what will be used to bind PLC devices to the HMI and can be any unique string - -**Example HMI Configuration** + * **Example of HMI Configuration:** ``` : { "name_system": , @@ -171,8 +168,7 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config * 9d.2 The IP address will be assigned during the initialization phase of deployment * 9d.3 The controller can have as many actuators and sensors necessary but, must have atleast one actuator or sensor. * 9d.4 The PLC Identifier is a unique string that identifies the HMI. This is what will be used to bind PLC devices to the HMI and can be any unique string - -**Example Controller Configuration** + * **Example of Controller Configuration:** ``` : { "name_system": , @@ -189,8 +185,7 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config * 9e.2 The variability is the how far +- the sensor readings will fluctuate from the current_value * 9e.3 The valid types are: "locked", "enabled", "open", "temperature", "pressure", "humidity", "flow", "live-stream", "speed", "rotation", "power", "motion" * 9e.4 The threshold is optional if not defined the PLC will only fail if the controller tells it to fail. Otherwise the Sensors Controller will fail/shutoff if the sensor reads below the min or above the max - -**Example Sensor Configuration** + * **Example of the Sensor Configuration:** ``` : { "type": , @@ -206,8 +201,7 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config * 9f.3 The valid types are: "locked", "enabled", "live-stream", "variable", "relational" with locked, enabled and live-stream will have sensors the reflect the actuator current value * 9f.4 Type with Variable will have a relationship of positive or negative while relational will have a relationship of variable * 9f.5 The master field must have the sensor identifier of which sensor that will reflect the changes spawned from the actuator - -**Example Actuator Configuration** + * **Example of Actuator Configuration:** ``` : { "type": , From 86d82337696bcf2f142c441bb11d22b3107707ba Mon Sep 17 00:00:00 2001 From: Dusty <24461751+ploparmor@users.noreply.github.com> Date: Thu, 19 Sep 2019 14:16:51 -0500 Subject: [PATCH 6/8] Update README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6b3c0bf..ac61df5 100755 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config * 9b.3 The "Status" Actuator is required for all devices this allows users to turn on and off services that the device provides as well as all services dependent on the device ex: if the Historian is disabled then all HMIs will be disabled and all PLC devices relying on the HMI. * 9b.4 The Historian only has one Actuator and cannot have any additional sensors or actuators. * 9b.5 **Example of Historian Configuration:** -``` +```json5 { "Historian": { "name_system": , @@ -144,7 +144,7 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config * 9c.3 The HMI only has one Actuator and cannot have any additional sensors or actuators. * 9c.4 The HMI Identifier is a unique string that identifies the HMI. This is what will be used to bind PLC devices to the HMI and can be any unique string * **Example of HMI Configuration:** -``` +```json5 : { "name_system": , "name": , @@ -169,7 +169,7 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config * 9d.3 The controller can have as many actuators and sensors necessary but, must have atleast one actuator or sensor. * 9d.4 The PLC Identifier is a unique string that identifies the HMI. This is what will be used to bind PLC devices to the HMI and can be any unique string * **Example of Controller Configuration:** -``` +```json5 : { "name_system": , "name": , @@ -186,7 +186,7 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config * 9e.3 The valid types are: "locked", "enabled", "open", "temperature", "pressure", "humidity", "flow", "live-stream", "speed", "rotation", "power", "motion" * 9e.4 The threshold is optional if not defined the PLC will only fail if the controller tells it to fail. Otherwise the Sensors Controller will fail/shutoff if the sensor reads below the min or above the max * **Example of the Sensor Configuration:** -``` +```json5 : { "type": , "units": , @@ -202,7 +202,7 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config * 9f.4 Type with Variable will have a relationship of positive or negative while relational will have a relationship of variable * 9f.5 The master field must have the sensor identifier of which sensor that will reflect the changes spawned from the actuator * **Example of Actuator Configuration:** -``` +```json5 : { "type": , "initial_value": , @@ -213,7 +213,7 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config * **9e. Complete Example:** **Example** -``` +```json5 { "Historian": { "name_system": "SCADA System", From 3f0862f848e248bc29a43f89db65b5af85d32f9f Mon Sep 17 00:00:00 2001 From: Dusty <24461751+ploparmor@users.noreply.github.com> Date: Thu, 19 Sep 2019 14:20:45 -0500 Subject: [PATCH 7/8] Update README.md --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index ac61df5..194a23f 100755 --- a/README.md +++ b/README.md @@ -137,7 +137,6 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config "sub_devices" : {} } ``` - * **9c. HMI** * 9c.1 The required keys are: name_system, name, location, actuators, and sub_devices. The default Host and HMI IP address is 127.0.0.1 and listening port for the host is 5020 and HMI is 5021 * 9c.2 The Host IP address is the web page front end for the HMI while the HMI IP address is the interface communicating with the PLC devices @@ -211,8 +210,6 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config } ``` * **9e. Complete Example:** - -**Example** ```json5 { "Historian": { From 4af29d37b58c2cfd7fa8e42c514878c25214b4f6 Mon Sep 17 00:00:00 2001 From: Dusty <24461751+ploparmor@users.noreply.github.com> Date: Mon, 6 Jan 2020 11:42:42 -0600 Subject: [PATCH 8/8] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 194a23f..03d60e6 100755 --- a/README.md +++ b/README.md @@ -310,7 +310,7 @@ $ python ./PLC_engine.py -H http://:/api/modbus-config ``` ## 10. Install and Configure Docker -To install Docker on your PLC Box follow the instructions in the following Link: https://docs.docker.com/engine/installation/, however this guide will be going over how to install on a CentOS 5 or above. +To install Docker on your PLC Box follow the instructions in the following Link: https://docs.docker.com/engine/installation/, however this guide will be going over how to install on a CentOS 5 or above. **Download and Install Docker (you must be in the scada home directory)** ```bash $ cp ./docker.repo /etc/yum.repos.d