Make sure that:
the web.config file is copied into each of the domain folders
no runtimeid.config files are copied to these new folders as they uniquely identify the applications$ delete them if they are present.
To create the IIS admin panel, please, launch the Internet Information Services (IIS) Manager and select “Add Website ...” from the Actions list.
In the window that appears, the following fields should be filled:
Site name: wfs_admin
Physical path: the path to the wfs_admin folder, created in Step 2.
Port: a unallocated port through which the admin panel is available, for example 8077.
The Application pool for the wfs_admin site should be set up to avoid unnecessary restarts of the Workflow Server runtime or shutdowns when idle. Thus, in the Internet Information Services (IIS) Manager, go to the Application Pools List and select the wfs_admin pool.
Select Edit Application Pool -> Recycling, in the dialog box that appears, turn off the Regular time intervals (in minutes) option.
Click Next -> Finish Select Edit Application Pool -> Advanced Settings In the window that appears, find the Process Model -> Idle time-out (minutes) option, and change its value from 20 to 0.
Press OK, the wfs_admin pool is set up.
Then, prepare the config.json file for the admin panel. In the default mode, Workflow Server starts 2 web hosts simultaneously (the admin panel and the form manager). This operation mode is incompatible with IIS, therefore we set the ServerType property to Admin, and change the BackendFolder property so that it contains the relative path from the wfs_admin folder to the backend folder copied in Step 2. Since we are going to launch 2 copies of the Workflow Server, we enable the Multiserver mode by setting the IsMultiServer property to true.
{
"BackendFolder": "../backend",
"ServerType": "Admin",
"IsMultiServer": true,
}
Please, note that the url property set in config.json is ignored; instead, the IIS binding sets for the wfs_admin site are used.
Now, we publish Workflow Server for the wfs_admin site.
Using Visual Studio 2019.
In the context menu of the WorkflowServer project, select Publish (or, select Build -> Publish WorkflowServer in the main menu)
In the publishing window that appears, create a new profile by selecting "new":
In the dialog box that appears, select Folder and press Next:
As the Folder location, specify the path to the wfs_admin folder created in Step 2, and click Finish.
Publish Workflow Server by pressing the Publish button.
Alternatively, publishing can be performed without Visual Studio, through the command line. In the workflowserver project folder, containing WorkflowServer.sln, run the command:
dotnet publish WorkflowServer.sln -o <WFS_ADMIN_PATH>
Where
If the wfs_admin folder is not available on the computer where the application is being developed, any available folder can be seleced for publishing; then, its contents should be copied to the wfs_admin folder.
Then, we create the form manager IIS site and configure its Application pool as described in Steps 3-5. The site settings are:
Now, we prepare the config.json file to publish the form manager. First, set the ServerType property to Forms, then, change the FrontendFolder property so that it contains the relative path from the wfs_forms folder to the frontend folder copied in Step 2. Since we are going to launch 2 copies of Workflow Server, we enable the Multiserver mode by setting the IsMultiServer property to true.
{
"FrontendFolder": "../frontend",
"ServerType": "Forms",
"IsMultiServer": true,
}
Please, note that the DefaultFrontendPort property set in the config.json file is ignored; instead, the ISS binding sets for the wfs_forms site are used.
Now, we publish Workflow Server for the wfs_forms site, similarly to Step 7, using the wfs_forms folder created in Step 2 as the target for publishing.
IIS deploy is done; both the admin panel and the form manager are accessible according to the ISS binding sets, specified for the wfs_admin site and the wfs_forms site respectively.
In case of any issues, please check the steps you've taken in the Troubleshooting section
Ensure the following measures have been taken:
To deploy WFS with nginx as a reverse-proxy, we need at least 2 Docker containers ; one for Workflow Server, and the other for nginx. To manage the containers, we use Docker Compose and take docker-files/docker-compose.yml from the workflowserver project as the basis solution for deploying Workflow Server and PostgreSql. This solution consists of the following three containers:
To correctly determine the IP address and client protocol in WFS when working through a reverse-proxy, the forwarded headers must be enabled. To configure forwarding, the ProxySettings property in ServerSettings is used as follows:
public class ProxySettings
{
public List<string> KnownNetworks { get; set; } = new List<string>();
public List<string> KnownProxies { get; set; } = new List<string>();
public List<ForwardedHeaders> Headers { get; set; } = new List<ForwardedHeaders> { ForwardedHeaders.XForwardedFor, ForwardedHeaders.XForwardedProto };
public bool Enabled { get; } = true;
}
Where Headers
is the list of headers to be forwarded.Possible values are:
You can also see more info here
For security reasons, header forwarding should be restricted to trusted proxies only. You can set the trusted proxies using the following properties:
KnownNetworks
- the list of trusted subnets in the CIDR notation (IP address / mask)KnownProxies
- the list of the IPs of trusted proxy servers.ProxySettings parameters can be configured using both config.json and environment variables. For debugging purposes, ProxySettings can be used without specifying KnownNetworks
or KnownProxies
, then the headers are forwarded for any addresses. To enable this mode, set the environment variable ProxySettings__Enabled
to true
.
Warning! In production mode, ProxySettings without specifying KnownNetworks or KnownProxies are not recommended.
We define the parameters of the subnet made for our containers. The subnet is created when the compose project is launched for the first time; thus, we start this project using startcontainer.bat or startcontainer.sh, and then stop it by pressing Ctrl+C.
In the command prompt, execute the following:
docker network inspect docker-files_default
It shows the default network info of the workflowserver project.
As you can see, in our case, the default network has 172.27.0.0/16 mask and 172.27.0.1 gateway.
The containers are given dynamic addresses on creating. To set KnownProxies
, we assign static addresses for the existing containers by adding a node to each service configuration:
networks:
default:
ipv4_address: <IP_address>
where
We create the configuration file nginx.conf in the folder docker-compose/postgresql. It contains the following:
worker_processes 4;
events { worker_connections 1024; }
http {
sendfile on;
server {
listen 8077;
location / {
proxy_pass http://workflowserver:8077;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 8078;
location / {
proxy_pass http://workflowserver:8078;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
The file describes the two servers corresponding to the two Workflow Server web hosts: Admin Panel/Web API and Form Manager.
Line 9:
listen 8077;
It sets the external port to access Admin Panel/Web API.
Line 11:
proxy_pass http://workflowserver:8077;
It indicates the Admin Panel/Web API address in the internal network. The workflowserver host name corresponds to the service name in the docker-compose.yml configuration file, and the port number must match the url specified in config.json.
Similarly, line 23 defines the external port to access Form Manager, and line 25 indicates the Form Manager address in the internal network (the port number must match DefaultFrontendPort specified in config.json).
To remove the port from the workflowserver container, making it inaccessible from the external network, we delete these lines in docker-compose.yml:
ports:
- "8077:8077"
- "8078:8078"
We add the following description of the nginx container in docker-compose.yml:
nginx:
depends_on:
- workflowserver
image: nginx:latest
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- "8077:8077"
- "8078:8078"
networks:
default:
ipv4_address: 172.27.0.5
To add the nginx server IP-address to the list of KnownProxie
s, we add the following line in docker-compose.yml in the environment node of the workflowserver:
ProxySettings__KnownProxies__0: 172.27.0.5
docker-compose.yml is ready, the full listing is as follows:
version: '3.4'
services:
db:
image: postgres:alpine
environment:
POSTGRES_DB: wfs
POSTGRES_USER: dbuser
POSTGRES_PASSWORD: dbuserpassword
volumes:
- dbdata:/var/lib/postgresql/data
restart: always
ports:
- "5432:5432"
networks:
default:
ipv4_address: 172.27.0.2
start_db:
image: jbergknoff/postgresql-client
depends_on:
- db
volumes:
- ./docker-files:/home/.docker
entrypoint: /home/.docker/wait-for-db.sh db dbuser dbuserpassword wfs
networks:
default:
ipv4_address: 172.27.0.3
workflowserver:
depends_on:
- db
build:
context: ../..
dockerfile: ./WorkflowServer/Dockerfile
volumes:
- ./logs:/app/logs
- ./license:/app/license
environment:
ConnectionString: HOST=db;User ID=dbuser;Password=dbuserpassword;Database=wfs;Port=5432
Provider: postgresql
LicensePath: /app/license/
DefaultLoggerConfig__FileTarget__0: Debug
DefaultLoggerConfig__FileTarget__1: Information
DefaultLoggerConfig__FileTarget__2: Error
DefaultLoggerConfig__FileSettings__FileName: /app/logs/log.txt
DefaultLoggerConfig__FileSettings__RollingInterval: Day
DefaultLoggerConfig__FileSettings__RetainedFileCountLimit: 30
ProxySettings__KnownProxies__0: 172.27.0.5
networks:
default:
ipv4_address: 172.27.0.4
nginx:
depends_on:
- workflowserver
image: nginx:latest
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- "8077:8077"
- "8078:8078"
networks:
default:
ipv4_address: 172.27.0.5
volumes:
dbdata:
Now, we run the containers using any of the scripts: startcontainer.bat or startcontainer.sh.
As seen in the logs, queries come from 172.27.0.1 (the client IP-address) to nginx_1(the reverse-proxy server) and successfully redirected to workflowserver_1, where Workflow Server is running. In turn, Workflow Server correctly defines the RemoteIPAddress of the client as 172.27.0.1.