Files
scadalink-design/docs/deployment/installation-guide.md
Joseph Doherty b659978764 Phase 8: Production readiness — failover tests, security hardening, sandboxing, deployment docs
- WP-1-3: Central/site failover + dual-node recovery tests (17 tests)
- WP-4: Performance testing framework for target scale (7 tests)
- WP-5: Security hardening (LDAPS, JWT key length, no secrets in logs) (11 tests)
- WP-6: Script sandboxing adversarial tests (28 tests, all forbidden APIs)
- WP-7: Recovery drill test scaffolds (5 tests)
- WP-8: Observability validation (structured logs, correlation IDs, metrics) (6 tests)
- WP-9: Message contract compatibility (forward/backward compat) (18 tests)
- WP-10: Deployment packaging (installation guide, production checklist, topology)
- WP-11: Operational runbooks (failover, troubleshooting, maintenance)
92 new tests, all passing. Zero warnings.
2026-03-16 22:12:31 -04:00

5.7 KiB

ScadaLink Installation Guide

Prerequisites

  • Windows Server 2019 or later
  • .NET 10.0 Runtime
  • SQL Server 2019+ (Central nodes only)
  • Network connectivity between all cluster nodes (TCP ports 8081-8082)
  • LDAP/Active Directory server accessible from Central nodes
  • SMTP server accessible from all nodes (for Notification Service)

Single Binary Deployment

ScadaLink ships as a single executable (ScadaLink.Host.exe) that runs in either Central or Site role based on configuration.

Windows Service Installation

# Central Node
sc.exe create "ScadaLink-Central" binPath="C:\ScadaLink\ScadaLink.Host.exe" start=auto
sc.exe description "ScadaLink-Central" "ScadaLink SCADA Central Hub"

# Site Node
sc.exe create "ScadaLink-Site" binPath="C:\ScadaLink\ScadaLink.Host.exe" start=auto
sc.exe description "ScadaLink-Site" "ScadaLink SCADA Site Agent"

Directory Structure

C:\ScadaLink\
  ScadaLink.Host.exe
  appsettings.json
  appsettings.Production.json
  data\                          # Site: SQLite databases
    site.db                      # Deployed configs, static overrides
    store-and-forward.db         # S&F message buffer
  logs\                          # Rolling log files
    scadalink-20260316.log

Configuration Templates

Central Node — appsettings.json

{
  "ScadaLink": {
    "Node": {
      "Role": "Central",
      "NodeHostname": "central-01.example.com",
      "RemotingPort": 8081
    },
    "Cluster": {
      "SeedNodes": [
        "akka.tcp://scadalink@central-01.example.com:8081",
        "akka.tcp://scadalink@central-02.example.com:8081"
      ]
    },
    "Database": {
      "ConfigurationDb": "Server=sqlserver.example.com;Database=ScadaLink;User Id=scadalink_svc;Password=<CHANGE_ME>;Encrypt=true;TrustServerCertificate=false",
      "MachineDataDb": "Server=sqlserver.example.com;Database=ScadaLink_MachineData;User Id=scadalink_svc;Password=<CHANGE_ME>;Encrypt=true;TrustServerCertificate=false"
    },
    "Security": {
      "LdapServer": "ldap.example.com",
      "LdapPort": 636,
      "LdapUseTls": true,
      "AllowInsecureLdap": false,
      "LdapSearchBase": "dc=example,dc=com",
      "JwtSigningKey": "<GENERATE_A_32_PLUS_CHAR_RANDOM_STRING>",
      "JwtExpiryMinutes": 15,
      "IdleTimeoutMinutes": 30
    },
    "HealthMonitoring": {
      "ReportInterval": "00:00:30",
      "OfflineTimeout": "00:01:00"
    },
    "Logging": {
      "MinimumLevel": "Information"
    }
  },
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "Akka": "Warning"
      }
    }
  }
}

Site Node — appsettings.json

{
  "ScadaLink": {
    "Node": {
      "Role": "Site",
      "NodeHostname": "site-01-node-a.example.com",
      "SiteId": "plant-north",
      "RemotingPort": 8081
    },
    "Cluster": {
      "SeedNodes": [
        "akka.tcp://scadalink@site-01-node-a.example.com:8081",
        "akka.tcp://scadalink@site-01-node-b.example.com:8081"
      ]
    },
    "Database": {
      "SiteDbPath": "C:\\ScadaLink\\data\\site.db"
    },
    "DataConnection": {
      "ReconnectInterval": "00:00:05",
      "TagResolutionRetryInterval": "00:00:30"
    },
    "StoreAndForward": {
      "SqliteDbPath": "C:\\ScadaLink\\data\\store-and-forward.db",
      "DefaultRetryInterval": "00:00:30",
      "DefaultMaxRetries": 50,
      "ReplicationEnabled": true
    },
    "SiteRuntime": {
      "ScriptTimeoutSeconds": 30,
      "StaggeredStartupDelayMs": 50
    },
    "SiteEventLog": {
      "RetentionDays": 30,
      "MaxStorageMB": 1024,
      "PurgeIntervalHours": 24
    },
    "Communication": {
      "CentralSeedNode": "akka.tcp://scadalink@central-01.example.com:8081"
    },
    "HealthMonitoring": {
      "ReportInterval": "00:00:30"
    },
    "Logging": {
      "MinimumLevel": "Information"
    }
  }
}

Database Setup (Central Only)

SQL Server

  1. Create the configuration database:
CREATE DATABASE ScadaLink;
CREATE LOGIN scadalink_svc WITH PASSWORD = '<STRONG_PASSWORD>';
USE ScadaLink;
CREATE USER scadalink_svc FOR LOGIN scadalink_svc;
ALTER ROLE db_owner ADD MEMBER scadalink_svc;
  1. Create the machine data database:
CREATE DATABASE ScadaLink_MachineData;
USE ScadaLink_MachineData;
CREATE USER scadalink_svc FOR LOGIN scadalink_svc;
ALTER ROLE db_owner ADD MEMBER scadalink_svc;
  1. Apply EF Core migrations (development):

    • Migrations auto-apply on startup in Development environment.
  2. Apply EF Core migrations (production):

    • Generate SQL script: dotnet ef migrations script --project src/ScadaLink.ConfigurationDatabase
    • Review and execute the SQL script against the production database.

Network Requirements

Source Destination Port Protocol Purpose
Central A Central B 8081 TCP Akka.NET remoting
Site A Site B 8081 TCP Akka.NET remoting
Site nodes Central nodes 8081 TCP Central-site communication
Central nodes LDAP server 636 TCP/TLS Authentication
All nodes SMTP server 587 TCP/TLS Notification delivery
Central nodes SQL Server 1433 TCP Configuration database
Users Central nodes 443 HTTPS Blazor Server UI

Firewall Rules

Ensure bidirectional TCP connectivity between all Akka.NET cluster peers. The remoting port (default 8081) must be open in both directions.

Post-Installation Verification

  1. Start the service: sc.exe start ScadaLink-Central
  2. Check the log file: type C:\ScadaLink\logs\scadalink-*.log
  3. Verify the readiness endpoint: curl http://localhost:5000/health/ready
  4. For Central: verify the UI is accessible at https://central-01.example.com/