๐ท .NET Core Applications on AlmaLinux: Complete Deployment Guide
Welcome to the cross-platform revolution of .NET development! ๐ Today weโll master deploying .NET Core and ASP.NET Core applications on AlmaLinux, bringing the power of Microsoftโs framework to the stability of enterprise Linux. Think of this as breaking down barriers - your C# applications can now run everywhere! ๐
Gone are the days when .NET meant Windows-only. With .NET Core (now .NET 5/6/7/8), Microsoft has embraced open source and Linux, making it possible to run high-performance .NET applications on AlmaLinux servers. Letโs unlock this powerful combination! ๐ช
๐ค Why is .NET Core on Linux Important?
.NET Core on Linux is a game-changer for enterprise development! โก Hereโs why it matters:
- ๐ Blazing Performance - .NET Core is one of the fastest web frameworks available
- ๐ฐ Cost Savings - No Windows Server licenses required
- ๐ง Linux Benefits - Leverage Linuxโs stability, security, and tooling
- ๐ True Cross-Platform - Develop on Windows, Mac, or Linux, deploy anywhere
- ๐ฆ Container Ready - Perfect for Docker and Kubernetes deployments
- ๐ข Enterprise Support - Microsoft fully supports .NET on Linux
- โก Modern Framework - Built for cloud-native and microservices
- ๐ค Massive Ecosystem - Access to NuGet packages and .NET libraries
๐ฏ What You Need
Before deploying .NET applications on Linux, ensure you have:
โ
AlmaLinux system (physical or virtual machine)
โ
Root or sudo access for installing .NET runtime
โ
At least 1GB RAM (2GB+ recommended for development)
โ
Basic C# knowledge (helpful but weโll guide you)
โ
Text editor like nano, vim, or VS Code
โ
Internet connection for downloading packages
โ
Basic command line skills (weโll explain everything!)
โ
10GB free disk space for SDK and applications
๐ Installing .NET on AlmaLinux
Letโs install the latest .NET SDK and runtime! ๐ ๏ธ
# Update your system first
sudo dnf update -y
# Ensures you have the latest packages
# Install Microsoft package repository
sudo rpm -Uvh https://packages.microsoft.com/config/rhel/8/packages-microsoft-prod.rpm
# Adds Microsoft's official .NET repository
# Install .NET SDK (includes runtime)
sudo dnf install -y dotnet-sdk-8.0
# Installs .NET 8 SDK (latest LTS version)
# Install ASP.NET Core runtime (if you only need runtime)
sudo dnf install -y aspnetcore-runtime-8.0
# For production servers that don't need SDK
# Verify installation
dotnet --version
# Should show: 8.0.x
dotnet --list-sdks
# Shows all installed SDK versions
dotnet --list-runtimes
# Shows all installed runtime versions
# Install useful development tools
sudo dnf install -y git wget curl
# Tools for development and deployment
Set up environment variables:
# Add .NET tools to PATH
echo 'export PATH=$PATH:$HOME/.dotnet/tools' >> ~/.bashrc
echo 'export DOTNET_CLI_TELEMETRY_OPTOUT=1' >> ~/.bashrc
source ~/.bashrc
# Configures .NET environment
# Install Entity Framework tools (for database work)
dotnet tool install --global dotnet-ef
# Installs EF Core command-line tools
# Install code formatting tool
dotnet tool install --global dotnet-format
# Helps maintain consistent code style
๐ง Creating Your First ASP.NET Core Application
Letโs build a web API to demonstrate deployment! ๐๏ธ
# Create a new ASP.NET Core Web API project
dotnet new webapi -n MyApi -o ~/MyApi
cd ~/MyApi
# Creates a new Web API project
# Create a simple controller
cat > Controllers/HelloController.cs << 'EOF'
using Microsoft.AspNetCore.Mvc;
namespace MyApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class HelloController : ControllerBase
{
private readonly ILogger<HelloController> _logger;
public HelloController(ILogger<HelloController> logger)
{
_logger = logger;
}
[HttpGet]
public IActionResult Get()
{
return Ok(new
{
Message = "Hello from .NET on AlmaLinux! ๐",
Timestamp = DateTime.UtcNow,
Platform = System.Runtime.InteropServices.RuntimeInformation.OSDescription,
DotNetVersion = Environment.Version.ToString()
});
}
[HttpGet("{name}")]
public IActionResult GetByName(string name)
{
_logger.LogInformation($"Greeting requested for {name}");
return Ok(new
{
Message = $"Hello {name}! Welcome to .NET on Linux! ๐",
ServerTime = DateTime.UtcNow
});
}
[HttpPost]
public IActionResult Post([FromBody] UserData data)
{
return Created("", new
{
Id = Guid.NewGuid(),
Name = data.Name,
Email = data.Email,
CreatedAt = DateTime.UtcNow
});
}
}
public class UserData
{
public string Name { get; set; } = "";
public string Email { get; set; } = "";
}
EOF
# Creates a sample API controller
# Test the application locally
dotnet run
# Starts the development server
# In another terminal, test the API
curl http://localhost:5000/api/hello
# Should return JSON response
# Build for production
dotnet publish -c Release -o ./publish
# Creates optimized production build
๐ Configuring Kestrel Web Server
Kestrel is .NETโs cross-platform web server! ๐
# Configure Kestrel settings
cat > appsettings.Production.json << 'EOF'
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://0.0.0.0:5000"
},
"Https": {
"Url": "https://0.0.0.0:5001",
"Certificate": {
"Path": "/etc/ssl/certs/mycert.pfx",
"Password": "CertPassword123!"
}
}
},
"Limits": {
"MaxConcurrentConnections": 100,
"MaxConcurrentUpgradedConnections": 100,
"MaxRequestBodySize": 52428800,
"RequestHeadersTimeout": "00:01:00"
}
},
"AllowedHosts": "*"
}
EOF
# Configures Kestrel for production
# Update Program.cs for production configuration
cat > Program.cs << 'EOF'
var builder = WebApplication.CreateBuilder(args);
// Add services
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Configure Kestrel
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.MaxConcurrentConnections = 100;
serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
serverOptions.Limits.MaxRequestBodySize = 52428800; // 50MB
serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
});
// Add CORS
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll",
policy => policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
});
var app = builder.Build();
// Configure pipeline
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseCors("AllowAll");
app.UseAuthorization();
app.MapControllers();
// Add health check endpoint
app.MapGet("/health", () => Results.Ok(new { Status = "Healthy", Time = DateTime.UtcNow }));
app.Run();
EOF
# Configures the application startup
โ Creating a Systemd Service
Letโs make our .NET app run as a service! ๐ฏ
# Create systemd service file
sudo cat > /etc/systemd/system/dotnet-myapi.service << 'EOF'
[Unit]
Description=.NET Core API on AlmaLinux
After=network.target
[Service]
Type=notify
User=dotnetuser
Group=dotnetuser
WorkingDirectory=/var/www/myapi
ExecStart=/usr/bin/dotnet /var/www/myapi/MyApi.dll
Restart=always
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-myapi
# Environment variables
Environment="ASPNETCORE_ENVIRONMENT=Production"
Environment="DOTNET_PRINT_TELEMETRY_MESSAGE=false"
Environment="ASPNETCORE_URLS=http://0.0.0.0:5000"
# Limits
LimitNOFILE=100000
LimitNPROC=4096
# Hardening
PrivateTmp=true
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
EOF
# Creates systemd service for automatic startup
# Create user for running the service
sudo useradd -r -s /bin/false dotnetuser
# Creates system user for security
# Deploy application files
sudo mkdir -p /var/www/myapi
sudo cp -r ~/MyApi/publish/* /var/www/myapi/
sudo chown -R dotnetuser:dotnetuser /var/www/myapi
# Copies application to production location
# Enable and start the service
sudo systemctl daemon-reload
sudo systemctl enable dotnet-myapi
sudo systemctl start dotnet-myapi
# Starts the .NET application
# Check service status
sudo systemctl status dotnet-myapi
# Should show "active (running)"
# View logs
sudo journalctl -u dotnet-myapi -f
# Shows real-time application logs
๐ฎ Quick Examples
Letโs explore practical .NET deployment scenarios! ๐ฏ
Example 1: Nginx Reverse Proxy Configuration
# Install Nginx
sudo dnf install -y nginx
# Configure Nginx for .NET Core
sudo cat > /etc/nginx/conf.d/dotnet-app.conf << 'EOF'
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
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;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Buffering
proxy_buffering off;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
}
# WebSocket support for SignalR
location /hub {
proxy_pass http://localhost:5000;
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;
}
}
EOF
# Test and restart Nginx
sudo nginx -t
sudo systemctl restart nginx
# Applies reverse proxy configuration
Example 2: Docker Deployment
# Create Dockerfile for .NET application
cat > Dockerfile << 'EOF'
# Build stage
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /source
# Copy project file and restore dependencies
COPY *.csproj .
RUN dotnet restore
# Copy everything and build
COPY . .
RUN dotnet publish -c Release -o /app
# Runtime stage
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build /app .
# Create non-root user
RUN useradd -m -s /bin/false dotnetuser && chown -R dotnetuser:dotnetuser /app
USER dotnetuser
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:5000/health || exit 1
EXPOSE 5000
ENTRYPOINT ["dotnet", "MyApi.dll"]
EOF
# Build Docker image
docker build -t myapi:latest .
# Run Docker container
docker run -d -p 5000:5000 --name myapi \
-e ASPNETCORE_ENVIRONMENT=Production \
myapi:latest
# Check container logs
docker logs myapi
Example 3: Database Integration with Entity Framework
# Install PostgreSQL provider
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
# Create database context
cat > Data/AppDbContext.cs << 'EOF'
using Microsoft.EntityFrameworkCore;
namespace MyApi.Data;
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options) { }
public DbSet<User> Users { get; set; }
public DbSet<Product> Products { get; set; }
}
public class User
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string Email { get; set; } = "";
public DateTime CreatedAt { get; set; }
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = "";
public decimal Price { get; set; }
public int Stock { get; set; }
}
EOF
# Configure database in Program.cs
cat >> Program.cs << 'EOF'
// Add database context
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
EOF
# Add connection string to appsettings
cat >> appsettings.json << 'EOF'
,
"ConnectionStrings": {
"DefaultConnection": "Host=localhost;Database=myapi;Username=apiuser;Password=ApiPass123!"
}
EOF
# Run migrations
dotnet ef migrations add InitialCreate
dotnet ef database update
# Creates database schema
๐จ Fix Common Problems
Encountering issues? Here are solutions:
Problem 1: Port Already in Use
# Check what's using port 5000
sudo netstat -tlnp | grep :5000
# Shows process using the port
# Kill the process if needed
sudo kill -9 <PID>
# Replace <PID> with process ID
# Or change the port in appsettings.json
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://0.0.0.0:5050"
}
}
}
Problem 2: SSL Certificate Issues
# Generate development certificate
dotnet dev-certs https --trust
# Creates and trusts development certificate
# For production, use Let's Encrypt
sudo dnf install -y certbot
sudo certbot certonly --standalone -d your-domain.com
# Convert to PFX for .NET
openssl pkcs12 -export -out certificate.pfx \
-inkey /etc/letsencrypt/live/your-domain.com/privkey.pem \
-in /etc/letsencrypt/live/your-domain.com/cert.pem \
-certfile /etc/letsencrypt/live/your-domain.com/chain.pem
Problem 3: Permission Denied Errors
# Fix directory permissions
sudo chown -R dotnetuser:dotnetuser /var/www/myapi
sudo chmod 755 /var/www/myapi
# Fix SELinux context (if enabled)
sudo setsebool -P httpd_can_network_connect 1
sudo chcon -R -t httpd_sys_content_t /var/www/myapi
# Check current permissions
ls -la /var/www/myapi/
Problem 4: Application Wonโt Start
# Check service logs
sudo journalctl -u dotnet-myapi -n 100
# Shows last 100 log entries
# Run application manually to see errors
cd /var/www/myapi
sudo -u dotnetuser dotnet MyApi.dll
# Shows startup errors directly
# Check for missing dependencies
ldd /usr/share/dotnet/shared/Microsoft.NETCore.App/8.0.0/*.so | grep "not found"
# Shows missing libraries
# Reinstall .NET runtime if needed
sudo dnf reinstall aspnetcore-runtime-8.0
Problem 5: High Memory Usage
# Configure garbage collection
export DOTNET_gcServer=false # Use workstation GC
export DOTNET_GCHeapCount=2 # Limit heap count
# Add to service file
Environment="DOTNET_gcServer=false"
Environment="DOTNET_GCHeapCount=2"
# Monitor memory usage
dotnet-counters monitor -p $(pgrep dotnet)
# Shows real-time performance counters
# Enable memory dumps for analysis
export COMPlus_DbgEnableMiniDump=1
export COMPlus_DbgMiniDumpType=4
๐ Simple Commands Summary
Hereโs your .NET on Linux quick reference! ๐
Command | Purpose | Example |
---|---|---|
dotnet new webapi | Create new API | dotnet new webapi -n MyApp |
dotnet run | Run application | dotnet run --urls http://0.0.0.0:5000 |
dotnet publish | Build for production | dotnet publish -c Release |
dotnet ef migrations add | Create migration | dotnet ef migrations add Initial |
dotnet test | Run unit tests | dotnet test --logger "console" |
dotnet watch | Hot reload development | dotnet watch run |
systemctl status dotnet-app | Check service | Shows if app is running |
dotnet --info | Show .NET info | Displays SDK/runtime details |
๐ก Tips for Success
Follow these best practices for .NET on Linux success! ๐
๐ Performance Optimization
- Use ReadyToRun compilation for faster startup
- Enable tiered compilation
- Configure appropriate GC mode
- Use response caching where applicable
๐ Security Best Practices
- Never run as root user
- Use HTTPS in production
- Enable CORS carefully
- Keep .NET runtime updated
๐ Monitoring and Logging
- Use structured logging (Serilog)
- Implement health checks
- Monitor with Application Insights
- Set up proper log rotation
๐ง Linux Integration
- Follow Linux filesystem conventions
- Use systemd for service management
- Integrate with Linux logging
- Respect Linux security model
๐ฆ Deployment Strategies
- Use Docker for consistency
- Implement CI/CD pipelines
- Version your releases
- Keep rollback strategies ready
โก Development Workflow
- Use VS Code with C# extension
- Leverage dotnet watch for hot reload
- Write unit tests from the start
- Use async/await properly
๐ What You Learned
Congratulations! Youโve mastered .NET Core on AlmaLinux! ๐ Hereโs what you accomplished:
โ
Installed .NET SDK and runtime on AlmaLinux successfully
โ
Created ASP.NET Core applications from scratch
โ
Configured Kestrel web server for production use
โ
Set up systemd services for automatic startup
โ
Implemented Nginx reverse proxy for production serving
โ
Deployed with Docker for containerized environments
โ
Integrated databases using Entity Framework Core
โ
Solved deployment issues like a seasoned DevOps engineer
๐ฏ Why This Matters
.NET Core on Linux represents a fundamental shift in enterprise development - the walls between platforms have finally come down! ๐
This combination gives you the best of both worlds: Microsoftโs powerful, productive framework running on Linuxโs stable, cost-effective platform. You can now build high-performance applications that run anywhere, from on-premises servers to cloud containers, without vendor lock-in.
Whether youโre migrating existing .NET applications to Linux, building cloud-native microservices, or starting fresh with cross-platform development, these skills position you at the forefront of modern application development. The future is cross-platform, and youโre ready for it! ๐
Remember: .NET is no longer just for Windows developers. By embracing Linux, youโre joining a growing community that values openness, performance, and choice. Keep exploring, keep building, and enjoy the freedom of true cross-platform development! โญ
Great job on completing this comprehensive .NET Core on Linux guide! Youโre now ready to deploy enterprise .NET applications that run everywhere! ๐