Oqtane Silent Installation Guide

Oqtane Silent Installation Guide

OK, I’ve been wanting to write this article for a few days now, but I’ve been vibing a lot — writing tons of prototypes and working on my Oqtane research. This morning I got blocked by GitHub Copilot because I hit the rate limit, so I can’t use it for a few hours. I figured that’s a sign to take a break and write some articles instead.

Actually, I’m not really “writing” — I’m using the Windows dictation feature (Windows key + H). So right now, I’m just having coffee and talking to my computer. I’m still in El Salvador with my family, and it’s like 5:00 AM here. My mom probably thinks I’ve gone crazy because I’ve been talking to my computer a lot lately. Even when I’m coding, I use dictation instead of typing, because sometimes it’s just easier to express yourself when you talk. When you type, you tend to shorten things, but when you talk, you can go on forever, right?

Anyway, this article is about Oqtane, specifically something that’s been super useful for me — how to set up a silent installation. Usually, when you download the Oqtane source or use the templates to create a new project or solution, and then run the server project, you’ll see the setup wizard first. That’s where you configure the database, email, host password, default theme, and all that.

Since I’ve been doing tons of prototypes, I’ve seen that setup screen thousands of times per day. So I downloaded the Oqtane source and started digging through it — using Copilot to generate guides whenever I got stuck. Honestly, the best way to learn is always by looking at the source code. I learned that the hard way years ago with XAF from DevExpress — there was no documentation back then, so I had to figure everything out manually and even assemble the projects myself because they weren’t in one solution. With Oqtane, it’s way simpler: everything’s in one place, just a few main projects.

Now, when I run into a problem, I just open the source code and tell Copilot, “OK, this is what I want to do. Help me figure it out.” Sometimes it goes completely wrong (as all AI tools do), but sometimes it nails it and produces a really good guide.

So the guide below was generated with Copilot, and it’s been super useful. I’ve been using it a lot lately, and I think it’ll save you a ton of time if you’re doing automated deployment with Oqtane.

I don’t want to take more of your time, so here it goes — I hope it helps you as much as it helped me.


Oqtane Installation Configuration Guide

This guide explains the configuration options available in the appsettings.json file under the Installation section for automated installation and default site settings.

Overview

The Installation section in appsettings.json controls the automated installation process and default settings for new sites in Oqtane. These settings are particularly useful for:

  • Automated installations – Deploy Oqtane without manual configuration
  • Development environments – Quickly spin up new instances
  • Multi-tenant deployments – Standardize new site creation
  • CI/CD pipelines – Automate deployment processes

Configuration Structure

{
  "Installation": {
    "DefaultAlias": "",
    "HostPassword": "",
    "HostEmail": "",
    "SiteTemplate": "",
    "DefaultTheme": "",
    "DefaultContainer": ""
  }
}
  
Key Purpose Required
DefaultAlias Initial site URL(s)
HostPassword Super admin password
HostEmail Super admin email
SiteTemplate Initial site structure Optional
DefaultTheme Site appearance Optional
DefaultContainer Module wrapper style Optional

SiteTemplate

A Site Template defines the initial structure and content of a new site, including pages, modules, folders, and navigation.

"SiteTemplate": "Oqtane.Infrastructure.SiteTemplates.DefaultSiteTemplate, Oqtane.Server"

Default options:

  • DefaultSiteTemplate – Home, Privacy, example content
  • EmptySiteTemplate – Minimal, clean slate
  • AdminSiteTemplate – Internal use

If empty, Oqtane uses the default template automatically.


DefaultTheme

A Theme controls the visual appearance and layout of your site (page structure, navigation, header/footer, and styling).

"DefaultTheme": "Oqtane.Themes.OqtaneTheme.Default, Oqtane.Client"

Built-in themes:

  • Oqtane Theme (default) – clean and responsive
  • Blazor Theme – Blazor-branded styling
  • Bootswatch variants – Cerulean, Cosmo, Darkly, Flatly, Lux, etc.
  • Corporate Theme – business layout

