Asp net core apache

I want to test the "new" ASP.NET Core on my Ubuntu server. I use Apache, but the official documentation ( only covers Nginx. Can somebody help me to "translate" the Nginx configuration for the reverse proxy to an Apache VHost?

Source: ASP.NET Core Documentation (see above)

2 Answers 2

Check for more detail here.

The available documentation for the (still rather new) ASP.NET Core have been updated since I’ve asked this question. Here a two links to articles (thanks to David Peden) that explain the needed configuration for Apache. Even though they target CentOS, it is no problem to use them for Ubuntu.



Hot Network Questions

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

site design / logo © 2020 Stack Exchange Inc; user contributions licensed under cc by-sa 4.0 with attribution required. rev 2020.1.10.35756

Using this guide, learn how to set up Apache as a reverse proxy server on CentOS 7 to redirect HTTP traffic to an ASP.NET Core web app running on Kestrel server. The mod_proxy extension and related modules create the server’s reverse proxy.


  • Server running CentOS 7 with a standard user account with sudo privilege.
  • Install the .NET Core runtime on the server.
    1. Visit the Download .NET Core page.
    2. Select the latest non-preview .NET Core version.
    3. Download the latest non-preview runtime in the table under Run apps — Runtime.
    4. Select the Linux Package manager instructions link and follow the CentOS instructions.
    5. An existing ASP.NET Core app.

    At any point in the future after upgrading the shared framework, restart the ASP.NET Core apps hosted by the server.

    Publish and copy over the app

    If the app is run locally and isn’t configured to make secure connections (HTTPS), adopt either of the following approaches:

    • Configure the app to handle secure local connections. For more information, see the HTTPS configuration section.
    • Remove https://localhost:5001 (if present) from the applicationUrl property in the Properties/launchSettings.json file.

    Run dotnet publish from the development environment to package an app into a directory (for example, bin/Release/ /publish) that can run on the server:

    The app can also be published as a self-contained deployment if you prefer not to maintain the .NET Core runtime on the server.

    Copy the ASP.NET Core app to the server using a tool that integrates into the organization’s workflow (for example, SCP, SFTP). It’s common to locate web apps under the var directory (for example, var/www/helloapp).

    Under a production deployment scenario, a continuous integration workflow does the work of publishing the app and copying the assets to the server.

    Configure a proxy server

    A reverse proxy is a common setup for serving dynamic web apps. The reverse proxy terminates the HTTP request and forwards it to the ASP.NET app.

    A proxy server is one which forwards client requests to another server instead of fulfilling requests itself. A reverse proxy forwards to a fixed destination, typically on behalf of arbitrary clients. In this guide, Apache is configured as the reverse proxy running on the same server that Kestrel is serving the ASP.NET Core app.

    Because requests are forwarded by reverse proxy, use the Forwarded Headers Middleware from the Microsoft.AspNetCore.HttpOverrides package. The middleware updates the Request.Scheme , using the X-Forwarded-Proto header, so that redirect URIs and other security policies work correctly.

    Any component that depends on the scheme, such as authentication, link generation, redirects, and geolocation, must be placed after invoking the Forwarded Headers Middleware. As a general rule, Forwarded Headers Middleware should run before other middleware except diagnostics and error handling middleware. This ordering ensures that the middleware relying on forwarded headers information can consume the header values for processing.

    Invoke the UseForwardedHeaders method in Startup.Configure before calling UseAuthentication or similar authentication scheme middleware. Configure the middleware to forward the X-Forwarded-For and X-Forwarded-Proto headers:

    If no ForwardedHeadersOptions are specified to the middleware, the default headers to forward are None .

    Proxies running on loopback addresses (, [::1]), including the standard localhost address (, are trusted by default. If other trusted proxies or networks within the organization handle requests between the Internet and the web server, add them to the list of KnownProxies or KnownNetworks with ForwardedHeadersOptions. The following example adds a trusted proxy server at IP address to the Forwarded Headers Middleware KnownProxies in Startup.ConfigureServices :

    Читайте также:  Doom на андроид 4pda

    Install Apache

    Update CentOS packages to their latest stable versions:

    Install the Apache web server on CentOS with a single yum command:

    Sample output after running the command:

    In this example, the output reflects httpd.86_64 since the CentOS 7 version is 64 bit. To verify where Apache is installed, run whereis httpd from a command prompt.

    Configure Apache

    Configuration files for Apache are located within the /etc/httpd/conf.d/ directory. Any file with the .conf extension is processed in alphabetical order in addition to the module configuration files in /etc/httpd/conf.modules.d/ , which contains any configuration files necessary to load modules.

    Create a configuration file, named helloapp.conf, for the app:

    The VirtualHost block can appear multiple times, in one or more files on a server. In the preceding configuration file, Apache accepts public traffic on port 80. The domain is being served, and the * alias resolves to the same website. See Name-based virtual host support for more information. Requests are proxied at the root to port 5000 of the server at For bi-directional communication, ProxyPass and ProxyPassReverse are required. To change Kestrel’s IP/port, see Kestrel: Endpoint configuration.

    Failure to specify a proper ServerName directive in the VirtualHost block exposes your app to security vulnerabilities. Subdomain wildcard binding (for example, * ) doesn’t pose this security risk if you control the entire parent domain (as opposed to *.com , which is vulnerable). See rfc7230 section-5.4 for more information.

    Logging can be configured per VirtualHost using ErrorLog and CustomLog directives. ErrorLog is the location where the server logs errors, and CustomLog sets the filename and format of log file. In this case, this is where request information is logged. There’s one line for each request.

    Save the file and test the configuration. If everything passes, the response should be Syntax [OK] .

    Monitor the app

    Apache is now setup to forward requests made to http://localhost:80 to the ASP.NET Core app running on Kestrel at . However, Apache isn’t set up to manage the Kestrel process. Use systemd and create a service file to start and monitor the underlying web app. systemd is an init system that provides many powerful features for starting, stopping, and managing processes.

    Create the service file

    Create the service definition file:

    An example service file for the app:

    If the user apache isn’t used by the configuration, the user must be created first and given proper ownership of files.

    Use TimeoutStopSec to configure the duration of time to wait for the app to shut down after it receives the initial interrupt signal. If the app doesn’t shut down in this period, SIGKILL is issued to terminate the app. Provide the value as unitless seconds (for example, 150 ), a time span value (for example, 2min 30s ), or infinity to disable the timeout. TimeoutStopSec defaults to the value of DefaultTimeoutStopSec in the manager configuration file (systemd-system.conf, system.conf.d, systemd-user.conf, user.conf.d). The default timeout for most distributions is 90 seconds.

    Some values (for example, SQL connection strings) must be escaped for the configuration providers to read the environment variables. Use the following command to generate a properly escaped value for use in the configuration file:

    Colon ( : ) separators aren’t supported in environment variable names. Use a double underscore ( __ ) in place of a colon. The Environment Variables configuration provider converts double-underscores into colons when environment variables are read into configuration. In the following example, the connection string key ConnectionStrings:DefaultConnection is set into the service definition file as ConnectionStrings__DefaultConnection :

    Save the file and enable the service:

    Start the service and verify that it’s running:

    With the reverse proxy configured and Kestrel managed through systemd, the web app is fully configured and can be accessed from a browser on the local machine at http://localhost . Inspecting the response headers, the Server header indicates that the ASP.NET Core app is served by Kestrel:

    View logs

    Since the web app using Kestrel is managed using systemd, events and processes are logged to a centralized journal. However, this journal includes entries for all of the services and processes managed by systemd. To view the kestrel-helloapp.service -specific items, use the following command:

    For time filtering, specify time options with the command. For example, use —since today to filter for the current day or —until 1 hour ago to see the previous hour’s entries. For more information, see the man page for journalctl.

    Читайте также:  Как закачать фильм на планшет с компьютера

    Data protection

    The ASP.NET Core Data Protection stack is used by several ASP.NET Core middlewares, including authentication middleware (for example, cookie middleware) and cross-site request forgery (CSRF) protections. Even if Data Protection APIs aren’t called by user code, data protection should be configured to create a persistent cryptographic key store. If data protection isn’t configured, the keys are held in memory and discarded when the app restarts.

    If the key ring is stored in memory when the app restarts:

    • All cookie-based authentication tokens are invalidated.
    • Users are required to sign in again on their next request.
    • Any data protected with the key ring can no longer be decrypted. This may include CSRF tokens and ASP.NET Core MVC TempData cookies.

    To configure data protection to persist and encrypt the key ring, see:

    Secure the app

    Configure firewall

    Firewalld is a dynamic daemon to manage the firewall with support for network zones. Ports and packet filtering can still be managed by iptables. Firewalld should be installed by default. yum can be used to install the package or verify it’s installed.

    Use firewalld to open only the ports needed for the app. In this case, port 80 and 443 are used. The following commands permanently set ports 80 and 443 to open:

    Reload the firewall settings. Check the available services and ports in the default zone. Options are available by inspecting firewall-cmd -h .

    HTTPS configuration

    Configure the app for secure (HTTPS) local connections

    The dotnet run command uses the app’s Properties/launchSettings.json file, which configures the app to listen on the URLs provided by the applicationUrl property (for example, https://localhost:5001;http://localhost:5000 ).

    Configure the app to use a certificate in development for the dotnet run command or development environment (F5 or Ctrl+F5 in Visual Studio Code) using one of the following approaches:

    Configure the reverse proxy for secure (HTTPS) client connections

    To configure Apache for HTTPS, the mod_ssl module is used. When the httpd module was installed, the mod_ssl module was also installed. If it wasn’t installed, use yum to add it to the configuration.

    To enforce HTTPS, install the mod_rewrite module to enable URL rewriting:

    Modify the helloapp.conf file to enable URL rewriting and secure communication on port 443:

    This example is using a locally-generated certificate. SSLCertificateFile should be the primary certificate file for the domain name. SSLCertificateKeyFile should be the key file generated when CSR is created. SSLCertificateChainFile should be the intermediate certificate file (if any) that was supplied by the certificate authority.

    Save the file and test the configuration:

    Additional Apache suggestions

    Restart apps with shared framework updates

    After upgrading the shared framework on the server, restart the ASP.NET Core apps hosted by the server.

    Additional headers

    In order to secure against malicious attacks, there are a few headers that should either be modified or added. Ensure that the mod_headers module is installed:

    Secure Apache from clickjacking attacks

    Clickjacking, also known as a UI redress attack, is a malicious attack where a website visitor is tricked into clicking a link or button on a different page than they’re currently visiting. Use X-FRAME-OPTIONS to secure the site.

    To mitigate clickjacking attacks:

    Edit the httpd.conf file:

    Add the line Header append X-FRAME-OPTIONS "SAMEORIGIN" .

    MIME-type sniffing

    The X-Content-Type-Options header prevents Internet Explorer from MIME-sniffing (determining a file’s Content-Type from the file’s content). If the server sets the Content-Type header to text/html with the nosniff option set, Internet Explorer renders the content as text/html regardless of the file’s content.

    Edit the httpd.conf file:

    Add the line Header set X-Content-Type-Options "nosniff" . Save the file. Restart Apache.

    Load Balancing

    This example shows how to setup and configure Apache on CentOS 7 and Kestrel on the same instance machine. In order to not have a single point of failure; using mod_proxy_balancer and modifying the VirtualHost would allow for managing multiple instances of the web apps behind the Apache proxy server.

    In the configuration file shown below, an additional instance of the helloapp is set up to run on port 5001. The Proxy section is set with a balancer configuration with two members to load balance byrequests.

    Rate Limits

    Using mod_ratelimit, which is included in the httpd module, the bandwidth of clients can be limited:

    The example file limits bandwidth as 600 KB/sec under the root location:

    Long request header fields

    Proxy server default settings typically limit request header fields to 8,190 bytes. An app may require fields longer than the default (for example, apps that use Azure Active Directory). If longer fields are required, the proxy server’s LimitRequestFieldSize directive requires adjustment. The value to apply depends on the scenario. For more information, see your server’s documentation.

    Читайте также:  Фотошопы для профессиональных фотографов

    Don’t increase the default value of LimitRequestFieldSize unless necessary. Increasing the value increases the risk of buffer overrun (overflow) and Denial of Service (DoS) attacks by malicious users.

    Подготовка окружения

    Для начала, добавим dotnet-репозиторий:

    На выходе получаем примерно следующее:

    Теперь обновим индекс наших пакетов:

    Далее, мы можем просто установить dotnet-пакет при помощи apt-get:

    Теперь можем смело приступать к созданию приложения

    Создание приложения

    При помощи команды dotnet new мы можем создать шаблон для нашего приложения, подобно шаблонам из Visual Studio. Подробная документация к команде.

    На текущий момент (07.2017), команда dotnet new поддерживает следующие шаблоны:

    Мы создадим веб-приложение ASP.NET Core:

    На выходе консоль выдаст нам следующее сообщение:

    Чтобы убедиться, что шаблон сгенерировался правильно, заглянем в содержимое папки при помощи команды ls -la .

    Все необходимые папки для сборки приложения на месте, приступим! Для начала, восстановим все пакеты при помощи dotnet restore .

    Теперь можем собрать приложение:

    Запустим приложение с помощью:

    Консоль говорит нам, что приложение запустилось по адресу localhost:5000/. Проверим:

    Желающих подробнее узнать, как работает web-сервер отсылаю к официальному источнику.

    Теперь убьём процесс нажав Ctrl + C и опубликуем приложение командой dotnet publish. Эта команда упаковывает приложение и все его зависимости для дальнейшего развёртывания (желающим интимных подробностей сюда).

    В случае проблем с правами доступа Вам поможет команда sudo chmod и эта страница документации.

    Развертывание на сервере.

    Если мы хотим развернуть наше приложение под linux-сервером, необходимо настроить прокси и демонизировать процесс запуска приложения. Для проксирования мы будем использовать nginx, для демонизации процесса systemd. Краткое описание утилиты

    Как следует из документации выше, с core в коробке идет kestrel — веб-сервер для приложений. Зачем нам тогда нужен прокси-сервер? Ответ даётся на официальной странице Microsoft:

    Если вы выставляете ваше приложение в интернет, Вы должны использовать IIS, Nginx или Apache как обратный прокси-сервер.

    Обратный прокси-сервер получает HTTP запросы из сети и направляет их в Kestrel после первоначальной обработки, как показано на след диаграмме:

    Главная причина, по которой следует использовать обратный прокси сервер — безопасность. Kestrel относительно нов и ещё не имеет полного комплекта защиты от атак.

    Ещё одна причина, по которой следует использовать обратный прокси-сервер — наличие на сервере нескольких приложений, использующих один порт. Kestrel не поддерживает разделение одного порта между несколькими приложениями.

    Так же, использование обратного прокси-сервера может облегчить распределение нагрузки и поддержку SSL.

    Как говорилось выше, в качестве прокси-сервера мы будем использовать nginx.

    Т.к. в качестве прокси-сервера у нас используется не IIS, следует добавить следующие строки в метод Configure файла Startap.cs.

    Здесь мы включаем поддержку ForwardedHeaders мидлвера из пакета. Microsoft.AspNetCore.HttpOverrides, который будет вставлять в Http-запрос заголовки X-Forwarded-For и X-Forwarded-Proto, использующиеся для определения исходного IP адреса клиента и передачи его прокси-серверу. Определение мидлверов и практическое использование так же будет рассмотрено в дальнейших частях этого гайда.

    Если у Вас nginx не установлен, выполните следующую команду.

    и запустите его командой:

    Далее, нам необходимо сконфигурировать nginx для проксирования http-запросов.

    Создадим файл /etc/nginx/sites-available/aspnetcore.conf. Папка sites-avalible укахывает nginx-у, какие веб-сайты доступны на текущем сервере для обработки. Добавим в него следующие строки:

    Создадим символическую ссылку на aspnetcore.conf в папку sites-enabled, в которой отражаются запущенные nginx-ом сайты.

    Nginx настроен на то, чтобы принимать запросы с localhost:8888. Перезапускаем nginx командой sudo service nginx restart , чтобы созданные нами конфигурационные файлы вступили в силу. Проверяем:

    502-я ошибка говорит, что сервер перенаправляет нас в другое место и в этом месте что-то пошло не так. В нашем случае — я убил процесс с нашим веб-приложением, которое было ранее запущено командой dotnet run. Потому что могу 🙂

    На самом деле, потому что запускать dotnet run в консоли и вечно держать эту вкладку открытой грустно. Именно поэтому процесс будем демонизировать, то есть настроем автозапуск после перезагрузки и автоматическую работу в фоне с помощью systemd.

    Для этого создадим файл в директории /etc/systemd/system/ с расширением .service

    Назовём его kestrel-test:

    И положим в него следующее содержимое:

    Description=Example .NET Web API Application running on Ubuntu

    WorkingDirectory=/home/robounicorn/projects/ #путь к publish папке вашего приложения
    ExecStart=/usr/bin/dotnet /home/robounicorn/projects/ # путь к опубликованной dll
    RestartSec=10 # Перезапускать сервис через 10 секунд при краше приложения
    Syslog > User=root # пользователь, под которым следует запускать ваш сервис

    Теперь включим и запустим сервис при помощи следующих команд:

    Проверим статус сервиса:

    Если всё было сделано правильно, на эта команда выдаст нам следующее: