%\documentclass[12pt]{article}
|
|
%\usepackage{geometry}
|
|
%\geometry{margin=1in}
|
|
%\usepackage{listings}
|
|
%\usepackage{setspace} % For setting line spacing
|
|
%
|
|
%\begin{document}
|
|
\newpage
|
|
\appendix % This command ensures correct section numbering
|
|
|
|
\section*{APPENDIX A: SUPPLEMENTARY MATERIAL} % Main appendix title - all caps
|
|
\label{appendix:supp_material} % Label for the appendix
|
|
|
|
\subsection*{A.1 Additional Data} % Sub-section within the appendix
|
|
\doublespacing % Apply double spacing here
|
|
The following code template are used to provide services for component of system mentions in table \ref{table:spec}. To modify the services and software, refer to next section for configuration.
|
|
|
|
\begin{itemize}
|
|
\item A more detailed breakdown of experimental results.
|
|
\item Additional statistical analyzes.
|
|
\item Copies of survey instruments.
|
|
\end{itemize}
|
|
\singlespacing % Revert to single spacing if needed for other parts
|
|
|
|
\subsection*{A.2 Code Template}
|
|
\lstset{
|
|
language=bash, % Changed from 'none' to a specific language
|
|
caption=Kubernetes Deployment Template,
|
|
basicstyle=\ttfamily\footnotesize,
|
|
breaklines=true,
|
|
%numbers=left, % If you want line numbers
|
|
numberstyle=\tiny\color{gray}, % Style for line numbers
|
|
stepnumber=1,
|
|
numbersep=5pt,
|
|
frame=single, % Add a frame around the code
|
|
%backgroundcolor=\color{yellow!10}, % Light background color
|
|
}
|
|
\begin{lstlisting}
|
|
---
|
|
# Deployment for Mosquitto
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: mosquitto-deployment
|
|
labels:
|
|
app: mosquitto
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: mosquitto
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: mosquitto
|
|
spec:
|
|
containers:
|
|
- name: mosquitto-mqtt
|
|
image: eclipse-mosquitto
|
|
ports:
|
|
- containerPort: 1883
|
|
- containerPort: 1990
|
|
volumeMounts:
|
|
- name: mosquitto-config
|
|
mountPath: /mosquitto/config
|
|
- name: mosquitto-data
|
|
mountPath: /mosquitto/data
|
|
- name: mosquitto-log
|
|
mountPath: /mosquitto/log
|
|
volumes:
|
|
- name: mosquitto-config
|
|
persistentVolumeClaim:
|
|
claimName: mosquitto-config-pvc
|
|
- name: mosquitto-data
|
|
persistentVolumeClaim:
|
|
claimName: mosquitto-data-pvc
|
|
- name: mosquitto-log
|
|
persistentVolumeClaim:
|
|
claimName: mosquitto-log-pvc
|
|
---
|
|
# Service for Mosquitto
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: mosquitto-service
|
|
labels:
|
|
app: mosquitto
|
|
spec:
|
|
selector:
|
|
app: mosquitto
|
|
ports:
|
|
- name: mqtt
|
|
protocol: TCP
|
|
port: 1883
|
|
targetPort: 1883
|
|
- name: admin
|
|
protocol: TCP
|
|
port: 1990
|
|
targetPort: 1990
|
|
type: ClusterIP # Or NodePort, if you need external access
|
|
---
|
|
# Persistent Volume Claims for Mosquitto
|
|
apiVersion: v1
|
|
kind: PersistentVolumeClaim
|
|
metadata:
|
|
name: mosquitto-config-pvc
|
|
spec:
|
|
accessModes:
|
|
- ReadWriteOnce
|
|
resources:
|
|
requests:
|
|
storage: 100Mi # Adjust as needed
|
|
---
|
|
apiVersion: v1
|
|
kind: PersistentVolumeClaim
|
|
metadata:
|
|
name: mosquitto-data-pvc
|
|
spec:
|
|
accessModes:
|
|
- ReadWriteOnce
|
|
resources:
|
|
requests:
|
|
storage: 1Gi # Adjust as needed
|
|
---
|
|
apiVersion: v1
|
|
kind: PersistentVolumeClaim
|
|
metadata:
|
|
name: mosquitto-log-pvc
|
|
spec:
|
|
accessModes:
|
|
- ReadWriteOnce
|
|
resources:
|
|
requests:
|
|
storage: 1Gi # Adjust as needed
|
|
---
|
|
# Deployment for Home Assistant
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: home-assistant-deployment
|
|
labels:
|
|
app: home-assistant
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: home-assistant
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: home-assistant
|
|
spec:
|
|
containers:
|
|
- name: home-assistant
|
|
image: "ghcr.io/home-assistant/home-assistant:stable"
|
|
ports:
|
|
- containerPort: 8123
|
|
volumeMounts:
|
|
- name: hass-config
|
|
mountPath: /config
|
|
- name: hass-localtime
|
|
mountPath: /etc/localtime
|
|
securityContext:
|
|
privileged: true # Required for some Home Assistant features
|
|
volumes:
|
|
- name: hass-config
|
|
persistentVolumeClaim:
|
|
claimName: hass-config-pvc
|
|
- name: hass-localtime
|
|
hostPath:
|
|
path: /etc/localtime # Mount from the host
|
|
---
|
|
# Service for Home Assistant
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: home-assistant-service
|
|
labels:
|
|
app: home-assistant
|
|
spec:
|
|
selector:
|
|
app: home-assistant
|
|
ports:
|
|
- protocol: TCP
|
|
port: 8123
|
|
targetPort: 8123
|
|
type: ClusterIP # Or NodePort
|
|
---
|
|
# Persistent Volume Claim for Home Assistant config
|
|
apiVersion: v1
|
|
kind: PersistentVolumeClaim
|
|
metadata:
|
|
name: hass-config-pvc
|
|
spec:
|
|
accessModes:
|
|
- ReadWriteOnce
|
|
resources:
|
|
requests:
|
|
storage: 2Gi # Adjust as needed
|
|
---
|
|
# Deployment for Node-RED
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: node-red-deployment
|
|
labels:
|
|
app: node-red
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: node-red
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: node-red
|
|
spec:
|
|
containers:
|
|
- name: node-red-container
|
|
image: nodered/node-red:latest
|
|
ports:
|
|
- containerPort: 1880
|
|
volumeMounts:
|
|
- name: nodered-data
|
|
mountPath: /data
|
|
env:
|
|
- name: TZ
|
|
value: America/Los_Angeles
|
|
securityContext:
|
|
privileged: true
|
|
volumes:
|
|
- name: nodered-data
|
|
persistentVolumeClaim:
|
|
claimName: nodered-data-pvc
|
|
---
|
|
# Service for Node-RED
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: node-red-service
|
|
labels:
|
|
app: node-red
|
|
spec:
|
|
selector:
|
|
app: node-red
|
|
ports:
|
|
- protocol: TCP
|
|
port: 1880
|
|
targetPort: 1880
|
|
type: ClusterIP # Or NodePort
|
|
---
|
|
# Persistent Volume Claim for Node-RED data
|
|
apiVersion: v1
|
|
kind: PersistentVolumeClaim
|
|
metadata:
|
|
name: nodered-data-pvc
|
|
spec:
|
|
accessModes:
|
|
- ReadWriteOnce
|
|
resources:
|
|
requests:
|
|
storage: 1Gi # Adjust as needed
|
|
---
|
|
# Deployment for Grafana
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: grafana-deployment
|
|
labels:
|
|
app: grafana
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: grafana
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: grafana
|
|
spec:
|
|
containers:
|
|
- name: grafana
|
|
image: grafana/grafana:latest
|
|
ports:
|
|
- containerPort: 3000
|
|
volumeMounts:
|
|
- name: grafana-data
|
|
mountPath: /var/lib/grafana
|
|
env:
|
|
- name: GF_SECURITY_ADMIN_USER
|
|
value: admin
|
|
- name: GF_SECURITY_ADMIN_PASSWORD
|
|
value: password # Change this! Use a real password.
|
|
volumes:
|
|
- name: grafana-data
|
|
persistentVolumeClaim:
|
|
claimName: grafana-data-pvc
|
|
---
|
|
# Service for Grafana
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: grafana-service
|
|
labels:
|
|
app: grafana
|
|
spec:
|
|
selector:
|
|
app: grafana
|
|
ports:
|
|
- protocol: TCP
|
|
port: 3000
|
|
targetPort: 3000
|
|
type: ClusterIP # Or NodePort
|
|
---
|
|
# Persistent Volume Claim for Grafana data
|
|
apiVersion: v1
|
|
kind: PersistentVolumeClaim
|
|
metadata:
|
|
name: grafana-data-pvc
|
|
spec:
|
|
accessModes:
|
|
- ReadWriteOnce
|
|
resources:
|
|
requests:
|
|
storage: 2Gi # Adjust as needed
|
|
---
|
|
# Deployment for MinIO (Object Storage)
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: minio-deployment
|
|
labels:
|
|
app: minio
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: minio
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: minio
|
|
spec:
|
|
containers:
|
|
- name: minio
|
|
image: minio/minio:latest
|
|
ports:
|
|
- containerPort: 9000
|
|
- containerPort: 9001
|
|
env:
|
|
- name: MINIO_ROOT_USER
|
|
value: minio
|
|
- name: MINIO_ROOT_PASSWORD
|
|
value: minio123 # Change this! Use a real password
|
|
volumeMounts:
|
|
- name: minio-data
|
|
mountPath: "/data"
|
|
command: ["server", "/data", "--console-address", ":9001"]
|
|
volumes:
|
|
- name: minio-data
|
|
persistentVolumeClaim:
|
|
claimName: minio-data-pvc
|
|
---
|
|
# Service for MinIO
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: minio-service
|
|
labels:
|
|
app: minio
|
|
spec:
|
|
selector:
|
|
app: minio
|
|
ports:
|
|
- name: minio-api
|
|
protocol: TCP
|
|
port: 9000
|
|
targetPort: 9000
|
|
- name: minio-console
|
|
protocol: TCP
|
|
port: 9001
|
|
targetPort: 9001
|
|
type: ClusterIP # Or NodePort
|
|
---
|
|
# Persistent Volume Claim for MinIO data
|
|
apiVersion: v1
|
|
kind: PersistentVolumeClaim
|
|
metadata:
|
|
name: minio-data-pvc
|
|
spec:
|
|
accessModes:
|
|
- ReadWriteOnce
|
|
resources:
|
|
requests:
|
|
storage: 10Gi # Adjust as needed
|
|
---
|
|
# Deployment for ReadTheDocs
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: readthedocs-deployment
|
|
labels:
|
|
app: readthedocs
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: readthedocs
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: readthedocs
|
|
spec:
|
|
containers:
|
|
- name: readthedocs
|
|
image: readthedocs/readthedocs:latest
|
|
ports:
|
|
- containerPort: 8000
|
|
volumeMounts:
|
|
- name: readthedocs-data
|
|
mountPath: /home/docs
|
|
env:
|
|
- name: DJANGO_SECRET_KEY
|
|
value: "my-secret-key" # Change this! Use a real secret key
|
|
- name: DATABASE_URL
|
|
value: "postgres://user:password@postgres:5432/readthedocs" # Update
|
|
volumes:
|
|
- name: readthedocs-data
|
|
persistentVolumeClaim:
|
|
claimName: readthedocs-data-pvc
|
|
---
|
|
# Service for ReadTheDocs
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: readthedocs-service
|
|
labels:
|
|
app: readthedocs
|
|
spec:
|
|
selector:
|
|
app: readthedocs
|
|
ports:
|
|
- protocol: TCP
|
|
port: 8000
|
|
targetPort: 8000
|
|
type: ClusterIP # Or NodePort
|
|
---
|
|
# Persistent Volume Claim for ReadTheDocs data
|
|
apiVersion: v1
|
|
kind: PersistentVolumeClaim
|
|
metadata:
|
|
name: readthedocs-data-pvc
|
|
spec:
|
|
accessModes:
|
|
- ReadWriteOnce
|
|
resources:
|
|
requests:
|
|
storage: 10Gi # Adjust as needed
|
|
---
|
|
# Nginx Reverse Proxy Deployment
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: nginx-reverse-proxy
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: nginx-reverse-proxy
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: nginx-reverse-proxy
|
|
spec:
|
|
containers:
|
|
- name: nginx
|
|
image: nginx:latest
|
|
ports:
|
|
- containerPort: 80
|
|
volumeMounts:
|
|
- name: nginx-config
|
|
mountPath: /etc/nginx/conf.d
|
|
volumes:
|
|
- name: nginx-config
|
|
configMap:
|
|
name: nginx-configmap
|
|
---
|
|
# Nginx Reverse Proxy Service
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: nginx-reverse-proxy-service
|
|
spec:
|
|
selector:
|
|
app: nginx-reverse-proxy
|
|
ports:
|
|
- port: 80
|
|
targetPort: 80
|
|
type: NodePort # Expose the service
|
|
---
|
|
# Nginx ConfigMap
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: nginx-configmap
|
|
data:
|
|
default.conf: |
|
|
server {
|
|
listen 80;
|
|
server_name grafana.local;
|
|
location / {
|
|
proxy_pass http://grafana-service:3000;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
}
|
|
server {
|
|
listen 80;
|
|
server_name nodered.local;
|
|
location / {
|
|
proxy_pass http://node-red-service:1880;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
}
|
|
server {
|
|
listen 80;
|
|
server_name docs.local;
|
|
location / {
|
|
proxy_pass http://readthedocs-service:8000;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
}
|
|
\end{lstlisting}
|
|
|
|
\subsection*{A.3 ReadTheDocs Configuration}
|
|
|
|
ReadTheDocs uses a configuration file, typically named `.readthedocs.yaml`, to define how your documentation is built. This file should be located in the root of your Git repository. Here's a basic example:
|
|
|
|
\begin{lstlisting}[language=Bash]
|
|
# .readthedocs.yaml
|
|
version: 2.0
|
|
build:
|
|
os: ubuntu-22.04
|
|
tools:
|
|
python: "3.11"
|
|
apt_packages:
|
|
- libffi-dev
|
|
- zlib1g-dev
|
|
python:
|
|
install:
|
|
- requirements: docs/requirements.txt
|
|
system_dependencies:
|
|
- pkg: libpq-dev
|
|
version: ">=12"
|
|
sphinx:
|
|
configuration: docs/conf.py
|
|
builder: html
|
|
fail_on_warning: false
|
|
formats:
|
|
- pdf
|
|
- epub
|
|
- htmlzip
|
|
\end{lstlisting}
|
|
|
|
This configuration does the following:
|
|
\begin{itemize}
|
|
\item Specifies Read the Docs configuration schema version.
|
|
\item Sets the operating system.
|
|
\item Sets the Python version.
|
|
\item Installs OS-level dependencies.
|
|
\item Installs Python dependencies from a requirements file.
|
|
\item Specifies the location of your Sphinx configuration file.
|
|
\item Builds documentation.
|
|
\item Configures the output formats.
|
|
|
|
\end{itemize}
|
|
%\end{document}
|