Introduction
Background and Advantages
<span>ASP.NET Core</span> has supported cross-platform deployment since <span>.NET Core 1.0</span> (2016), and deploying on <span>Linux</span> offers the following advantages:
- • High Performance:
<span>Linux</span>servers (such as<span>Ubuntu</span>) have low resource consumption, suitable for high concurrency. - • Cost-Effective: Open-source operating system reduces server costs.
- • Ecosystem Support: Supports
<span>MySQL, Docker, Nginx</span>, compatible with microservices and cloud-native. - • Active Community:
<span>Linux</span>is the preferred choice for cloud deployments (such as<span>AWS, Azure</span>).
Deployment Methods
<span>ASP.NET Core Web</span> projects have the following main deployment methods on <span>Linux</span>:
- • Self-contained Deployment:
- • Package the application and
<span>.NET</span>runtime to run independently. - • Suitable for
<span>Linux</span>servers without the<span>.NET</span>runtime. - • Framework-dependent Deployment:
- • Only package the application, relying on the server-installed
<span>.NET SDK</span>/runtime. - • Suitable for servers with a configured
<span>.NET</span>environment. - • Docker Container Deployment:
- • Use
<span>Docker</span>containers to encapsulate the application and dependencies. - • Suitable for microservices, cloud-native, and
<span>CI/CD</span>. - • Cloud Platform Deployment:
- • Use cloud services (such as
<span>Azure App Service, AWS Elastic Beanstalk</span>). - • Suitable for rapid deployment and scaling.
Prerequisites
Target Machine
- • Distribution (
<span>Ubuntu, CentOS, Debian, Alpine</span>, etc.) - • Installed
<span>.NET</span>runtime or<span>SDK</span>(recommended at least<span>.NET 6 LTS</span>or higher)
<span>.NET</span> Installation
# Install .NET 6 runtime on Ubuntu as an example
wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt update
sudo apt install -y aspnetcore-runtime-6.0
Firewall and Ports
Ensure that the ports used by the hosted application (such as <span>5000</span> or <span>80/443</span>) are open in the firewall/security group.
Publishing and Running (Self-Contained vs Framework-Dependent)
<span>Framework-Dependent</span> Deployment
Depends on the target host having the <span>.NET</span> runtime installed, resulting in a smaller publish package.
dotnet publish -c Release -o ./publish
<span>Self-Contained</span> Deployment
Includes the runtime, no need for pre-installed <span>.NET</span>, but larger in size.
dotnet publish -c Release -r linux-x64 --self-contained true -o ./publish
- •
<span>-c Release</span>: Publish optimized version. - •
<span>-o ./publish</span>: Output to<span>publish</span>directory. - •
<span>--self-contained true</span>: Include<span>.NET</span>runtime. - •
<span>-r linux-x64</span>: Target runtime (<span>Linux 64</span>bit).
Run: <span>./publish/YourApp</span>
Deploy Application
Transfer Files
- • Use
<span>scp</span>or<span>rsync</span>to upload the<span>publish</span>directory to the<span>Linux</span>server:
scp -r ./publish user@server:/var/www/yourapp
Set Permissions
sudo chown -R www-data:www-data /var/www/yourapp
sudo chmod -R 755 /var/www/yourapp
Run Directly (Kestrel Self-Hosted)
Start Application
cd yourapp
dotnet YourApp.dll # Framework-Dependent
# or ./YourApp # Self-Contained
Listen on All Interfaces
Configure in <span>appsettings.json</span> or environment variables:
"Kestrel": {
"Endpoints": {
"Http": { "Url": "http://0.0.0.0:5000" }
}
}
Or:
export ASPNETCORE_URLS="http://0.0.0.0:5000"
dotnet YourApp.dll
- • Advantages: Simple deployment;
- • Disadvantages: Lacks load balancing,
<span>TLS</span>termination, logging management, and other enterprise features.
Using systemd Daemon
Run the application as a service in the background and start it with the system.
Create <span>systemd Unit</span> file <span>/etc/systemd/system/kestrel-yourapp.service</span>:
[Unit]
Description=YourApp ASP.NET Core Service
After=network.target
[Service]
WorkingDirectory=/var/www/yourapp
ExecStart=/usr/bin/dotnet /var/www/yourapp/YourApp.dll
Restart=always
RestartSec=10
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=ASPNETCORE_URLS=http://0.0.0.0:5000
[Install]
WantedBy=multi-user.target
Start and Enable
sudo systemctl daemon-reload
sudo systemctl start kestrel-yourapp
sudo systemctl enable kestrel-yourapp
sudo journalctl -fu kestrel-yourapp
Reverse Proxy (Nginx/Apache) + Kestrel
It is recommended to use a reverse proxy in production environments to achieve static file caching, <span>TLS</span> termination, path rewriting, etc.
Install Nginx
sudo apt install -y nginx
Configure Nginx
In <span>/etc/nginx/sites-available/yourapp</span>:
server {
listen 80;
server_name your.domain.com;
# Redirect HTTP to HTTPS (optional)
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name your.domain.com;
ssl_certificate /etc/ssl/certs/your.crt;
ssl_certificate_key /etc/ssl/private/your.key;
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;
}
# Optional: Direct connection for static files
location /static/ {
root /var/www/yourapp/wwwroot;
expires 30d;
}
}
Enable the configuration and restart <span>Nginx</span>:
sudo ln -s /etc/nginx/sites-available/yourapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
Containerized Deployment (Docker)
Use <span>Docker</span> to achieve environment consistency and portability.
Dockerfile Example
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["YourApp.csproj", "./"]
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "YourApp.dll"]
Build and Run
docker build -t yourapp:1.0 .
docker run -d -p 80:80 --name yourapp -e ASPNETCORE_ENVIRONMENT=Production yourapp:1.0
Using Docker Compose
version: '3.8'
services:
web:
image: yourapp:latest
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:80"
environment:
- ASPNETCORE_ENVIRONMENT=Production
depends_on:
- mysql
networks:
- app-network
mysql:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=password
volumes:
- mysql-data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- app-network
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- web
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
mysql-data:
<span>Nginx</span> Configuration (<span>nginx.conf</span>):
events {}
http {
server {
listen 80;
location / {
proxy_pass http://web:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
PaaS Platform Deployment
If you do not want to manage the server yourself, you can choose cloud vendors’ <span>PaaS</span>:
- • Azure App Service for Linux
- • AWS Elastic Beanstalk (Docker/.NET Core platform)
- • Google Cloud Run (containerized)
- • Heroku (using Docker buildpacks)
These platforms typically only require pushing code or images, automatically completing building, running, load balancing, and <span>TLS</span>.
Operations and Monitoring
- • Centralized Logging
Use <span>Microsoft.Extensions.Logging</span> to output to files, <span>Syslog</span>, <span>ELK/EFK</span>, or <span>Prometheus</span>.
- • Health Checks
Configure health check endpoints in <span>Startup</span> with <span>app.MapHealthChecks("/health")</span>, and let the load balancer probe the health.
- • Automatic Restart
<span>systemd</span> with <span>Restart=always</span> or <span>Kubernetes</span> with <span>livenessProbe</span>.
- • Performance Analysis
Utilize <span>dotnet-counters, dotnet-trace, Application Insights, Prometheus + Grafana</span>, etc.
# Install dotnet-counters
dotnet tool install -g dotnet-counters
# Monitor application performance
dotnet-counters monitor -n your-app --counters System.Runtime,Microsoft.AspNetCore.Http
# Install dotnet-trace
dotnet tool install -g dotnet-trace
# Collect performance traces
dotnet-trace collect -n your-app --format Speedscope
Key Diagnostic Commands
# Check port listening
sudo ss -tulpn | grep ':5000\|:5001'
# View application logs
journalctl -u your-app --since "10 minutes ago" -f
# Test database connection
psql -h localhost -U your_app_user -d your_app_db -c "SELECT 1"
# Network connectivity test
curl -v http://localhost:5000/health
# Analyze memory usage
top -p $(pgrep -f YourApp)
Best Practices Checklist
Environment Standardization:
- • Use the same version of
<span>OS</span>and<span>.NET</span>runtime - • Configure unified environment variable management
Security First:
- • Principle of least privilege (run as non-
<span>root</span>user) - • Regularly update security patches
- • Enforce
<span>HTTPS</span>connections
Reliable Deployment:
- • Use
<span>CI/CD</span>pipelines for automated deployment - • Implement blue-green deployment or canary releases
- • Retain rollback capability for the previous version
Performance Optimization:
- • Enable
<span>ReadyToRun</span>compilation - • Configure response compression
- • Use load balancing and horizontal scaling
Monitoring and Alerts:
- • Implement comprehensive health checks
- • Integrate
<span>APM</span>tools (such as<span>Application Insights</span>) - • Set alerts for key metrics (CPU, memory, error rate)
Disaster Recovery:
- • Regularly back up databases and application configurations
- • Develop and test recovery plans
- • Deploy critical applications across multiple regions
Conclusion
| Method | Advantages | Disadvantages |
|---|---|---|
| Direct Run (Kestrel) | Most straightforward, zero dependencies | Lacks TLS, load balancing |
| systemd Management | Stable restart, auto-start on boot | No reverse proxy, certificate management requires additional effort |
| Nginx/Apache Reverse Proxy + systemd | TLS termination, path rewriting, static caching | Configuration is slightly complex |
| Docker Containerization | Environment isolation, portability, high consistency | Learning curve, image management |
| Cloud PaaS | Minimal operations, automatic scaling | Platform dependency, relatively high costs |
Resources and Documentation
Official Documentation:
- •
<span>ASP.NET Core on Linux</span>: https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx - •
<span>Docker with ASP.NET Core</span>: https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/docker