# 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

```powershell
# 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`

```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`

```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:
```sql
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;
```

2. Create the machine data database:
```sql
CREATE DATABASE ScadaLink_MachineData;
USE ScadaLink_MachineData;
CREATE USER scadalink_svc FOR LOGIN scadalink_svc;
ALTER ROLE db_owner ADD MEMBER scadalink_svc;
```

3. Apply EF Core migrations (development):
   - Migrations auto-apply on startup in Development environment.

4. 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/`
