Linux Self-host without Docker

I have…

I’m submitting a…

  • [ ] Regression (a behavior that stopped working in a new release)
  • [ ] Bug report
  • [ ] Performance issue
  • [ ] Documentation issue or request

Current behavior

  • dotnet runtime 6.0 is installed.
  • MongodDB installed and running.
  • run the app with: dotnet Squidex.dll
  • Kestrel server runs without errors.
  • the console prints the correct hostname.
  • the console prints the following also:
    “logLevel”: “Information”,
    “message”: “Now listening on: http://localhost:5000”,
    even tho I have changed the baseUrl to the server IP before I deploy and run.
    When I open http://<server_ip>:5000 or http://:5000 nothing loads
    The port is open and no firewall is blocking.

Expected behavior

Squidex to load.

Minimal reproduction of the problem


Rocky Linux 8.5 RHEL 8

App Name: Squidex

  • [ ] Self hosted with docker
  • [ ] Self hosted with IIS
  • [x] Self hosted with other version
  • [ ] Cloud version

Version: 6.4.0


  • [ ] Chrome (desktop)
  • [ ] Chrome (Android)
  • [ ] Chrome (iOS)
  • [ ] Firefox
  • [ ] Safari (desktop)
  • [ ] Safari (iOS)
  • [ ] IE
  • [x] Edge

The configs are set as:
// Set it to true to redirect the user from http to https permanently.
“enforceHttps”: false,
// Set it to true to return a 400 if the host does not match.
“enforceHost”: false,
so it’s not SSL

Hi, it looks like you have the .NET SDK installed on your machine.

Then Squidex runs in development mode and requests the frontend files from the dev server.

You have to ensure that you ASPNETCORE_ENVIRONENMENT=Production is set. Then Squidex should listen to port 80 by default if not confgured otherwise.

More about how to configure URLS:

Hello Sebastian.
Do you mean installed in the production machine?

Because I installed it by following MS documents and there are two options for running dotnet is by installing SDK or Runtime. I went to runtime option and it has two sub runtimes, either to
install aspnetcore:
sudo dnf install aspnetcore-runtime-6.0

or dotnet:
sudo dnf install dotnet-runtime-6.0

The difference is that dotnet alone doesn’t support ASP.Net Core. Which is essentially in webapps? So I installed aspnetcore-runtime

The command for the SDK is dotnet-**sdk**-6.0 Which I didn’t use at all. I only have the SDK installed on my local machine and I have ran the app first after build for release on my local machine then I deployed it. Do you think that is the reason? Perhaps the app saved some configs?

Whatever it is, it looks like the ASPNETCORE_ENVIRONENMENT environment variable is set to Development and not to Production.

It’s not possible to set the ASPNETCORE_ENVIRONMENT environment in runtime. Or let’s say it’s useless as it get completely ignored by the runtime.
Anyways here’s what I did, but still the same

Here’s the rest

So, do u suggest to install SDK instead?

Can you search for something like Hosting Environment: Production in the logs? I still do not believe the result. It pretty much looks like development.

Or: Hosting Environment: Development of course.

I am also confused what you meant exactly with:

What do you mean with “nothing loads”?

I mean when I navigate to the IP with the mention Port I get connection error,
Strangly when I crul curl http://localhost:5000 the url from the server it self I get the home page response.

anyways here’s the complete output after running the command in the first line:
output.json · GitHub

hosts are correctly set. also the server uses /etc/cloud/templates/hosts.redhat.tmpl. I assured they are correctly set

If you want access to the server I’ll PM you. Perhaps it will help you investigating this in short time

This sounds very much like a firewall or routing issue.

I updated the link.

I think I know the problem. I will update you …

1 Like

I had doubts about selinux enforcement so I completely disabled it, but nothing changed.
I reverse proxy the app from 80 to 5000 and I only get a blank page.
It’s definitely a server-side issue not from your app. Because it fully met requirements of running cross-platform. I even complied Squidex to native code, but still no luck.
Anyways here’s the system service I used to run the app on RHEL as a service.
in case you going to add documents for running the app on kestrel without docker you can add this snippet as well.

[root@server backend]# cat /etc/systemd/system/backend.service
Description=Squidex .NET Web API on Kestrel

ExecStart=/usr/bin/dotnet /srv/www/backend/Squidex.dll
# Use root user to be able to open 80, 443 ports
# Restart service after 10 seconds if the dotnet service crashes:



I am not sure how to help here, you have very, very likely much more knowledge about Linux administration than me.

You have a great platform, it’s open-source and free.
You did a great job, you are very supportive and responsive.

When I get free time, I will try to implement it again , and help you add documents for that.
Thank you so much for your time.

1 Like

Have you just tried docker btw?

I haven’t, I don’t like using VM for production that’s why I went to direct implementation.
It will mostly work. I will try it now and let you know.

by default Squidex does not provide a certificate and https. You need a proxy for that. Perhaps this is the misunderstanding. Can recommend caddy:


I had free time today and I did some digging.

The reason for Squidex to run on port 5000:5001 even in a non development environment is because Squidex is configured to be “Docker-dependent” in production?

Which is unnecessary in my opinion because it adds an extra layer to the API call. That’s why I wanted to use Squidex with Kestrel on the edge.

And I know the reason of using Docker which is to ease the work on the end-user which is something that adds extra points to Squidex to be plug-and-play And I recommend it to stay that way :+1:.

Anyways here are the steps I did to find the core issue:

  • Squidex runs on ports 5000:5001 even if no proxy is in presence: docker-compose-noproxy.yml

  • Using the following didn’t solve the problem:

    dotnet publish -c release

    export ASPNETCORE_ENVIRONMENT=Production <- this to add env variable to Linux.

  • Dotnet-runtime ASPNETCORE_ENVIRONMENT is set to Production by default HostingEnvironment.cs or if not present in settings HostingEnvironmentExtensions.cs.

  • appSettings.json doesn’t have any option to force the Environment.

That led to the conclusion; it is hardcoded issue (Correct me if I’m wrong)

Here is the default configuration of Kestrel for Squidex:

builder.ConfigureKestrel((context, serverOptions) =>
    if (context.HostingEnvironment.IsDevelopment() || context.Configuration.GetValue<bool>("devMode:enable"))
    serverOptions.ListenAnyIP(5001,listenOptions => listenOptions.UseHttps("../../../dev/squidex-dev.pfx", "password"));



I added the following to environment checking condition:


And it solved the “problem” :smiley:

Of course it’s not the ideal solution. It could be something like options set at appsettings.json, it could look like the following for example:

"kestrel": {
    **use "IsProduction": true**
    **or leave it open to the user so they can type any custom publishing environment?**
    **like Development, Production, Stagging ...etc as following**
    "Environment": "Production",
    "SSLCertificatePath": "/root/path/to/pfx",
    "SSLPassword": "password"

Sorry for the long post, but I wanted it to be easier to be implemented instead of putting your time on debugging this.

I can make a PR if wanted.

Thank you for your time.

Yes, thats true. I thought it runs on port 80 in production mode, but it seems that the url is overriden in the official docker images to port 80.

Therefore this line is wrong I guess:

But you can configure everythin in kestrel over environment variables already:

There is a better article, but I cannot find it right now. I think we do not need code changes.

I mean this article:

It is very weird, but the German version has a better sample:

  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:80"
      "Https": {
        "Url": "https://localhost:443",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "<certificate password>"

With env vars it should look like this: