diff --git a/front/plugins/node_sync/.gitignore b/front/plugins/node_sync/.gitignore
deleted file mode 100644
index 817dbd13..00000000
--- a/front/plugins/node_sync/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-front/plugins/node_sync/
\ No newline at end of file
diff --git a/front/plugins/node_sync/README.md b/front/plugins/node_sync/README.md
new file mode 100755
index 00000000..b6e106be
--- /dev/null
+++ b/front/plugins/node_sync/README.md
@@ -0,0 +1,13 @@
+## Overview
+
+A simple setting-based plugin for setting the password.
+
+### Usage
+
+- Head to **Settings** > **Set Password** to adjust the default values.
+
+### Notes
+
+- The default password is 123456.
+- When enabled a login dialog is displayed. If facing issues, you can always disable the login by setting SETPWD_enable_password=False in your app.conf file.
+- SHA256 hash is used
\ No newline at end of file
diff --git a/front/plugins/node_sync/config.json b/front/plugins/node_sync/config.json
new file mode 100755
index 00000000..ac5736be
--- /dev/null
+++ b/front/plugins/node_sync/config.json
@@ -0,0 +1,259 @@
+{
+ "code_name": "node_sync",
+ "template_type": "database-entry",
+ "unique_prefix": "NODESYNC",
+ "plugin_type": "system",
+ "enabled": true,
+ "data_source": "template",
+ "show_ui": false,
+ "localized": ["display_name", "description", "icon"],
+ "display_name": [{
+ "language_code": "en_us",
+ "string": "Node synchronization"
+ }],
+ "description": [{
+ "language_code": "en_us",
+ "string": "Plugin to synchronize multiple NetAlertX instances."
+ }],
+ "icon": [
+ {
+ "language_code": "en_us",
+ "string": ""
+ }
+ ],
+ "params" : [
+ {
+ "name" : "password",
+ "type" : "setting",
+ "value" : "SETPWD_password"
+ }
+ ],
+ "settings":[
+ {
+ "function": "enable",
+ "type": "boolean",
+ "default_value": false,
+ "options": [],
+ "localized": ["name", "description"],
+ "name": [
+ {
+ "language_code": "en_us",
+ "string": "Enable login"
+ }
+ ],
+ "description": [
+ {
+ "language_code": "en_us",
+ "string": "When enabled a login dialog is displayed. If facing issues, you can always disable the login by setting SETPWD_enable_password=False in your app.conf file."
+ }
+ ]
+ },
+ {
+ "function": "plugins",
+ "type": "text.multiselect",
+ "maxLength": 50,
+ "default_value": [
+ ],
+ "options": ["{value}"],
+ "options_params" : [
+ {
+ "name" : "value",
+ "type" : "setting",
+ "value" : "LOADED_PLUGINS"
+ }
+ ],
+ "localized": ["name", "description"],
+ "name": [
+ {
+ "language_code": "en_us",
+ "string": "Plugins"
+ }
+ ],
+ "description": [
+ {
+ "language_code": "en_us",
+ "string": "Plugins to synchronize. Only plugins that produce some kind of output in last_result.log can be synchronized."
+ }
+ ]
+ },
+ {
+ "function": "target_url",
+ "type": "text",
+ "maxLength": 50,
+ "default_value": "",
+ "options": [],
+ "localized": ["name", "description"],
+ "name": [
+ {
+ "language_code": "en_us",
+ "string": "Target URL"
+ }
+ ],
+ "description": [
+ {
+ "language_code": "en_us",
+ "string": "Target URL to send the data to."
+ }
+ ]
+ },
+ {
+ "function": "password",
+ "type": "password.SHA256",
+ "maxLength": 50,
+ "default_value": "",
+ "options": [],
+ "localized": ["name", "description"],
+ "name": [
+ {
+ "language_code": "en_us",
+ "string": "Password"
+ },
+ {
+ "language_code": "es_es",
+ "string": "Contraseña"
+ }
+ ],
+ "description": [
+ {
+ "language_code": "en_us",
+ "string": "The password "
+ }
+ ]
+ },{
+ "function": "RUN",
+ "events": ["run"],
+ "type": "text.select",
+ "default_value":"schedule",
+ "options": ["disabled", "once", "schedule", "always_after_scan", "on_new_device"],
+ "localized": ["name", "description"],
+ "name" :[{
+ "language_code":"en_us",
+ "string" : "When to run"
+ },
+ {
+ "language_code":"es_es",
+ "string" : "Cuándo ejecutar"
+ },
+ {
+ "language_code":"de_de",
+ "string" : "Wann laufen"
+ }],
+ "description": [{
+ "language_code":"en_us",
+ "string" : "When the backup should be created. A daily or weekly SCHEDULE is a good option."
+ },
+ {
+ "language_code":"es_es",
+ "string" : "Cuándo se debe crear la copia de seguridad. Un SCHEDULE diario o semanal es una buena opción."
+ },
+ {
+ "language_code":"de_de",
+ "string" : "Wann das Backup erstellt werden soll. Ein täglicher oder wöchentlicher SCHEDULE ist eine gute Option."
+ }]
+},
+ {
+ "function": "CMD",
+ "type": "readonly",
+ "default_value": "python3 /app/front/plugins/csv_backup/script.py overwrite={overwrite} location={location}",
+ "options": [],
+ "localized": ["name", "description"],
+ "name": [
+ {
+ "language_code": "en_us",
+ "string": "Command"
+ },
+ {
+ "language_code": "es_es",
+ "string": "Comando"
+ },
+ {
+ "language_code": "de_de",
+ "string": "Befehl"
+ }
+ ],
+ "description": [
+ {
+ "language_code": "en_us",
+ "string": "Command to run. This can not be changed"
+ },
+ {
+ "language_code": "es_es",
+ "string": "Comando a ejecutar. Esto no se puede cambiar"
+ },
+ {
+ "language_code": "de_de",
+ "string": "Befehl zum Ausführen. Dies kann nicht geändert werden"
+ }
+ ]
+ },
+ {
+ "function": "RUN_SCHD",
+ "type": "text",
+ "default_value":"0 2 * * 3",
+ "options": [],
+ "localized": ["name", "description"],
+ "name" : [{
+ "language_code":"en_us",
+ "string" : "Schedule"
+ },
+ {
+ "language_code":"es_es",
+ "string" : "Schedule"
+ },
+ {
+ "language_code":"de_de",
+ "string" : "Schedule"
+ }],
+ "description": [{
+ "language_code":"en_us",
+ "string" : "Only enabled if you select schedule in the CSVBCKP_RUN setting. Make sure you enter the schedule in the correct cron-like format (e.g. validate at crontab.guru). For example entering 0 4 * * * will run the scan after 4 am in the TIMEZONE you set above. Will be run NEXT time the time passes."
+ },
+ {
+ "language_code":"es_es",
+ "string" : "Solo está habilitado si selecciona schedule en la configuración CSVBCKP_RUN. Asegúrese de ingresar la programación en el formato similar a cron correcto (por ejemplo, valide en crontab.guru). Por ejemplo, ingresar 0 4 * * * ejecutará el escaneo después de las 4 a.m. en el TIMEZONE código> que configuró arriba. Se ejecutará la PRÓXIMA vez que pase el tiempo."
+ },
+ {
+ "language_code":"de_de",
+ "string" : "Nur aktiviert, wenn Sie schedule in der CSVBCKP_RUN-Einstellung auswählen. Stellen Sie sicher, dass Sie den Zeitplan im richtigen Cron-ähnlichen Format eingeben (z. B. validieren unter crontab.guru). Wenn Sie beispielsweise 0 4 * * * eingeben, wird der Scan nach 4 Uhr morgens in der TIMEZONE ausgeführt. Code> den Sie oben festgelegt haben. Wird das NÄCHSTE Mal ausgeführt, wenn die Zeit vergeht."
+ }]
+ },
+ {
+ "function": "RUN_TIMEOUT",
+ "type": "integer",
+ "default_value": 30,
+ "options": [],
+ "localized": ["name", "description"],
+ "name": [
+ {
+ "language_code": "en_us",
+ "string": "Run timeout"
+ },
+ {
+ "language_code": "es_es",
+ "string": "Tiempo límite de ejecución"
+ },
+ {
+ "language_code": "de_de",
+ "string": "Zeitüberschreitung"
+ }
+ ],
+ "description": [
+ {
+ "language_code": "en_us",
+ "string": "Maximum time in seconds to wait for the script to finish. If this time is exceeded the script is aborted."
+ },
+ {
+ "language_code": "es_es",
+ "string": "Tiempo máximo en segundos para esperar a que finalice el script. Si se supera este tiempo, el script se cancela."
+ },
+ {
+ "language_code": "de_de",
+ "string": "Maximale Zeit in Sekunden, die auf den Abschluss des Skripts gewartet werden soll. Bei Überschreitung dieser Zeit wird das Skript abgebrochen."
+ }
+ ]
+ }
+
+
+ ]
+
+ }
diff --git a/front/plugins/node_sync/ignore_plugin b/front/plugins/node_sync/ignore_plugin
new file mode 100755
index 00000000..e69de29b
diff --git a/front/plugins/node_sync/script.py b/front/plugins/node_sync/script.py
new file mode 100755
index 00000000..97ef2081
--- /dev/null
+++ b/front/plugins/node_sync/script.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+
+import os
+import pathlib
+import argparse
+import sys
+import hashlib
+import csv
+import sqlite3
+from io import StringIO
+from datetime import datetime
+
+# Register NetAlertX directories
+INSTALL_PATH="/app"
+sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
+
+from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64
+from logger import mylog, append_line_to_file
+from helper import timeNowTZ
+from const import logPath, applicationPath, fullDbPath
+
+
+CUR_PATH = str(pathlib.Path(__file__).parent.resolve())
+LOG_FILE = os.path.join(CUR_PATH, 'script.log')
+RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log')
+
+pluginName = 'NODESYNC'
+
+def main():
+
+ # the script expects a parameter in the format of devices=device1,device2,...
+ parser = argparse.ArgumentParser(description='Export devices data to CSV')
+ parser.add_argument('overwrite', action="store", help="Specify 'TRUE' to overwrite an existing file, or 'FALSE' to create a new file")
+ parser.add_argument('location', action="store", help="The directory where the CSV file will be saved")
+ values = parser.parse_args()
+
+ overwrite = values.overwrite.split('=')[1]
+
+ if (overwrite.upper() == "TRUE"):
+ overwrite = True
+ else:
+ overwrite = False
+
+ mylog('verbose', [f'[{pluginName}] In script'])
+
+ # Connect to the App database
+ conn = sqlite3.connect(fullDbPath)
+ cursor = conn.cursor()
+
+ # Execute your SQL query
+ cursor.execute("SELECT * FROM Devices")
+
+ # Get column names
+ columns = [desc[0] for desc in cursor.description]
+
+ if overwrite:
+ filename = 'devices.csv'
+ else:
+ timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
+ filename = f'devices_{timestamp}.csv'
+
+ fullPath = os.path.join(values.location.split('=')[1], filename)
+
+ mylog('verbose', ['[CSVBCKP] Writing file ', fullPath])
+
+ # Create a CSV file in the specified location
+ with open(fullPath, 'w', newline='') as csvfile:
+ # Initialize the CSV writer
+ csv_writer = csv.writer(csvfile, delimiter=',', quoting=csv.QUOTE_MINIMAL)
+
+ # Wrap the header values in double quotes and write the header row
+ csv_writer.writerow([ '"' + col + '"' for col in columns])
+
+ # Fetch and write data rows
+ for row in cursor.fetchall():
+ # Wrap each value in double quotes and write the row
+ csv_writer.writerow(['"' + str(value) + '"' for value in row])
+
+ # Close the database connection
+ conn.close()
+
+ # Open the CSV file for reading
+ with open(fullPath, 'r') as file:
+ data = file.read()
+
+ # Replace all occurrences of """ with "
+ data = data.replace('"""', '"')
+
+ # Open the CSV file for writing
+ with open(fullPath, 'w') as file:
+ file.write(data)
+
+ return 0
+
+
+#===============================================================================
+# BEGIN
+#===============================================================================
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/front/plugins/node_sync/server.php b/front/plugins/node_sync/server.php
new file mode 100755
index 00000000..e69de29b