AdminUI has recently been made available as a universal project, meaning we now support a Linux installation scenario rather than recommending Docker as a multiplatform approach. This article will go through the steps needed to get AdminUI up and running on Linux.
Using Docker to run AdminUI gave many advantages, but also came with significant disadvantages:
Pros:
- Quick install for demo purposes
- Docker has a big community with many large corporations like Microsoft involved
- Acted as an example of how to set up AdminUI with a reverse proxy
Cons:
- Required domain knowledge of Docker
- Company infrastructure might not use micro-service architecture
- Docker is still a relatively recent technology
- Existing IdentityServer customers are unlikely to have a current Docker configuration and may require a large amount of developer effort to reconfigure to test AdminUI
This article is aimed at those who:
- Have no Docker experience but have Linux experience
- Have their IdentityServer or want their IdentityServer installed in a non-docker scenario
- Have limited time and need a solution up and running quickly
Note: if you have an existing IdentityServer or ASP.NET Identity solution you will need to follow this article to get up and running with our database schema and be able to run our migrations in the setting up API
In the case of ASP.NET Identity users who already have a working database and have .NET Core 3.1 installed you can skip to the setup of IdentityServer in this tutorial.
This tutorial will be ran using Ubuntu. However, as the files we are using are a framework-dependent cross-platform binary you can use any Linux distribution that the .NET Core runtime supports.
Permissions
Before getting started with this article please make sure the user you're running under has either root permissions or If you are not running under a root user then you need to be able to create, edit and access the following folders:
- .NET Core runtime folder
- This is typically the /usr/ and /share/ folder
- If you need to verify the install location to ensure access at runtime you can verify the folder location after installing the .NET Core runtimes (see below) by running the command
whereis dotnet
- Nginx folders
- Installed under the /etc/ folder
Nginx will also create a user called nginx
and do chmod
, chgroup
and chown
commands to allow it to run under that user.
.NET Core Setup
You’ll need a few things installed for AdminUI to run on Linux. The first task is to install NET Core 3.1 on our distribution.
Note: the below works on Debian based distributions. If you are not running a Debian based distribution, find instructions for your distribution.
In a terminal window run the following commands to add the Microsoft package signing key to your list of trusted keys and add the package repository:
wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
From there you can install the SDK with the following command:
sudo apt-get update; sudo apt-get install -y apt-transport-https && \ sudo apt-get update && \ sudo apt-get install -y aspnetcore-runtime-5.0
Note: aspnetcore-runtime-5.0
will install support for .NET 5.0 as well. If you would like to only include .NET 3.1 you can run replace aspnetcore-runtime-5.0
with aspnetcore-runtime-3.1
Verify that dotnet is installed with the following command:
dotnet --list-runtimes
You will see an output that looks like the following, depending on what version(s) you installed:
Database Setup
AdminUI supports the following database providers: SqlServer, Postgres and MySQL. You can use whatever database provider you like here but for the purposes of this tutorial we’ll use MySQL. If you choose another database provider, please be aware that the connection string and any SQL commands will be slightly different.
If you’ve skipped installing ASP.NET Core, then make sure you run apt-get update
to ensure you get the latest version of MySQL.
To install MySQL, use the following command:
apt-get install mysql-server
The steps you’re following in this tutorial are for demo purposes only. There are more steps you should take to secure your MySQL instance but I will skip them in this tutorial.
Once MySQL is installed, you will need to create a new user granted with the required privileges to allow you to apply the AdminUI Migrations and to execute any commands required to make AdminUI fully functional:
sudo mysql
CREATE USER 'sam'@'localhost' IDENTIFIED BY ‘Password123!';
GRANT CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, SELECT, REFERENCES, RELOAD, INDEX on *.* TO 'sam'@'localhost' WITH GRANT OPTION;
Explanation of .NET Core, Kestrel and Reverse-Proxying with NGINX
In order to run .NET Core applications on Linux a webserver is required. If you run the compiled binary for AdminUI from the command line, .NET will start a basic server on http://localhost:5000:
dotnet <your-dotnetcore-dll>.dll
The .dlls produced for AdminUI are NSC files. This means that the dlls aren’t packaged with the required runtime which is why you downloaded them earlier via the CLI. Because this is the case you may encounter errors when running the .dlls - to fix this please make sure the user running the commands had correct run and execture access to the runtimes folder.
Kestrel is .NET Core’s cross-platform web server and whilst it is useful for development it is not recommended for production due to its limited capabilities. It is therefore good practice to setup a more fully-fledged webserver in front of Kestrel to handle the heavy lifting of our requests such as HTTPS and Header Forwarding.
The following sections will outline the required configuration for NGINX to reverse proxy calls to this Kestrel server and terminate the HTTPS requests.
IdentityServer Setup (optional)
Note: ASP .NET Core HTTPS development certificates are not trusted automatically on Linux. For more information on trusting the certificates you can read this Microsoft article.
For the first part of this setup it is enough to run IdentityServer over HTTP. Later in the tutorial, you will learn how to use a reverse proxy to configure HTTPS.
If you have IdentityServer installed you can skip getting the repo, however, there are some modifications that will need to be made to your existing IdentityServer installation to get it up and running. You can find more information about configuring an existing IdentityServer solution for AdminUI in this article.
For a fresh install of IdentityServer you will need to install the .NET Core SDK:
sudo apt install -y aspnetcore-sdk-5.0
Once the SDK is installed, you can build the AdminUI IdentityServer quick start project found on the Rock Solid Knowledge GitHub. You can download the zip directly from GitHub, or if you have Git installed locally you can run the following command to the directory of your choice:
git clone https://github.com/RockSolidKnowledge/Samples.IdentityServer4.AdminUiIntegration.git
Once done, you can navigate into the dir/Samples.IdentityServer4.AdminUIIntegration
directory and run the following commands to restore the required NuGet packages build and publish the output:
dotnet restore
dotnet publish -c Release -o out
The next step is to make some minor configuration changes to appsettings.json
to make sure the site is running on the correct URL, and connected to our configured MySQL database
{"Urls":"http://localhost:5003","DbProvider":"MySql","IdentityConnectionString":"Server=127.0.0.1;Port=3306;Database=IdentityExpressDb;Uid=sam;Pwd= Password123!;","IdentityServerConnectionString":"Server=127.0.0.1;Port=3306;Database=IdentityExpressDb;Uid=sam;Pwd= Password123!;"}
To check the configuration is correct run the following:
dotnet Samples.IdentityServer4.AdminUIIntegration.dll
And navigate to http://localhost:5003 (note: if you want to edit the url the site runs on, edit the ‘urls’ property in the json above):
Signing up for the demo
Now you need an instance of AdminUI running locally. If you do not have the product already downloaded alongside a license key then Rock Solid Knowledge offer an easy way to get both. Following the link and registering will give you a demo license key valid for one month and access to the .zips for the AdminUI UI and API.
After registering you will receive an email with a license key.The email will also contain a link to https://www.identityserver.com/downloads/adminui
On that page, click the .zip button for the latest 4.X.X version:
The zip structure will look something like:
- NSCUI
- API
- Create a root folder for AdminUI place the UI and API folder under it.
Now that you have AdminUI and IdentityServer downloaded and our database setup then all that’sneeded is to tie them together.
Note: if you want the API and UI to run on different URLs you can edit the URL in the “Kestrel” section of the config. If you do this please be aware that you must change these URLs in all config files include the nginx.conf
. You can find more information in our documentation.
Our first step will be modifying our configuration file in the AdminUI API directory. Modify the appsettings.json
to point to the MySql database, IdentityServer and the AdminUI UI. You will also need to include the license key we spoke about earlier. If you do not have an appsettings.json
file included in your .zip, create one now. Once created you can copy the config from below or modify your appsettings.json
to look like the following
{"Kestrel":{"Endpoints":{"Http":{"Url":"http://localhost:5001"}}},"DbProvider":"MySql","IdentityConnectionString":"Server=127.0.0.1;Port=3306;Database=IdentityExpressDb;Uid=sam;Pwd=Password123!;","IdentityServerConnectionString":"Server=127.0.0.1;Port=3306;Database=IdentityExpressDb;Uid=sam;Pwd=Password123!;","AuditRecordsConnectionString":"Server=127.0.0.1;Port=3306;Database=IdentityExpressDb;Uid=sam;Pwd=Password123!;","AuthorityUrl":"https://localhost:5003","UiUrl":"http://localhost:5000","RequireHttpsMetadata":false,"LicenseKey":"<Your license key here>","CER_FULL_PATH":"./Data/gateway.cer","PasswordPolicy":{"RequireDigit":true,"RequireLowercase":true,"RequireNonAlphanumeric":true,"RequireUppercase":true,"RequiredLength":6,"RequiredUniqueChars":1},"UsernamePolicy":{"UseReferenceTokens":false,"Secret":"password"},"AdminUIClientSecret":"Demo"}
After you’ve added these URLs, you will need to run the following command in the same directory as the API to apply the necessary migrations and confirm that the database has been configured correctly:
Note: if you have an existing IdentityServer or ASP.NET Identity solution you will need to follow this article to get up and running with our database schema and be able to run our migrations in the setting up API
dotnet IdentityExpress.Manager.Api.dll -migrate all
Once the migrations have successfully completed you will need to do similar config changes for the AdminUI UI. In the AdminUI UI directory modify the appsettings.json
file to look like the following:
{"Kestrel":{"Endpoints":{"Http":{"Url":"http://localhost:5000"}},"AllowedHosts":"*","AuthorityUrl":"http://localhost:5003","UiUrl":"http://localhost:5000","ApiUrl":"http://localhost:5001","AdminUIClientSecret":"Demo"}}
Note: because AdminUI uses a backend for frontend (BFF) service to handle token exchange we now require a secret to encrypt the cookie. In a production scenario we would ask that you generate this secret and add it to your Continuous Integration (CI) pipeline or deployment option. In our case, we are just using the key “AdminUIClientSecret” with “Demo” as the value, but this MUST be secure in production.
Proving AdminUI is running and can communicate with IdentityServer
Now you can run the AdminUI websites you have setup above by going into the UI, API and IdentityServer installation folders and running these commands respectively:
dotnet IdentityExpress.Manager.UI.dll
dotnet IdentityExpress.Manager.Api.dll
dotnet Rsk.Samples.IdentityServer4.AdminUiIntegration.dll
This will run the three sites over HTTP.
When you navigate to http://localhost:5000 you will see the AdminUI homepage. Upon clicking login and entering the default login details ([email protected] – Password123!), you will see the AdminUI homepage:
Configuring NGINX as a reverse proxy
If you have skipped any of the previous steps, ensure you run apt update
before running the following command:
sudo apt install nginx
For this demo you're going to use the NGINX full configuration; however, this is not recommended for production:
By default, ufw blocks most traffic and so you may need to modify your firewall to allow http and https traffic for nginx. If you need to do so you can run the following commands:
sudo ufw app list
sudo ufw allow 'Nginx Full’
sudo ufw status
To prove that our nginx server is working we can run the command systemctl status nginx
which will display a similar output at the command prompt:
If you navigate to http://localhost:80 you’ll see the nginx server up and running:
Running the Kestrel websites over HTTPS
Running over HTTP is not a recommended scenario for our customers so we’ll go through how to setup NGINX to communicate with our new Kestrel websites via reverse proxying so we can run them on HTTPS.
To start we’ll generate a local self-signed certificate for our test environment. Please note that a self-signed certificate isn’t recommended for production purposes.
To generate the cert, verify that OpenSSL is installed and run the following command to create a localhost.crt
and a localhost.key
file:
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout . /localhost.key -out . /localhost.crt -passin pass:Password123! -subj '/CN=localhost' -addext "subjectAltName=DNS:localhost,DNS:ids"
To trust the certificate, copy it your local store:
cp ./localhost.crt /usr/local/share/ca-certificates/localhost.crt
cp ./localhost.crt /etc/ssl/certs/localhost.crt
cp ./localhost.key /etc/ssl/private/localhost.key
Run the following command to update the certificates now that the self-signed certificate has been copied to the correct location:
sudo update-ca-certificates
NGINX Configuration
You will now need to update your nginx configuration to allow HTTPS connections and to forward them to the correct port, I have explained some of this config below and if you want to know more about nginx configuration you can do so you can find the nginx docs here. The location of this configuration file can be found in one of 3 places: /usr/local/nginx/conf
, /etc/nginx
, or /usr/local/etc/nginx
.
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
#The upstream keyword here gives us a convenient way to name our services for later reference
upstream web-ui {
server localhost:5000;
}
upstream web-api {
server localhost:5001;
}
upstream web-ids {
server localhost:5003;
}
#A server block is a subset of Nginx’s configuration that defines a virtual server used to handle
#requests of a defined type, it defines how nginx should handle requests to our servers
#listen along side the use of the ssl keyword lets nginx know what ssl port we want to use
#ssl_certificate will point to the location of our generated certificates from earlier
#The important part of the location section is the set_header sections
#The notable sections are X-Forwarded-For, X-Forwarded-Proto and X-Forwarded-Host
#These are all required for Kestral to be able to accept our forward proxying from nginx.
#We also increase the buffer size and AdminUI uses larger than standard cookie size
server {
listen 5010 ssl;
server_name $hostname;
ssl_certificate /etc/ssl/certs/localhost.crt;
ssl_certificate_key /etc/ssl/private/localhost.key;
location / {
proxy_pass http://web-ui;
proxy_redirect off;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for:$server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
}
server {
listen 5011 ssl;
server_name $hostname;
ssl_certificate /etc/ssl/certs/localhost.crt;
ssl_certificate_key /etc/ssl/private/localhost.key;
location / {
proxy_pass http://web-api;
proxy_redirect off;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for:$server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host:$server_port;
}
}
server {
listen 5013 ssl;
server_name $hostname;
ssl_certificate /etc/ssl/certs/localhost.crt;
ssl_certificate_key /etc/ssl/private/localhost.key;
location / {
proxy_pass http://web-ids;
proxy_redirect off;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for:$server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host:$server_port;
}
}
}
You can verify the config changes with the command nginx -c [conf-file-name] -t
The final step is to change your settings to match the new SSL settings.
In the appsettings.json
in your UI and API project change the appropriate URLs to the following:
AuthorityUrl: https://localhost:5013
UiUrl: https://localhost:5010
ApiURL: https://localhost:5011
From here, restart NGINX with systemctl reload nginx
and access the URL https://localhost:5010. Login with the default credentials as used in the previous step and voila. We now have AdminUI up and running over HTTPS in Linux.
Summary
In summary, we have achieved the following:
- Setup a MySQL database
- Setup an IdentityServer website
- Downloaded and setup our two AdminUI websites, one for the UI and one for the API
- Ran the AdminUI migrations against our MySQL database
- Setup NGINX to reverse proxy HTTPS requests the IdentityServer and AdminUI Kestrel websites
All in all, I hope this article got you setup and running with AdminUI and let you see where it can fit into an existing or new Identity/IdentityServer solution.
If you have any questions or need any support with AdminUI or an existing IdentityServer solution, please don’t hesitate to contact us at [email protected].