Deploy a Dotnet Web API on Ubuntu with Nginx Reserve Proxy
2022-04-09
0. Goal
Today I’d like to deploy a dotnet web api server on a Linux remote machine and access the api endpoint from my browser using the server’s public ip address.
- Web API (.net core 6.0)
- Remote Ubuntu server
- Enter public ip address in browser to access api endpoints
Reference
Host ASP.NET Core on Linux with Nginx - don’t blindly follow it, check this tutorial.
Resources
1. Local Setup
a. Create a dotnet web api app
b. Run it on local debug mode
c. Stop the app
d. Publish the app
dotnet publish -r linux-x64 --self-contained false -o published
or use UI to publish, the only thing to note is don’t use “single file mode”, we need to have a dll for this tutorial to work.
e. Run app from the published folder
f. Check the api again
- 5000 is for http
- 5001 is for https
2. Ubuntu Env Setup - General
a. Create a Ubuntu Server on Cloud
Ubuntu version: 20.04 LTS
b. Connect with the VM
3. Ubuntu Setup - Dotnet WebApi
a. Install dotnet sdk and runtime
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
rm packages-microsoft-prod.deb
sudo apt update
sudo apt install -y apt-transport-https
sudo apt-get install -y dotnet-sdk-6.0
sudo apt install -y aspnetcore-runtime-6.0
sudo apt install -y dotnet-runtime-6.0
sudo apt update
sudo apt upgrade
Verify the installation
dotnet
b. Install Nginx Web Server
sudo apt-get install nginx
sudo systemctl status nginx
Optional: Check Firewall Rules
How to Check Firewall Status in Ubuntu Firewall (configserverfirewall.com)
sudo ufw status
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
Create folder to hold the files
sudo unlink /etc/nginx/sites-enabled/default
cd /var/www
sudo mkdir dotnetwebapi
cd dotnetwebapi
sudo chmod 777 dotnetwebapi # this is bad, I'm only using it to write file with FileZilla, you can use git or other methods to transfer the files
c. Transfer Files - FileZilla (cross platform)
Connect with the server, drag and drop files into the folder we just created.
d. Run dotnet app from ubuntu server
cd /var/www/dotnetwebapi
dotnet dotnetwebapi.dll
e. Try to access the api from curl
We’ll use http in the config files (in later section)
# the http ones should work
curl -v http://localhost:5000/weatherforecast
curl -v http://127.0.0.1:5000/weatherforecast
# the https one are unlikely to work but it's fine
curl -v https://localhost:5001/weatherforecast
curl -v https://127.0.0.1:5001/weatherforecast
4. Configure Reverse Proxy
a. Install package - HttpOverrides
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
var app = builder.Build();
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
app.MapControllers();
app.Run();
b. Repulish and copy to the ubuntu server
c. Update /etc/nginx/sites-available/default
file
sudo nano /etc/nginx/sites-available/default
File content
server {
listen 80;
root /var/www/dotnetwebapi; # make sure to match this with your folder name
location / {
proxy_pass http://127.0.0.1:5000;
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;
}
}
Enable the site
ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/
Reload & Restart (Reload is sufficient)
sudo nginx -t # check syntax
sudo nginx -s reload # reload
sudo systemctl restart nginx # restart
Test with ip address
curl -v http://ipaddress/weatherforecast
5. Troubleshooting
If the local address in the server is working but the ip address one is not working, check your network status and make sure nginx is listening on the right port
sudo apt install net-tools
sudo netstat -pantu
6. Run API server with pm2
a. Install npm and pm2
sudo api install npm
sudo npm install -g pm2
b. run dotnet app with pm2
cd /var/www/dotnetwebapi
pm2 start "dotnet dotnetwebapi.dll" --name dotnetwebapi
c. use curl
to double check if the app is still running
curl http://localhost:5000/weatherforecast
d. pm2 useful commands
pm2 start "<command>" --name <name>
pm2 stop <name>
pm2 list
pm2 logs <name>
pm2 info <name>
pm2 monit <name>
7. Summary
- Create a dotnet webapi app
- Create a Ubuntu server
- Install nginx web server
- Copy the published files into the Ubuntu server
- Configure the site config (you can use the default one or a different one)
- Reload nginx and verify
- Use
pm2
to run the api server in background
Bonus - What is reverse proxy?
Nginx and other web servers allow us to host multiple apps on the same machine and each of them can be mapped to a different server name, e.g., api.lunawen.com, project.lunawen.com.
We use Nginx config files to do the mapping.
Bonus - Why not HTTPs?
Since you are likely to have a domain name instead of the ip address for your application, usually the CDN (e.g., cloudflare) will already have https enabled, so you don’t have to use https in your nginx config.