TX Text Control .NET Server

Secure Deployment

Topic

When an application moves from a developer machine to a production server, some defaults that make development easy have to change. The Document Editor backend listens on all network interfaces, HTTPS has to be set up for the server or its proxy, and a nuget.config with an API token can end up in the publish output. The checklist below names each point, explains why it matters and links the page of the Deployment Guide that shows the steps for your platform.

The Checklist

CheckWhyRead
The site runs on HTTPS, and the editor connects with wssDocuments and editing sessions are encrypted in transitServe the Application Over HTTPS
The Document Editor backend listens on the loopback address or a private network onlyIts TCP port accepts connections from any client that reaches itKeep the Backend Private
The application's account has only the rights it needsThe backend and its worker processes share the accountRun With Least Privileges
No nuget.config with credentials in the output or in an imageIt contains the API token of the Text Control Private NuGet FeedKeep Secrets Out of the Deployment
The backend's messages reach your logsThey show whether the backend runs and which editors connectWatch the Logs
All TX Text Control packages are current and on the same versionService packs contain fixes, and mixed versions cause connection problemsKeep the Packages Current

Protecting the endpoints themselves with authentication and access tokens is part of Authentication and WebSocket Security.

Serve the Application Over HTTPS

On a page served over HTTPS, the Document Editor connects with wss, because it builds its WebSocket address from the address of the page, and the connection uses the same security layer as the page. The Document Viewer uses ordinary HTTP requests, so HTTPS protects both.

  • Redirect to HTTPS and send HSTS headers. The ASP.NET Core templates call UseHttpsRedirection and, outside the development environment, UseHsts. HSTS tells browsers to use only HTTPS for the site; Microsoft recommends starting with a short maximum age when you introduce HTTPS and raising it later.
  • Terminate HTTPS at the reverse proxy. Behind nginx, the proxy listens on port 443 with a certificate from a trusted certificate authority, and the application behind it stays on HTTP on the loopback address. The Forwarded Headers Middleware tells the application the original scheme; without it, HTTPS redirection behind such a proxy ends in a redirect loop. Prepare the Application in Ubuntu shows the code.
  • Trust only your own proxies. The Forwarded Headers Middleware accepts headers only from proxies on the loopback address by default. For a proxy on another machine, add its address to the known proxies instead of accepting all, or clients can spoof their IP address.
  • Configure a certificate for a service without IIS. An ASP.NET Core application that runs as a Windows service can't use the HTTPS development certificate, as Host the Document Editor in a Service notes.

Microsoft describes the options in Enforce HTTPS in ASP.NET Core and Configure ASP.NET Core to work with proxy servers and load balancers.

Keep the Backend Private

The WebSocket middleware in your application talks to the Document Editor backend TXTextControl.Web.Server.Core over plain TCP. Without configuration, the backend listens on port 4283 on all network interfaces, for IPv4 and IPv6, and accepts connections from any client that reaches the port. Only your application needs to reach it.

When the backend runs on the same machine or in the same container as the application, bind it to the loopback address: set ListenAddress to 127.0.0.1 in the DocumentEditorWorker section of appsettings.json and pass the same address and port to app.UseTXWebSocketMiddleware("127.0.0.1", 4283), as Prepare the Application in Ubuntu shows. If the values differ, the editor can't connect. In containers and cloud services, the environment variables DocumentEditorWorker__ListenAddress and DocumentEditorWorker__Port set the same values, as Run the Backend in the Application Container shows.

The application log then shows "Listen address "127.0.0.1" provided via options.", and on Linux, sudo ss -ltnp shows the backend on 127.0.0.1:4283.

Warning

Working Directory. Start the application from its own folder: if it doesn't find appsettings.json in its working directory, the backend listens on all interfaces again.

Where the backend runs decides how you keep its port closed:

SetupHow the port stays privateRead
Backend started by the application on a serverLoopback address, and the firewall closes every port the site doesn't useConfigure the Firewall
Backend in the application containerLoopback address, and port 4283 isn't published with -pRun the Backend in the Application Container
Backend in its own containerexpose in Docker Compose makes the port reachable for the other services only; no ports entryRun the Backend in Its Own Container
Backend on its own machineThe firewall allows port 4283 for the web servers onlyHost the Document Editor in a Service
Azure App Service on LinuxApp settings bind the backend to the loopback address; a container needs no exposed port for itConfigure the Application With App Settings

