Chris Straw
SHARE:

My Notes – Standup .Net API with Angular on Ubuntu

This is my notes on how I setup a .net core web api with an Angular frontend on a Ubuntu Linux Server

*****************************************************************

Prerequisites
Get the updated list of packages from the Internet

sudo apt update

Install nano editor

sudo apt install nano

*****************************************************************

Install SFTP (aka SSH) (if not installed)

https://linuxconfig.org/how-to-setup-sftp-server-on-ubuntu-20-04-focal-fossa-linux

sudo apt install ssh

Edit the Config

sudo nano /etc/ssh/sshd_config

Paste this at the bottom of the config file (using VIM)

Match group sftp
ChrootDirectory /home
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp

Restart the ssh service

sudo systemctl restart ssh

Create SFTP user account (optional)
You can use your regular account to SFTP instead of creating an account

Add a new group called sftp

sudo addgroup sftp

Add a new user call sftpuser

sudo useradd -m sftpuser -g sftp

Create a Password for the new user

sudo passwd sftpuser

Grant permissions to the users home directory

sudo chmod 700 /home/sftpuser/

*****************************************************************

Install nginx

sudo apt install nginx

*****************************************************************

Install dotnet

https://tecadmin.net/how-to-install-net-core-on-ubuntu-20-04/

Step 1 – Enable Microsoft PPA (Do this in your home directory)

wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb 
sudo dpkg -i packages-microsoft-prod.deb 

Step 2 – Install Dotnet Core Runtime

sudo apt update 
sudo apt install apt-transport-https 

Change to match the version of .net you want to install

sudo apt install dotnet-sdk-6.0

Step 3 – Test

dotnet --list-runtimes

*****************************************************************
Configure app with nginx

Step 1 – SFTP

Set Permission (if need)

sudo chmod 777 /var/www
mkdir /var/www/appname
mkdir /var/www/appname/frontend
mkdir /var/www/appname/api

Open FileZilla SFTP to the server and transfer the files to the directories under /var/www/appname

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Step 2 – Configure nginx

This default config
file location: /etc/nginx/sites-available

NOTE: I like editing these files locally and then SFTP to my home directory and copying the file to the nginx directory

sudo cp default /etc/nginx/sites-available/default

Check Config Syntax

 sudo nginx -t

Gracefully stop and restart the service after updating the config

sudo nginx -s reload

My Example of the nginx config. I have the .Net API listing on port 8500.
I originally had several issues with Angular and the browser cache. These cache settings seem to work the best

server {
  listen 80 default_server;
  listen [::]:80 default_server;
  root /var/www/appname/frontend;
  server_name appname.domain.com www.appname.domain.com;

  client_max_body_size 30M;

  # X-Frame-Options is to prevent from clickJacking attack
  #add_header X-Frame-Options SAMEORIGIN;

  # disable content-type sniffing on some browsers.
  #add_header X-Content-Type-Options nosniff;

  # This header enables the Cross-site scripting (XSS) filter
  #add_header X-XSS-Protection "1; mode=block";

  #add_header Referrer-Policy "no-referrer-when-downgrade";
  
  index index.html;

  server_name _;

  gzip on;
  gzip_http_version 1.1;
  gzip_disable "MSIE [1-6]\.";
  gzip_min_length 256;
  gzip_vary on;
  gzip_proxied expired no-cache no-store private auth;
  gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
  gzip_comp_level 9;

  if ($http_user_agent ~* "MSIE ([5-8]{1,}\.\d{0,}\w?\d?);") {
      return 480;
  }
  
  location / {
    try_files $uri $uri/ /index.html =404;
    # add_header Cache-Control 'max-age=3600'; # one day
    # add_header Cache-Control 'no-store';
    # add_header Cache-Control 'no-cache';
    expires -1;
    add_header Cache-Control "no-store, no-cache, must-revalidate";
  }

  location /api {
      root /var/www/appname/api;
      proxy_pass http://localhost:8500;
      proxy_http_version 1.1;
      proxy_set_header   Upgrade $http_upgrade;
      proxy_set_header   Connection keep-alive;
      proxy_set_header   Host $host;
      proxy_cache_bypass $http_upgrade;
      proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header   X-Forwarded-Proto $scheme;
  }

  location /hubs {
      proxy_pass http://localhost:8500;
      proxy_http_version 1.1;
      proxy_set_header   Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_set_header   Host $host;
      proxy_cache_bypass $http_upgrade;
  }

}

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Set the Environment Variables

sudo nano /etc/environment
ASPNETCORE_ENVIRONMENT="Test"
DOTNET_ENVIRONMENT="Test"

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Step 4 – Test api

cd /var/www/appname/api
dotnet MyApp.WebApi.dll

pull up API URL (assuming SSL disabled and running from root)
http://{domainhere}/api/general/ping?api-version=1.0

Now pull up the Angular app
http://{domainhere}

Step 4 – Create a Service
1) Create a file named kestrel-appname.service locally and copy the text below and save
2) SFTP to your home directory

The Service Definition

[Unit]
Description=AppName.NET Web API App

[Service]
WorkingDirectory=/var/www/appname/api
ExecStart=/usr/bin/dotnet /var/www/appname/api/MyApp.WebApi.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-appname
User=www-data
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target

Copy file

sudo cp kestrel-appname.service /etc/systemd/system/kestrel-appname.service

Enable Service

sudo systemctl enable kestrel-appname.service
sudo systemctl start kestrel-appname.service
sudo systemctl status kestrel-appname.service

To see the logs

sudo journalctl -u kestrel-appname.service --since "2021-08-08"