If left blank, it defaults to the Oqtane Theme.


DefaultContainer

A Container is the wrapper around each module, controlling how titles, buttons, and borders look.

"DefaultContainer": "Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client"

Common containers:

  • OqtaneTheme.Container – standard and responsive
  • AdminContainer – management modules
  • Theme-specific containers – match the chosen theme

Defaults automatically if left empty.


Example Configurations

Minimal Configuration

{
  "Installation": {
    "DefaultAlias": "localhost",
    "HostPassword": "YourSecurePassword123!",
    "HostEmail": "admin@example.com"
  }
}
  

Custom Theme and Container

{
  "Installation": {
    "DefaultAlias": "localhost",
    "HostPassword": "YourSecurePassword123!",
    "HostEmail": "admin@example.com",
    "SiteTemplate": "Oqtane.Infrastructure.SiteTemplates.DefaultSiteTemplate, Oqtane.Server",
    "DefaultTheme": "Oqtane.Theme.Bootswatch.Flatly.Default, Oqtane.Theme.Bootswatch.Oqtane",
    "DefaultContainer": "Oqtane.Theme.Bootswatch.Flatly.Container, Oqtane.Theme.Bootswatch.Oqtane"
  }
}
  

Troubleshooting

  • Settings ignored during installation: Ensure all required fields are filled (DefaultAlias, HostPassword, HostEmail).
  • Theme not found: Check assembly reference and type name.
  • Container displays incorrectly: Use a container matching your theme.
  • Site template creates no pages: Ensure your template returns valid page definitions.

Logs can be found in Logs/oqtane-log-YYYYMMDD.txt.


Best Practices

  • Match your theme and container.
  • Leave defaults empty unless customization is needed.
  • Test in development first.
  • Document any custom templates or themes.
  • Use environment-specific appsettings (e.g. appsettings.Development.json).

Summary

The Installation configuration in appsettings.json lets you fully automate your Oqtane setup.

  • SiteTemplate: defines structure
  • DefaultTheme: defines appearance
  • DefaultContainer: defines module layout

Empty values use defaults, and you can override them for automation, branding, or custom scenarios.

Running Docker on a Windows Surface ARM64 Using WSL2

Running Docker on a Windows Surface ARM64 Using WSL2

My Docker Adventure in Athens

Hello fellow tech enthusiasts!

I’m currently in Athens, Greece, enjoying a lovely Easter Sunday, when I decided to tackle a little tech project – getting Docker running on my Microsoft Surface with an ARM64 CPU. If you’ve ever tried to do this, you might know it’s not as straightforward as it sounds!

After some research, I discovered something important: there’s a difference between Docker Enterprise and Docker Community Edition (CE). While the enterprise version doesn’t support ARM64 yet, Docker CE does have versions for both ARM64 and x64 architectures. Perfect!

The WSL2 Solution

I initially tried to install Docker directly on Windows, but quickly ran into roadblocks. That’s when I decided to try the Windows Subsystem for Linux (WSL2) route instead. Spoiler alert: it worked like a charm!

While you won’t get the nice Docker Desktop UI that Windows users might be accustomed to, the command line interface through WSL2 works perfectly fine. After all, Docker was born on Linux, so running it in a Linux environment makes sense!

Step-by-Step Guide to Installing Docker CE on WSL2

Here’s how I got Docker CE up and running on my Surface using WSL2:

Step 1: Update Your Packages

First, make sure your WSL2 system is up to date:

sudo apt update && sudo apt upgrade -y

Step 2: Install Required Packages

Install the necessary packages to use HTTPS repositories:

sudo apt install -y apt-transport-https ca-certificates curl software-properties-common gnupg lsb-release

Step 3: Add Docker’s Official GPG Key

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Step 4: Set Up the Stable Docker Repository

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Step 5: Update APT with the New Repository

sudo apt update

Step 6: Install Docker CE

sudo apt install -y docker-ce docker-ce-cli containerd.io

Step 7: Start the Docker Service

sudo service docker start

Step 8: Add Your User to the Docker Group

This allows you to run Docker without sudo:

