Table of Contents

Prerequisites

Business clusters images

In order to run your Neos cluster in the Kubernetes environment, you will need to provide for each cluster a Docker image of the backend and frontend parts. If your cluster calls background server methods, you will also need to provider a Docker image of the task-runner.

These images should be based on the same Neos version as the application version of the Helm chart.

Backend example

# syntax=docker/dockerfile:1.2

# Use this dockerfile to generate technicaldemos-backend image.
#
# Build arguments :
# - NEOS_VERSION : neos-fmk image version to use for cluster generation (default: latest)
#
# /!\ The build command has to be run from the cluster root directory context :
#   docker build -t technicaldemos-backend:{version} -f ./docker/backend.Dockerfile --build-arg NEOS_VERSION={version} . #from technicaldemos root directory

ARG NEOS_VERSION=latest
# To build the application, we use a neos-fmk image as base so we can directly run the neos commands
FROM "harbor.hexanet.fr:8443/neos/neos-fmk:${NEOS_VERSION}" AS builder

COPY ./modules /usr/src/technicaldemos/modules
COPY ./*.yml /usr/src/technicaldemos/

# The persistence configuration is mandatory for the build but it can be overridden in the appsettings.json file
RUN echo 'PersistenceType: PostgreSQL' > /usr/src/technicaldemos/technicaldemos.persistence.yml
# /!\ DONT PUT YOUR REAL CONNECTIONSTRING HERE /!\
# We just want to generate the application so we need to set a value but it will not be used by the process.
# In production the connectionstring should be overridden either by :
# - mounting a specific appsettings.json file
# - setting the PersistenceSettings__ConnectionString environment variable
RUN echo 'ConnectionString: None' >> /usr/src/technicaldemos/technicaldemos.persistence.yml
WORKDIR /usr/src/technicaldemos

# We only need to build the server part of the cluster
RUN neos generate --build-configuration Release Server

# The backend will run inside a container having dotnet installed
FROM mcr.microsoft.com/dotnet/aspnet:8.0

# Copy the result of the AspNetCore application build into the dotnet image
COPY --from=builder /usr/src/technicaldemos/server/bin/TechnicalDemos.AspNetCore/ /app

# Create an unprivileged user to run the application in an isolated directory (/app)
RUN adduser --disabled-password \
    --home /app \
    --gecos '' neos && chown -R neos /app
USER neos

WORKDIR /app

# Indicates the port on with the backend will be listening
ENV ASPNETCORE_URLS=http://+:7000

# Set this variable to true to enable multitenancy mode
ENV Multitenancy=true

# When the container is started, it will run the application backend server
ENTRYPOINT ["dotnet", "TechnicalDemos.AspNetCore.dll"]

Task-runner example

# syntax=docker/dockerfile:1.2

# Use this dockerfile to generate technicaldemos-task-runner image.
#
# Build arguments :
# - NEOS_VERSION : neos-fmk image version to use for cluster generation (default: latest)
#
# /!\ The build command has to be run from the cluster root directory context :
#   docker build -t technicaldemos-task-runner:{version} -f ./docker/task-runner.Dockerfile --build-arg NEOS_VERSION={version} . #from technicaldemos root directory

ARG NEOS_VERSION=latest
# To build the application, we use a neos-fmk image as base so we can directly run the neos commands
FROM "harbor.hexanet.fr:8443/neos/neos-fmk:${NEOS_VERSION}" AS builder

COPY ./modules /usr/src/technicaldemos/modules
COPY ./*.yml /usr/src/technicaldemos/

# The persistence configuration is mandatory for the build but it can be overridden in the appsettings.json file
RUN echo 'PersistenceType: PostgreSQL' > /usr/src/technicaldemos/technicaldemos.persistence.yml
# /!\ DONT PUT YOUR REAL CONNECTIONSTRING HERE /!\
# We just want to generate the application so we need to set a value but it will not be used by the process.
# In production the connectionstring should be overridden either by :
# - mounting a specific appsettings.json file
# - setting the PersistenceSettings__ConnectionString environment variable
RUN echo 'ConnectionString: None' >> /usr/src/technicaldemos/technicaldemos.persistence.yml
WORKDIR /usr/src/technicaldemos

# We only need to build the server part of the cluster
RUN neos generate --build-configuration Release Server

# The task-runner will run inside a container having dotnet installed
FROM mcr.microsoft.com/dotnet/aspnet:8.0

# Copy the result of the task-runner application build into the dotnet image
COPY --from=builder /usr/src/technicaldemos/server/bin/TechnicalDemos.TaskRunner/ /app

# Create an unprivileged user to run the application in an isolated directory (/app)
RUN adduser --disabled-password \
    --home /app \
    --gecos '' neos && chown -R neos /app
USER neos

WORKDIR /app

# Indicates the port on with the task-runner will be listening
ENV ASPNETCORE_URLS=http://+:7000

# Set this variable to true to enable multitenancy mode
ENV Multitenancy=true

# When the container is started, it will run the application task-runner server
ENTRYPOINT ["dotnet", "TechnicalDemos.TaskRunner.dll"]

Frontend example

# syntax=docker/dockerfile:1.2

# Use this dockerfile to generate technicaldemos-frontend image.
#
# Build arguments :
# - NEOS_VERSION : neos-fmk image version to use for cluster generation (default: latest)
#
# Use this dockerfile to generate technicaldemos-frontend image.
# /!\ The build command has to be run from the cluster root directory context :
#   docker build -t technicaldemos-frontend:{version} -f ./docker/frontend.Dockerfile --build-arg NEOS_VERSION={version} . #from technicaldemos root directory

ARG NEOS_VERSION=latest
# To build the application, we use a neos-fmk image as base so we can directly run the neos commands
FROM "harbor.hexanet.fr:8443/neos/neos-fmk:${NEOS_VERSION}" AS builder

COPY ./modules /usr/src/technicaldemos/modules
COPY ./*.yml /usr/src/technicaldemos/

# The persistence configuration is mandatory for the build but it can be overridden in the appsettings.json file
RUN echo 'PersistenceType: PostgreSQL' > /usr/src/technicaldemos/technicaldemos.persistence.yml
# /!\ DONT PUT YOUR REAL CONNECTIONSTRING HERE /!\
# We just want to generate the application so we need to set a value but it will not be used by the process.
# In production the connectionstring should be overridden either by :
# - mounting a specific appsettings.json file
# - setting the PersistenceSettings__ConnectionString environment variable
RUN echo 'ConnectionString: None' >> /usr/src/technicaldemos/technicaldemos.persistence.yml

WORKDIR /usr/src/technicaldemos
# Build the cluster
RUN neos generate --build-configuration Release

WORKDIR /usr/src/technicaldemos/client
# Build the client website
RUN npm install
RUN npm run build

# To serve the frontend website, we use a Nginx server as a base image
FROM nginx:stable
# Provides some basic nginx configuration
COPY ./docker/frontend/nginx/nginx.conf /etc/nginx/conf.d/default.conf
# Copy the client website files into the nginx serving directory
COPY --from=builder /usr/src/technicaldemos/client/dist /usr/share/nginx/html

Secrets

Gateway

The gateway provides authentication so you need to configure the authentication tokens as environment variables. These environment variables should be set in a secret which will then be mounted inside the gateway container.

Note

The environment variables are dotnet override of the appsettings.json file. Please see this article for more information.

You can set the secret name as the value of gateway.envSecret property in your Helm values file.

Example (Neos development authentication server) :

Authentication__Preset=NeosDevAuth

Example (Azure AD B2C) :

Authentication__Preset=AzureAdB2C
Authentication__Authority=https://SomeApplication.b2clogin.com/SomeApplication.onmicrosoft.com/B2C_1A_SIGNUP_SIGNIN/v2.0
Authentication__ClientId=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Authentication__ClientSecret=somesecretvalue
Authentication__Scopes__0=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Authentication__Scopes__1=profile
Note

If your application has server methods which are not subject to authentication (eg Authentication required set to false in the server method configuration), you need to add them to the AnonymousRoutes configuration of the gateway :

AnonymousRoutes__0=/webapi/firstanonymousmethod
AnonymousRoutes__1=/webapi/secondanonymousmethod
Note

If one or several cluster in your deployment is not subject to authentication you need to add their host to the AnonymousHosts configuration of the gateway :

AnonymousHosts__0=first.unauthenticated.cluster.com
AnonymousHosts__1=second.unauthenticated.cluster.com

Reporting

The Stimulsoft license has to be configured inside the report container so you will need to provide the license key in a secret for the Reporting__StimulsoftLicenceKey environment variable.

You can set the secret name as the value of report.envSecret property in your Helm values file.

Tenant management

The tenant management needs to run with a database so you'll need to provide the connection string in a secret for the PersistenceSettings__ConnectionString environment variable.

Note

Connection string needs to follow the DotNet syntax.

You can set the secret name as the value of tenantManagement.envSecret property in your Helm values file.

If you need to expose the tenant manager outside the Kubernetes cluster, you need to provide a TLS certificate as a Kubernetes secret.

You can set the secret name as the value of tenantManagement.tslSecret property in your Helm values file.

License management

The license management needs to run with a database so you'll need to provide the connection string in a secret for the PersistenceSettings__ConnectionString environment variable.

Note

Connection string needs to follow the DotNet syntax.

You can set the secret name as the value of licenseManagement.envSecret property in your Helm values file.

If you need to expose the license manager outside the Kubernetes cluster, you need to provide a TLS certificate as a Kubernetes secret.

You can set the secret name as the value of licenseManagement.tslSecret property in your Helm values file.

Clusters

If you need to expose the cluster application outside the Kubernetes cluster, you need to provide a TLS certificate as a Kubernetes secret.

You can set the secret name as the value of clusters[n].tslSecret property in your Helm values file.

If the cluster's backend needs to run with a database so you'll need to provide the connection string in a secret for the PersistenceSettings__ConnectionString environment variable.

Note

Connection string needs to follow the DotNet syntax.

You can set the secret name as the value of clusters[n].backend.envSecret property in your Helm values file.

To allow the Kubernetes cluster to pull the images of your cluster, you may need to create a secret containing your registry credentials.

You can set the secret names as the values of clusters[n].backend.imagePullSecret and clusters[n].frontent.imagePullSecret property in your Helm values file.

Configuration with AzureAD B2C

If you use AzureAD B2C authentication, you'll need to provide configuration to Tenant Management and your clusters using UserPermissions. This configuration will allow UserPermissions to create or read AzureAD B2C users.

You can set in secrets to setup the environment variables in the following example :

AuthenticationMode=AzureB2C
AzureB2COption__ClientId=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
AzureB2COption__TenantId=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
AzureB2COption__TenantName=xxxx.onmicrosoft.com
AzureB2COption__ClientSecretKey=yoursecret
AzureB2COption__B2cExtensionAppClientId=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
AzureB2COption__EmailContent__RedirectUrl=https://yourapp/
AzureB2COption__EmailContent__Title=Your title
AzureB2COption__EmailContent__Content1=Your email content
AzureB2COption__EmailContent__Content2=Your email content2
AzureB2COption__EmailContent__LinkText=Text
SendGrid__Key=yoursecret
SendGrid__From__Name=yourappname
SendGrid__From__Address=aaa@bbb.cc

Configure the first administrator user with UserPermissions module

If your deployed application is not multi-tenant, when the database is created, there are no users yet. To create the first administrator user, you can configure a new environment variable UserPermissions__DefaultUserAccountLogin or see Configuration in ASP.NET Core.

When the database is migrated, this user will be automatically created with all permissions.

Sending logs to Application Insights

Each Neos application can be configured to send logs to Application Insights, please see this article for more information.

Environnement variables for .Net processes

You can configure Application Insights for Neos .Net processes by setting options as environnement variables in the secret associated to the process.

The following processes are supported :

Example (cluster backend)

ApplicationInsights__ConnectionString=1a11a111-1a1a-1111-a111-1aaa1a1a1a11;IngestionEndpoint=https://westeurope-5.in.  applicationinsights.azure.com/;LiveEndpoint=https://westeurope.livediagnostics.monitor.azure.com/;  ApplicationId=2b22b222-2b2b-2222-b222-2bbb2b2b2b22
ApplicationInsights__EnableHeartbeat=false
ApplicationInsights__RoleName=NorthwindServer
ApplicationInsights__RequestCollectionOptions__TrackExceptions=true
Note

For more information on available options, see this article.

JSON configuration for frontend

To configure Application Insights for frontend, you can create a secret containing an applicationInsights.json file content.

Example

JSON file content :

{
  "clusterVersion": "0.5.1",
  "connectionString": "1a11a111-1a1a-1111-a111-1aaa1a1a1a11;IngestionEndpoint=https://westeurope-5.in.  applicationinsights.azure.com/;LiveEndpoint=https://westeurope.livediagnostics.monitor.azure.com/;  ApplicationId=2b22b222-2b2b-2222-b222-2bbb2b2b2b22",
  "correlationHeaderExcludedDomains": [
    "domain1.com",
    "domain2.com"
  ],
  "disableAjaxTracking": true,
  "enableAutoRouteTracking": true,
  "enableCorsCorrelation": true,
  "enableUnhandledPromiseRejectionTracking": true,
  "neosVersion": "1.21.0",
  "roleName": "NorthwindClient"
}

Associated secret :

apiVersion: v1
kind: Secret
data:
  applicationInsights.json: <base64encodedJSONfilecontent>
metadata:
  name: northwind-frontend-conf
Note

To create the secret directly from an existing applicationInsights.json file on your computer you can use the following command :

kubectl create secret generic <your-secret-name> --from-file=path/to/the/file/applicationInsights.json

See this article for more information on how to create secrets in Kubernetes.

Note

For more information on available options, see this article.

Ingress controller

This charts is configured to work with a Nginx ingress controller.