Публикация ASP.NET Core приложения с Angular на Ubuntu 20.04 через Nginx

Рейтинг: 0Ответов: 1Опубликовано: 03.07.2023

Я пытаюсь задеплоить asp.net приложение с Angular на Ubuntu 20.04, при этом использую Nginx. Вроде как все что нужно установил, настроил, но все равно выдает ошибку при введении адреса. Мои конфиги:

Program.cs

builder.Services.AddControllersWithViews();

/* Подключение контекстов */

var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    //app.UseHsts();
}

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

//app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller}/{action=Index}/{id?}");

app.MapFallbackToFile("index.html"); ;

app.Run();

Вроде как между Nginx и ASPNET должно быть HTTP подключение, а вот у пользователя и Nginx может быть HTTPS. По этой причине я закомментировал строки, касающиеся HSTS и HTTPSRedirection.

nginx/sites-enabled/domain.ru

server {
    server_name domain.ru www.domain.ru;
    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;
    }

    listen [::]:443 ssl ipv6only=on;
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/domain.ru/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/domain.ru/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
    if ($host = domain.ru) {
        return 301 https://$host$request_uri;
    } # managed by Certbot
    if ($host = www.domain.ru) {
        return 301 https://$host$request_uri;
    }

    server_name domain.ru www.domain.ru;
    listen        80;
    listen [::]:80;
    return 404;
}

Тут всячески пробовал менять порт. В статусе демона написано, что приложение запущено на 5000 порту, но тогда по запросу https://domain.ru вернется 404, если поменять порт на любой другой (5001, 7163), то будет возвращаться 502 ошибка Bad Gateway.

Приложение я демонизирую службой: /etc/systemd/system/daemon.service

[Unit]
Description=Example .NET Web API App running on Linux

[Service]
WorkingDirectory=/home/ASPsite/ASPsite/bin/Debug/net6.0
ExecStart=/usr/bin/dotnet /home/ASPsite/ASPsite/bin/Debug/net6.0/ASPsite.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-example
User=www-data
#envs
Environment=ASPNETCORE_ENVIRONMENT=Production

[Install]
WantedBy=multi-user.target

При всем этом, если я введу IP адрес сервера в поиск, то на HTTP мне вернется стартовая страница Nginx, а на HTTPS 404. Открывать в ufw 5000 и 5001 порт я уже пробовал, вроде как не помогло.

package.json:

"scripts": {
    "ng": "ng",
    "prestart": "node aspnetcore-https",
    "start": "run-script-os",
    "start:windows": "ng serve --port 44454 --ssl --ssl-cert %APPDATA%\\ASP.NET\\https\\%npm_package_name%.pem --ssl-key %APPDATA%\\ASP.NET\\https\\%npm_package_name%.key",
    "start:default": "ng serve --port 44454 --ssl --ssl-cert $HOME/.aspnet/https/${npm_package_name}.pem --ssl-key $HOME/.aspnet/https/${npm_package_name}.key",
    "build": "ng build",
    "build:ssr": "ng run ASPNETsite:server:dev",
    "watch": "ng build --watch --configuration development",
    "test": "ng test"
  },

dotnet publish:

MSBuild version 17.3.2+561848881 for .NET
  Determining projects to restore...
  All projects are up-to-date for restore.
  ASPNETsite-> /home/ASPNETsite/ASPNETsite/bin/Debug/net6.0/ASPNETsite.dll

  removed 1 package, and audited 1420 packages in 13s

  181 packages are looking for funding
    run `npm fund` for details

  42 vulnerabilities (2 low, 30 moderate, 10 high)

  To address issues that do not require attention, run:
    npm audit fix

  To address all issues possible (including breaking changes), run:
    npm audit fix --force

  Some issues need review, and may require choosing
  a different dependency.

  Run `npm audit` for details.

  > @fuse/starter@0.0.0 build
  > ng build --prod

  Option "--prod" is deprecated: No need to use this option as this builder defaults to configuration "production".

  <--- Last few GCs --->

  [29962:0x60fe090]   193888 ms: Scavenge 960.4 (1001.7) -> 959.3 (1002.9) MB, 18.7 / 0.0 ms  (average mu = 0.737, current mu = 0.649) allocation failure;
  [29962:0x60fe090]   193968 ms: Scavenge 961.1 (1002.9) -> 960.3 (1004.7) MB, 41.4 / 0.0 ms  (average mu = 0.737, current mu = 0.649) allocation failure;
  [29962:0x60fe090]   194192 ms: Scavenge 963.2 (1004.7) -> 962.1 (1013.4) MB, 179.1 / 0.0 ms  (average mu = 0.737, current mu = 0.649) allocation failure;


  <--- JS stacktrace --->

EXEC : FATAL error : Reached heap limit Allocation failed - JavaScript heap out of memory [/home/ASPNETsite/ASPNETsite/ASPNETsite.csproj]
   1: 0xb7a940 node::Abort() [ng build --prod]
   2: 0xa8e823  [ng build --prod]
   3: 0xd5c990 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [ng build --prod]
   4: 0xd5cd37 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [ng build --prod]
   5: 0xf3a435  [ng build --prod]
   6: 0xf4c91d v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [ng build --prod]
   7: 0xf2701e v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [ng build --prod]
   8: 0xf283e7 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [ng build --prod]
   9: 0xf095ba v8::internal::Factory::NewFillerObject(int, v8::internal::AllocationAlignment, v8::internal::AllocationType, v8::internal::AllocationOrigin) [ng build --prod]
  10: 0x12ce7ff v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [ng build --prod]
  11: 0x16fb6f9  [ng build --prod]
  Aborted
/home/ASPNETsite/ASPNETsite/ASPNETsite.csproj(58,5): error MSB3073: The command "npm run build -- --prod" exited with code 134.

Ответы

▲ 1Принят

При публикации asp.net core - приложения следует следить за двумя параметрами: content root и web root.

Content root - это папка в которой находятся файлы необходимые бекенду, обычно это конфиги. Значение content root по умолчанию - текущая директория, также называемая рабочей

Web root - это папка в которой находятся статические файлы, раздаваемые по HTTP. Значение Web root по умолчанию - это папка wwwroot внутри Content root.

Поэтому, когда вы прописываете WorkingDirectory - вы должны указывать её не "от балды", а вы должны указать ту папку, внутри которой лежат ваши appsettings.json и wwwroot.

Тут есть два подхода. Если делать тяп-ляп для отладки, то достаточно повторить ту конфигурацию в которой приложение обычно запускается из IDE:

WorkingDirectory=/home/my/ASPsite
ExecStart=/usr/bin/dotnet bin/Debug/net6.0/ASPsite.dll

Однако для использования в проде нужно подготовить приложение командой dotnet publish и скопировать результат в место постоянного нахождения:

Environment="DOTNET_ENVIRONMENT=Production"
WorkingDirectory=/opt/ASPsite
ExecStart=/usr/bin/dotnet ASPsite.dll

Отдельно замечу про nginx. Если вы используете nginx - то зачем вообще полагаться на раздачу статики вашим приложением и почему не поручить это дело nginx?

Выглядеть это будет как-то так:

    root /opt/ASPsite/wwwroot;

    location / {
        try_files $uri index.html; # SPA fallback
    }

    location /static {
        try_files $uri;
    }

    location /api {
        proxy_pass         http://127.0.0.1:5000/;
        # …
    }