.NET Core 应用部署到 CentOS

文本主要记录 .NET Core 应用 (pzy.io,即本博客) 部署到 CentOS  上的全过程,包括安装 .NET Core Runtime,申请域名SSL证书,使用域名SSL证书,启用  https 访问,使用 Nginx 反向代理和建立.NET CentOS  后台服务。本次部署 Linux 版本为 CentOS 7.4,.NET Core Runtime 版本为 .NET Core Runtime on Linux CentOS / Oracle x64

一、CentOS 安装 .NET Runtime 2.2

.net core 应用在 Linux 上运行的必要条件是需要安装 .net core runtime。在安装 .NET 之前,需要注册 Microsoft 密钥,注册产品存储库并安装所需的依赖项。 每台机器玩只需完成一次即可。打开命令提示符并运行以下命令:

$sudo rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm

为本次安装更新可用的产品,然后安装 .NET Runtime。运行以下命令行:

$sudo yum update 
$sudo yum install aspnetcore-runtime-2.2

二、申请域名 SSL 证书

本博客证书是在免费 SSL 证书申请网站(freessl.cn)上申请的,申请过程比较简单,使用该网站默认选项,可参考如下示意图:

选择SSL品牌-pzy.io
选择SSL品牌-pzy.io
选择证书生成方式-pzy.io
选择证书生成方式

然后是验证域名和证书下载(略),下载的证书 zip 文件中含证书文件 full_chain.pem 和私钥文件 private.key,但并不能直接应用于 .NET 应用,需要转化为 *.pfx 格式的文件,可在第三方网站上进行证书格式转换,可参考如下图示:

证书格式转换
证书格式转换

其中 *.pfx 证书对应的目标格式为 PKCS12。选定格式后,按照顺序分别上传证书文件 full_chain.pem 和私钥文件 private.key,再设定新的*.pfx 证书密钥(私钥密码不填),如下示意图:

设置证书密码
设置证书密码

三、使用域名 SSL 证书

为使 .NET Core 应用对于 SSL 具有较强的可配置性和扩展性,添加以下配置类

namespace Notex.WebUI.Https 
{ 
   public class EndpointOptions 
   { 
       /// <summary> 
       /// 主机IP或域名 
       /// </summary> 
       public string Host { get; set; } 
       /// <summary> 
       /// 端口 
       /// </summary> 
       public int? Port { get; set; } 
       /// <summary> 
       /// 架构,http/https 
       /// </summary> 
       public string Scheme { get; set; } 
       /// <summary> 
       /// https *.pfx文件路径 
       /// </summary> 
       public string FilePath { get; set; } 
       /// <summary> 
       /// *.pfx 密码 
       /// </summary> 
       public string Password { get; set; } 
   } 
}

引入 Kestrel 配置扩展

namespace Notex.WebUI.Https 
{ 
   /// <summary> 
   /// KestrelServerOptions 扩展 
   /// </summary> 
   public static class KestrelServerOptionsExtensions 
   { 
       /// <summary> 
       /// 配置端点 
       /// </summary> 
       /// <param name="options">参数</param> 
       public static void ConfigureEndpoints(this KestrelServerOptions options) 
       { 
           var configuration = options.ApplicationServices.GetRequiredService<IConfiguration>(); 
            
           var endpoints = configuration.GetSection("HttpServer:Endpoints") 
               .GetChildren() 
               .ToDictionary(section => section.Key, section => 
               { 
                   var endpoint = new EndpointOptions(); 
                   section.Bind(endpoint); 
                   return endpoint; 
               }); 
           foreach (var endpoint in endpoints) 
           { 
               var config = endpoint.Value; 
               var port = config.Port ?? (config.Scheme == "https" ? 443 : 80); 
               var ipAddresses = new List<IPAddress>(); 
               if (config.Host == "localhost") 
               { 
                   ipAddresses.Add(IPAddress.IPv6Loopback); 
                   ipAddresses.Add(IPAddress.Loopback); 
               } 
               else if (IPAddress.TryParse(config.Host, out var address)) 
               { 
                   ipAddresses.Add(address); 
               } 
               else 
               { 
                   ipAddresses.Add(IPAddress.IPv6Any); 
               } 
               foreach (var address in ipAddresses) 
               { 
                   options.Listen(address, port, 
                       listenOptions => 
                       { 
                           if (config.Scheme == "https") 
                           { 
                               var certificate = LoadCertificate(config); 
                               listenOptions.UseHttps(certificate); 
                           } 
                       }); 
               } 
           } 
       } 
       private static X509Certificate2 LoadCertificate(EndpointOptions endpointOptions) 
       { 
           if (endpointOptions.FilePath != null && endpointOptions.Password != null) 
           { 
               return new X509Certificate2(endpointOptions.FilePath, endpointOptions.Password); 
           } 
           throw new InvalidOperationException("找不到当前端点的有效证书配置。"); 
       } 
   } 
}

