# Configuration

> How-to guide: Configure the server: application, certificate, server endpoints and network binding, data transfer limits, and XML configuration.

> This content was machine translated and may contain errors. [Read in German](https://www.traeger.de/docs/development/opcua/server/configuration)

**Sample applications:**

- Server.ConfiguredViaCode ([C#](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/cs/Configuration/Server.ConfiguredViaCode), [VB.NET](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/vb/Configuration/Server.ConfiguredViaCode)): This sample demonstrates how to configure an OPC UA server using in code configuration.
- Server.ConfiguredViaXml ([C#](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/cs/Configuration/Server.ConfiguredViaXml), [VB.NET](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/vb/Configuration/Server.ConfiguredViaXml)): This sample demonstrates how to configure an OPC UA server using a XML configuration file.

## Configure the application

Types used: `OpcServer`, `OpcApplicationConfiguration`, `OpcCertificateStores`, `OpcCertificateStoreInfo`

All code snippets on this page configure the server in code, unless they work with the default configuration of the server. The `OpcServer` instance is the central place for configuring the server application. The server's `Security` property provides the security settings as an instance of the `OpcServerSecurity` class. The `CertificateStores` property provides the certificate store settings as an instance of the `OpcCertificateStores` class.

If the server should also be configurable through XML, load its configuration from an XML file. The section [Configuration through an XML file](https://www.traeger.de/en/docs/development/opcua/server/configuration#configuration-through-an-xml-file) shows how the file is structured. To load the settings:

**Load the configuration file by the name of the configuration**: The `LoadServerConfig` method looks for the file `<Name>.Config.xml` in the working directory of the application, in the following example `Opc.UaFx.Server.Config.xml`.

```csharp
server.Configuration = OpcApplicationConfiguration.LoadServerConfig("Opc.UaFx.Server");

```

```vbnet
server.Configuration = OpcApplicationConfiguration.LoadServerConfig("Opc.UaFx.Server")

```

**Load the configuration file by the path to the XML file**: If the file is missing or cannot be read, `LoadServerConfig` and `LoadServerConfigFile` do not throw an exception but return `null`. If you assign this value to the `Configuration` property, the server silently starts with its default configuration. Check the return value:

```csharp
var configuration = OpcApplicationConfiguration.LoadServerConfigFile(
        "MyServerAppNameConfig.xml");
 
// The method returns a null reference in case the file could not be loaded.
if (configuration == null)
    throw new InvalidOperationException("The server configuration could not be loaded.");
 
server.Configuration = configuration;

```

```vbnet
Dim configuration = OpcApplicationConfiguration.LoadServerConfigFile( _
        "MyServerAppNameConfig.xml")

'The method returns a null reference in case the file could not be loaded.
If configuration Is Nothing Then
    Throw New InvalidOperationException("The server configuration could not be loaded.")
End If

server.Configuration = configuration
```

You can configure the server application in the following ways, among others:

**Configure the application** (in code): If you set no `ApplicationName`, the server uses the value of the `AssemblyTitle` attribute, alternatively that of the `AssemblyProduct` attribute, and otherwise `OPC Application`. At startup, the server takes the `ApplicationUri` from the Subject Alternative Name of its application certificate and overrides a value set in code. It uses the value from the code only when it creates a new certificate:

```csharp
// Default: Value of AssemblyTitleAttribute of entry assembly.
server.ApplicationName = "MyServerAppName";
 
// Default: A null reference to use the URI of the application certificate.
// The value is used to create a new application certificate.
server.ApplicationUri = new Uri("urn:localhost:MyServerAppName");
```

```vbnet
'Default: Value of AssemblyTitleAttribute of entry assembly.
server.ApplicationName = "MyServerAppName"

'Default: A null reference to use the URI of the application certificate.
'The value is used to create a new application certificate.
server.ApplicationUri = New Uri("urn:localhost:MyServerAppName")
```

In XML (below the `OpcApplicationConfiguration` element):

```xml
<ApplicationName>MyServerAppName</ApplicationName>
<ApplicationUri>urn:localhost:MyServerAppName</ApplicationUri>
```

**Configure the certificate stores** (in code): By default, the certificate stores are in the `CertificateStores` folder in the application directory. The application certificate is in `CertificateStores\App`, rejected certificates are in `CertificateStores\Rejected`, and trusted certificates and issuers are in `CertificateStores\Trusted`. If the application directory is not writable, the server uses `%ProgramData%\OPC Foundation\CertificateStores` or `%AppData%\OPC Foundation\CertificateStores` instead. The `OpcCertificateStores.PathProbings` property defines which paths the server checks and in which order:

```csharp
// Default: ".\CertificateStores\App"
server.CertificateStores.ApplicationStore.Path
        = @"%LocalApplicationData%\MyServerAppName\App Certificates";
 
// Default: ".\CertificateStores\Rejected"
server.CertificateStores.RejectedStore.Path
        = @"%LocalApplicationData%\MyServerAppName\Rejected Certificates";
 
// Default: ".\CertificateStores\Trusted"
server.CertificateStores.TrustedIssuerStore.Path
        = @"%LocalApplicationData%\MyServerAppName\Trusted Issuer Certificates";
 
// Default: ".\CertificateStores\Trusted"
server.CertificateStores.TrustedPeerStore.Path
        = @"%LocalApplicationData%\MyServerAppName\Trusted Peer Certificates";
```

```vbnet
'Default: ".\CertificateStores\App"
server.CertificateStores.ApplicationStore.Path _
        = "%LocalApplicationData%\MyServerAppName\App Certificates"

'Default: ".\CertificateStores\Rejected"
server.CertificateStores.RejectedStore.Path _
        = "%LocalApplicationData%\MyServerAppName\Rejected Certificates"

'Default: ".\CertificateStores\Trusted"
server.CertificateStores.TrustedIssuerStore.Path _
        = "%LocalApplicationData%\MyServerAppName\Trusted Issuer Certificates"

'Default: ".\CertificateStores\Trusted"
server.CertificateStores.TrustedPeerStore.Path _
        = "%LocalApplicationData%\MyServerAppName\Trusted Peer Certificates"
```

In XML (below the `OpcApplicationConfiguration` element):

```xml
<SecurityConfiguration>
  <ApplicationCertificate>
    <StoreType>Directory</StoreType>
    <StorePath>%LocalApplicationData%\MyServerAppName\CertificateStores\App Certificates</StorePath>
    <SubjectName>MyServerAppName</SubjectName>
  </ApplicationCertificate>

  <RejectedCertificateStore>
    <StoreType>Directory</StoreType>
    <StorePath>%LocalApplicationData%\MyServerAppName\CertificateStores\Rejected Certificates</StorePath>
  </RejectedCertificateStore>

  <TrustedIssuerCertificates>
    <StoreType>Directory</StoreType>
    <StorePath>%LocalApplicationData%\MyServerAppName\CertificateStores\Trusted Issuer Certificates</StorePath>
  </TrustedIssuerCertificates>

  <TrustedPeerCertificates>
    <StoreType>Directory</StoreType>
    <StorePath>%LocalApplicationData%\MyServerAppName\CertificateStores\Trusted Peer Certificates</StorePath>
  </TrustedPeerCertificates>
</SecurityConfiguration>
```

**Product information of the server**: Clients see the manufacturer, product name, and version in the status information of the server (BuildInfo). The server determines them from the entry assembly of the application: the manufacturer from `AssemblyCompany`, the product name from `AssemblyTitle`, and the version from `AssemblyVersion`. If `ApplicationName` is set, the server uses this value as the product name instead. To retrieve the information, call `GetInfo`:

```csharp
OpcServerInfo info = server.GetInfo();
 
Console.WriteLine("{0} {1} {2}", info.CompanyName, info.ProductName, info.ProductVersion);
Console.WriteLine("Product URI: {0}", info.ProductUri);
```

```vbnet
Dim info As OpcServerInfo = server.GetInfo()

Console.WriteLine("{0} {1} {2}", info.CompanyName, info.ProductName, info.ProductVersion)
Console.WriteLine("Product URI: {0}", info.ProductUri)
```

```csharp
[assembly: AssemblyCompany("Example Machines Ltd.")]
[assembly: AssemblyTitle("Example Machine Server")]
[assembly: AssemblyVersion("1.2.0.0")]
```

```vbnet
<Assembly: AssemblyCompany("Example Machines Ltd.")>
<Assembly: AssemblyTitle("Example Machine Server")>
<Assembly: AssemblyVersion("1.2.0.0")>
```

If the information should not come from the assembly, for example to also provide a product URI, override the `GetInfoCore` method in a derived server class:

```csharp
public class MachineServer : OpcServer
{
    public MachineServer()
        : base("opc.tcp://localhost:4840/")
    {
    }
 
    protected override OpcServerInfo GetInfoCore()
    {
        return new OpcServerInfo(
                companyName: "Example Machines Ltd.",
                productName: "Example Machine Server",
                productVersion: new Version(1, 2, 0, 0),
                buildDate: new DateTime(2026, 1, 15),
                productUri: new Uri("urn:example:machine-server"));
    }
}
```

```vbnet
Public Class MachineServer
    Inherits OpcServer

    Public Sub New()
        MyBase.New("opc.tcp://localhost:4840/")
    End Sub

    Protected Overrides Function GetInfoCore() As OpcServerInfo
        Return New OpcServerInfo( _
                companyName:="Example Machines Ltd.", _
                productName:="Example Machine Server", _
                productVersion:=New Version(1, 2, 0, 0), _
                buildDate:=New DateTime(2026, 1, 15), _
                productUri:=New Uri("urn:example:machine-server"))
    End Function
End Class

```

## Application certificate

Types used: `OpcServer`, `OpcCertificateManager`, `OpcCertificateSettings`, `OpcServerSecurity`, `OpcCertificateStores`, `OpcCertificateStoreInfo`

The OPC UA .NET SDK loads certificates of the types `.der` and `.cer` (public part only) as well as `.pfx` and `.p12` (with private key). If the server should provide a secure endpoint, the certificate must have a private key. A secure endpoint uses the `OpcSecurityMode` `Sign` or `SignAndEncrypt`.

**1.** To load an **existing certificate** from any path:

```csharp
var certificate = OpcCertificateManager.LoadCertificate("MyServerCertificate.pfx");
```

```vbnet
Dim certificate = OpcCertificateManager.LoadCertificate("MyServerCertificate.pfx")
```

To load a password-protected certificate, pass the password:

```csharp
var certificate = OpcCertificateManager.LoadCertificate(
        "MyServerCertificate.pfx",
        password: "password");
```

```vbnet
Dim certificate = OpcCertificateManager.LoadCertificate( _
        "MyServerCertificate.pfx", _
        password:="password")
```

**2.** To create a **new certificate** in memory:

```csharp
var certificate = OpcCertificateManager.CreateCertificate(server);

```

```vbnet
certificate = OpcCertificateManager.CreateCertificate(server)

```

To set properties of the certificate, use the `OpcCertificateSettings` class. These include, for example, the validity in months (600 by default), the `ApplicationUri`, or the names of the domains under which the server is reachable. The `Organization` property adds the organization (O) to the subject of the certificate, unless you set a `SubjectName` of your own:

```csharp
// Lifetime in months, default: 600.
var settings = new OpcCertificateSettings("MyServerAppName") {
    ApplicationUri = new Uri("urn:localhost:MyServerAppName"),
    Lifetime = 60
};
 
settings.DomainNames.Add("localhost");
 
var certificate = OpcCertificateManager.CreateCertificate(settings);
```

```vbnet
'Lifetime in months, default: 600.
Dim settings = New OpcCertificateSettings("MyServerAppName") With { _
    .ApplicationUri = New Uri("urn:localhost:MyServerAppName"), _
    .Lifetime = 60 _
}

settings.DomainNames.Add("localhost")

Dim certificate = OpcCertificateManager.CreateCertificate(settings)
```

A certificate that the SDK creates for the server by itself names the manufacturer from the product information of the server as the organization. It also contains the fully qualified domain name of the machine if DNS resolves it.

**3.** To save the certificate to any path:

```csharp
OpcCertificateManager.SaveCertificate("MyServerCertificate.pfx", certificate);

```

```vbnet
OpcCertificateManager.SaveCertificate("MyServerCertificate.pfx", certificate)

```

**4.** Set the server certificate:

```csharp
server.Certificate = certificate;

```

```vbnet
server.Certificate = certificate

```

**5.** The certificate must be stored in the certificate store for **application certificates** (`ApplicationStore`):

```csharp
if (!server.CertificateStores.ApplicationStore.Contains(certificate))
    server.CertificateStores.ApplicationStore.Add(certificate);

```

```vbnet
If Not server.CertificateStores.ApplicationStore.Contains(certificate) Then
    server.CertificateStores.ApplicationStore.Add(certificate)
End If

```

**6.** If you set **no certificate**, the server looks in the `ApplicationStore` for a certificate whose name matches the `ApplicationName`. Before that, it raises the `CertificateRequested` event, through which the application can provide a certificate itself. If the server finds no certificate, by default it automatically creates and uses a new certificate. Up to version 2.58, this also applies to an invalid certificate. As of version 2.59, the server keeps an existing but invalid certificate and raises the `CertificateRequested` event with the reason (see [Protect your own certificate](https://www.traeger.de/en/docs/development/opcua/security/server#protect-your-own-certificate)). If that fails as well, the server uses a temporary certificate in memory. If the server should use only the specified certificate, turn off this feature. To do so, set the `AutoCreateCertificate` property to `false`:

```csharp
server.CertificateStores.AutoCreateCertificate = false;

```

```vbnet
server.CertificateStores.AutoCreateCertificate = False

```

The [Secure servers](https://www.traeger.de/en/docs/development/opcua/security/server) page describes how the server manages user identities, validates client certificates, and secures its endpoints and network interfaces. It also explains how to harden the server for production.

## Endpoints

Types used: `OpcServer`, `OpcServerSecurity`, `OpcSecurityPolicy`, `OpcSecurityMode`, `OpcSecurityAlgorithm`

The endpoints of the server result from the cross product of the base addresses in use and the security policies configured for endpoints. A base address consists of a supported pair of scheme and port plus the host (IP address or DNS name). For data exchange, you can define several schemes on different ports. The supported schemes are `opc.tcp` and `https`. The server rejects other schemes with an `ArgumentException`.

By default, the server uses no particular policy to provide a secure endpoint. As a result, there are exactly as many endpoints as base addresses. If a server defines exactly one base address, there is only one endpoint with this base address and the security policy with the mode `None`. With n different base addresses, there are likewise only n different endpoints with the same security policy. With only one particular security policy, there are still n endpoints, all with exactly this policy. With m different security policies (s<sub>1</sub> to s<sub>m</sub>) and n different base addresses (b<sub>1</sub> to b<sub>n</sub>), each pairing of policy and base address results in one endpoint: s<sub>1</sub>+b<sub>1</sub>, s<sub>1</sub>+b<sub>2</sub> to s<sub>1</sub>+b<sub>n</sub>, then s<sub>2</sub>+b<sub>1</sub> to s<sub>2</sub>+b<sub>n</sub>, and so on up to s<sub>m</sub>+b<sub>n</sub>.

Besides the mode for securing the communication (security mode), the security policy of an endpoint defines a security algorithm and a level. According to the OPC Foundation, the level is a relative measure of the security mechanisms an endpoint uses. By definition, an endpoint with a higher level is therefore more secure than an endpoint with a lower level. However, this is only a guideline that nobody checks or enforces. The SDK calculates the level from the mode and the algorithm (`OpcSecurityPolicy.Level` property).

For example, if a server uses two security policies, they could be defined as follows:

- Security policy A: Level=0, Security-Mode=None, Security-Algorithm=None
- Security policy B: Level=1, Security-Mode=Sign, Security-Algorithm=Basic256Sha256

In addition, there are, for example, three base addresses for different schemes:

- Base address A: `"https://mydomain.com/"`
- Base address B: `"opc.tcp://192.168.0.123:4840/"`
- Base address C: `"opc.tcp://192.168.0.123:12345/"`

The cross product results in the following endpoint descriptions:

- Endpoint 1: Address=`"https://mydomain.com/"`, Level=0, Security-Mode=None, Security-Algorithm=None
- Endpoint 2: Address=`"https://mydomain.com/"`, Level=1, Security-Mode=Sign, Security-Algorithm=Basic256Sha256
- Endpoint 3: Address=`"opc.tcp://192.168.0.123:4840/"`, Level=0, Security-Mode=None, Security-Algorithm=None
- Endpoint 4: Address=`"opc.tcp://192.168.0.123:4840/"`, Level=1, Security-Mode=Sign, Security-Algorithm=Basic256Sha256
- Endpoint 5: Address=`"opc.tcp://192.168.0.123:12345/"`, Level=0, Security-Mode=None, Security-Algorithm=None
- Endpoint 6: Address=`"opc.tcp://192.168.0.123:12345/"`, Level=1, Security-Mode=Sign, Security-Algorithm=Basic256Sha256

You set the primary base address either in the constructor of the `OpcServer` class or through the `Address` property of an `OpcServer` instance. If you set none, the server uses the address `opc.tcp://localhost:4840`:

```csharp
var server = new OpcServer("opc.tcp://localhost:4840/");
server.Address = new Uri("opc.tcp://localhost:4840/");

```

```vbnet
Dim server As New OpcServer("opc.tcp://localhost:4840/")
server.Address = New Uri("opc.tcp://localhost:4840/")

```

If the server should support additional base addresses, manage them with the `RegisterAddress` and `UnregisterAddress` methods. The `Addresses` property returns all base addresses the server uses, that is, all registered ones. If the value of the `Address` property was not set before, it takes the first address you define with `RegisterAddress`.

Define two additional base addresses:

```csharp
server.RegisterAddress("https://mydomain.com/");
server.RegisterAddress("opc.tcp://192.168.0.123:12345/");
```

```vbnet
server.RegisterAddress("https://mydomain.com/")
server.RegisterAddress("opc.tcp://192.168.0.123:12345/")
```

Remove (unregister) two base addresses from the server, which also changes the primary base address:

```csharp
server.UnregisterAddress("https://mydomain.com/");
 
// server.Address becomes: "opc.tcp://192.168.0.123:12345/"
server.UnregisterAddress("opc.tcp://localhost:4840/");
```

```vbnet
server.UnregisterAddress("https://mydomain.com/")

'server.Address becomes: "opc.tcp://192.168.0.123:12345/"
server.UnregisterAddress("opc.tcp://localhost:4840/")
```

If you unregister all addresses of the `Addresses` property, the value of the `Address` property is not set either.

The following code defines a secure policy for the endpoints of the server. If you do not specify an algorithm (`OpcSecurityAlgorithm.Auto`), the SDK chooses `Basic256Sha256` for `Sign` and `SignAndEncrypt`. Other current algorithms are, for example, `Aes128_Sha256_RsaOaep` or `Aes256_Sha256_RsaPss`. `Basic256` and `Basic128Rsa15` are considered deprecated:

```csharp
server.Security.EndpointPolicies.Add(new OpcSecurityPolicy(
        OpcSecurityMode.Sign,
        OpcSecurityAlgorithm.Basic256Sha256));
```

```vbnet
server.Security.EndpointPolicies.Add(New OpcSecurityPolicy( _
        OpcSecurityMode.Sign, _
        OpcSecurityAlgorithm.Basic256Sha256))
```

As soon as you define a specific security policy for endpoints, the default policy with the mode `None` no longer applies. This policy is not recommended for production. If the server should support it anyway, add it explicitly to the list of endpoint policies:

```csharp
server.Security.EndpointPolicies.Add(new OpcSecurityPolicy(
	OpcSecurityMode.None, OpcSecurityAlgorithm.None));

```

```vbnet
server.Security.EndpointPolicies.Add(New OpcSecurityPolicy(
	OpcSecurityMode.None, OpcSecurityAlgorithm.None))

```

### Bind to network interfaces

Types used: `OpcServer`, `OpcServerBinding`, `OpcAddressScope`

The server's `Binding` property defines the network interfaces to which the server binds its ports. By default, the server binds to all IPv4 and IPv6 addresses (`OpcAddressScope.IPvX`). Through the `Addresses` property, you can restrict the binding to specific IP addresses. In addition, the server binds its ports exclusively by default (`UseExclusiveAddress` property), so that no second process can use the same port. Starting a second server on the same port then fails:

```csharp
// Default: OpcAddressScope.IPvX (IPv4 and IPv6)
server.Binding.AddressScope = OpcAddressScope.IPv4;
 
// Default: empty (bind to all network interfaces of the address scope)
server.Binding.Addresses.Add(IPAddress.Parse("192.168.0.123"));
 
// Default: true (only one process can bind to the port)
server.Binding.UseExclusiveAddress = false;
```

```vbnet
'Default: OpcAddressScope.IPvX (IPv4 and IPv6)
server.Binding.AddressScope = OpcAddressScope.IPv4

'Default: empty (bind to all network interfaces of the address scope)
server.Binding.Addresses.Add(IPAddress.Parse("192.168.0.123"))

'Default: True (only one process can bind to the port)
server.Binding.UseExclusiveAddress = False
```

## Data transfer limits

Types used: `OpcServer`, `OpcTransport`, `OpcOperationLimits`

The server limits the size of the data it exchanges with its clients. If a value exceeds one of these limits, encoding or decoding fails, for example with the status `BadEncodingLimitsExceeded`. If you transfer large strings, arrays, or structures, raise the limits through the server's `Transport` property:

```csharp
server.Transport.MaxStringLength = 1048576;      // Default: 65535
server.Transport.MaxByteStringLength = 10485760; // Default: 5242880
server.Transport.MaxArrayLength = 1000000;       // Default: 65535
server.Transport.MaxMessageSize = 20971520;      // Default: 10485760
```

```vbnet
server.Transport.MaxStringLength = 1048576      'Default: 65535
server.Transport.MaxByteStringLength = 10485760 'Default: 5242880
server.Transport.MaxArrayLength = 1000000       'Default: 65535
server.Transport.MaxMessageSize = 20971520      'Default: 10485760
```

The values correspond to the entries below the `TransportQuotas` element of the XML configuration. The server tells clients through its operation limits how many nodes a client may read, write, or subscribe to per request. By default, it reports no limits. With the `OperationLimits` property, the server determines suitable limits based on the available system resources and reports them to its clients:

```csharp
// Default: false (the server does not announce any operation limits)
server.OperationLimits.AutoDetermineLimits = true;
```

```vbnet
'Default: False (the server does not announce any operation limits)
server.OperationLimits.AutoDetermineLimits = True
```

## Configuration through an XML file

If the server should also be configurable through XML, load its configuration from an XML file. The XML file must have the following standard XML tree:

```xml
<?xml version="1.0" encoding="utf-8" ?>
<OpcApplicationConfiguration xmlns="http://opcfoundation.org/UA/SDK/Configuration.xsd"
                             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                             xmlns:ua="http://opcfoundation.org/UA/2008/02/Types.xsd">
</OpcApplicationConfiguration>
```

The settings from the previous sections follow below the `OpcApplicationConfiguration` element. You load the file in one of the following ways:

- **By the path to the XML file** with the `LoadServerConfigFile` method. The file can have any name and be in any location.
- **By the name of the configuration** with the `LoadServerConfig` method. The file must then be named `<Name>.Config.xml` (for example `Opc.UaFx.Server.Config.xml`) and be in the working directory of the application.

Both methods return `null` if the file is missing or cannot be read (see [Configure the application](https://www.traeger.de/en/docs/development/opcua/server/configuration#configure-the-application)). The SDK does not support configuration through the `App.config` of the application (`configSections` with a reference to the XML file).