When the backend runs on another machine, keep both machines in a private network. Network Ports lists every port an application uses.

Run With Least Privileges

The Document Editor backend and its worker processes run under the account of your application, so every right of this account is also a right of the backend. The account needs read access to the application folder and write access only where the application writes.

  • Containers. The Dockerfile of Write the Dockerfile switches to the non-root user app of the .NET images with USER $APP_UID. Chiseled images go further: they contain only the files .NET needs, have no shell or package manager and run as a non-root user by default. TX Text Control needs the gconv modules in them, as Use a Chiseled Image shows.
  • Linux with systemd. The service runs as www-data, which owns the application files; the backend and its worker processes run as the same user, as Run the Application as a systemd Service shows.
  • IIS. The application pool runs as IIS AppPool\<name> and needs read and execute permissions on the application folder. Keep the generated web.config: without it, IIS may serve files such as MyApp.runtimeconfig.json to the public. Don't use top-level wildcard bindings such as http://*:80/. IIS shows the steps.
  • Windows services. A dedicated account with the right to log on as a service runs the service and every process it starts. Grant it access only to the folders, certificates and databases the service uses, as What Changes in a Service describes.

Keep Secrets Out of the Deployment

The license of TX Text Control is compiled into your assembly when you build it, so a deployment needs no license key or other secret for TX Text Control at run time. The only secret TX Text Control involves is the API token of the Text Control Private NuGet Feed, and it's needed only while packages are restored:

  • Keep nuget.config out of the project folder. A web project copies .config files from its folder into the build and publish output, so a nuget.config next to the project file would be deployed together with its API token. Keep it in the folder above.
  • Pass it to Docker as a build secret. A build secret is available only during the restore and isn't written to any image layer. A .dockerignore file keeps nuget.config out of the build context. Keep nuget.config Out of the Image shows both.
  • Store the credentials as pipeline secrets. Build servers write nuget.config from secrets before the first dotnet command, as CI/CD Authentication describes.
  • Replace a leaked token. If a token or a nuget.config was shared by mistake, delete the token under Manage API tokens and create a new one, as Creating an API Token describes.

Certificates for digital signatures are secrets of your application; Digital Signatures covers them.

Watch the Logs

DocumentEditorWorkerManager forwards the output of the backend to the logging of your application, with the prefix [TXTextControl.Web.Server.Core], and the configuration file in the backend package writes nothing to disk. The messages show whether the backend started and which editors connect: for each editor, the backend logs "Starting web editor worker process with connection ID" followed by the ID.

  • Windows services. The event log shows messages of level Warning and higher by default. Set Logging:EventLog:LogLevel:Default to Information to see the backend's output.
  • File logging. With LogTarget set to File, the backend writes log files to its FolderPath, ./logs in the working directory in the configuration the package ships, and the account needs write access there.

Keep the Packages Current

Service packs contain bug fixes and minor updates to many components, and Text Control recommends updating your applications to the latest service pack. Subscribers receive an email when one is released.

  • Update all packages together. Keep the engine package, the web packages and the npm packages of the Document Editor and the Document Viewer on the same major version; client and server packages of different versions can cause connection problems. dotnet list package --outdated lists the packages with newer versions, as Updating NuGet Packages shows.
  • Redeploy a separate backend. A backend that runs in its own container or on its own machine is updated when you rebuild and redeploy it, not with the application.
  • Scan for known vulnerabilities. SBOM describes the signed SBOMs of the TX Text Control packages and the vulnerability checks of the .NET SDK.

Next Steps

  • Authentication: protect the endpoints of the editor, the viewer and your controllers.
  • WebSocket Security: check the WebSocket connection of the Document Editor before it's accepted.
  • Deployment Guide: the complete steps for Windows, Linux, Docker, Kubernetes and the cloud.
  • Security Overview: the parts of an application and how they fit into its security.