将证书信息配置到appsettings.json

{     
   "HttpServer": { 
       "Endpoints": { 
           "Http": { 
               "Host": "pzy.io", 
               "Port": 5000, 
               "Scheme": "http" 
           }, 
           "Https": { 
               "Host": "pzy.io", 
               "Port": 433, 
               "Scheme": "https", 
               "FilePath": "/path/to/pzy.pfx", 
               "Password": "cert_password" 
           } 
       } 
   } 
}

使用证书配置

public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 
           WebHost.CreateDefaultBuilder(args) 
               .UseStartup<Startup>() 
               .UseKestrel(options => options.ConfigureEndpoints());

四、启用 https 访问

上述就绪后,接下来将 .NET Core 应用发布并部署到 CentOS,并启用 https 访问,发布建立使用“依赖框架”和“可移植”,如下图示:

.NET Core 应用发布-pzy.io
.NET Core 应用发布

在 CentOS 上建立.NET Core 运行目录,并使用 WinSCP 将 .NET 应用上传到 CentOS,再启动dotnet xxx.dll .NET 应用,启动成功后,在浏览器输入https://pzy.io即可正常浏览。

$sudo mkdir /home/dotnet/xapp
$sudo chmod 777 -R /home/dotnet/xapp ##赋予全部访问权限

但同时也存在一个问题,当用户访问http://pzy.io时,如何让用户仍然正常访问呢?这是下文要讲述的主题。

五、使用 Nginx 反向代理

从上文的appsettings.json可知,非 https (即http)的端口为5000,只要使用 Nginx 将 pzy.io 80 端口外部请求,转发到 5000 端口的应用程序,便可解决问题(Nginx  安装略)。

修改 Nginx 配置文件,转发外部请求到应用程序:

$vi /usr/local/nginx/conf/nginx.conf

将配置文件替换为以下内容:

server { 
    listen       80; 
    server_name  pzy.io; 
    location / { 
            proxy_pass http://pzy.io: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; 
    }
}

重新加载 Nginx 配置:./nginx -s reload

因 .NET 应用内部已设置将 http 请求自动跳转到 https,上述问题得到解决。

六、建立 .NET CentOS 后台服务

前文运行 .NET 应用都是基于 SSH 会话,当 SSH 关闭时应用也停止运行,并且到 CentOS 重启后,如何保证 .NET 应用也启动呢?

在此,我们需要使用 CentOS 服务,首先创建服务脚本:

$ sudo vi /etc/systemd/system/pzyblog.service

在服务脚本输入以下内容:

[Unit] 
Description=PZY .NET Core Blog App 
[Service] 
WorkingDirectory=/home/dotnet/xapp #替换为应用目录 
ExecStart=/usr/bin/dotnet /home/dotnet/xapp/xxx.dll #替换为应用启动dll 
Restart=always 
RestartSec=10 
KillSignal=SIGINT 
SyslogIdentifier=pzyblogapp 
User=root 
[Install] 
WantedBy=multi-user.target 

启用该后台服务

$ sudo systemctl enable pzyblog.service #启用服务,disable 为禁用服务

启动和查询后台服务状态

$sudo systemctl start pzyblog.service #启动服务,停止服务使用 stop
$sudo systemctl status pzyblog.service #查看服务状态

当后台服务正常运行时,服务状态信息如下:

.NET 应用服务状态
.NET 应用服务状态

至此,.NET Core 应用部署到 CentOS 记述完毕。

《.NET Core 应用部署到 CentOS》的相关评论

发表评论

必填项已用 * 标记,邮箱地址不会被公开。