sudo usermod -aG docker $USER

Step 9: Apply the Group Changes

Either log out and back in, or run:

newgrp docker

Step 10: Verify Your Installation

docker --version
docker run hello-world

Pro Tip!

If you want Docker to start automatically when you launch WSL2, add the service start command to your .bashrc or .zshrc file:

echo "sudo service docker start" >> ~/.bashrc

Final Thoughts

What started as a potentially frustrating experience turned into a surprisingly smooth process. WSL2 continues to impress me with how well it bridges the Windows and Linux worlds. If you have a Surface or any other ARM64-based Windows device and need to run Docker, I highly recommend the WSL2 approach.

Have you tried running Docker on an ARM device? What was your experience like? Let me know in the comments below!

Happy containerizing! 🐳

Understanding AppDomains in .NET Framework and .NET 5 to 8

Understanding AppDomains in .NET Framework and .NET 5 to 8

Understanding AppDomains in .NET Framework and .NET 5 to 8

AppDomains, or Application Domains, have been a fundamental part of isolation and security in the .NET Framework, allowing multiple applications to run under a single process without affecting each other. However, the introduction of .NET Core and its evolution through .NET 5 to 8 has brought significant changes to how isolation and application boundaries are handled. This article will explore the concept of AppDomains in the .NET Framework, their transition and replacement in .NET 5 to 8, and provide code examples to illustrate these differences.

AppDomains in .NET Framework

In the .NET Framework, AppDomains served as an isolation boundary for applications, providing a secure and stable environment for code execution. They enabled developers to load and unload assemblies without affecting the entire application, facilitating application updates, and minimizing downtime.

Creating an AppDomain

using System;

namespace NetFrameworkAppDomains
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a new application domain
            AppDomain newDomain = AppDomain.CreateDomain("NewAppDomain");

            // Load an assembly into the application domain
            newDomain.ExecuteAssembly("MyAssembly.exe");

            // Unload the application domain
            AppDomain.Unload(newDomain);
        }
    }
}

AppDomains in .NET 5 to 8

With the shift to .NET Core and its successors, the concept of AppDomains was deprecated, reflecting the platform’s move towards cross-platform compatibility and microservices architecture. Instead of AppDomains, .NET 5 to 8 emphasizes on assembly loading contexts for isolation and the use of containers (like Docker) for application separation.

AssemblyLoadContext in .NET 5 to 8

using System;
using System.Reflection;
using System.Runtime.Loader;

namespace NetCoreAssemblyLoading
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a new AssemblyLoadContext
            var loadContext = new AssemblyLoadContext("MyLoadContext", true);

            // Load an assembly into the context
            Assembly assembly = loadContext.LoadFromAssemblyPath("MyAssembly.dll");

            // Execute a method from the assembly (example method)
            MethodInfo methodInfo = assembly.GetType("MyNamespace.MyClass").GetMethod("MyMethod");
            methodInfo.Invoke(null, null);

            // Unload the AssemblyLoadContext
            loadContext.Unload();
        }
    }
}

Differences and Considerations

  • Isolation Level: AppDomains provided process-level isolation without needing multiple processes. In contrast, AssemblyLoadContext provides a lighter-weight mechanism for loading assemblies but doesn’t offer the same isolation level. For higher isolation, .NET 5 to 8 applications are encouraged to use containers or separate processes.
  • Compatibility: AppDomains are specific to the .NET Framework and are not supported in .NET Core and its successors. Applications migrating to .NET 5 to 8 need to adapt their architecture to use AssemblyLoadContext or explore alternative isolation mechanisms like containers.
  • Performance: The move away from AppDomains to more granular assembly loading and containers reflects a shift towards microservices and cloud-native applications, where performance, scalability, and cross-platform compatibility are prioritized.

Conclusion

While the transition from AppDomains to AssemblyLoadContext and container-based isolation marks a significant shift in application architecture, it aligns with the modern development practices and requirements of .NET applications. Understanding these differences is crucial for developers migrating from the .NET Framework to .NET 5 to