Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
This guide provides instructions on how to set up, configure, deploy, and manage WorkflowGen integrations with Docker and Kubernetes.
This section presents how to quickly run the WorkflowGen container with a minimal architecture on your local machine.
There are known limitations when using Hyper-V isolation with the WorkflowGen container in WorkflowGen versions 7.19.2 and earlier. It's recommended to use process isolation exclusively. This limitation no longer applies as of WorkflowGen version 7.20.0.
Make sure to have a valid WorkflowGen license.
If you're using Windows Server, make sure that it's Windows Server 2019, and use the tag that corresponds to that version. For example, for Windows Server 2019, use the tag that ends with ltsc2019.
At the end of this section, the following architecture will be deployed on your local machine:
Inside the Docker engine on your machine, you'll have a running WorkflowGen server and a WorkflowGen database. Both of these will use volumes mapped to your local machine to persist data files.
Make sure to have installed Docker on your machine.
Follow the instructions in the guide to install Docker for Windows. You must be using Windows containers, so you need at least Windows 10 Pro.
For Windows Server
Do not install Docker for Windows on Windows Server. It is designed for development only.
Follow the instructions in the guide to install Docker on Windows Server.
For this setup, it's recommended to use WorkflowGen's database Docker image. You can also use a SQL database installed on your local machine.
To download the database image into your local machine, open PowerShell and enter the following:
For WorkflowGen to work, you need to run the database before running WorkflowGen. Before creating the container, create a Docker volume in order to externalize the database files (.mdf and .ldf). This will ensure that the data are still there after the deletion of the container.
The physical location of the volume can be obtained using the following command:
Typically, it will be stored in C:\ProgramData\Docker\volumes\sqldata\_data. Make sure that the container has write access to this directory (see the Microsoft article for information).
You're now ready to run the database container. To do this, execute the following command:
This last command will set the passwords of the SA database user, the WFGEN_USER database user, and the wfgen_admin WorkflowGen account asstrong(!)Pass. Per the nature of Docker, the SA_PASSWORD and ACCEPT_EULA environment variables come from the microsoft/mssql-server-windows-express base container and are not directly handled by the WorkflowGen container.
Enter the following to download the WorkflowGen image:
For this container, you need two volumes in order to correctly persist the WorkflowGen data:
WorkflowGen licenses (licenses)
WorkflowGen's data (data), which contains the following:
The App_data folder (appdata
You now need to copy your WorkflowGen license into the licenses volume. To do this, execute the following command:
This way, the WorkflowGen container will be able to pick it up via the volume. You also need an encryption key for the container; use the following command to generate one:
To run the actual container, replace <YOUR_WFG_LIC_KEY> with your WorkflowGen license key and <YOUR_NEW_GUID> with the GUID that you generated in the last step, then execute the following command:
When the container is ready, open a browser and go to http://localhost:8080/wfgen, where you'll be prompted for WorkflowGen authentication. By default, the container is configured with the application authentication method.
Once you're done with this environment, you can shut down containers by stopping them. They can be restarted later.
To completely remove containers, there's only one command to execute:
This will remove the database and WorkflowGen containers including, any manual change in the container's file system that is not part of a volume. Even if the containers are gone, the data in the volumes are retained and can be used by other containers. For example, you could launch three other WorkflowGen containers that use the same volumes and they will all get the exact same files at the mount point of the volume.
This section describes the recommended way to easily deploy a local development environment without having to enter a lot of commands. You can find out more about Docker Compose in the Docker documentation at .
At the end of this section, the following architecture will be deployed on your local machine:
Inside the Docker engine on your machine, you'll have a running WorkflowGen server and a WorkflowGen database. Both of these will use volumes mapped to your local machine to persist data files.
Follow the instructions in the guide to install Docker for Windows. You must be using Windows containers, so you need at least Windows 10 Pro.
For Windows Server
Do not install Docker for Windows on Windows Server. It is designed for development only.
Follow the instructions for Windows Server in the guide to install Docker on Windows Server.
On Windows Server only, you also need to install the Docker Compose tool, since it's not installed by default. Follow the instructions for Windows Server in the guide. To verify that Docker Compose is properly installed, run the following command:
For this setup, it's recommended to use WorkflowGen's database Docker image. You can also use a SQL database installed on your local machine.
Before creating the services, you need to create the license volume externally from the composition in order to have the licenses present at the time of container creation. To do this, execute the following command:
Then, you need to copy your license file to the licenses directory. The following command will show you where the license will be stored:
To copy your license, execute the following command:
This value should be generated by you. A simple GUID will suffice since it has sufficient entropy not to be guessed:
For each service that you'll create (one for WorkflowGen and one for the database), you'll need a file that contains all of the environment variables for that service.
Use the following file as a template:
Save it as database.env using the path where you'll put the Compose file.
Use the following file as a template:
Save this file as workflowgen.env using the path where you'll put the Compose file.
To deploy services with Docker Compose, you need a Compose file that describes them. Use the following Compose file for this example:
Save this file as docker-compose.yml using the path where you put your environment variable files, then execute the following command:
Wait a few minutes for the containers to get started, then open a browser and navigate to http://localhost:8080/wfgen, where you will be prompted for authentication. Enter the credentials (username wfgen_admin and password strong(!)Pass) and it should display the WorkflowGen home page.
Workflow applications (wfapps)
docker image pull advantys/workflowgen-sql:7.18.2-express-win-ltsc2019docker volume create sqldatadocker volume inspect -f "{{.Mountpoint}}" sqldatadocker container run -it `
--env ACCEPT_EULA=Y `
--env 'SA_PASSWORD=strong(!)Pass' `
--env WFGEN_DATABASE_USER_USERNAME=WFGEN_USER `
--env 'WFGEN_DATABASE_USER_PASSWORD=strong(!)Pass' `
--env 'WFGEN_ADMIN_PASSWORD=strong(!)Pass' `
-v sqldata:C:\wfgen\sql `
--name wfgen_sql `
--hostname database `
advantys/workflowgen-sql:7.18.2-express-win-ltsc2019docker image pull advantys/workflowgen:7.18.2-win-ltsc2019"licenses", "wfgdata" | ForEach-Object { docker volume create $_ }Copy-Item C:\Path\To\WorkflowGen.lic $(docker volume inspect -f "{{.Mountpoint}}" licenses)[guid]::NewGuid().ToString('N')
# fda7a6a81db2428b8885bd1210522755docker container run -it `
--env 'WFGEN_APP_SETTING_ApplicationUrl=http://localhost:8080/wfgen' `
--env 'WFGEN_APP_SETTING_ApplicationSerialNumber=<YOUR_WFG_LIC_KEY>' `
--env 'WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey=<YOUR_NEW_GUID>' `
--env 'WFGEN_DATABASE_CONNECTION_STRING=Data Source=database,1433;Network Library=DBMSSOCN;Initial Catalog=WFGEN;User ID=WFGEN_USER;Password=strong(!)Pass;' `
-p 8080:80 `
-v wfgdata:C:\wfgen\data `
-v licenses:C:\wfgen\licenses:RO `
--name wfgen `
advantys/workflowgen:7.18.2-win-ltsc2019# Stopping the containers
"wfgen", "wfgen_sql" | ForEach-Object { docker container stop $_ }
# Starting the containers
docker container start wfgen_sql
# Wait for the database to be ready and then start the WorkflowGen container
docker container start wfgen
# Restarting the containers
"wfgen_sql", "wfgen" | ForEach-Object { docker container restart $_ }"wfgen", "wfgen_sql" | ForEach-Object { docker container rm -f $_ }docker-compose versiondocker volume create licensesdocker volume inspect -f "{{.Mountpoint}}" licensesCopy-Item C:\Path\To\WorkflowGen.lic $(docker volume inspect -f "{{.Mountpoint}}" licenses)[guid]::NewGuid().ToString('N')
# fda7a6a81db2428b8885bd1210522755SA_PASSWORD=strong(!)Pass
WFGEN_DATABASE_USER_USERNAME=WFGEN_USER
WFGEN_DATABASE_USER_PASSWORD=strong(!)Pass
WFGEN_ADMIN_PASSWORD=strong(!)PassWFGEN_APP_SETTING_ApplicationUrl=http://localhost:8080/wfgen
WFGEN_APP_SETTING_ApplicationSerialNumber=<YOUR_WFG_LIC_KEY>
WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey=<YOUR_NEW_GUID>
WFGEN_DATABASE_CONNECTION_STRING=Data Source=database,1433;Network Library=DBMSSOCN;Initial Catalog=WFGEN;User ID=WFGEN_USER;Password=strong(!)Pass;version: '3.8'
services:
workflowgen:
image: advantys/workflowgen:7.18.2-win-ltsc2019
restart: always
env_file:
- '.\workflowgen.env'
ports:
- '8080:80'
volumes:
- 'wfgdata:C:\wfgen\data'
- 'licenses:C:\wfgen\licenses:RO'
depends_on:
- database
database:
image: advantys/workflowgen-sql:7.18.2-express-win-ltsc2019
env_file:
- '.\database.env'
volumes:
- 'sqldata:C:\wfgen\sql'
volumes:
wfgdata:
licenses:
external: true
sqldata:
Set-Location C:\Path\To\ComposeFile
docker-compose upIn Kubernetes, there are tools to help you manage certificates and achieve a TLS connection. This is easier than making a custom architecture using the reverse proxy method. You can read more about managing certificates with Kubernetes at the following link:
is a cloud native application that manages certificates for you. It includes mechanisms to ask for Let's Encrypt certificates automatically and get certificates from , or you can use your own certificates generated by a certificate authority (CA) or a self-signed certificate.
This section presents ways to configure a secure connection (HTTPS) to the WorkflowGen container using a certificate. With Docker, containers run on an internal network, and only exposed ports will be available publicly. Therefore, you can't set up a TLS connection on one container only; you have to do it for all the containers, but this method doesn't scale well.
This method uses the Nginx web server as a reverse proxy configured with a TLS connection that will redirect all traffic to the WorkflowGen container(s). This method can be applied regardless of whether you have orchestration or not.
See the following pages for more information:
Traefik is a reverse proxy that handles routing, TLS termination, and load balancing, among other things. It's available as a container and you can use it in front of the WorkflowGen container. For more information about Traefik, see its documentation page.
In Azure, you can use the Application Gateway service in order to get a TLS connection for domains that you own. See the Overview of TLS termination and end to end TLS with Application Gateway Microsoft article to get you started.
For more information and recommendations about TLS/SSL handling in Kubernetes, see the TLS/SSL page in the Kubernetes section.
This section presents how to achieve multitenancy with WorkflowGen images and Kubernetes. By the nature of containers and tools present in Kubernetes, a single cluster can have multiple instances of WorkflowGen with relative isolation from one another. The best isolation can be achieved with multiple clusters.
As reference for best practices, see the following links to Google Kubernetes Engine and Azure Kubernetes Service documentation:
You should have at least three different storage shares to handle WorkflowGen persistent files. If you used custom SMB file shares, you should have a strategy to back up the disks for the file share. If a problem occurs, you can restore a backup. Don't forget to restore the database data to the exact time as the file share backup.
For Azure Files, see the following documentation on backups and restorations:
For Azure Disks, see the following documentation on backups and restorations:
See the Operations section in the WorkflowGen Technical Guide for information on backup and restoration of on-premise databases.
See the following Microsoft documentation on business continuity with Azure SQL:
Creating backups and recovering with them in Kubernetes can be complicated, but tools exist to help manage this. Here's an article about backups with Kubernetes:
There are two main tools for backup and recovery:
As with other Azure Services, Microsoft provides guides for backups and restorations:
See the following documentation for Azure SQL setup:
See the following documentation about the requirements for on-premise databases:
WorkflowGen has a production-ready database image based on the Microsoft SQL Server image for Linux. It has the same options as the Microsoft image with some additional features such as automatic creation of the WorkflowGen database and setting the wfgen_admin username and password. The image is available on Docker Hub:
For more information about the WorkflowGen database image, see Configuration in the WorkflowGen Database Image section.
Persistent data is different depending if you use the Linux version or the Windows version.
The Linux version has a more managed way to persist the database's data. Instead of only persisting the .mdf and .ldf file of the WorkflowGen database, you instead persist all of the SQL Server state data, including the master database files. For more information on how to persist the data in the Linux, see Configure SQL Server container images on Docker in the official Microsoft documentation for SQL Server.
Since the Windows version's base image hasn't been updated by Microsoft for quite some time, WorkflowGen's database files have to be persisted manually. Therefore, the database container has a defined volume that will contain only the WorkflowGen database files. As well, it's recommended to use SQL Server's contained database feature to keep the credentials at the database level instead of at the SQL Server system level. For more information about the contained database feature, see contained database authentication Server Configuration Option in the official Microsoft documentation.
Name
Description
C:\wfgen\sql
This path contains the .mdf and .ldf files of the WorkflowGen database.
Volumes are handled differently with Windows Containers compared to Linux Containers. The permission model changes and is different depending on whether you use process isolation or Hyper-V isolation. Before continuing with the procedures in this section, you should read the Microsoft documentation on container storage.
In Docker, there is an internal DNS that handles domain names for containers and machines. You can easily configure an internal domain name for each container just by passing simple parameters. See the following link for more information:
For domain names that are public, you'll typically need an external service (e.g. NameCheap or AWS Route 53) that sells domain names, and then configure that service to point to the public IP of the public-facing containers.
All you need to do is to expose the port of the container (or service) you need and it will be available publicly.
This will expose the container port 80 to the host's port 80. The public IP is that of the Docker host.
docker container run `
# ...
-p 80:80 `
# ...
advantys/workflowgen:7.18.3-win-ltsc2019Before beginning with the recommended architectures, it is important to note some security concerns that derive from using Windows containers. The WorkflowGen image is a Windows container image. Some security features present in Linux containers are not necessarily available in Windows containers, such as AppArmor and SELinux profiles and Linux capabilities. See Intro to Windows support in Kubernetes for all of the current limitations.
The important thing in multitenant clusters is isolating tenants from one another and limiting possible actions in case of intrusion. You can achieve a good isolation level with network policies on Kubernetes. These are specifications that require third-party software to be installed to enforce those policies. At this time, only the Calico project has a Windows support (see Calico for Windows for more information).
For in-container security, at this time, only runAsUserName is available to run the container instance as a different username than ContainerAdministrator (see Configure RunAsUserName for Windows pods and containers for more information). It's not necessary for the WorkflowGen container since the web applications run as a user of the IIS_IUSRS group.
Make sure that the WorkflowGen Windows Services pod has inbound traffic denied. It should not be public facing.
Make sure that the WorkflowGen database pods are not public facing. They are only used by the WorkflowGen container.
The WorkflowGen web applications' pods should only be publicly available through HTTPS. HTTP is highly discouraged. However, you should not be able to access WorkflowGen at all from inside the cluster, even in HTTPS.
Every WorkflowGen pod in a namespace should not be able to contact other pods in other namespaces. Be sure to have a network policy for this.
In general, you should always deny any inbound traffic unless you explicitly need it.
The basic idea behind multitenancy is to have reproducible deployment. This schema shows two identical deployments but in different namespaces. Each has its own data, configuration, and license. Isolation between the namespaces should be enforced by network policies. Optionally, you might want to use an Ingress controller with cert-manager to manage routing and certificates easily.
This architecture also applies to multicluster (multiregion) environments. The only thing that will change is how you route to the correct instance. The same security concerns apply.
This section contains details on the recommended architecture to use when deploying WorkflowGen for Docker. The following schema illustrates all of the components in action:
As shown, all runtime components are inside one or more Docker hosts. You can use as many web application containers as you want for higher availability and better performance, but you can only have one instance of each WorkflowGen Windows Service. You also don't have to use the database container; if you want, you can externalize the database to a cloud provider such as Azure SQL or your own on-premise SQL Server.
As usual, you can configure the SMTP service that you want to use with WorkflowGen's container. There is no special setup needed for this.
All persistent data is externalized. The licenses used for WorkflowGen, the application data (App_Data), and the workflow applications (wfapps) are all persisted into a distinct shared space (wfgdata in the diagram). For example, this could be a file share, an Azure Files file share or Azure Disk disk, or any other service that is capable of acting as directory on a Docker host.
As well, in this diagram, the database files are in a Docker volume. This volume should be a disk, such as a local disk on the Docker host whose backups you can control, or something like an Azure Disk disk so that you can take snapshots. In the case of the database, it's important to have a disk to maintain good performance. For optimal results, you should externalize the database. See the SQL Server Hosting Options page for more details.
This section describes each of the WorkflowGen container's runtime environments. Keep in mind that all environments are packaged in a single image.
When you run the container's web applications, the following components are running:
User Portal
Administration Module
All APIs:
GraphQL
SOAP
SCIM v2
Webhooks
OpenID Connect authentication
ASP.NET web forms
Workflow applications (.NET assemblies)
These are all of the components that you need to make every web service and graphical interface work.
When you run the container's Windows Services, the following components are running:
Directory synchronization service
Engine service
These are shared spaces between the containers where data that should be persistent and that can't be in the database are located. A shared space for WorkflowGen licenses is required because a license can't be stored directly into an image. Instead, it's retrieved at runtime from the container and placed at the correct location inside the container.
The WorkflowGen App_Data folder should be shared between the containers. It contains the following pieces of information that WorkflowGen needs to work properly:
Design time process files
Runtime process files
Log files
Workflow application temporary files
Customized User Portal menus
Process templates
Mail templates
The wfapps IIS web application is also shared among the containers because the web forms contained at this location are ASP.NET files generated at design time; this is why they're considered as storage. The App_Data and wfapps folders are grouped in the same shared space called wfgdata.
In this architecture, the WorkflowGen database is containerized and its data is stored in a shared space, preferably backed by a high performance disk as well. You can add other containerized databases as read replicas with their own shared space for their data. For more details about the database container or database management with containers, see the SQL Server Hosting Options section.
WorkflowGen relies on an SMTP gateway to send email notifications. A SMTP server or service with a low network latency and a high availability is recommended.
Depending on if the upgrade container is online or offline, this step gets the update package of the ToVersion parameter. If the container is online, it will try to get the update package from the updatepackages volume first. If not found, the container will download it from the workflowgen-releases GitHub repository. If the container is offline, it will try to get the update package from the updatepackages volume. If it can't, it will write an error message and exit.
You have to provide your own WorkflowGen update packages when using the container offline. By default, when you mount the updatepackages volume, the container expects the following file structure:
As you can see, the structure expected has only folders at the top level with the exact version of WorkflowGen. Inside them is an archive called update.zip, which is the WorkflowGen official update package. You need only to have the ToVersion update package when you run the container.
Optionally, if the update package is located elsewhere within the volume, you can specify the file name and path in the WFGEN_UPGRADE_UPDATE_PACKAGE_FILE_NAME environment variable. For example, you could specify the value 7.15.2.zip if ToVersion is 7.15.2 and the directory structure is flat. You could also specify the value workflowgen/updates/7.15.2/update.zip if the update package is further down the directory tree.
For more information about environment variables, see the Configuration page of this section.
Before this operation, a backup will be made of all the folders and files from within the bind mount and temporarily copied to a path inside the container. At all times, the Files, LogFiles, and Ws folders are ignored, including during the merge operation. The container will then merge the App_Data files from the update package into your App_Data folder that you have linked to the container through the data bind mount. The merge is additive only, which means that any file that don't exist in the update package will be kept as-is.
In the same manner as the App_Data merge operation, the wfapps folder will also be merged with your wfapps provided in the data bind mount. This operation is also additive only.
The upgrade container will then apply any SQL migration files found in the update package that satisfy the condition where is the version of the SQL migration file, is the FromVersion value and is the ToVersion value.
This is the simplest use of the upgrade container. For example, if you want to upgrade WorkflowGen from version 7.14.6 to 7.18.2 and the container has access to the Internet, you would call it like this:
In this example, the container will download the update package from the 7.18.2 version, merge the App_Data and wfapps files in /mnt/data/appdata and /mnt/data/wfapps respectively and apply any database migrations using the SQL scripts in the update package.
You can ignore files and folders with environment variables when the container merges files. For more information, see the Configuration page of this section.
If the container doesn't have access to the Internet, you can pass the WorkflowGen update package yourself. Make sure that it is the exact version of the ToVersion argument passed to the container. You would call the container like this:
In this example, there are two changes compared to the online example. First, a bind mount has been added for provisioning update packages. The container will first look in it to find an update package. Second, the -Offline flag has been passed to the container. This flag tells the container to not try to download the update package if it doesn't find the package in the bind mount. In other words, the container will not attempt any network-related access.
The path and name of the update package can be modified with environment variables. For more information, see the Configuration page of this section.
# "wfgdata" groups appdata and wfapps folders
docker container run -i --name wfgen-upgrade `
--env 'WFGEN_DATABASE_CONNECTION_STRING=Server=someserver,1433;...' `
--mount "type=bind,src=C:\path\to\your\wfgdata,dst=/mnt/data" `
advantys/workflowgen-upgrade:latest-ubuntu-18.04 `
-FromVersion 7.14.6 -ToVersion 7.18.2
# When has terminated, you can analyse the container or review the logs.
# Then, remove the container.
docker container rm wfgen-upgrade# "wfgdata" groups appdata and wfapps folders
docker container run -i --name wfgen-upgrade \
--env 'WFGEN_DATABASE_CONNECTION_STRING=Server=someserver,1433;...' \
--mount type=bind,src=C:\path\to\your\wfgdata,dst=/mnt/data \
advantys/workflowgen-upgrade:latest-ubuntu-18.04 \
-FromVersion 7.14.6 -ToVersion 7.18.2
# When has terminated, you can analyse the container or review the logs.
# Then, remove the container.
docker container rm wfgen-upgrade# "wfgdata" groups appdata and wfapps folders
docker container run -i --name wfgen-upgrade `
--env 'WFGEN_DATABASE_CONNECTION_STRING=Server=someserver,1433;...' `
--mount "type=bind,src=C:\path\to\your\wfgdata,dst=/mnt/data" `
--mount "type=bind,src=C:\path\to\packages,dst=/mnt/updatepackages" `
advantys/workflowgen-upgrade:latest-ubuntu-18.04 `
-FromVersion 7.14.6 -ToVersion 7.18.2 -Offline# "wfgdata" groups appdata and wfapps folders
docker container run -i --name wfgen-upgrade \
--env 'WFGEN_DATABASE_CONNECTION_STRING=Server=someserver,1433;...' \
--mount type=bind,src=C:\path\to\your\wfgdata,dst=/mnt/data \
--mount type=bind,src=C:\path\to\packages,dst=/mnt/updatepackages \
advantys/workflowgen-upgrade:latest-ubuntu-18.04 \
-FromVersion 7.14.6 -ToVersion 7.18.2 -Offlineupdatepackages/
7.14.0/
update.zip
7.15.0/
update.zipThis section shows which persistent data are exposed and where. It also recommends some ways to persist, share, and back up the data. For backup strategies and recommendations, see the Business Continuity & Disaster Recovery section.
There are three elements that must be persisted in WorkflowGen: the App_Data folder, the wfapps web application folder, and the SQL data. The first two are grouped in the same file share for simplicity and ease of use. To deploy a database, see the section.
The other two are files from WorkflowGen, and the reasons they must be persisted through a file share is explained in the section.
Additionally, you must have a file share with a valid WorkflowGen license in it so that the container can pick it up. Those folders must be exposed to the WorkflowGen containers through volumes. For more information about Docker volumes, see the Docker article.
Volumes are handled differently with Windows Containers compared to Linux Containers. The permission model changes and is different depending on whether you use process isolation or Hyper-V isolation. Before continuing with the procedures in this section, you should read the Microsoft documentation on .
Essentially, you must ensure that WorkflowGen containers can read and write to the wfgdata volume and read from the licenses volume. The group in the container that will access the volumes is named IIS_IUSRS.
This is the simplest way to persist WorkflowGen files with the containers. It consists of creating a local volume or using a bind mount on your Docker host that will retain the files after a container is removed. Volumes are the preferred way to persist files versus bind mounts because they're managed by Docker. This method doesn't scale well across multiple Docker hosts, however, so other methods should be considered in this case.
To create a volume for each data path in the container, execute the following command:
Then, you need to copy (or move) your license file to the licenses volume by executing the following command:
Now, you can run WorkflowGen container with those volumes to persist the data.
run commandYou have now successfully persisted WorkflowGen's files.
Remember that you manage bind mounts manually. They are specific paths on the Docker host that you control. To use bind mounts as volumes, you only need to pass the paths when you execute the run command like so:
You can use an SMB file share with Windows Containers such as Azure Files. Concretely, you connect the share to the Docker host and then mount it like a bind mount to containers; this is called an SMB mount. You can read more about SMB mounts in the Microsoft documentation.
In Kubernetes, you'll use a Persistent Volume object to specify a place where Kubernetes will put data from pods. For more information about persistent volumes, see the page on the Kubernetes website.
Concretely, for WorkflowGen, you'll have to configure a volume that can handle the permission ReadWriteMany for the WorkflowGen data volume because multiple pods at the same time will access this volume to read and write data. Typically, to do this, you'll have to create a storage claim on the cluster like so:
In this example, the claim references a Storage Class, but you can reference a persistent volume directly, or other cloud-specific storage services depending on the cloud provider. Here, the azurefile storage class is provided by Azure Kubernetes Service. The allocation of the storage will be done automatically by the service. It will create a storage account with a file share that has 50 GB capacity.
If you configure WorkflowGen to use a pickup directory for notifications, you'll also need to specify a volume in order to expose the notifications to other services that will process them.
The default path for the pickup directory is C:\inetpub\mailroot\Pickup. You can change it by supplying the WFGEN_APP_SETTING_ApplicationSmtpPickupDirectory environment variable with any path inside the container. Then, you'll need to create a volume for the files like so:
You can now map this volume to the configured pickup directory:
At this point, you could deploy another container with your service to take care of the notifications and bind the same volume to share the notification files.
This section presents how to manage WorkflowGen updates and deploy them safely in your environments.
Back up all of the file shares.
Back up the database.
For more information about business continuity and disaster recovery, see the section.
These actions can include moving, deleting, or adding some files around in the file shares, updating some configuration in your orchestrator or configuration files, adding secrets, adding or removing services, etc. The actions are detailed in the (choose the version to which you want to upgrade).
Only execute the actions that concern the files in the file shares. Any actions pertaining to files or services in WorkflowGen's container must be ignored. These will already be done once the new version of the image is in place. For example, don't stop the IIS service, since it's useless with a Docker container.
See the section in the (choose the version to which you want to upgrade).
If you're using the WorkflowGen database image, after upgrading the database, you need to update the container as well:
Skip this step if you don't have a custom WorkflowGen image. See the section for more information.
If you have a custom WorkflowGen image, you have to perform the actions required for the web.config files if you have custom web.config files. Carefully read the section in the to see if you need to change anything in your files.
Your Dockerfile should be based on the WorkflowGen image (FROM instruction). Update the version number of the WorkflowGen image, build your image, and push it to your container registry. For example, if your version of WorkflowGen is 7.16.0 and you want to update to 7.16.1, execute the following change on the FROM instruction line:
Then, build your custom WorkflowGen image:
Finally, push the image to your container registry:
Since containers are stateless, updating them is as simple as replacing currently running ones with the new version. To do this:
Pull the new version of the container.
Remove containers with the old version.
Run containers with the new version.
For example, if you want to update to WorkflowGen version 7.16.1:
Name
Description
C:\wfgen\data
This path contains all of the WorkflowGen data, including the App_Data folder and all the workflow applications created within WorkflowGen (e.g. in the wfapps folder).
The wfapps\webforms folder is mounted as a web application in IIS.
C:\wfgen\licenses
This path contains custom licenses that you want for WorkflowGen. The container will take the first one that it detects. It's recommended to put only one license in this directory to avoid licensing problems.
If you don't have a trial license, don't forget to set the WFGEN_CONFIG_ApplicationSerialNumber environment variable according to your license.
"wfgdata", "licenses" | ForEach-Object { docker volume create $_ }Copy-Item C:\Path\To\WorkflowGen.lic $(docker volume inspect -f "{{.Mountpoint}}" licenses)docker container run `
# ...
--mount "type=volume,src=wfgdata,dst=C:\wfgen\data" `
--mount "type=volume,src=licenses,dst=C:\wfgen\licenses,readonly" `
# ...
advantys/workflowgen:7.18.3-win-ltsc2019docker container run `
# ...
--mount "type=bind,src=C:\some\path\to\wfgdata,dst=C:\wfgen\data" `
--mount "type=bind,src=C:\some\path\to\wfgen\licenses,dst=C:\wfgen\licenses,readonly" `
# ...
advantys/workflowgen:7.16.0-win-ltsc2019apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wfgdata-pvc
spec:
accessModes:
- ReadWriteMany
storageClassName: azurefile
resources:
requests:
storage: 50Gi
docker volume create pickupdocker container run `
# ...
--env WFGEN_APP_SETTING_ApplicationSmtpDeliveryMethod=PickupDirectory `
--env WFGEN_APP_SETTING_ApplicationSmtpPickupDirectory=C:\inetpub\mailroot\Pickup `
--mount "type=volume,src=pickup,dst=C:\inetpub\mailroot\Pickup" `
# ...
advantys/workflowgen:7.18.3-win-ltsc2019- FROM advantys/workflowgen-sql:7.18.2-ubuntu-18.04
+ FROM advantys/workflowgen-sql:7.18.3-ubuntu-18.04- FROM advantys/workflowgen:7.16.0-win-ltsc2019
+ FROM advantys/workflowgen:7.16.1-win-ltsc2019Set-Location C:\Path\To\Custom\Context
docker image build `
# ...
-t mycorporation/workflowgen:7.16.1-win-ltsc2019 `
# ...
.# Docker Hub is the default container registry
docker image push mycorporation/workflowgen:7.16.1-win-ltsc2019# 1. Pull the new version of the container.
# For custom images, use the name of your account instead of "advantys".
docker pull advantys/workflowgen:7.16.1-win-ltsc2019
# 2. Remove the containers with the old version.
# This code loops through all containers whose name contains "wfgen"
docker container ls --format name=wfgen -q `
| ForEach-Object { docker container rm -f $_ }
# 3. Run containers with the new version
docker container run `
# ...
advantys/workflowgen:7.16.1-win-ltsc2019This section presents what is logged in the WorkflowGen image and how. It also shows pointers to configure centralized logging with some services and orchestrators.
WorkflowGen doesn't come with metrics generation out-of-the-box. Nevertheless, you can configure some existing software or services with WorkflowGen's container in order to get more valuable metrics for monitoring performance and traffic.
When deploying WorkflowGen, many applications provide logs through different streams. This table lists the different log sources and their streams:
As you can see, there are many log sources and not all are handled directly by the container. Some of them need to be managed manually.
These logs are written in files in the App_Data folder, which is exposed through a volume. For more information about exposed volumes, see the section.
In order to centralize these logs in a logging service or system, you need to develop your own script or application that will periodically read the logs in the App_Data volume and push them to the service. Concretely, this is done by developing a Singleton container that has access to the WorkflowGen data volume. In Kubernetes, you would deploy this container inside a pod that has only one replica to avoid problems with concurrency.
These logs are written to the Windows Events API and are retrieved by the WorkflowGen container only when the start mode is win_services, dir_sync, or engine. In any other case, it's the IIS logs that are redirected to the standard output and the Windows Services logs are discarded.
IIS logs are written in multiple files inside the WorkflowGen container. You don't have to manually manage them. The container reads the logs and directs them to the standard output of the container. The standard output of each container is picked up by the Docker logging system.
There are many Docker logging drivers to indicate to Docker where to put these logs. By default, they are written on the host in JSON format at the C:\ProgramData\Docker\logs path. The rest of this section provides more information about the Docker logging system and how to use it to centralize logs.
In Kubernetes, you can configure your own logging agent or use the default one provided. For more details about logging in Kubernetes, see its page. Many cloud providers offer a centralized service to visualize logs from pods in their Kubernetes service. Refer to your cloud provider's documentation for details.
These logs are disabled by default and can be enabled by setting the following environment variables for the WorkflowGen container:
As shown, the logging is done on a per application and per container basis. To get these logs from the container, you have to use volumes and a custom application to centralize the logs, or build your own image based on the WorkflowGen image that will redirect those logs in some way to the container's standard output. For more information about making a custom WorkflowGen image, see the section.
In order to centralize logs outside of a Docker host, you first need to choose a logging system or service. Once this is done, you need to use your orchestrator's specific method to link the service to the logs.
Kubernetes has a similar functionality available to manage logs for containers. See the following link for more information:
You can also use Azure Monitor with your Kubernetes Cluster. See the following link for more information:
The Azure Kubernetes Service documentation recommends using Azure Monitor for containers. See its documentation page for more details:
This software can help you reduce costs related to monitoring applications using a cloud service. Prometheus can be deployed as a container inside your cluster alongside WorkflowGen. You'll need to add a utility to the WorkflowGen container, so you'll need to make a custom WorkflowGen image. For more information about making a custom WorkflowGen image, see the section.
Here are some links to the Prometheus documentation and Dockerfile examples to help you get started with application metrics with Prometheus:
Grafana can help you visualize metrics coming from the cluster. It also has a paid cloud service. Here are some links to get you started:
If you prefer to gather only IIS logs directly from the container, Azure Application Insights provides a PowerShell tool called Application Insights Agent that's installed directly in the container. See for more information. You'll need to create your own image that incorporates this tool inside the container. For more information about custom WorkflowGen images, see the section.
Source
Streams
WorkflowGen web applications
Logs written in the App_Data folder
WorkflowGen Windows Services
Logs written through the Windows Events API
Internet Information Services (IIS)
Logs written in files in the container
iisnode
Logs written in multiple files in each Node.js application's folder inside the container
WFGEN_IISNODE_AUTH_loggingEnabled=true
WFGEN_IISNODE_GRAPHQL_loggingEnabled=true
WFGEN_IISNODE_SCIM_loggingEnabled=true
WFGEN_IISNODE_HOOKS_loggingEnabled=true
# Also specify these values to expose the logs through HTTP
WFGEN_ENABLE_IISNODE_OPTION_AUTH=exposelogs
WFGEN_ENABLE_IISNODE_OPTION_GRAPHQL=exposelogs
WFGEN_ENABLE_IISNODE_OPTION_SCIM=exposelogs
WFGEN_ENABLE_IISNODE_OPTION_HOOKS=exposelogsWindows 10 Pro with Docker Desktop for Windows installed and Windows Containers enabled OR
Windows Server 2019 with Docker Enterprise installed
WorkflowGen's image provides a useful variant named advantys/workflowgen:7.18.3-win-ltsc2019-onbuild that can be used to easily customize any file contained in C:\inetpub\wwwroot or C:\Program Files\Advantys\WorkflowGen. All you need to do is create your own image with a Dockerfile that inherits from the onbuild variant and put the customized files in the Docker build context.
Here's a simple example that replaces the web.config file, customizes the banner, and adds a custom library.
Here's the file tree of the context directory from which you'll build your custom WorkflowGen image:
File tree:
Here's the content of the Dockerfile:
Build with Docker Compose
With Docker Compose, you can specify the build parameters in a declarative format in order to integrate the Docker build process with the run. For example, you could have the following Compose file named docker-compose.yml in your context directory:
(This file is from the Getting started section.)
Then, to build and tag automatically, you could run the following command:
Docker Compose will then build and tag your image with the tag present in the image property. If you want to immediately update your Compose deployment on your local machine or immediately execute this deployment after the build, execute the following command, which will build your container in addition to running the services after the build:
To push the image using Docker Compose, execute the following command:
You now have a customized WorkflowGen image. For more information on updating your container when a new WorkflowGen version is available, see the Update Management section.
Let's say in addition to DLLs and custom banners you have an ASP.NET 2.0 web application to add to the wfapps folder and configure in IIS. You would perform the same steps as before, but also add a custom Docker CMD script that will configure the application in IIS.
Multiple PowerShell scripts come with the WorkflowGen image and have different purposes:
docker-entrypoint.ps1: This is the main script that gets executed when you run a container. It handles the parsing of environment variables, configuration of authentication methods, etc.
monitor-services.ps1: This script handles the monitoring of processes (IIS and Windows services), as well as gathering the logs of the container and redirecting them to the standard output.
healthcheck.ps1: This handles the periodic check that indicates if WorkflowGen is working properly or not. This is defined in the WorkflowGen Dockerfile and is handled by the Docker engine.
*.psm1: Various developed PowerShell modules available in the image.
ServiceMonitor.exe: Binary executable provided by Microsoft. This is the main executable used by the monitoring script to check the state of a service. (You can find more information about ServiceMonitor on its GitHub page at ).
set-state.ps1: Sets the state of the container, such as bringing the website offline or online.
By creating your own WorkflowGen image in Docker, you can replace any script with your own that does something else completely, and it's a best practice to do so if the stock scripts don't do what you want. In the case of this example, the stock scripts don't take care of setting the added web application as in IIS; you need to develop your own script for this. Here's the one that you'll use in this example:
In this script, note the following:
You're checking for the start service type and checking if you've already added the web service as a web application in IIS.
Rationale
This is because the entrypoint script is re-run between restarts of the container. Therefore, this script will also be re-run after a restart. When restarting a container, the IIS configuration stays and the ConvertTo-WebApplication command will cause the start procedure to fail when trying to add an already-added web application. Consequently, you have to check that you haven't already added the application.
Also, you're checking if the container is running in web applications mode. When it isn't, you don't need to add your web service in IIS because there will be only Windows services that will run.
You're checking for arguments and executing them if there are some. If not, you start to monitor the container's services.
Rationale
This is a general good practice in a Docker container. For example, if you're debugging the container and only want to prompt a PowerShell command line after the start sequence, you would pass powershell as an argument to the run command like so:
The powershell argument will be executed by the Invoke-Expression command and a new PowerShell command prompt will be displayed. If no arguments are passed, the default behavior is to start monitoring the services. Since the image already has a script for that, you only need to execute it.
Your Dockerfile will then be as follows:
After that, you'll perform the same build and push steps as the previous example.
context-dir\
inetpub\
wwwroot\
web.config
wfgen\
web.config
bin\
MyCustomLib.dll
ws\
bin\
MyCustomLib.dll
App_Themes\
Default\
portal\
banner\
banner.htm
Program Files\
Advantys\
WorkflowGen\
Services\
Bin\
MyCustomLib.dll context-dir\
Dockerfile
inetpub\
wwwroot\
web.config
wfgen\
web.config
bin\
MyCustomLib.dll
ws\
bin\
MyCustomLib.dll
App_Themes\
Default\
portal\
banner\
banner.htm
Program Files\
Advantys\
WorkflowGen\
Services\
Bin\
MyCustomLib.dll #escape=`
FROM advantys/workflowgen:7.18.3-win-ltsc2019-onbuild
# You can add any instructions in order to install other services or tools, etc.
# You also can add other files at any other location in the container. Set-Location C:\Path\To\context-dir
docker image build -t mycorporation/workflowgen:7.18.3-win-ltsc2019 .
# Optionally, you can push your custom image to your container registry
docker image push mycorporation/workflowgen:7.18.3-win-ltsc2019 version: '3.7'
services:
workflowgen:
build:
context: .
dockerfile: .\Dockerfile
image: mycorporation/workflowgen:7.18.3-win-ltsc2019
restart: always
env_file:
- '.\workflowgen.env'
ports:
- '8080:80'
volumes:
- 'wfgdata:C:\wfgen\data'
- 'licenses:C:\wfgen\licenses:RO'
depends_on:
- database
database:
image: advantys/workflowgen-sql:7.18.3-express-win-ltsc2019
env_file:
- '.\database.env'
volumes:
- 'sqldata:C:\wfgen\sql'
volumes:
wfgdata:
licenses:
external: true
sqldata:
docker-compose build workflowgen docker-compose up --build docker-compose push workflowgen<#
.SYNOPSIS
Add the custom web application to IIS.
.NOTES
File name: custom-web-app-install.ps1
#>
#requires -Version 5.1
Import-Module IISAdministration
Import-Module C:\Const.psm1 -Variable Constants
Import-Module C:\Utils.psm1 -Fonction "Get-EnvVar"
$wfgenStartService = (Get-EnvVar "WFGEN_START_SERVICE" -DefaultValue "all").ToLower()
$isWebServices = $wfgenStartService -eq $Constants.SERVICE_ALL -or
$wfgenStartService -eq $Constants.SERVICE_WEB_APPS
if ($isWebServices -and (Get-WebApplication -Site "wfgenroot" -Name "wfgen/wfapps/<YOUR_WEB_SERVICE_NAME>").Count -le 0) {
Write-Host "CONFIG: Adding mywebapp to IIS ... " -NoNewLine
ConvertTo-WebApplication -PSPath "IIS:\Sites\wfgenroot\wfgen\WfApps\<YOUR_WEB_SERVICE_NAME>" | Out-Null
Write-Host "done" -ForegroundColor Green
}
if ($args.Count -gt 0) {
Invoke-Expression ($args -join " ")
} else {
. C:\monitor-services.ps1
}#escape=`
FROM advantys/workflowgen:7.18.3-win-ltsc2019-onbuild
SHELL ["powershell", "-Command"]
COPY .\custom-web-app-install.ps1 C:\
CMD C:\custom-web-app-install.ps1 docker container run -it `
# ...
mycorporation/workflowgen:7.18.3-win-ltsc2019 C:\custom-web-app-install.ps1 powershellThis section explains how to completely configure a WorkflowGen database container. Everything is configurable via an environment variable.
Some variables are available in the base images that provide functionalities related to SQL Server. For the Linux version, see the Docker Hub page and the Microsoft article. For the Windows version, see the Docker Hub page.
The WorkflowGen database container adds special environment variables to enable additional features related to WorkflowGen. The following table provides descriptions for each of them:
When using an orchestrator such as Kubernetes, you'll probably want to secure secrets using their built-in secret management tools. Follow the specific guide for your orchestrator to know how to create a secret.
For Kubernetes, see .
It's recommended to inject secrets into WorkflowGen containers as files because they won't be exposed as environment variables and they'll be removed from the container when it's stopped or removed.
In order to get the secret value in the file, you need to suffix any environment variable you want to get the value of in this way with _FILE and set its value to the path of the file containing the secret. The container will then get the value in the file at the specified path and set the environment variable without the suffix with that value.
For example, let's say you want to set sa account password in SQL Server to strong(!)Pass using the environment variable SA_PASSWORD, but you want to use a secret for the value. All you have to do is suffix the environment variable name with _FILEso that it becomes SA_PASSWORD_FILE. Then, set the value of this variable to the path of the file containing the password.
For Kubernetes, you would create a ConfigMap that complements your secret like this:
Then, you would map the ConfigMap as environment variables and mount the secret as a volume like this:
Kubernetes also has a built-in object called ConfigMap to manage pod configuration. See the Kubernetes article for more information and how to use it. You should use this object to configure environment variables for WorkflowGen.
You can also manage sensitive information by protecting it further in the orchestrator in a secure area. See the Kubernetes article for more information and instructions on how to use it. You should use this object to protect sensitive information such as the WorkflowGen license key, usernames, passwords, cryptographic keys, API keys, etc.
Some popular configuration managers support Docker containers out-of-the-box. Here are a few links to their specific documentation to get you started:
The Linux version of the database has some security features that can be used to improve the overall security of the database. For more information on security features in SQL Server for Linux, see in the Microsoft SQL Server documentation.
The Windows version of the container doesn't have the security features of the Linux version. It's advised to use the Windows version only for development and testing purposes.
You can configure replication with this container, but you'll have to make a custom image. For more information about making a custom image, see the page of this section. For more information about configuring replication in SQL Server, see in the Microsoft documentation.
You should always deploy the database container within a StatefulSet so that each container has its own separated storage. It also ensures that each container has a unique DNS name inside the cluster so that it can be found easily by other containers. You can also configure each of the instances based on an incremental identifier so that you can set a read/write instance and several read-only instances. Here's an example of a simple StatefulSet deployment with the WorkflowGen database container:
You can use this example as a starting point to configure multiple database containers. For more information about StatefulSets, see in the Kubernetes documentation. You might need custom code to be able to configure multiple instances properly. See the page of this section for more information about how you can add custom code to the container.
The username of the WorkflowGen administrative user
Default value: wfgen_admin
WFGEN_ADMIN_PASSWORD
Required variable
The password of the WorkflowGen administrative user
WFGEN_AUTH_APPLICATION
Indicates if the authentication method of WorkflowGen is applicative or not
Possible values: Y (default), N
Variable
Description & values
WFGEN_DATABASE_NAME
The name of the WorkflowGen database
Default value: WFGEN
WFGEN_DATABASE_CONTAINMENT
Sets the WorkflowGen database to contain database users for more portability (see contained database authentication Server configuration option for more information)
Possible values: Y (default), N
WFGEN_DATABASE_USER_USERNAME
The username of the database user that has access to the WorkflowGen database
Default value: WFGEN_USER
WFGEN_DATABASE_USER_PASSWORD
Required variable
The password of the database user that has access to the WorkflowGen database
WFGEN_DATABASE_FILE_PATH
Do not modify for Linux version
Internal path to the .mdf and .ldf database files inside the container
Default value:
Windows: C:\wfgen\sql
Linux: /var/opt/mssql/data
WFGEN_ADMIN_USERNAME
# Create the secret for the license serial number
'strong(!)Pass' | docker secret create SA_PASSWORD -
# Create the container service in Docker Swarm
docker service create `
# ...
--env WFGEN_APP_SETTING_ApplicationSerialNumber_FILE=/run/secrets/SA_PASSWORD `
--secret SA_PASSWORD `
# ...
advantys/workflowgen-sql:7.18.3-ubuntu-18.04# Create the secret for the license serial number
echo 'strong(!)Pass' | docker secret create SA_PASSWORD -
# Create the container service in Docker Swarm
docker service create \
# ...
--env WFGEN_APP_SETTING_ApplicationSerialNumber_FILE=/run/secrets/SA_PASSWORD \
--secret SA_PASSWORD \
# ...
advantys/workflowgen-sql:7.18.3-ubuntu-18.04apiVersion: v1
kind: ConfigMap
metadata:
name: database-config
data:
SA_PASSWORD_FILE: /mnt/secrets/SA_PASSWORD
---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: database-secret
data:
# "c3Ryb25nKCEpUGFzcwo=" is the base64-encoded value of "strong(!)Pass"
SA_PASSWORD: 'c3Ryb25nKCEpUGFzcwo='
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: wfgen-database
spec:
selector:
matchLabels:
# ...
template:
metadata:
labels:
# ...
spec:
containers:
- name: database
image: advantys/workflowgen-sql:7.18.3-ubuntu-18.04
# ...
envFrom: # ConfigMap as environment variables
- configMapRef:
name: database-config
# ...
volumeMounts:
# ...
- mountPath: /mnt/secrets # Mount Secret as a volume
readOnly: true
name: secrets
volumes:
# ...
- name: secrets # Mount Secret as a volume
secret:
secretName: database-secretapiVersion: v1
kind: Service
metadata:
name: database
spec:
type: ClusterIP
clusterIP: None
ports:
- port: 1433
targetPort: mssql
protocol: TCP
name: mssql
selector:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: database
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: database
spec:
replicas: 1
serviceName: database
selector:
matchLabels:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: database
template:
metadata:
labels:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: database
spec:
terminationGracePeriodSeconds: 10
nodeSelector:
kubernetes.io/os: linux
containers:
- name: database
image: advantys/workflowgen-sql:7.18.3-ubuntu-18.04
imagePullPolicy: Always
securityContext:
runAsUser: 0
runAsGroup: 0
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "1"
envFrom:
- configMapRef:
name: database-config
ports:
- name: mssql
containerPort: 1433
livenessProbe:
initialDelaySeconds: 30
timeoutSeconds: 5
exec:
command:
- pwsh
- -NoLogo
- -NoProfiles
- /usr/local/bin/healthcheck.ps1
readinessProbe:
initialDelaySeconds: 20
timeoutSeconds: 5
exec:
command:
- pwsh
- -NoLogo
- -NoProfiles
- /usr/local/bin/healthcheck.ps1
volumeMounts:
- mountPath: /var/opt/mssql
name: sqldata
- mountPath: /mnt/secrets
readOnly: true
name: secrets
volumes:
- name: secrets
secret:
secretName: database-sec
volumeClaimTemplates:
- metadata:
name: sqldata
spec:
accessModes:
- ReadWriteOnce
storageClassName: default
resources:
requests:
storage: 100GiThis section presents the recommended container architecture for WorkflowGen in order to run the web portals and Windows services. There will be many references to the image configuration properties; see the Configuration section for information on these.
See the section for information on SQL database deployments, and the section for information on volume deployment.
This is the simplest architecture you can run with WorkflowGen: a single container without replicas that runs both web applications and Windows Services. Therefore, you would set the WFGEN_START_SERVICE environment variable to all. This architecture is well suited to development and test environments, but it can also be considered when the performance with a single container fits the product usage. You can't replicate the container because there should only be one instance of each WorkflowGen Windows Service running.
This is the same example as in the section. It has one WorkflowGen container that runs every service (web applications and Windows Services).
This example is different from the example. This Helm release is not scalable in the cluster. It has a pod that runs all of the WorkflowGen services (web applications and Windows services) and another pod for the database. You can use the steps in the example to generate the requested values. Don't forget to get the external IP address of the load balancer once it's created.
Since there can be only one instance of each WorkflowGen Windows Service running at a time, this architecture lets you run multiple replicas of the web applications in order to scale WorkflowGen to meet your traffic and processing needs without having more instances of the Windows Services.
You'll need to set the WFGEN_START_SERVICE environment variable to web_apps for the web applications' containers, and to win_services for the single container to run all of the Windows Services without web applications. This architecture is good for scaling the web portals to the traffic and processing needs, without too much pressure on the Windows Services.
This is the same example as in the section. The Windows Services containers will always be in the same pod when you use the WorkflowGen Helm chart. You can use the steps in the example to generate the requested values. Don't forget to get the external IP address of the load balancer once it's created.
This recommended architecture is the most scalable. It has multiple containers for the web applications that can be scaled for increased traffic or processing needs, and has dedicated containers for each Windows Service: one for the directory synchronization service and one for the engine service. Therefore, you would set the WFGEN_START_SERVICE environment variable to web_apps for the web applications' containers, to dir_sync for the directory synchronization service container, and to engine for the engine service container. This architecture is good for high availability and high performance scenarios.
This is the same example as in the section. The Windows services containers will always be in the same pod when you use the WorkflowGen Helm chart. You can use the steps in the example to generate the requested values. Don't forget to get the external IP address of the load balancer once it's created.
This section explains how to completely configure a WorkflowGen container, including the web.config file, iisnode configuration for Node.js applications, database connection strings, etc. Everything is configurable via an environment variable except the license file, which is configured via a volume.
WorkflowGen's image provides a number of specific environment variables that makes specific configurations possible. The following table provides descriptions of each of them:
WorkflowGen's image also exposes various environment variables based on a specific format in order to configure more generic elements.
web.configIn WorkflowGen, the web.config file is the main point of configuration. Since a container is by definition ephemeral, any changes made in the Configuration Panel would not persist between container restarts.
In order to set configuration properties in the web.config file, you need to use a specific format for an environment variable that will contain the value of the property you want to set; this format is WFGEN_APP_SETTING_<name>.
For example, if you want to set the ApplicationUrl property in the web.config to https://mycorporation.com/wfgen, you would set the WFGEN_APP_SETTING_ApplicationUrl=https://mycorporation.com/wfgen environment variable in the container.
run commandFor a list of web.config parameters and their descriptions and possible values, see the appendix in the .
You can also set specific iisnode properties for each Node.js application. To do this, you need to set an environment variable with the following format: WFGEN_IISNODE_<node name>_<property name>.
Replace <node name> with the name of the Node.js application (AUTH, HOOKS, GRAPHQL, or SCIM).
Replace <property name> with the name of the property you want to set for the <iisnode/> XML node in the specific Node.js application's web.config
For example, if you want to set the iisnode loggingEnabled property in the Auth application to true, you would set the environment variable WFGEN_IISNODE_AUTH_loggingEnabled=true.
run commandThere are some special options that you can enable for each Node.js application by setting an environment variable that has the following template: WFGEN_ENABLE_IISNODE_OPTION_<node app name>. Then, you replace <node app name> with the name of the Node.js application (AUTH for example) and the value must be one of the following:
The main connection string can be configured via the WFGEN_DATABASE_CONNECTION_STRING environment variable. You can put any string in this variable and its value will be put in WorkflowGen's web.config file at the MainDbSource connection string.
Here's how to specify the connection string with the run command:
If you have a read-only replica, you can configure it in the container as well. You can specify it with the WFGEN_DATABASE_READONLY_CONNECTION_STRING environment variable. It will be added to WorkflowGen's web.config file as a new entry in the connection strings with the name ReadOnlyDbSource.
Here's how to specify the read-only connection string with the run command:
You can also configure more connections to custom data sources if you need to. They can be configured using a specific environment variable format: WFGEN_CUSTOM_CONNECTION_STRING_<name>=<connection_string>.
For example, if you want a data source named MyDataSource with the connection string value of MyConnectionString in the WorkflowGen web.config, you would specify the following environment variable: WFGEN_CUSTOM_CONNECTION_STRING_MyDataSource=MyConnectionString.
run commandWhen using an orchestrator such as Kubernetes, you'll probably want to secure secrets using their built-in secret management tools. Follow the specific guide for your orchestrator to know how to create a secret.
For Kubernetes, see .
It's recommended to inject secrets into WorkflowGen containers as files because they won't be exposed as environment variables and they'll be removed from the container when it's stopped or removed.
In order to get the secret value in the file, you need to suffix any environment variable you want to get the value of this way with _FILE and set its value to the path of the file containing the secret. The container will then get the value in the file at the specified path and set the environment variable without the suffix with that value.
For example, let's say you want to set the license serial number in the web.config to WFG-SOME-LICENSE-KEY using the environment variable WFGEN_APP_SETTING_ApplicationSerialNumber, but you want to use a secret for the value. All you have to do is suffix the environment variable name with _FILE so it becomes WFGEN_APP_SETTING_ApplicationSerialNumber_FILE. Then, set the value of this variable to the path of the file containing the serial number.
For Kubernetes, you would create a ConfigMap that complements your secret like this:
Then, you would map the ConfigMap as environment variables and mount the secret as a volume like this:
In order to let WorkflowGen handle authentication and the storage of user passwords, you don't need to configure anything special in the container. Keep in mind that the default username for the WorkflowGen administrative account is wfgen_admin.
In order to make Windows or Basic authentication modes work, your host needs to be in an Active Directory forest. Creating a user account on the host for Basic authentication won't work, because the IIS web server inside the container will try to find a user account registered inside the container instead of the host. For this reason, you need Active Directory.
To configure your Docker host to work with Active Directory to authenticate users, follow the (gMSA) guide from Microsoft in its Windows Containers documentation.
Kubernetes supports gMSAs for Windows pods and containers as of version 1.18. See the Kubernetes article for details on how to configure it. Keep in mind that not all cloud providers supports gMSAs with Kubernetes. For example, Azure Kubernetes Service doesn't support this feature.
You can't use Basic authentication with Kubernetes.
For these providers, there is no special configuration to do other than setting the WFGEN_AUTH_MODE variable. For configuration instructions, see the guide.
For these providers, there is no special configuration to do other than setting the WFGEN_AUTH_MODE variable. For configuration instructions, see the .
In order to configure your license, you need to set a specific environment variable with your license and copy your license file into a volume exposed to the WorkflowGen container. To do this, you first need to create a license volume or have your license at a specific path.
This will create a volume at a specific path on your file system (typically C:\ProgramData\Docker\volumes\licenses\_data) managed by Docker. You can get the path to the volume by executing the following command:
Then, you need to copy your license file to this location:
Now, you can run the WorkflowGen container like so:
Here, you'll provide a path that you control as a volume to the container. You only need to pass the path when you run WorkflowGen:
You can bring the web applications inside WorkflowGen's container offline by executing a script embedded in the image. This is useful to ensure that the site is still available when you want to perform maintenance tasks on its data without anything new being written. With pure containers, you can execute the following command:
With Kubernetes, you can use kubectl:
If you browse to your WorkflowGen website, you'll see the default offline web page. You can customize this web page by adding your own HTML file at the path <wfgen appdata>\Templates\server\offline.htm. If this file is present, it will be taken instead of the default one. If you have a volume for WorkflowGen's data, you can execute the following script:
You can bring the site back online by executing the following command:
Kubernetes also has a built-in object called ConfigMap to manage pod configuration. See the Kubernetes article for more information and instructions on how to use it. You should use this object to configure environment variables for WorkflowGen.
You can also manage sensitive information by protecting it further in the orchestrator in a secure area. See the Kubernetes article for more information and instructions on how to use it. You should use this object to protect sensitive information such as the WorkflowGen license key, usernames, passwords, cryptographic keys, API keys, etc.
In order to use your own configuration files, you should build your own WorkflowGen image using the WorkflowGen onbuild image variant. See the page in the WorkflowGen Image section for more information.
Some popular configuration managers support Docker containers out-of-the-box. Here are a few links to their specific documentation to get you started:
version: '3.7'
services:
workflowgen:
image: advantys/workflowgen:7.18.3-win-ltsc2019
restart: always
env_file:
- '.\workflowgen.env'
ports:
- '8080:80'
volumes:
- 'wfgdata:C:\wfgen\data'
- 'licenses:C:\wfgen\licenses:RO'
depends_on:
- database
database:
image: advantys/workflowgen-sql:7.18.3-express-win-ltsc2019
env_file:
- '.\database.env'
volumes:
- 'sqldata:C:\wfgen\sql'
volumes:
wfgdata:
licenses:
external: true
sqldata:
scalable: false
workflowgen:
resources:
limits:
cpu: '1'
memory: 2Gi
requests:
cpu: '1'
memory: 2Gi
config:
WFGEN_APP_SETTING_ApplicationUrl: http://10.0.1.1/wfgen
WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\ApplicationSerialNumber
WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\ApplicationSecurityPasswordSymmetricEncryptionKey
WFGEN_MACHINE_KEY_DECRYPTION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_DECRYPTION_KEY
WFGEN_MACHINE_KEY_VALIDATION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_VALIDATION_KEY
secret:
ApplicationSerialNumber: <YOUR_WFG_LIC_KEY>
ApplicationSecurityPasswordSymmetricEncryptionKey: <YOUR_NEW_GUID>
WFGEN_DATABASE_CONNECTION_STRING: 'Server=wfgen-database-0.wfgen-database.default.svc.cluster.local,1433;Database=WFGEN;User ID=WFGEN_USER;Password=strong(!)Pass;'
WFGEN_MACHINE_KEY_DECRYPTION_KEY: '39B3AE9CCCF94AA47D795EC84F7CCB7928F5D59BE2EB2BBA4FE2AC0B3C8D0C85'
WFGEN_MACHINE_KEY_VALIDATION_KEY: '82F6247A5DBF8666FB60B8EFE6483360436F0EC426CC0351A9569C607B46C1FAD6497406DD8B0B519DD83CAA6764904C89999D742638ECE756E7C0B8799B45E9'
license:
secretName: wfgen-license-secret
items:
- key: WorkflowGen.lic
path: WorkflowGen.lic
dataPvcSpec:
accessModes:
- ReadWriteMany
storageClassName: azurefile
resources:
requests:
storage: 50Gi
service:
type: LoadBalancer
database:
fullnameOverride: wfgen-database
nodeSelector:
kubernetes.io/os: linux
securityContext:
runAsUser: 0
runAsGroup: 0
resources:
limits:
cpu: '1'
memory: 2Gi
requests:
cpu: '500m'
memory: 1Gi
config:
ACCEPT_EULA: 'Y'
SA_PASSWORD_FILE: /mnt/secrets/SA_PASSWORD
WFGEN_DATABASE_USER_USERNAME_FILE: /mnt/secrets/WFGEN_DATABASE_USER_USERNAME
WFGEN_DATABASE_USER_PASSWORD_FILE: /mnt/secrets/WFGEN_DATABASE_USER_PASSWORD
WFGEN_ADMIN_PASSWORD_FILE: /mnt/secrets/WFGEN_ADMIN_PASSWORD
secret:
SA_PASSWORD: 'strong(!)Pass'
WFGEN_DATABASE_USER_PASSWORD: 'strong(!)Pass'
WFGEN_ADMIN_PASSWORD: 'strong(!)Pass'
WFGEN_DATABASE_USER_USERNAME: WFGEN_USER
volumeClaimTemplateSpec:
accessModes:
- ReadWriteOnce
storageClassName: default
resources:
requests:
storage: 100Gi
ingress:
enabled: false
version: '3.7'
services:
workflowgen-web-apps:
image: advantys/workflowgen:7.18.3-win-ltsc2019
restart: always
env_file:
- '.\workflowgen.env'
environment:
WFGEN_START_SERVICE: web_apps
ports:
- '8080:80'
volumes:
- 'wfgdata:C:\wfgen\data'
- 'licenses:C:\wfgen\licenses:RO'
depends_on:
- database
workflowgen-win-services:
image: advantys/workflowgen:7.18.3-win-ltsc2019
restart: always
env_file:
- '.\workflowgen.env'
environment:
WFGEN_START_SERVICE: win_services
volumes:
- 'wfgdata:C:\wfgen\data'
- 'licenses:C:\wfgen\licenses:RO'
depends_on:
- database
database:
image: advantys/workflowgen-sql:7.18.3-express-win-ltsc2019
env_file:
- '.\database.env'
volumes:
- 'sqldata:C:\wfgen\sql'
volumes:
appdata:
licenses:
external: true
sqldata:
replicaCount: 3
workflowgen:
resources:
limits:
cpu: '1'
memory: 2Gi
requests:
cpu: '1'
memory: 2Gi
config:
WFGEN_APP_SETTING_ApplicationUrl: http://10.0.1.1/wfgen
WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\ApplicationSerialNumber
WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\ApplicationSecurityPasswordSymmetricEncryptionKey
WFGEN_MACHINE_KEY_DECRYPTION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_DECRYPTION_KEY
WFGEN_MACHINE_KEY_VALIDATION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_VALIDATION_KEY
secret:
ApplicationSerialNumber: <YOUR_WFG_LIC_KEY>
ApplicationSecurityPasswordSymmetricEncryptionKey: <YOUR_NEW_GUID>
WFGEN_DATABASE_CONNECTION_STRING: 'Server=wfgen-database-0.wfgen-database.default.svc.cluster.local,1433;Database=WFGEN;User ID=WFGEN_USER;Password=strong(!)Pass;'
WFGEN_MACHINE_KEY_DECRYPTION_KEY: '39B3AE9CCCF94AA47D795EC84F7CCB7928F5D59BE2EB2BBA4FE2AC0B3C8D0C85'
WFGEN_MACHINE_KEY_VALIDATION_KEY: '82F6247A5DBF8666FB60B8EFE6483360436F0EC426CC0351A9569C607B46C1FAD6497406DD8B0B519DD83CAA6764904C89999D742638ECE756E7C0B8799B45E9'
license:
secretName: wfgen-license-secret
items:
- key: WorkflowGen.lic
path: WorkflowGen.lic
dataPvcSpec:
accessModes:
- ReadWriteMany
storageClassName: azurefile
resources:
requests:
storage: 50Gi
service:
type: LoadBalancer
winServices:
dirSync:
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: '500M'
memory: 1Gi
engine:
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: '500M'
memory: 1Gi
database:
fullnameOverride: wfgen-database
nodeSelector:
kubernetes.io/os: linux
securityContext:
runAsUser: 0
runAsGroup: 0
resources:
limits:
cpu: '1'
memory: 2Gi
requests:
cpu: '500m'
memory: 1Gi
config:
ACCEPT_EULA: 'Y'
SA_PASSWORD_FILE: /mnt/secrets/SA_PASSWORD
WFGEN_DATABASE_USER_USERNAME_FILE: /mnt/secrets/WFGEN_DATABASE_USER_USERNAME
WFGEN_DATABASE_USER_PASSWORD_FILE: /mnt/secrets/WFGEN_DATABASE_USER_PASSWORD
WFGEN_ADMIN_PASSWORD_FILE: /mnt/secrets/WFGEN_ADMIN_PASSWORD
secret:
SA_PASSWORD: 'strong(!)Pass'
WFGEN_DATABASE_USER_PASSWORD: 'strong(!)Pass'
WFGEN_ADMIN_PASSWORD: 'strong(!)Pass'
WFGEN_DATABASE_USER_USERNAME: WFGEN_USER
volumeClaimTemplateSpec:
accessModes:
- ReadWriteOnce
storageClassName: default
resources:
requests:
storage: 100Gi
version: '3.7'
services:
workflowgen-web-apps:
image: advantys/workflowgen:7.18.3-win-ltsc2019
restart: always
env_file:
- '.\workflowgen.env'
environment:
WFGEN_START_SERVICE: web_apps
ports:
- '8080:80'
volumes:
- 'wfgdata:C:\wfgen\data'
- 'licenses:C:\wfgen\licenses:RO'
depends_on:
- database
workflowgen-dir-sync-service:
image: advantys/workflowgen:7.18.3-win-ltsc2019
restart: always
env_file:
- '.\workflowgen.env'
environment:
WFGEN_START_SERVICE: dir_sync
volumes:
- 'wfgdata:C:\wfgen\data'
- 'licenses:C:\wfgen\licenses:RO'
depends_on:
- database
workflowgen-engine-service:
image: advantys/workflowgen:7.18.3-win-ltsc2019
restart: always
env_file:
- '.\workflowgen.env'
environment:
WFGEN_START_SERVICE: engine
volumes:
- 'wfgdata:C:\wfgen\data'
- 'licenses:C:\wfgen\licenses:RO'
depends_on:
- database
database:
image: advantys/workflowgen-sql:7.18.3-express-win-ltsc2019
env_file:
- '.\database.env'
volumes:
- 'sqldata:C:\wfgen\sql'
volumes:
wfgdata:
licenses:
external: true
sqldata:
replicaCount: 3
workflowgen:
resources:
limits:
cpu: '1'
memory: 2Gi
requests:
cpu: '1'
memory: 2Gi
config:
WFGEN_APP_SETTING_ApplicationUrl: http://10.0.1.1/wfgen
WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\ApplicationSerialNumber
WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\ApplicationSecurityPasswordSymmetricEncryptionKey
WFGEN_MACHINE_KEY_DECRYPTION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_DECRYPTION_KEY
WFGEN_MACHINE_KEY_VALIDATION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_VALIDATION_KEY
secret:
ApplicationSerialNumber: <YOUR_WFG_LIC_KEY>
ApplicationSecurityPasswordSymmetricEncryptionKey: <YOUR_NEW_GUID>
WFGEN_DATABASE_CONNECTION_STRING: 'Server=wfgen-database-0.wfgen-database.default.svc.cluster.local,1433;Database=WFGEN;User ID=WFGEN_USER;Password=strong(!)Pass;'
WFGEN_MACHINE_KEY_DECRYPTION_KEY: '39B3AE9CCCF94AA47D795EC84F7CCB7928F5D59BE2EB2BBA4FE2AC0B3C8D0C85'
WFGEN_MACHINE_KEY_VALIDATION_KEY: '82F6247A5DBF8666FB60B8EFE6483360436F0EC426CC0351A9569C607B46C1FAD6497406DD8B0B519DD83CAA6764904C89999D742638ECE756E7C0B8799B45E9'
license:
secretName: wfgen-license-secret
items:
- key: WorkflowGen.lic
path: WorkflowGen.lic
dataPvcSpec:
accessModes:
- ReadWriteMany
storageClassName: azurefile
resources:
requests:
storage: 50Gi
service:
type: LoadBalancer
winServices:
dirSync:
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: '500M'
memory: 1Gi
engine:
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: '500M'
memory: 1Gi
database:
fullnameOverride: wfgen-database
nodeSelector:
kubernetes.io/os: linux
securityContext:
runAsUser: 0
runAsGroup: 0
resources:
limits:
cpu: '1'
memory: 2Gi
requests:
cpu: '500m'
memory: 1Gi
config:
ACCEPT_EULA: 'Y'
SA_PASSWORD_FILE: /mnt/secrets/SA_PASSWORD
WFGEN_DATABASE_USER_USERNAME_FILE: /mnt/secrets/WFGEN_DATABASE_USER_USERNAME
WFGEN_DATABASE_USER_PASSWORD_FILE: /mnt/secrets/WFGEN_DATABASE_USER_PASSWORD
WFGEN_ADMIN_PASSWORD_FILE: /mnt/secrets/WFGEN_ADMIN_PASSWORD
secret:
SA_PASSWORD: 'strong(!)Pass'
WFGEN_DATABASE_USER_PASSWORD: 'strong(!)Pass'
WFGEN_ADMIN_PASSWORD: 'strong(!)Pass'
WFGEN_DATABASE_USER_USERNAME: WFGEN_USER
volumeClaimTemplateSpec:
accessModes:
- ReadWriteOnce
storageClassName: default
resources:
requests:
storage: 100Gi
See the Access the Kubernetes web dashboard in Azure Kubernetes Service (AKS) Microsoft article for instructions on how to connect to it in Azure Kubernetes Service.
Octant is an open source software from VMware to visualize Kubernetes clusters. You can also edit some YAML definitions and forward ports directly to your machine.
File name (including extension) of the license needed in the C:\licenses volume
If none is specified, the first file found is taken.
WFGEN_START_SERVICE
Indicates what the container should run
You can either run the WorkflowGen web application or Windows Services, or both. In a cluster, you'd probably want to have multiple containers in web app mode and only one container in Windows Services mode. You can also divide more by running multiple containers in web app mode, one container in engine mode, and one container in directory sync mode.
Possible values:
all (default)
WFGEN_MACHINE_KEY_VALIDATION_KEY
Represents the validationKey property of the machineKey element in the web.config file
By default, IIS generates one when it isn't there. It's recommended to use this environment variable to share the machine key between instances of this container (e.g. in a web farm). See the and Microsoft articles for more details.
WFGEN_MACHINE_KEY_DECRYPTION_KEY
Represents the decryptionKey property of the machineKey element in the web.config file
By default, IIS generates one when it isn't there. It's recommended to use this environment variable to share the machine key between instances of this container (e.g. in a web farm). See the and Microsoft articles for more details.
WFGEN_MACHINE_KEY_VALIDATION_ALG
Represents the validation property of the machineKey element in the web.config file
The algorithm name used to generate the validation key. Default: HMACSHA256
WFGEN_MACHINE_KEY_DECRYPTION_ALG
Represents the decryption property of the machineKey element in the web.config file
The algorithm name used to generate the decryption key.
Default: AES
WFGEN_DEPENDENCY_CHECK_INTERVAL
Time between dependency check retries in milliseconds
Default: 1000 (1 second)
WFGEN_DEPENDENCY_CHECK_RETRIES
Number of retries to attempt for each dependency check
Default: 10
WFGEN_DEPENDENCY_CHECK_ENABLED
Indicates whether or not the dependency check should be done
Possible values: Y (default), N
WFGEN_GRAPHQL_CORS_ENABLED
Enables CORS headers for the GraphQL API
Possible values: Y (default), N
WFGEN_GRAPHQL_CORS_ALLOWED_ORIGINS
Comma-separated list of origins from which CORS will allow requests
Default: *
Variable
Description & values
WFGEN_ADMIN_USERNAME
The username for the WorkflowGen administrator account
Changing this value is useful when you are configuring this image with an OpenID provider. You can set it to a username that exists on the provider that you have access to. Then, when you browse to WorkflowGen, you can authenticate with it and it will log you in as an administrator.
For example, if you have a username on your provider named [email protected], then you can set this environment variable to this username and authenticate with it in the container to have administrative access to WorkflowGen.
✏️ Note: If you change this, make sure to update the database as well.
Possible values: wfgen_admin (default)
WFGEN_DATABASE_CONNECTION_STRING
Required variable
The connection string of the main database source
This environment variable must be present, or else the container will throw an error and exit.
WFGEN_DATABASE_READONLY_
CONNECTION_STRING
The connection string of the read-only database source for a database setup with replicas
WFGEN_AUTH_MODE
This variable indicates which authentication method to be used by WorkflowGen
Possible values:
adfs
application (default)
auth0
azure-v1
basic
ms-identity-v2
okta
windows
WFGEN_GEN_APP_SYM_ENCRYPT_KEY
Indicates whether or not the ApplicationSecurityPasswordSymmetricEncryptionKey should be generated if no value is provided
If Y, the ApplicationSecurityPasswordSymmetricEncryptionKey is regenerated when the container restarts. It is not compatible for usage in production because the secrets will be encrypted with different keys. Therefore, use Y only for developing or testing a single container scenario.
Possible values: Y (default), N
Value name
Description
exposelogs
Exposes the logs of the application through http. They will then be available at https://example.com/wfgen/auth/iisnode if the chosen Node.js application is AUTH.
✏️ Note: This option is for debugging purposes only. It is not recommended to use it in production.
WFGEN_LICENSE_FILE_NAME
docker container run `
# ...
--env 'WFGEN_APP_SETTING_ApplicationUrl=https://mycorporation.com/wfgen' `
# ...
advantys/workflowgen:7.16.0-win-ltsc2019docker container run `
# ...
--env WFGEN_IISNODE_AUTH_loggingEnabled=true `
# ...
advantys/workflowgen:7.16.0-win-ltsc2019docker container run `
# ...
--env WFGEN_DATABASE_CONNECTION_STRING=SomeConnectionString `
# ...
advantys/workflowgen:7.16.0-win-ltsc2019docker container run `
# ...
--env WFGEN_DATABASE_CONNECTION_STRING=SomeConnectionString `
--env WFGEN_DATABASE_READONLY_CONNECTION_STRING=SomeReadOnlyConnectionString `
# ...
advantys/workflowgen:7.16.0-win-ltsc2019docker container run `
# ...
--env WFGEN_DATABASE_CONNECTION_STRING=SomeConnectionString `
--env WFGEN_DATABASE_READONLY_CONNECTION_STRING=SomeReadOnlyConnectionString `
--env WFGEN_CUSTOM_CONNECTION_STRING_MyDataSource=MyConnectionString `
# ...
advantys/workflowgen:7.16.0-win-ltsc2019# Create the secret for the license serial number
"WFG-SOME-LICENSE-KEY" | docker secret create ApplicationSerialNumber -
# Create the container service in Docker Swarm
docker service create `
# ...
--env WFGEN_APP_SETTING_ApplicationSerialNumber_FILE=C:\ProgramData\Docker\secrets\ApplicationSerialNumber `
--secret ApplicationSerialNumber `
# ...
advantys/workflowgen:7.18.3-win-ltsc2019apiVersion: v1
kind: ConfigMap
metadata:
name: wfgen-config
data:
WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\ApplicationSerialNumber
---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: wfgen-secret
data:
# "V0ZHLVNPTUUtTElDRU5TRS1LRVkK" is the base64-encoded value of "WFG-SOME-LICENSE-KEY"
ApplicationSerialNumber: 'V0ZHLVNPTUUtTElDRU5TRS1LRVkK'
apiVersion: apps/v1
kind: Deployment
metadata:
name: wfgen
spec:
selector:
matchLabels:
# ...
template:
metadata:
labels:
# ...
spec:
containers:
- name: wfgen
image: advantys/workflowgen:7.18.3-win-ltsc2019
# ...
envFrom: # ConfigMap as environment variables
- configMapRef:
name: wfgen-config
env:
- name: WFGEN_START_SERVICE
value: webapps
# ...
volumeMounts:
# ...
- mountPath: C:\secrets # Mount Secret as a volume
readOnly: true
name: secrets
volumes:
# ...
- name: secrets # Mount Secret as a volume
secret:
secretName: wfgen-secdocker volume create licensesdocker volume inspect -f "{{.Mountpoint}}" licensesCopy-Item C:\Path\To\WorkflowGen.lic $(docker volume inspect -f "{{.Mountpoint}}" licenses)docker container run `
# ...
--env WFGEN_APP_SETTING_ApplicationSerialNumber=YOUR-WFG-LIC-NUM `
--mount "type=volume,src=licenses,dst=C:\wfgen\licenses,readonly" `
# ...
advantys/workflowgen:7.16.0-win-ltsc2019docker container run `
# ...
--env WFGEN_APP_SETTING_ApplicationSerialNumber=YOUR-WFG-LIC-NUM `
--mount "type=bind,src=C:\Path\To\Your\Licenses,dst=C:\wfgen\licenses,readonly" `
# ...
advantys/workflowgen:7.16.0-win-ltsc2019docker container exec -i wfgen powershell C:\set-state.ps1 Offlinekubectl exec -i wfgen-pod -- powershell C:\set-state.ps1 Offline$offlinePath = ".\offline.htm"
$serverTemplatePath = [io.path]::Combine(
$(docker volume inspect --format "{{ .Mountpoint }}" wfgdata),
"appdata" , "Template", "server"
)
if (-not (Test-Path $serverTemplatePath)) {
New-Item $serverTemplatePath -ItemType Directory -Force
}
Copy-Item $offlinePath $serverTemplatePath
docker container exec -i wfgen powershell C:\set-state.ps1 Onlinekubectl exec -i wfgen-pod -- powershell C:\set-state.ps1 Onlinedir_sync
engine
web_apps
win_services



This page explains how to create a custom image of the WorkflowGen database in order to add custom code or SQL scripts to execute. Keep in mind that this guide provides simple examples, so you're not limited to what is shown here. The examples will use the Linux version of the image. All code examples are in PowerShell.
A Linux machine with Docker installed. See the specific instructions for your distribution to install and configure the Docker engine. See for installation instructions. It might not have all the supported distributions.
A Mac with installed.
A Windows 10 Pro machine with installed and the Linux containers enabled. It is recommended to use the WSL 2 (Windows Subsystem for Linux) backend if available. Otherwise, use the default.
Creating your own WorkflowGen image is as simple as creating a Dockerfile file. Create a context directory and add an empty file called Dockerfile to it:
File tree:
You'll then open the Dockerfile and add some code to it:
This instruction says that you want to base your image on the WorkflowGen database image. From here, you can add other instructions to add some files or scripts to execute and perform the custom initialization that you want. For example, you could add a custom SQL script and execute it:
File tree:
Dockerfile:
As you can see, PowerShell is available in the Linux container so that scripting can be done easily between Windows and Linux. If you prefer Bash scripting, you can use it just as easily by replacing the .ps1 script by your own .sh script.
customcode.ps1:
This script looks like a lot but is in fact simple. It begins by importing the SqlServer, Utils, and Crypto libraries, then gets some information from the environment and initializes variables based on that. Afterward, it checks if the database has already been created by checking for the existence of an .mdf file before hashing and salting a custom secret, creating a custom database and executing a script with a prepared variable. If there are no arguments passed to the script, it restarts the SQL Server process so that its logs are written to the standard output. If there are some arguments, it executes what is passed.
The condition to check if the database is already created is there because the script will be executed after each container restart and run. Therefore, the state files including the .mdf and .ldf files of all the databases inside SQL Server will already be there. There will be no need to re-create the database.
The last part is a general good practice in a Docker container. For example, if you're debugging the container and only want to prompt a PowerShell command line after the start sequence, you would pass powershell as an argument to the run command like so:
The powershell argument will be executed by the Invoke-Expression command and a new PowerShell command prompt will be displayed.
Now, all you have to do is build the container:
Advantys has developed some PowerShell scripts and modules to take care of some functionalities. Here's a list of those scripts with their descriptions:
docker-entrypoint.ps1: This is the main script that gets executed when you run a container. It handles the parsing of environment variables, initialization of the WorkflowGen database, etc.
Windows path: C:\docker-entrypoint.ps1
Linux path: /usr/local/bin/docker-entrypoint.ps1
C:\monitor-database.ps1 (Windows version only): This script handles the monitoring of the database process, as well as gathering the container logs and redirecting them to the standard output. The Linux version doesn't need this script because the SQL Server process runs in the foreground and writes its logs in the standard output.
/usr/local/bin/healthcheck.ps1 (Linux version only): This script handles the periodic check that indicates if the database is working properly or not. This is defined in the Dockerfile and is handled by the Docker engine. The Windows version also has a healthcheck defined. It's a simple command that doesn't need its own script.
In Kubernetes, it's ignored, so you must provide a liveness probe. See the Configure Liveness, Readiness and Startup Probes Kubernetes article for more information.
*.psm1: Various developed PowerShell modules available in the image.
Windows path: C:\
Linux path: /usr/local/lib/
/usr/local/bin/set-state.ps1 (Linux version only): Sets the state of the container, such as bringing the WorkflowGen database offline or online.
Windows path: C:\
Linux path: /usr/local/bin/
context-dir/
DockerfileFROM advantys/workflowgen-sql:7.18.3-ubuntu-18.04context-dir/
Dockerfile
myscript.sql
customcode.ps1FROM advantys/workflowgen-sql:7.18.3-ubuntu-18.04
COPY ./myscript.sql /usr/local/mycorporation/scripts/
COPY ./customcode.ps1 /usr/local/bin/
CMD /usr/local/bin/customcode.ps1<#
.SYNOPSIS
Custom script that creates a new database if not exists and executes
a custom SQL script with a prepared variable.
.NOTES
File name: customcode.ps1
#>
#requires -Version 7.0
Import-Module SqlServer
Import-Module /usr/local/lib/Utils.psm1 -Function "Get-EnvVar"
Import-Module /usr/local/lib/Crypto.psm1
$saPassword = Get-EnvVar "SA_PASSWORD"
$aSecret = Get-EnvVar "MYCORPORATION_SECRET"
$myCustomDatabaseName = "MYDB"
$myDatabasePath = Join-Path "/" "var" "opt" "mssql" "data" "$myCustomDatabaseName.mdf"
$myScriptPath = Join-Path "/" "usr" "local" "mycorporation" "scripts" "myscript.sql"
$commonArgs = @{
ServerInstance = "localhost"
Username = "sa"
Password = $saPassword
}
# MYDB not created
if (-not (Test-Path $myDatabasePath)) {
$secretSalt = Get-Salt # from Crypto.psm1
$secretPassHash = Get-PasswordHash ($salt + $aSecret)
Invoke-Sqlcmd "CREATE DATABASE [`$(DATABASE_NAME)] CONTAINMENT = PARTIAL" `
-Variable ,"DATABASE_NAME=$myCustomDatabaseName" `
@commonArgs
Invoke-Sqlcmd -InputFile $myScriptPath `
-Variable ,"A_SECRET=$secretPassHash" `
@commonArgs
}
if ($args.Count -gt 0 {
Invoke-Expression $args
} else {
# Restart the SQL Server process so that the logs
# are written in the standard output file
Stop-Process -Name sqlservr -Force
Start-Process -FilePath /opt/mssql/bin/sqlservr -Wait
} docker container run -it `
# ...
mycorporation/workflowgen-sql:7.18.3-ubuntu-18.04 /usr/local/bin/customcode.ps1 pwsh docker container run -it \
# ...
mycorporation/workflowgen-sql:7.18.3-ubuntu-18.04 /usr/local/bin/customcode.ps1 pwshSet-Location path/to/context-dir
docker container build `
-t mycorporation/workflowgen-sql:7.18.3-ubuntu-18.04 `
.cd path/to/context-dir
docker container build \
-t mycorporation/workflowgen-sql:7.18.3-ubuntu-18.04 \
.This example is designed for Azure Kubernetes Service (AKS). To get started with AKS, see the Create a Windows Server container on an Azure Kubernetes Service (AKS) cluster using the Azure CLI Microsoft article.
At the end of this section, you'll have this cluster configuration:
Every container in the cluster will have access to the configuration and secrets inside their namespaces. Several Azure services will be deployed by Azure Kubernetes Service. This doesn't require any manual steps other than interacting with Kubernetes itself. The load balancer that the service will create will dispatch the requests between the WorkflowGen server replicas.
You must have a working Kubernetes cluster with Windows Server 2019 nodes. See the Azure resources view above for a basic AKS setup. See Deploy a Windows Server container on an Azure Kubernetes Service (AKS) cluster using Azure CLI to get started with creating an AKS cluster with Windows nodes support.
You must have installed the kubectl command line tool and it must be connected to the cluster. See the Connect to the cluster section in the Deploy a Windows Server container on an Azure Kubernetes Service (AKS) cluster using Azure CLI Microsoft article for instructions on how to connect kubectl with AKS.
As well, note that you should not create any other resources in Azure besides the cluster and its nodes. All required resources for the containers will be created by Kubernetes automatically. AKS is a fully-managed platform.
Now, you need to add a claim that represent the WorkflowGen data volume that will be used by your deployment. To do this, apply the following YAML to your cluster:
Then, apply it to the cluster using the following command:
Kubernetes enables you to manage secrets and configurations as files inside the cluster and inject them into pods. In this case, you'll add your license file as a secret and later inject it to the WorkflowGen pod. To add your license to the cluster, execute the following command:
As mentioned earlier, there is a mechanism in Kubernetes that allows you to manage your containers' configurations. Here, you'll create one for WorkflowGen and another for the database:
Don't forget to apply this configuration:
Kubernetes also manages secrets for you. They are securely stored and only given to the containers as files.
You need an encryption key to put as a secret:
Before creating the secrets, you must encode them in base64:
Those encoded values will go into the secrets declaration. To create the required secrets for the services, apply the following YAML:
Don't forget to apply this:
You're now ready to deploy the services. You'll create two Deployment objects and one ReplicaSet object. The deployment will create ReplicaSets for all the services with different configurations. Those deployments can later be configured to automatically scale with the pods' usage. The ReplicaSet will provide the necessary services to the database container in order to run properly and avoid data losses. Don't forget that there should only be one instance of each WorkflowGen Windows Service running at all time. This container pattern is called a Singleton.
Database
This configuration will deploy the StatefulSet database along with a headless service. This object will also create a persistent volume claim based on the template provided in the declaration.
Apply the database first:
WorkflowGen web applications
Apply this replication controller:
Windows Services deployment
Apply the Windows Services:
Now, you need to add a public-facing load balancer in order to dispatch requests to your pods. To do this, execute the following command:
You now need to wait for the IP to be provisioned. Execute the following command periodically until you get the load balancer's public IP:
Once the value of EXTERNAL-IP is provisioned, copy it and modify the WorkflowGen configuration to change the WFGEN_APP_SETTING_ApplicationUrl value:
Apply it:
Then, restart all of the pods in the WorkflowGen deployment to apply the changes to them. You have to do this for the Windows services as well. To do this, execute the following commands:
You should now have a working WorkflowGen with a load balancer and a database.
Helm is a package manager–like tool for Kubernetes. It manages the sharing, deployment, updates and rollbacks of software developed for Kubernetes. Based on values provided, Helm generates definition files for the cluster with the template engine from the Go programming language. For each release, WorkflowGen now produces a chart that you can use with your cluster. To have the latest bug fixes and features from the chart, make sure to always pick the chart released with the latest update of WorkflowGen.
At the end of this section, you'll have this cluster configuration:
Every container in the cluster will have access to the configuration and secrets inside their namespaces. Several Azure services will be deployed by Azure Kubernetes Service. This doesn't require any manual steps other than interacting with Kubernetes itself. The load balancer that the service will create will dispatch the requests between the WorkflowGen server replicas.
You must have a working Kubernetes cluster with Windows Server 2019 nodes. See the Azure resources view above for a basic AKS setup. See Deploy a Windows Server container on an Azure Kubernetes Service (AKS) cluster using Azure CLI to get started with creating an AKS cluster with Windows node support.
You must have installed the kubectl command line tool and it must be connected to the cluster. See the Connect to the cluster section in the Deploy a Windows Server container on an Azure Kubernetes Service (AKS) cluster using Azure CLI Microsoft article for instructions on how to connect kubectl with AKS.
You must have installed the Helm command line tool. See the Installing Helm section on the Helm website for instructions on how to install it. Only Helm versions 3.0 and later are supported.
As well, note that you should not create any other resources in Azure besides the cluster and its nodes. All required resources for the containers will be created by Kubernetes automatically. AKS is a fully-managed platform.
This value should be generated by you. A simple GUID will suffice since it has sufficient entropy not to be guessed:
Kubernetes enables you to manage secrets and configurations as files inside the cluster and inject them into pods. In this case, you'll add your license file as a secret and later inject it to the WorkflowGen pod. To add your license to the cluster, execute the following command:
In order to generate the templates tailored to your configuration expectations, you have to provide some values to the helm command when you install or update a release. You can specify those values using the command line interface or with a file. In the case of a new installation, it will be easier with a file. Here are the values that you will need:
You can save this file as values.yaml. The name is not important.
You now need to install the chart with those values. To do this, execute the following command:
Helm will generate Kubernetes deployment files for you and install them on the cluster.
This configuration will create a load balancer in front of the WorkflowGen containers. You will need to wait for it to get a public IP address. Execute the following command periodically until you get the load balancer's public IP:
Once the value of EXTERNAL-IP is provisioned, copy it and modify the WorkflowGen configuration to change the WFGEN_APP_SETTING_ApplicationUrl value. To do this, you first need to get the name of the ConfigMap associated with the WorkflowGen deployment. The following command will give you all the ConfigMap objects in the default namespace:
Copy the WorkflowGen ConfigMap name and replace <WFG_CONFIG_MAP> with the value in the following command:
This will bring up an editor so you can replace the WFGEN_APP_SETTING_ApplicationUrl value with the correct IP address from the load balancer service. Save the file and exit the editor. To apply the changes made to the ConfigMap object, restart all of the pods in the WorkflowGen deployment. You have to do this for the Windows services as well. Get the name of the deployments with the following command:
Replace <WEB_APPS_DEPLOYMENT_NAME> and <WIN_SERVICES_DEPLOYMENT_NAME> in the following script with the correct deployment names to restart all containers:
You should now have a working WorkflowGen with a load balancer and a database.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wfgdata-pvc
spec:
accessModes:
- ReadWriteMany
storageClassName: azurefile
resources:
requests:
storage: 50Gikubectl apply -c .\wfgdata-pvc.ymlkubectl create secret generic wfgen-license-secret --from-file C:\Path\To\WorkflowGen.licapiVersion: v1
kind: ConfigMap
metadata:
name: wfgen-config
data:
WFGEN_APP_SETTING_ApplicationUrl: http://10.0.1.1/wfgen
WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\ApplicationSerialNumber
WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\ApplicationSecurityPasswordSymmetricEncryptionKey
WFGEN_MACHINE_KEY_DECRYPTION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_DECRYPTION_KEY
WFGEN_MACHINE_KEY_VALIDATION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_VALIDATION_KEY
---
apiVersion: v1
kind: ConfigMap
metadata:
name: database-config
data:
ACCEPT_EULA: 'Y'
SA_PASSWORD_FILE: /mnt/secrets/SA_PASSWORD
WFGEN_DATABASE_USER_USERNAME_FILE: /mnt/secrets/WFGEN_DATABASE_USER_USERNAME
WFGEN_DATABASE_USER_PASSWORD_FILE: /mnt/secrets/WFGEN_DATABASE_USER_PASSWORD
WFGEN_ADMIN_PASSWORD_FILE: /mnt/secrets/WFGEN_ADMIN_PASSWORDkubectl apply -f .\config.yml[guid]::NewGuid().ToString('N')
# fda7a6a81db2428b8885bd1210522755using namespace System.Text
function ConvertTo-Base64String {
[CmdletBinding()]
[OutputType([string])]
param (
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[string]$Value
)
process {
return [Convert]::ToBase64String([Encoding]::UTF8.GetBytes($Value))
}
}
# Database containers
"strong(!)Pass" | ConvertTo-Base64String # c3Ryb25nKCEpUGFzcw==
"WFGEN_USER" | ConvertTo-Base64String # V0ZHRU5fVVNFUg==
# WorkflowGen containers
"<YOUR_WFG_LIC_KEY>" | ConvertTo-Base64String # PFlPVVJfV0ZHX0xJQ19LRVk+
"<YOU_NEW_GUID>" | ConvertTo-Base64String # PFlPVV9ORVdfR1VJRD4=
"Server=database-0.database.default.svc.cluster.local,1433;Database=WFGEN;User ID=WFGEN_USER;Password=strong(!)Pass;" `
| ConvertTo-Base64String # V0ZHRU5fREFUQUJBU0VfQ09OTkVDVElPTl9TVFJJTkc9RGF0YSBTb3VyY2U9ZGF0YWJhc2UsMTQzMztOZXR3b3JrIExpYnJhcnk9REJNU1NPQ047SW5pdGlhbCBDYXRhbG9nPVdGR0VOO1VzZXIgSUQ9V0ZHRU5fVVNFUjtQYXNzd29yZD1zdHJvbmcoISlQYXNzOw==
"39B3AE9CCCF94AA47D795EC84F7CCB7928F5D59BE2EB2BBA4FE2AC0B3C8D0C85" | ConvertTo-Base64String # MzlCM0FFOUNDQ0Y5NEFBNDdENzk1RUM4NEY3Q0NCNzkyOEY1RDU5QkUyRUIyQkJBNEZFMkFDMEIzQzhEMEM4NQ==
"82F6247A5DBF8666FB60B8EFE6483360436F0EC426CC0351A9569C607B46C1FAD6497406DD8B0B519DD83CAA6764904C89999D742638ECE756E7C0B8799B45E9" `
| ConvertTo-Base64String # ODJGNjI0N0E1REJGODY2NkZCNjBCOEVGRTY0ODMzNjA0MzZGMEVDNDI2Q0MwMzUxQTk1NjlDNjA3QjQ2QzFGQUQ2NDk3NDA2REQ4QjBCNTE5REQ4M0NBQTY3NjQ5MDRDODk5OTlENzQyNjM4RUNFNzU2RTdDMEI4Nzk5QjQ1RTk=apiVersion: v1
kind: Secret
metadata:
name: database-sec
type: Opaque
data:
SA_PASSWORD: c3Ryb25nKCEpUGFzcw==
WFGEN_DATABASE_USER_PASSWORD: c3Ryb25nKCEpUGFzcw==
WFGEN_ADMIN_PASSWORD: c3Ryb25nKCEpUGFzcw==
WFGEN_DATABASE_USER_USERNAME: V0ZHRU5fVVNFUg==
---
apiVersion: v1
kind: Secret
metadata:
name: wfgen-sec
type: Opaque
data:
ApplicationSerialNumber: <YOUR_WFG_LIC_KEY_BASE64>
ApplicationSecurityPasswordSymmetricEncryptionKey: <YOUR_NEW_GUID_BASE64>
WFGEN_DATABASE_CONNECTION_STRING: V0ZHRU5fREFUQUJBU0VfQ09OTkVDVElPTl9TVFJJTkc9RGF0YSBTb3VyY2U9ZGF0YWJhc2UsMTQzMztOZXR3b3JrIExpYnJhcnk9REJNU1NPQ047SW5pdGlhbCBDYXRhbG9nPVdGR0VOO1VzZXIgSUQ9V0ZHRU5fVVNFUjtQYXNzd29yZD1zdHJvbmcoISlQYXNzOw==
WFGEN_MACHINE_KEY_DECRYPTION_KEY: MzlCM0FFOUNDQ0Y5NEFBNDdENzk1RUM4NEY3Q0NCNzkyOEY1RDU5QkUyRUIyQkJBNEZFMkFDMEIzQzhEMEM4NQ==
WFGEN_MACHINE_KEY_VALIDATION_KEY: ODJGNjI0N0E1REJGODY2NkZCNjBCOEVGRTY0ODMzNjA0MzZGMEVDNDI2Q0MwMzUxQTk1NjlDNjA3QjQ2QzFGQUQ2NDk3NDA2REQ4QjBCNTE5REQ4M0NBQTY3NjQ5MDRDODk5OTlENzQyNjM4RUNFNzU2RTdDMEI4Nzk5QjQ1RTk=kubectl apply -f secrets.ymlapiVersion: v1
kind: Service
metadata:
name: database
spec:
type: ClusterIP
clusterIP: None
ports:
- port: 1433
targetPort: mssql
protocol: TCP
name: mssql
selector:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: database
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: database
spec:
replicas: 1
serviceName: database
selector:
matchLabels:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: database
template:
metadata:
labels:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: database
spec:
terminationGracePeriodSeconds: 10
nodeSelector:
kubernetes.io/os: linux
containers:
- name: database
image: advantys/workflowgen-sql:7.18.3-ubuntu-18.04
imagePullPolicy: Always
securityContext:
runAsUser: 0
runAsGroup: 0
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "1"
envFrom:
- configMapRef:
name: database-config
ports:
- name: mssql
containerPort: 1433
livenessProbe:
initialDelaySeconds: 30
timeoutSeconds: 5
exec:
command:
- pwsh
- -NoLogo
- -NoProfiles
- /usr/local/bin/healthcheck.ps1
readinessProbe:
initialDelaySeconds: 20
timeoutSeconds: 5
exec:
command:
- pwsh
- -NoLogo
- -NoProfiles
- /usr/local/bin/healthcheck.ps1
volumeMounts:
- mountPath: /var/opt/mssql
name: sqldata
- mountPath: /mnt/secrets
readOnly: true
name: secrets
volumes:
- name: secrets
secret:
secretName: database-sec
volumeClaimTemplates:
- metadata:
name: sqldata
spec:
accessModes:
- ReadWriteOnce
storageClassName: default
resources:
requests:
storage: 100Gikubectl apply -f database.ymlapiVersion: apps/v1
kind: Deployment
metadata:
name: wfgen-webapps
spec:
replicas: 3
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: webapps
template:
metadata:
labels:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: webapps
spec:
nodeSelector:
kubernetes.io/os: windows
containers:
- name: wfgen
image: advantys/workflowgen:7.18.3-win-ltsc2019
imagePullPolicy: Always
resources:
requests:
memory: "2Gi"
cpu: "1"
limits:
memory: "2Gi"
cpu: "1"
ports:
- name: http
containerPort: 80
protocol: TCP
envFrom:
- configMapRef:
name: wfgen-config
env:
- name: WFGEN_START_SERVICE
value: webapps
livenessProbe:
periodSeconds: 30
timeoutSeconds: 5
initialDelaySeconds: 60
exec:
command:
- powershell
- C:\healthcheck.ps1
livenessProbe:
timeoutSeconds: 5
initialDelaySeconds: 60
exec:
command:
- powershell
- -Command
- if (Test-Path "C:\iislog\W3SVC\*log") { return 0 } else { return 1 }
volumeMounts:
- mountPath: C:\wfgen\data
name: wfgdata
- mountPath: C:\wfgen\licenses
readOnly: true
name: licenses
- mountPath: C:\secrets
readOnly: true
name: secrets
volumes:
- name: wfgdata
persistentVolumeClaim:
claimName: wfgdata-pvc
- name: licenses
secret:
secretName: wfgen-license-secret
items:
# The following must match the name of the license item in
# the license secret, e.g. the name of the license file
- key: WorkflowGen.lic
path: WorkflowGen.lic
- name: secrets
secret:
secretName: wfgen-seckubectl apply -f wfgen-webapps.ymlapiVersion: apps/v1
kind: Deployment
metadata:
name: wfgen-winservices
spec:
replicas: 1 # Singleton pattern
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: winservices
template:
metadata:
labels:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: winservices
spec:
nodeSelector:
kubernetes.io/os: windows
containers:
- name: wfgen-dir-sync
image: advantys/workflowgen:7.18.3-win-ltsc2019
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "750m"
envFrom:
- configMapRef:
name: wfgen-config
env:
- name: WFGEN_START_SERVICE
value: dir_sync
livenessProbe:
periodSeconds: 30
timeoutSeconds: 5
initialDelaySeconds: 60
exec:
command:
- powershell
- C:\healthcheck.ps1
volumeMounts:
- mountPath: C:\wfgen\data
name: wfgdata
- mountPath: C:\wfgen\licenses
readOnly: true
name: licenses
- mountPath: C:\secrets
readOnly: true
name: secrets
- name: wfgen-engine
image: advantys/workflowgen:7.18.3-win-ltsc2019
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "750m"
envFrom:
- configMapRef:
name: wfgen-config
env:
- name: WFGEN_START_SERVICE
value: engine
livenessProbe:
periodSeconds: 30
timeoutSeconds: 5
initialDelaySeconds: 60
exec:
command:
- powershell
- C:\healthcheck.ps1
volumeMounts:
- mountPath: C:\wfgen\data
name: wfgdata
- mountPath: C:\wfgen\licenses
readOnly: true
name: licenses
- mountPath: C:\secrets
readOnly: true
name: secrets
volumes:
- name: wfgdata
persistentVolumeClaim:
claimName: wfgdata-pvc
- name: licenses
secret:
secretName: fgen-license-secret
items:
# The following must match the name of the license item in
# the license secret, e.g. the name of the license file
- key: WorkflowGen.lic
path: WorkflowGen.lic
- name: secrets
secret:
secretName: wfgen-seckubectl apply -f wfgen-win-services.ymlkubectl expose deployment wfgen-webapps --type=LoadBalancer --name=wfgen-servicekubectl get services wfgen-service# wfgen-config.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: wfgen-config
data:
WFGEN_APP_SETTING_ApplicationUrl: 'http://<EXTERNAL_IP>/wfgen'
WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\ApplicationSerialNumber
WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\ApplicationSecurityPasswordSymmetricEncryptionKey
WFGEN_MACHINE_KEY_DECRYPTION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_DECRYPTION_KEY
WFGEN_MACHINE_KEY_VALIDATION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_VALIDATION_KEYkubectl apply -f wfgen-config.ymlkubctl scale deployment wfgen-webapps --replicas 0 -n wfgen-service
kubctl scale deployment wfgen-winservices --replicas 0 -n wfgen-service
# Wait until the scaling is done and then scale up
kubctl scale deployment wfgen-webapps --replicas 3 -n wfgen-service
kubctl scale deployment wfgen-winservices --replicas 1 -n wfgen-service[guid]::NewGuid().ToString('N')
# fda7a6a81db2428b8885bd1210522755kubectl create secret generic wfgen-license-secret --from-file C:\Path\To\WorkflowGen.licreplicaCount: 3
workflowgen:
resources:
limits:
cpu: '1'
memory: 2Gi
requests:
cpu: '1'
memory: 2Gi
config:
WFGEN_APP_SETTING_ApplicationUrl: http://10.0.1.1/wfgen
WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\ApplicationSerialNumber
WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\ApplicationSecurityPasswordSymmetricEncryptionKey
WFGEN_MACHINE_KEY_DECRYPTION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_DECRYPTION_KEY
WFGEN_MACHINE_KEY_VALIDATION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_VALIDATION_KEY
secret:
ApplicationSerialNumber: <YOUR_WFG_LIC_KEY>
ApplicationSecurityPasswordSymmetricEncryptionKey: <YOUR_NEW_GUID>
WFGEN_DATABASE_CONNECTION_STRING: 'Server=wfgen-database-0.wfgen-database.default.svc.cluster.local,1433;Database=WFGEN;User ID=WFGEN_USER;Password=strong(!)Pass;'
WFGEN_MACHINE_KEY_DECRYPTION_KEY: '39B3AE9CCCF94AA47D795EC84F7CCB7928F5D59BE2EB2BBA4FE2AC0B3C8D0C85'
WFGEN_MACHINE_KEY_VALIDATION_KEY: '82F6247A5DBF8666FB60B8EFE6483360436F0EC426CC0351A9569C607B46C1FAD6497406DD8B0B519DD83CAA6764904C89999D742638ECE756E7C0B8799B45E9'
license:
secretName: wfgen-license-secret
items:
- key: WorkflowGen.lic
path: WorkflowGen.lic
dataPvcSpec:
accessModes:
- ReadWriteMany
storageClassName: azurefile
resources:
requests:
storage: 50Gi
service:
type: LoadBalancer
winServices:
dirSync:
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: '500M'
memory: 1Gi
engine:
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: '500M'
memory: 1Gi
database:
fullnameOverride: wfgen-database
nodeSelector:
kubernetes.io/os: linux
securityContext:
runAsUser: 0
runAsGroup: 0
resources:
limits:
cpu: '1'
memory: 2Gi
requests:
cpu: '500m'
memory: 1Gi
config:
ACCEPT_EULA: 'Y'
SA_PASSWORD_FILE: /mnt/secrets/SA_PASSWORD
WFGEN_DATABASE_USER_USERNAME_FILE: /mnt/secrets/WFGEN_DATABASE_USER_USERNAME
WFGEN_DATABASE_USER_PASSWORD_FILE: /mnt/secrets/WFGEN_DATABASE_USER_PASSWORD
WFGEN_ADMIN_PASSWORD_FILE: /mnt/secrets/WFGEN_ADMIN_PASSWORD
secret:
SA_PASSWORD: 'strong(!)Pass'
WFGEN_DATABASE_USER_PASSWORD: 'strong(!)Pass'
WFGEN_ADMIN_PASSWORD: 'strong(!)Pass'
WFGEN_DATABASE_USER_USERNAME: WFGEN_USER
volumeClaimTemplateSpec:
accessModes:
- ReadWriteOnce
storageClassName: default
resources:
requests:
storage: 100Gi
ingress:
enabled: false
helm install -f .\values.yaml wfg https://github.com/advantys/workflowgen-releases/releases/download/7.18.3/workflowgen-0.0.3.tgzkubectl get services wfgen-servicekubectl get configmapkubectl edit configmap "<WFGEN_CONFIG_MAP>"kubectl get deploymentkubctl scale deployment "<WEB_APPS_DEPLOYMENT_NAME>" --replicas 0 -n wfgen-service
kubctl scale deployment "<WIN_SERVICES_DEPLOYMENT NAME>" --replicas 0 -n wfgen-service
# Wait until the scaling is done and then scale up
kubctl scale deployment "<WEB_APPS_DEPLOYMENT_NAME>" --replicas 3 -n wfgen-service
kubctl scale deployment "<WIN_SERVICES_DEPLOYMENT NAME>" --replicas 1 -n wfgen-serviceIn the case of the upgrade image, the environment variables are arguments that you should not have to change often when upgrading WorkflowGen. That way, you can easily pass a file that defines those variables and reuse it between runs. Here's the list of available environment variables with their descriptions:
Variables
Description & values
WFGEN_UPGRADE_UPDATE_PACKAGES_PATH
A path local to the container where the update packages are located. See the page of this section for more information and examples.
Default value:
Windows: C:\wfgen\updatepackages
Linux: /mnt/updatepackages
WFGEN_UPGRADE_UPDATE_PACKAGE_FILE_NAME
The name of the update package archive to pick in the update packages path for this upgrade. If no value is provided, <ToVersion>/update.zip will be picked where <ToVersion> is passed as an argument to the container.
WFGEN_DATABASE_CONNECTION_STRING
Required variable
The connection string to the WorkflowGen database. The user passed must have the rights to modify the schema of the database.
WFGEN_UPGRADE_EXCLUDE_FILES
Globally excluded files when copying App_Data files from the update package to your App_Data volume, and when copying wfapps files from the update package to your wfapps volume. The elements in this list must be comma-separated (e.g.myfile.txt,myfile2.txt).
✏️ Notes:
There is no distinction between files and folders in the Linux version.
WFGEN_UPGRADE_EXCLUDE_FOLDERS
Globally excluded folders when copying App_Data files from the update package to your App_Data volume, and when copying wfapps files from the update package to your wfapps volume. The elements in this list must be comma-separated (e.g.myfolder,myfolder).
✏️ Notes:
There is no distinction between files and folders in the Linux version.
Script parameters define options to pass as arguments directly to the upgrade container. These arguments are more likely to be defined each time you run the container, which is why they are not in environment variables. Here's the help file of the entrypoint script. It describes all of the parameters and their groupings, and provides a few examples:
Some popular configuration managers support Docker containers out-of-the-box. You would use an external configuration manager only for environment variables definition. Here are a few links to their specific documentation to get you started:
NAME
/usr/local/bin/docker-entrypoint.ps1
SYNOPSIS
Entrypoint script for the upgrade container.
SYNTAX
/usr/local/bin/docker-entrypoint.ps1 -FromVersion <String> -ToVersion <String> [-RemainingArgs <Object>] [-Offline] [<CommonParameters>]
/usr/local/bin/docker-entrypoint.ps1 -Command -RemainingArgs <Object> [<CommonParameters>]
/usr/local/bin/docker-entrypoint.ps1 -Help [<CommonParameters>]
DESCRIPTION
This script will merge files for the App_Data and wfapps directory between
the upgrade package of the destination version and the current installation
ones (passed as volumes).
It will also launch the required SQL migration scripts in order from lowest
to highest version. Make sure to use a SQL account that has the proper
rights to modify the database tables.
The "Files", "LogFiles" and "Ws" subfolders in App_Data are always ignored.
You don't have to specify them in the exclusion environment variables.
PARAMETERS
-FromVersion <String>
The current version of WorkflowGen. The starting version of the
migration.
Required? true
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false
-ToVersion <String>
The version to which you want to migrate the current one.
Required? true
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false
-Command [<SwitchParameter>]
Indicates to execute a command inside the container. This is used in
conjunction with RemainingArgs
Required? true
Position? named
Default value False
Accept pipeline input? false
Accept wildcard characters? false
-RemainingArgs <Object>
Commands to execute inside the container. If versions are not passed, it is
executed at the beginning and then it exits after the execution. If
versions are passed, it is executed at the end of the script.
Required? false
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false
-Help [<SwitchParameter>]
Get full help for this script.
Required? true
Position? named
Default value False
Accept pipeline input? false
Accept wildcard characters? false
-Offline [<SwitchParameter>]
If provided, the script will not try to download the update package.
This means that you have to provide the update package from a volume.
Required? false
Position? named
Default value False
Accept pipeline input? false
Accept wildcard characters? false
<CommonParameters>
This cmdlet supports the common parameters: Verbose, Debug,
ErrorAction, ErrorVariable, WarningAction, WarningVariable,
OutBuffer, PipelineVariable, and OutVariable.
For more information, see about_CommonParameters (https://go.microsoft.com/fwlink/?LinkID=113216).
NOTES
File name: docker-entrypoint.ps1
requires -Version 7.0
-------------------------- EXAMPLE 1 --------------------------
PS > docker container run -i "..." advantys/workflowgen-upgrade:latest-ubuntu-18.04 -Help
Displays the full help for the container.
-------------------------- EXAMPLE 2 --------------------------
PS > docker container run -i "..." advantys/workflowgen-upgrade:latest-ubuntu-18.04 -Command dir /mnt/appdata
This executes an arbitrary command inside the container. It can be useful
for debugging network issues or other problems prior to the migration.
-------------------------- EXAMPLE 3 --------------------------
PS > docker container run -i "..." advantys/workflowgen-upgrade:latest-ubuntu-18.04 -FromVersion 7.14.10 -ToVersion 7.18.2
This will launch the migration process to upgrade WorkflowGen from version
7.14.10 to the 7.18.2 version.
-------------------------- EXAMPLE 4 --------------------------
PS > docker container run -i "..." advantys/workflowgen-upgrade:latest-ubuntu-18.04 -FromVersion 7.14.10 -ToVersion 7.18.2 dir /mnt/appdata
This will launch the migration process to upgrade WorkflowGen from version
7.14.10 to the 7.18.2 version. In addition, it will execute an arbitrary command
at the end of the migration process.
Excluded files in Windows version are recursive.
You can't use sub-paths in the Windows version.
Excluded folders in the Windows version are recursive.
You can't use sub-paths in the Windows version.
WFGEN_UPGRADE_APPDATA_EXCLUDE_FILES
Globally excluded files when copying App_Data files from the update package to your App_Data volume. The elements in this list must be comma-separated (e.g.myfile.txt,myfile2.txt).
✏️ Notes:
There is no distinction between files and folders in the Linux version.
Excluded files in the Windows version are recursive.
You can't use sub-paths in the Windows version.
WFGEN_UPGRADE_WFAPPS_EXCLUDE_FILES
Globally excluded files when copying wfapps files from the update package to your wfapps volume. The elements in this list must be comma-separated (e.g.myfile.txt,myfile2.txt).
✏️ Notes:
There is no distinction between files and folders in the Linux version.
Excluded files in the Windows version are recursive.
You can't use sub-paths in the Windows version.
WFGEN_UPGRADE_APPDATA_EXCLUDE_FOLDERS
Globally excluded folders when copying App_Data files from the update package to your App_Data volume. The elements in this list must be comma-separated (e.g. myfolder,myfolder).
✏️ Notes:
There is no distinction between files and folders in the Linux version.
Excluded folders in the Windows version are recursive.
You can't use sub-paths in the Windows version.
WFGEN_UPGRADE_WFAPPS_EXCLUDE_FOLDERS
Globally excluded folders when copying wfapps files from the update package to your wfapps volume. The elements in this list must be comma-separated (e.g. myfolder,myfolder).
✏️ Notes:
There is no distinction between files and folders in the Linux version.
Excluded folders in the Windows version are recursive.
You can't use sub-paths in the Windows version.
This section presents the WorkflowGen Helm chart including usage, configuration options, and examples. Using the WorkflowGen chart simplifies the deployment of WorkflowGen in a Kubernetes cluster by not having to manage many Kubernetes deployment files. You only have to manage one "values" file.
You must have a working Kubernetes cluster with Windows Server 2019 nodes.
You must have installed the kubectl command line tool and it must be connected to the cluster.
You must have installed the helm command line tool. See the section on the Helm website for instructions on how to install it. Only the Helm version 3.0+ is supported.
From the :
A chart is a collection of files that describe a related set of Kubernetes resources.
These resources are written in YAML in the chart with the help of the Go templating language. This enables the chart to generate valid Kubernetes resource definition files based on values provided by the user of the chart. Therefore, when you use the chart to install or upgrade WorkflowGen, you can provide some values that will help you deploy the correct resources for WorkflowGen.
A chart has a manifest file called Chart.yaml. It has a version for the chart and a version for the application. For example, the chart version of WorkflowGen could be 0.0.3 and its application version 7.18.3. A chart also has a kubeVersion that tells which versions of Kubernetes are supported. In the case of WorkflowGen, only versions 1.14 and higher are supported since it is the first version to include Windows containers support.
You install a chart using the command line. For example:
This will install the chart that is at the path ./chart-path in the cluster with the release name release-name. It also sets a the value image.tag to 7.15.5-win-ltsc2019. More information about the install command including its --set parameter can be found in on the Helm website.
While useful for a few parameters, setting values from the command line can be cumbersome and prone to errors, which is why you can also set values from a YAML or JSON file. The first thing you need to do is to create the file:
Then, you can pass that file to the install command:
The following are all of the value names supported by the WorkflowGen chart and their default values, accompanied by brief descriptions.
The chart is divided in groups of configuration:
Global
WorkflowGen
WorkflowGen Windows services
Database
Global values control the overall deployment that results from the Helm generation. For example, the scalable value indicates if the resulting deployment should be scalable or not. If true, the resulting deployment will have a separate pod for the WorkflowGen Windows services that will be deployed using the Singleton deployment pattern. The WorkflowGen web services will be deployed with the number of replicas indicated by the replicaCount global value.If false, WorkflowGen web and Windows services will be deployed in a single pod using the Singleton pattern.
To deploy multiple WorkflowGen instances that must be isolated, the use of the tenantName value is recommended because it will prefix each object created by the installation with the name of the tenant and add a selector label named workflowgen.com/tenant=tenantName.
The WorkflowGen part groups the configuration options related to the WorkflowGen web and Windows services pods when configuring the WorkflowGen product. For infrastructure-related configuration, configuration options are in separate groups in order to be able to properly deploy each part individually but still having the same WorkflowGen-specific configuration.
There are two main ways to configure WorkflowGen with the chart: with the values file or by providing your own ConfigMap or Secret.
In your values file, you can use the sub YAML object workflowgen.config and workflowgen.secret to configure WorkflowGen's environment variables. Let's begin with an example:
Each key and value in the config part will be added as in a ConfigMap object and will be used by the WorkflowGen deployments. Concretely, the keys and values of the ConfigMap will be injected as environment variables in WorkflowGen's container. Each value must be of the string type. Therefore, YAML boolean values such as true, yes, and Y will be rejected. Use single or double quotes when needed, as in the example.
For secret values, you can do exactly like the config part. You only have to provide the name of the secret and its concrete value. The chart will add them to a Secret object and encode the value in Base64. The Secret object will then get injected as a volume inside WorkflowGen's container. Each key will become a file with its concrete value written inside it. Therefore, you need a corresponding
The chart generates a PersistentVolumeClaim (PVC) object based on values that you've provided. As with the WorkflowGen configuration, you can specify your own PVC outside of the chart and reference it.
In your values file, you can use the sub YAML object workflowgen.dataPvcSpec to configure the PersistentVolumeClaim for WorkflowGen's data (App_Data and wfapps). Let's begin with an example:
The content of the object is exactly the . What you write in there will be taken as-is in the object definition.
The license must be stored on the Kubernetes cluster before installing the chart. This is because it's more efficient to store it in a secret and inject it as a volume in the WorkflowGen pods instead of provisioning a file share and connecting it to the pods. For the chart to handle it, you need to specify the secret name where the license is stored and the license item name in the secret. Here's an example:
Step 1: Store your license in the cluster
This command will create a secret named wfgen-license-secret with an item named WFG.lic and its value will be the content of the file.
Step 2: Reference this secret in the values file
For more information about how to inject files from a Secret object into pods, see in the Kubernetes documentation.
To use your own WorkflowGen image, you can change the default reference like this:
There is a service that is created by the chart with the WorkflowGen pod for its discovery. By default, the chart will create a ClusterIP service that provides a cluster-wide IP address and domain name that you can reference from anywhere in the cluster. This works best with an Ingress controller to route external traffic to it. For more information about Ingress controllers, see in the Kubernetes documentation.
You can customize this to automatically create a load balancer instead by providing the following value:
There are many security features that aren't yet supported, or don't work in Windows but do work in Linux. It's important to plan the security of the deployments. To find out more about unsupported security features on Windows containers in Kubernetes, see the section in the documentation.
The web applications in the WorkflowGen container run as a user that is part of the IIS_IUSRS group. This is important for setting permissions for file storage. If this group doesn't have MODIFY permission on the files volume, the container will fail to write to the volume. Generally, you can set mount options for a persistent volume depending on the storage provider or you can run an init container to set the permissions. To get the mount options for Azure Files, see the section in the Microsoft documentation.
There are many more options for customizing your Helm release. The majority of them are dependent on your cluster environment. They are all Kubernetes terms, so you can search for them in a search engine and get useful information. The only one that this section will discuss is resources. The resources YAML object allows you to limit and request resource consumption for a given pod. Requests are to help the scheduler to assign pods to nodes. Limits are to limit the amount of resources the pod can use. The following requests and limits are known to work well for WorkflowGen pods:
The database part contains the values used to generate the deployment files for the WorkflowGen database StatefulSet and its related objects. It is an optional feature to deploy a database pod along with a WorkflowGen pod. You can disable the creation of the StatefulSet by setting the following values:
There are two main ways to configure the database with the chart: with the values file or by providing your own ConfigMap or Secret.
In your values file, you can use the sub YAML object database.config and database.secret to configure the environment variables of the database. Let's begin with an example:
Each key and value in the config part will be added as is in a ConfigMap object. It will be used by the StatefulSet. Concretely, the keys and values of the ConfigMap will get injected as environment variables in the database container. Each value must be of the string type. Therefore, YAML boolean values such as true, yes and Y will be rejected. Use single or double quotes when needed just like in the example.
For secret values, you can do exactly like the config part. You only have to provide the name of the secret and its concrete value. The chart will add them to a Secret object and encode the value in Base64. The Secret object will then get injected as a volume inside the database container. Each key will become a file with its concrete value written inside it. Therefore, you need a corresponding
A StatefulSet needs a PersistentVolumeClaim template to generate a volume claim for each of its replicas. You can't use your own PVC this time because it is a template, not a concrete object. This template is part of the StatefulSet specification. Here's an example:
The content of the template is exactly the . Anything you write will be added to the StatefulSet specification as-is. In this example, the access mode is ReadWriteOnly because the default storage class refers to an Azure Disk. Azure disks can only be bound to a single node and pod at a time. Physical disks are the preferred way to store database files for better performance. For more information about Azure Disks, see the Microsoft documentation.
To use your own WorkflowGen database image, you can change the default reference like this:
There is a service that is created by the chart with the database pod for its discovery. By default, the chart will create a ClusterIP service without a cluster IP address (clusterIP: None). This is called a headless service. It provides a way to get a cluster wide domain name to each pod of the StatefulSet. Therefore, you can refer directly to the database instance of your choice. It is recommended to leave the default values untouched. They are available in case you want to customize the service further. For more information about headless services in Kubernetes, see in its documentation.
Additionally, to make domain names predictable, you might want to override the full name of the StatefulSet, because the name is generated based on the chart's name and the release name, and you might not know the release name in advance. In this case, you can do the following:
This will ensure that each pod in the StatefulSet has a unique domain name based on this name. If this release is in the default namespace, the first pod will have the domain name my-database-0.my-database.default.svc.cluster.local. You then reference this domain name in the connection string of the WorkflowGen configuration at port 1433 and it should connect successfully.
Since the database image used is a Linux image by default, all of the security features are available. You can run the database with a non-root user and group. For more information about running the database container as a non-root user, see in the SQL Server documentation. Keep in mind that you also have to setup the permissions for the storage to be able to read and write into it.
For more information about Docker security features, see in the Docker documentation. To find out how to configure these security features in Kubernetes, see in the Kubernetes documentation.
There are many more options you can customize your Helm release with. The majority of them are dependent on your cluster environment. They are all Kubernetes terms, so you can search for them in a search engine and get useful information. The only one that this section will discuss is resources. The resources YAML object allows you to limit and request resource consumption for a given pod. Requests are to help the scheduler to assign pods to nodes. Limits are to limit the amount of resources the pod can use. The following requests and limits are known to work well for database pods:
Since WorkflowGen can only handle a main connection string and a read-only replica, you may want to limit the number of pods in the StatefulSet to two and scale vertically if you need more performance.
The ingress section of the values is a simplified view of the complete . It is optional to generate the Ingress rule object. To disable it, you can add the following values:
Otherwise, here's an example of how to use the Ingress section:
This is a complete example on how to use it. In this example, there are annotations set to add some information on how to handle them. The ingress.class tells Kubernetes to use the Nginx ingress controller to handle this Ingress rule. The Nginx ingress controller must be installed in your cluster for the routing to work. For more information about the Nginx ingress controller, see the or . The two have different feature sets and are not developed by the same entity. The cert-manager.io/cluster-issuer annotation is a Cert-Manager specific annotation that tells it to use the letsencrypt cluster issuer for the TLS certificate. See the page of this section for more information about cert-manager.
The hosts section is a list of domain names and where they lead in the container. In this case, when a user goes to myinstance.example.com, it will be routed to / on the WorkflowGen container which IIS will handle. The tls section tells what secret to use for what host. TLS certificates are stored in this secret.
In Helm, there is a concept of hooks that enables the developer to deploy some resources (temporary or permanently) at different event in the lifecycle of a chart.
The pre-upgrade hook deploys a Kubernetes Job that will add possible missing files and templates to your WorkflowGen database volume and migrate the database automatically. This deployment only occurs when you use the helm upgrade command. It will wait for the job to finish successfully before upgrading the WorkflowGen and database pods. This hook is optional and you can disable it by using the following values:
This pre-upgrade hook uses the WorkflowGen upgrade image to perform migrations. Here's a complete example to how to configure the hook:
There is no default tag specified for the image because both Windows and Linux versions of it are production-ready. For a better experience and performance, it is recommended to use the Linux version. The secret section of this example allows you to specify secret values to be put in a Secret object that will be deployed with the job. It will get deleted when the job is terminated. The name of the secret is generated from the release name. If your release name is wfgen, then the secret name will be wfgen-migrations-secret. The WFGEN_DATABASE_CONNECTION_STRING secret is required. It is automatically injected as an environment variable in the container. To customize the name of the secret to use for the upgrade container'sWFGEN_DATABASE_CONNECTION_STRING environment variable, you can populate the hooks.preupgrade.connectionStringSecretKey value. You can add your own environment variables as well.
The last part consists of the arguments to pass to the container. See for more information about configuring the WorkflowGen upgrade container.
This deployment is meant for a simple installation with a database deployed outside of the cluster. It will deploy a single WorkflowGen pod with all of its services including WorkflowGen Windows services. This diagram shows a high-level view of the objects that will be created when installing the release with the values given in the next part. This architecture is only vertically scalable. You can only scale up the limits of the pod to have a more performant instance.
First, create the values file:
Before installing a release of the chart, you have to create the WorkflowGen license secret object in your cluster. For this particular example, the name of the license file is WFG.lic and the name of the secret object is wfgen-license-secret. Execute the following command to create it:
With that done, you can now install the release:
The last argument is the path (or URL) to the WorkflowGen chart. You can use the URL directly or download it and use a local path. From this point, you should have a working WorkflowGen pod in your cluster.
This architecture is best suited for production workloads that have an external database. This deployment enables you to scale WorkflowGen web applications horizontally (by adding replicas), which has many benefits such as increased availability and performance. The WorkflowGen Windows services must be scaled vertically and cannot be scaled horizontally. Make sure to deploy that pod to a node that has sufficient resources.
This is the same example as for the simple deployment, except that the scalable property is gone (true by default), the number of replicas is three, and there are resource requests and limits for the Windows services.
Before installing a release of the chart, you have to create the WorkflowGen license secret object in your cluster. For this particular example, the name of the license file is WFG.lic and the name of the secret object is wfgen-license-secret. Execute the following command to create it:
With this done, you can now install the release:
The last argument is the path (or URL) to the WorkflowGen chart. You can use the URL directly or download it and use a local path. From this point, you should have a working WorkflowGen pod in your cluster.
This architecture is best suited for the complete automation experience and can help reduce costs by having the container inside the cluster instead of in an external environment. It is a scalable architecture where the WorkflowGen web applications can be scaled horizontally and vertically, the Windows Services can be scaled vertically only, and the WorkflowGen database can be scaled horizontally up to two replicas (read/write and read-only) and vertically.
This is the same example as before, except that a database section has been added. The security context specifies that the container should run as root. This should be avoided as a general security good practice. It is there for simplicity. You should always use a different user than root and check the permissions on the volumes, for example with an init container.
Before installing a release of the chart, you have to create the WorkflowGen license secret object in your cluster. For this particular example, the name of the license file is WFG.lic and the name of the secret object is wfgen-license-secret. Execute the following command to create it:
With this done, you can now install the release:
The last argument is the path (or URL) to the WorkflowGen chart. You can use the URL directly or download it and use a local path. From this point, you should have a working WorkflowGen pod in your cluster.
Ingress
Hooks
config_FILEC:\secrets. You can customize this path by providing the value workflowgen.secretMountPath.You also have the option to use your own ConfigMap and Secret objects. Keep in mind that these objects will not be managed by Helm or the WorkflowGen chart. Here's the same example as for the "Helm" method:
In the case of the secret, you have to encode the values in base64 yourself. For this, you can use the following code sample:
PowerShell
Bash
Then, you have to deploy the objects by using the following command:
The last step is to reference the objects that you've just deployed in your values file before installing:
You also have to option to use your own PVC object. Keep in mind that this object will not be managed by Helm or the WorkflowGen chart. Here's an example:
The last step is to reference the objects that you've just deployed in your values file before installing:
config_FILE/mnt/secrets. You can customize this path by providing the value database.secretMountPath.The WorkflowGen database image is based on the SQL Server Linux image. It is the recommended image to use for production workloads. The Windows version of the image should only be used for development and test environments.
You also have the option to use your own ConfigMap and Secret objects. Keep in mind that these objects will not be managed by Helm or the WorkflowGen chart. Here's the same example as for the "Helm" method:
In the case of the secret, you have to encode the values in base64 yourself. For this, you can .use the following code sample:
PowerShell
Bash
Then, you have to deploy the objects by using the following command:
The last step is to reference the objects that you've just deployed in your values file before installing:
These values assume that you own the example.com domain name and that it points to the load balancer's public IP address. In this particular case, the HTTPS means that the load balancer should work at network layer 7 and provide TLS termination. For more information about TLS handling in Kubernetes see the TLS/SSL page of this section.
The persistent volume claim that will be created assumes that you have a storage class already present in the cluster named azurefile. It is present by default on a Azure Kubernetes Service cluster. See the Create and use a volume with Azure Files in Azure Kubernetes Service (AKS) Microsoft article for more information.
These values assume that you own the example.com domain name and that it points to the load balancer's public IP address. In this particular case, the HTTPS means that the load balancer should work at network layer 7 and provide TLS termination. For more information about TLS handling in Kubernetes see the TLS/SSL page of this section.
The persistent volume claim that will be created assumes that you have a storage class already present in the cluster named azurefile. It is present by default on a Azure Kubernetes Service cluster. See the Create and use a volume with Azure Files in Azure Kubernetes Service (AKS) Microsoft article for more information.
These values assume that you own the example.com domain name and that it points to the public IP address of the load balancer. In this particular case, the HTTPS means that the load balancer should work at network layer 7 and provide TLS termination. For more information about TLS handling in Kubernetes see the TLS/SSL page of this section.
The persistent volume claim that will be created assumes that you have a storage class already present in the cluster named azurefile. It is present by default on a Azure Kubernetes Service cluster. See Dynamically create and use a persistent volume with Azure Files in Azure Kubernetes Service (AKS) for more information.
The persistent volume claim template that is used in the database part uses a storage class called default. It is present by default on a Azure Kubernetes Service cluster and represents the Azure Disks service. See the Create and use a volume with Azure Files in Azure Kubernetes Service (AKS) Microsoft article for more information.
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
data:
WFGEN_APP_SETTING_ApplicationUrl: https://example.com/wfgen
WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\WFGEN_APP_SETTING_ApplicationSerialNumber
WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
WFGEN_GEN_APP_SYM_ENCRYPT_KEY: 'N'
WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKeyapiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
WFGEN_DATABASE_CONNECTION_STRING: U2VydmVyPXNvbWUuc3FsLnNlcnZlci5jb20sMTQzMzsuLi4K
WFGEN_APP_SETTING_ApplicationSerialNumber: TVktV0ZHLUxJQy1OVU1CRVIK
WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey: MWY3M2M4NDI2OTJmNDM2YjkyNDExNjQxYzQ2ZmIzMzgKusing namespace System.Text
function ConvertTo-Base64String {
[CmdletBinding()]
[OutputType([string])]
param (
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[string]$Value
)
process {
return [Convert]::ToBase64String([Encoding]::UTF8.GetBytes($Value))
}
}
'Server=some.sql.server.com,1433;...' | ConvertTo-Base64String # U2VydmVyPXNvbWUuc3FsLnNlcnZlci5jb20sMTQzMzsuLi4K
'MY-WFG-LIC-NUMBER' | ConvertTo-Base64String # TVktV0ZHLUxJQy1OVU1CRVIK
'1f73c842692f436b92411641c46fb338' | ConvertTo-Base64String # MWY3M2M4NDI2OTJmNDM2YjkyNDExNjQxYzQ2ZmIzMzgKecho 'Server=some.sql.server.com,1433;...' | base64 # U2VydmVyPXNvbWUuc3FsLnNlcnZlci5jb20sMTQzMzsuLi4K
echo 'MY-WFG-LIC-NUMBER' | base64 # TVktV0ZHLUxJQy1OVU1CRVIK
echo '1f73c842692f436b92411641c46fb338' | base64 # MWY3M2M4NDI2OTJmNDM2YjkyNDExNjQxYzQ2ZmIzMzgKapiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-wfg-pvc
spec:
accessModes:
- ReadWriteMany
storageClassName: azurefile
resources:
requests:
storage: 50Gikubectl apply -f ./my-wfg-pvc.yamlapiVersion: v1
kind: ConfigMap
metadata:
name: my-db-configmap
data:
ACCEPT_EULA: 'Y'
SA_PASSWORD_FILE: /mnt/secrets/SA_PASSWORD
WFGEN_DATABASE_USER_USERNAME_FILE: /mnt/secrets/WFGEN_DATABASE_USER_USERNAME
WFGEN_DATABASE_USER_PASSWORD_FILE: /mnt/secrets/WFGEN_DATABASE_USER_PASSWORD
WFGEN_ADMIN_PASSWORD_FILE: /mnt/secrets/WFGEN_ADMIN_PASSWORDapiVersion: v1
kind: Secret
metadata:
name: my-db-secret
type: Opaque
data:
SA_PASSWORD: c3Ryb25nKCEpUGFzcwo=
WFGEN_DATABASE_USER_PASSWORD: c3Ryb25nKCEpUGFzcwo=
WFGEN_ADMIN_PASSWORD: c3Ryb25nKCEpUGFzcwo=
WFGEN_DATABASE_USER_USERNAME: V0ZHRU5fVVNFUgo=using namespace System.Text
function ConvertTo-Base64String {
[CmdletBinding()]
[OutputType([string])]
param (
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[string]$Value
)
process {
return [Convert]::ToBase64String([Encoding]::UTF8.GetBytes($Value))
}
}
'strong(!)Pass' | ConvertTo-Base64String # c3Ryb25nKCEpUGFzcwo=
'WFGEN_USER' | ConvertTo-Base64String # V0ZHRU5fVVNFUgo=echo 'strong(!)Pass' | base64 # c3Ryb25nKCEpUGFzcwo=
echo 'WFGEN_USER' | base64 # V0ZHRU5fVVNFUgo=helm install --set image.tag=7.15.5-win-ltsc2019 release-name ./chart-pathimage:
tag: 7.15.5-win-ltsc2019{
"image": {
"tag": "7.15.5-win-ltsc2019"
}
}# YAML
helm install --set-file ./my-values.yaml release-name ./chart-path
# JSON
helm install --set-file ./my-values.json release-name ./chart-path# Default values for WorkflowGen.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
# replicaCount Number of replicas to create per deployment of WorkflowGen. Doesn't impact database.
replicaCount: 1
# scalable Deploy WorkflowGen and its database in a scalable architecture.
scalable: true
# tenantName For multi-tenancy, it is recommended to populate this value in a multi-tenant architecture. This name will be put as a prefix for resources' name and the label "workflowgen.com/tenant: tenantName" will be added as a selector label.
tenantName: ""
# workflowgen Configuration related to the WorkflowGen pod.
workflowgen:
# image Configuration related to the image to be used for the WorkflowGen pod.
image:
# repository The repository to use to pull the image.
repository: advantys/workflowgen
# tag The image tag to use.
tag: ""
# pullPolicy The pull policy to adopt for this image.
pullPolicy: Always
# nameOverride Override the name of the chart.
nameOverride: ""
# fullnameOverride Override the name of the WorkflowGen deployment. It is based on the name by default.
fullnameOverride: ""
# runtimeClassName Runtime class to use with the deployment.
runtimeClassName: ""
# strategy The update strategy for the WorkflowGen deployment.
strategy:
type: Recreate
# nodeSelector Node selectors to use for the WorkflowGen pod. WorkflowGen only works on Windows Server.
nodeSelector:
kubernetes.io/os: windows
# annotations Annotations to attach to the WorkflowGen deployment. You can attach annotations to the deployment itself or its template.
annotations: {}
# deployment: {}
# template: {}
# tolerations Tolerations to apply to the WorkflowGen pod.
tolerations: []
# affinity Affinities to apply to the WorkflowGen pod.
affinity: {}
# createConfigMap Create a ConfigMap for WorkflowGen's configuration.
createConfigMap: true
# configMapNameOverride Override the name of WorkflowGen's ConfigMap.
configMapNameOverride: ""
# config The configuration to put in the ConfigMap.
config: {}
# createSecret Create a Secret for WorkflowGen's secret values.
createSecret: true
# secretNameOverride Override the name of WorkflowGen's Secret.
secretNameOverride: ""
# secretMountPath The mount path inside WorkflowGen's containers where to put the secret files.
secretMountPath: C:\secrets
# secret The secret values to put in the Secret object. Values will be automatically endoded in base64.
secret: {}
# license Configuration related to WorkflowGen's license.
license:
# volumeNameOverride Override the name of the license's volume.
volumeNameOverride: ""
# secretName The name of the secret that contains WorkfowGen's license.
secretName: ""
# items The specific items to use from the secret to inject in WorkflowGen's containers.
items: []
# - key: ""
# path: ""
# createDataPvc Create a PersistentVolumeClaim for the data volume of WorkflowGen.
createDataPvc: true
# dataPvcNameOverride Override the name of data's PersistentVolumeClaim.
dataPvcNameOverride: ""
# dataVolumeNameOverride Override the volume name associated to the PersistentVolumeClaim.
dataVolumeNameOverride: ""
# dataPvcSpec The data PersistentVolumeClaim specifications.
dataPvcSpec: {}
# accessModes:
# - ReadWriteMany
# storageClassName: storageclass
# resources:
# requests:
# storage: 4Gi
# additionalVolumes Additional volumes to attach to WorkflowGen's deployment.
additionalVolumes: []
# additionalVolumeMounts Additional volumes to mount in WorkflowGen's container.
additionalVolumeMounts: []
# podSecurityContext The security context of the pod.
podSecurityContext: {}
# fsGroup: 2000
# securityContext The security context of WorkflowGen's container.
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
# runAsUserName: ContainerUser
# resources Configuration related to the resources of the container.
resources: {}
# limits:
# cpu: '1'
# memory: 2Gi
# requests:
# cpu: '1'
# memory: 2Gi
# service Configuration related to the service associated with WorkflowGen's deployment.
service:
# type The type of the service.
type: ClusterIP
# port The port exposed from the service.
port: 80
# clusterIP The cluster IP address to use.
clusterIP: ""
# winServices Configuration related to WorkflowGen's Windows Services deployment. Ignored when release not scalable.
winServices:
# nameOverride Override the chart name of this deployment.
nameOverride: ""
# runtimeClassName Runtime class to use with the deployment.
runtimeClassName: ""
# nodeSelector Node selectors to use for the WorkflowGen Windows Services pod. WorkflowGen only works on Windows Server.
nodeSelector:
kubernetes.io/os: windows
# annotations Annotations to attach to the WorkflowGen Windows services deployment.
annotations: {}
# fullnameOverride Override the name of the Windows services deployment.
fullnameOverride: ""
# tolerations Tolerations to apply to the WorkflowGen Windows services pod.
tolerations: []
# affinity Affinities to apply to the WorkflowGen Windows services pod.
affinity: {}
# podSecurityContext The security context of the pod.
podSecurityContext: {}
# fsGroup: 2000
# dirSync Configuration related to the directory synchronization Windows service container.
dirSync:
# securityContext The security context of the directory synchronization Windows service container.
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
# runAsUserName: ContainerUser
# resources Configuration related to the resources of the container.
resources: {}
# limits:
# cpu: '1'
# memory: 2Gi
# requests:
# cpu: '1'
# memory: 2Gi
# engine Configuration related to the engine Windows service container.
engine:
# securityContext The security context of the engine Windows service container.
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
# runAsUserName: ContainerUser
# resources Configuration related to the resources of the container.
resources: {}
# limits:
# cpu: '1'
# memory: 2Gi
# requests:
# cpu: '1'
# memory: 2Gi
# database Configuration related to the database deployment.
database:
# image Configuration related to the image to be used for the database pod.
image:
# repository The repository to use to pull the image.
repository: advantys/workflowgen-sql
# tag The image tag to use.
tag: ""
# pullPolicy The pull policy to adopt for this image.
pullPolicy: Always
# create Create a database deployment to be used with the WorkflowGen deployment.
create: true
# createConfigMap Create a ConfigMap for the database configuration.
createConfigMap: true
# configMapNameOverride Override the name of the database ConfigMap.
configMapNameOverride: ""
# config The configuration to put in the ConfigMap.
config: {}
# createSecret Create a Secret for the database secret values.
createSecret: true
# secretNameOverride Override the name of the database Secret.
secretNameOverride: ""
# secretMountPath The mount path inside the database container where to put the secret files.
secretMountPath: /mnt/secrets
# secret The secret values to put in the Secret object. Values will be automatically endoded in base64.
secret: {}
# useEnv Indicates to use additional environement variables.
useEnv: false
# env Definition of the environment variables.
env: []
# - name: test
# value: value
# - name: test2
# valueFrom:
# secretKeyRef:
# key: test-key
# name: secret-name
# For MSSQL Linux, you may want to put this here or in the config section:
# - name: MSSQL_PID
# value: Express # You can replace with the edition you want: "Enterprise" or "Developer" or "Express"
# fullnameOverride Override the name of the database deployment.
fullnameOverride: ""
# nameOverride Override the chart name of this deployment.
nameOverride: ""
# args The arguments to pass to the database container.
args: []
# tolerations Tolerations to apply to the database pod.
tolerations: []
# affinity Affinities to apply to the database pod.
affinity: {}
# runtimeClassName Runtime class to use with the stateful set.
runtimeClassName: ""
# nodeSelector Node selectors to use for the database pod.
nodeSelector: {}
# kubernetes.io/os: linux
# annotations Annotations to attach to the database deployment. You can add annotations for the StatefulSet or its template.
annotations: {}
# statefulset: {}
# template: {}
# podSecurityContext The security context of the pod.
podSecurityContext: {}
# fsGroup: 2000
# securityContext The security context of the database container.
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
# runAsUserName: ContainerUser
# With MSSQL, you may want to use the mssql (10001) account
# runAsUser: 10001
# runAsGroup: 0
# If you can't configure the volumes with the correct permissions for mssql, you may want to run the container as root:
# runAsUser: 0
# runAsGroup: 0
# resources Configuration related to the resources of the container.
resources: {}
# limits:
# cpu: '1'
# memory: 2Gi
# requests:
# cpu: '1'
# memory: 2Gi
# volumeClaimTemplateSpec PersistentVolumeClaim specification for the StatefulSet PersistentVolumeClaimTemplate.
volumeClaimTemplateSpec: {}
# accessModes:
# - ReadWriteOnce
# storageClassName: default
# resources:
# requests:
# storage: 4Gi
# service Configuration related to the database cluster service.
service:
# type The type of the service.
type: ClusterIP
# port The port exposed from the service.
port: 1433
# clusterIP The cluster IP address to use.
clusterIP: None
# imagePullSecrets Secrets to inject in order to pull images from private repositories.
imagePullSecrets: []
# ingress Configuration related to the ingress rules.
ingress:
# enabled Whether or not to enable the ingress rules defined here.
enabled: true
# annotations Additional annotations to put on the Ingress object.
annotations: {}
# kubernetes.io/ingress.class: nginx
# cert-manager.io/cluster-issuer: letsencrypt
# kubernetes.io/tls-acme: "true"
# hosts List of hosts and routes for routing purposes.
hosts:
- host: chart-example.local
paths: []
# - host: example
# paths: []
# tls List of TLS hosts associated with a secret containing the proper TLS certificates.
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
# hooks Configuration related to the Helm hooks of this chart
hooks:
# preupgrade
preupgrade:
# enabled Enables the use of the pre-upgrade hook which will migrate WorkflowGen's data when upgrading.
enabled: true
# image Configuration related to the image to be used for the pre-upgrade pod.
image:
# repository The repository to use to pull the image.
repository: advantys/workflowgen-upgrade
# tag The image tag to use.
tag: ""
# args The arguments to pass to the migration container.
args: []
# env Definition of the environment variables.
env: []
# - name: test
# value: value
# - name: test2
# valueFrom:
# secretKeyRef:
# key: test-key
# name: secret-name
# connectionStringSecretKey The key to pick for the WFGEN_DATABASE_CONNECTION_STRING environment variable. Defaults to WFGEN_DATABASE_CONNECTION_STRING.
connectionStringSecretKey: ""
# secret The secret values to put in the Secret object for this hook. Values will be automatically endoded in base64.
secret: {}
# runtimeClassName The name of the RuntimeClass to use with this pod.
runtimeClassName: ""
# podSecurityContext The security context for the pod specification.
podSecurityContext: {}
# nodeSelector Node selectors to use for the pre-upgrade pod.
nodeSelector:
kubernetes.io/os: linux
# affinity Affinities to apply to the pre-upgrade pod.
affinity: {}
# tolerations Tolerations to apply to the pre-upgrade pod.
tolerations: []
workflowgen:
config:
WFGEN_APP_SETTING_ApplicationUrl: https://example.com/wfgen
WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\WFGEN_APP_SETTING_ApplicationSerialNumber
WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
WFGEN_GEN_APP_SYM_ENCRYPT_KEY: 'N'
WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey
secret:
WFGEN_DATABASE_CONNECTION_STRING: 'Server=some.sql.server.com,1433;...'
WFGEN_APP_SETTING_ApplicationSerialNumber: MY-WFG-LIC-NUMBER
WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey: 1f73c842692f436b92411641c46fb338workflowgen:
dataPvcSpec:
accessModes:
- ReadWriteMany
storageClassName: azurefile
resources:
requests:
storage: 50Gikubectl create secret generic wfgen-license-secret --from-file ./WFG.licworkflowgen:
license:
secretName: wfgen-license-secret
items:
- key: WFG.lic
path: WFG.licworkflowgen:
image:
reference: mycorporation/workflowgen
tag: 7.18.3-win-ltsc2019workflowgen:
service:
kind: LoadBalancerworkflowgen:
resources:
limits:
cpu: '1'
memory: 2Gi
requests:
cpu: '1'
memory: 2Gi
# Used when "scalable: true"
winServices:
dirSync:
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: '500M'
memory: 1Gi
engine:
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: '500M'
memory: 1Gidatabase:
create: falsedatabase:
config:
ACCEPT_EULA: 'Y'
SA_PASSWORD_FILE: /mnt/secrets/SA_PASSWORD
WFGEN_DATABASE_USER_USERNAME_FILE: /mnt/secrets/WFGEN_DATABASE_USER_USERNAME
WFGEN_DATABASE_USER_PASSWORD_FILE: /mnt/secrets/WFGEN_DATABASE_USER_PASSWORD
WFGEN_ADMIN_PASSWORD_FILE: /mnt/secrets/WFGEN_ADMIN_PASSWORD
secret:
SA_PASSWORD: 'strong(!)Pass'
WFGEN_DATABASE_USER_PASSWORD: 'strong(!)Pass'
WFGEN_ADMIN_PASSWORD: 'strong(!)Pass'
WFGEN_DATABASE_USER_USERNAME: WFGEN_USERdatabase:
volumeClaimTemplateSpec:
accessModes:
- ReadWriteOnce
storageClassName: default
resources:
requests:
storage: 100Gidatabase:
image:
reference: mycorporation/workflowgen-sql
tag: 7.18.3-ubuntu-18.04database:
fullnameOverride: my-databasedatabase:
resources:
limits:
cpu: '2'
memory: 4Gi
requests:
cpu: '1'
memory: 2Giingress:
enabled: falseingress:
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt
hosts:
- host: &wfgenHost myinstance.example.com
paths:
- /
tls:
- secretName: tls-secret
hosts:
- *wfgenHosthooks:
preupgrade:
enabled: falsehooks:
preupgrade:
image:
tag: latest-ubuntu-18.04
secret:
WFGEN_DATABASE_CONNECTION_STRING: 'Server=some.sql.server.com,1433;...'
mysecret: something secret
env:
- name: WFGEN_UPGRADE_EXCLUDE_FILES
value: file1,file2
- name: MY_SECRET_ENV
valueFrom:
secretKeyRef:
name: wfgen-migrations-secret # If release name is "wfgen"
key: mysecret
args:
- "-FromVersion"
- "7.14.10"
- "-ToVersion"
- "7.18.2"scalable: false
workflowgen:
resources:
limits:
cpu: '1'
memory: '2Gi'
requests:
cpu: '1'
memory: '2Gi'
config:
WFGEN_APP_SETTING_ApplicationUrl: https://example.com/wfgen
WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\WFGEN_APP_SETTING_ApplicationSerialNumber
WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
WFGEN_GEN_APP_SYM_ENCRYPT_KEY: 'N'
WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey
secret:
WFGEN_DATABASE_CONNECTION_STRING: 'Server=some.sql.server.com,1433;...'
WFGEN_APP_SETTING_ApplicationSerialNumber: MY-WFG-LIC-NUMBER
WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey: 1f73c842692f436b92411641c46fb338
license:
secretName: wfgen-license-secret
items:
- key: WFG.lic
path: WFG.lic
dataPvcSpec:
accessModes:
- ReadWriteMany
storageClassName: azurefile
resources:
requests:
storage: 50Gi
service:
type: LoadBalancer
database:
create: false
ingress:
enabled: false
kubectl create secret generic wfgen-license-secret --from-file ./WFG.lichelm install -f ./my-values.yaml wfgen https://github.com/advantys/workflowgen-releases/releases/download/7.18.2/workflowgen-0.0.3.tgzreplicaCount: 3
workflowgen:
resources:
limits:
cpu: '1'
memory: '2Gi'
requests:
cpu: '1'
memory: '2Gi'
config:
WFGEN_APP_SETTING_ApplicationUrl: https://example.com/wfgen
WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\WFGEN_APP_SETTING_ApplicationSerialNumber
WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
WFGEN_GEN_APP_SYM_ENCRYPT_KEY: 'N'
WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey
secret:
WFGEN_DATABASE_CONNECTION_STRING: 'Server=some.sql.server.com,1433;...'
WFGEN_APP_SETTING_ApplicationSerialNumber: MY-WFG-LIC-NUMBER
WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey: 1f73c842692f436b92411641c46fb338
license:
secretName: wfgen-license-secret
items:
- key: WFG.lic
path: WFG.lic
dataPvcSpec:
accessModes:
- ReadWriteMany
storageClassName: azurefile
resources:
requests:
storage: 50Gi
service:
type: LoadBalancer
winServices:
dirSync:
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: '500M'
memory: 1Gi
engine:
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: '500M'
memory: 1Gi
database:
create: false
ingress:
enabled: falsekubectl create secret generic wfgen-license-secret --from-file ./WFG.lichelm install -f ./my-values.yaml wfgen https://github.com/advantys/workflowgen-releases/releases/download/7.18.2/workflowgen-0.0.3.tgzreplicaCount: 3
workflowgen:
resources:
limits:
cpu: '1'
memory: 2Gi
requests:
cpu: '1'
memory: 2Gi
config:
WFGEN_APP_SETTING_ApplicationUrl: http://10.0.1.1/wfgen
WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\ApplicationSerialNumber
WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\ApplicationSecurityPasswordSymmetricEncryptionKey
WFGEN_MACHINE_KEY_DECRYPTION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_DECRYPTION_KEY
WFGEN_MACHINE_KEY_VALIDATION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_VALIDATION_KEY
secret:
ApplicationSerialNumber: <YOUR_WFG_LIC_KEY>
ApplicationSecurityPasswordSymmetricEncryptionKey: <YOUR_NEW_GUID>
WFGEN_DATABASE_CONNECTION_STRING: 'Server=wfgen-database-0.wfgen-database.default.svc.cluster.local,1433;Database=WFGEN;User ID=WFGEN_USER;Password=strong(!)Pass;'
WFGEN_MACHINE_KEY_DECRYPTION_KEY: '39B3AE9CCCF94AA47D795EC84F7CCB7928F5D59BE2EB2BBA4FE2AC0B3C8D0C85'
WFGEN_MACHINE_KEY_VALIDATION_KEY: '82F6247A5DBF8666FB60B8EFE6483360436F0EC426CC0351A9569C607B46C1FAD6497406DD8B0B519DD83CAA6764904C89999D742638ECE756E7C0B8799B45E9'
license:
secretName: wfgen-license-secret
items:
- key: WorkflowGen.lic
path: WorkflowGen.lic
dataPvcSpec:
accessModes:
- ReadWriteMany
storageClassName: azurefile
resources:
requests:
storage: 50Gi
service:
type: LoadBalancer
winServices:
dirSync:
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: '500M'
memory: 1Gi
engine:
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: '500M'
memory: 1Gi
database:
fullnameOverride: wfgen-database
nodeSelector:
kubernetes.io/os: linux
securityContext:
runAsUser: 0
runAsGroup: 0
resources:
limits:
cpu: '1'
memory: 2Gi
requests:
cpu: '500m'
memory: 1Gi
config:
ACCEPT_EULA: 'Y'
SA_PASSWORD_FILE: /mnt/secrets/SA_PASSWORD
WFGEN_DATABASE_USER_USERNAME_FILE: /mnt/secrets/WFGEN_DATABASE_USER_USERNAME
WFGEN_DATABASE_USER_PASSWORD_FILE: /mnt/secrets/WFGEN_DATABASE_USER_PASSWORD
WFGEN_ADMIN_PASSWORD_FILE: /mnt/secrets/WFGEN_ADMIN_PASSWORD
secret:
SA_PASSWORD: 'strong(!)Pass'
WFGEN_DATABASE_USER_PASSWORD: 'strong(!)Pass'
WFGEN_ADMIN_PASSWORD: 'strong(!)Pass'
WFGEN_DATABASE_USER_USERNAME: WFGEN_USER
volumeClaimTemplateSpec:
accessModes:
- ReadWriteOnce
storageClassName: default
resources:
requests:
storage: 100Gi
ingress:
enabled: false
kubectl create secret generic wfgen-license-secret --from-file ./WFG.lichelm install -f ./my-values.yaml wfgen https://github.com/advantys/workflowgen-releases/releases/download/7.18.2/workflowgen-0.0.3.tgzkubectl apply -f ./my-configmap.yaml
kubectl apply -f ./my-secret.yamlworkflowgen:
createConfigMap: false
configMapNameOverride: my-configmap
createSecret: false
secretNameOverride: my-secretworkflowgen:
createDataPvc: false
dataPvcNameOverride: my-wfg-pvckubectl apply -f ./my-db-configmap.yaml
kubectl apply -f ./my-db-secret.yamldatabase:
createConfigMap: false
configMapNameOverride: my-db-configmap
createSecret: false
secretNameOverride: my-db-secret