Publishing and Hosting Apps Developed in SnapDevelop
Last Updated: March 2020
Introduction
SnapDevelop currently offers three methods to publish your projects:
- File System
- Web Deploy
- Docker
The following table lists the available publication methods and publication results for all SnapDevelop projects.
Project | Available Publication Method | Publication Result |
---|---|---|
ASP .NET Core Web API | File System | Application files created in the target folder ready for deployment. |
Web Deploy | Application deployed to the target Web server. | |
Docker | Application image deployed to the target Docker registry. | |
Console App (.NET Core) | File System | Application files created in the target folder ready for deployment. |
Class Library (.NET Core) | File System | All library assembly files, including their dependency files, created in the target folder. |
Class Library (.NET Standard) | File System | All library assembly files, including their dependency files, created in the target folder. |
Shared Project | None | N/A. |
xUnit Test (.NET Core) | File System | Application files created in the target folder. |
Publishing a Project to a Local Folder with File System
Prerequisites:
SnapDevelop 2019 installed with the appropriate workloads:
Universal C Runtime (CRT)
Universal CRT is installed by default on Windows 10. On the other supported Windows platforms, you can follow the on-screen instructions to download and install the package when you install SnapDevelop. See Downloading and Installing UCRT.
Microsoft .NET Framework 4.6.1 SDK
Microsoft .NET Core SDK 2.1.6
TypeScript SDK 3.1
These three prerequisites will be automatically installed if the installer detects that they are not installed on the current machine. If your current machine runs on Windows 7, make sure that Service Pack 1 (KB976932) has already been installed; if your current machine runs on Windows 8.1, make sure that KB 2919355 has already been installed.
A project to publish
Publishing to a Local Folder
In Solution Explorer, right-click the project node and choose Publish (or use the Build > Publish menu item).
On the popup window, select File System, click Start, specify the target location of publication and click Next to continue.
You can check the "Use this connection string at runtime" if that applies to you. Then click Finish.
Check the publication status in the Output window.
Click Run on the toolbar or press Ctrl + F5 to run the application.
Publishing a Project to IIS with Web Deploy
Prerequisites
Before you use Web Deploy to publish an application, some requirements need to be satisfied on the server side and client side respectively.
Requirements for Server Side
Windows Server 2012 or 2016
Windows Server 2012 or 2016 is recommended. If your operating system is Windows 10, for example, you can use File System, rather than Web Deploy, to publish your project to your local folder.
Make sure that your Windows installation is up-to-date and includes KB2999226, which can be installed through Windows Update. If you don't have this update installed, you'll see an error like the following when you launch a .NET Core application: The program can't start because api-ms-win-crt-runtime-1-1-0.dll is missing from your computer. Try reinstalling the program to fix this problem.
Web Deploy 3.6 or higher
Download link for Web Deploy: https://www.iis.net/downloads/microsoft/web-deploy (32-bit and 64-bit versions of Web Deploy are available; install according to the version of your operating system)
Runtime & Hosting Bundle
Download link for Runtime & Hosting Bundle: https://dotnet.microsoft.com/download/dotnet-core/2.1 (Runtime 2.1.* | Windows | ASP.NET Core/.NET Core: Runtime & Hosting Bundle)
.NET Core Installer
Download link for .NET Core Installer: https://dotnet.microsoft.com/download/dotnet-core/2.1 (SDK 2.1.* | Windows | .NET Core Installer: x64 | x86; install according to the version of your operating system). Note that .NET SDK 2.1.* needs to be installed when SnapDevelop is not installed on the server side.
Requirements for Client Side
Windows 7/8.1/10
Make sure that your Windows installation is up-to-date and includes KB2999226, which can be installed through Windows Update. If you don't have this update installed, you'll see an error like the following when you launch a .NET Core application: The program can't start because api-ms-win-crt-runtime-1-1-0.dll is missing from your computer. Try reinstalling the program to fix this problem.
Web Deploy 3.6 or higher
Download link for Web Deploy: https://www.iis.net/downloads/microsoft/web-deploy (32-bit and 64-bit versions of Web Deploy are available; install according to the version of your operating system). Note that versions of Web Deploy must be the same on the server and client sides.
Configuring Server Side
Configuring IIS
To configure IIS, you should:
Launch Server Manager.
Use the Add Roles and Features wizard from the Manage menu or the link in Server Manager. On the Server Roles step, check the boxes for Web Server (IIS) and Management Tools.
On the Features step, check the boxes for .NET Framework 3.5 Features and .NET Framework 4.6 Features.
Confirm the roles and features you select and then click Install to continue.
View the results of the installations. Click Close if the installations are successful.
Installing and Configuring Web Deploy
Click the download link (https://www.iis.net/downloads/microsoft/web-deploy) to install Web Deploy. Enable the Web Management Service and Web Deployment Agent Service after Web Deploy is properly installed. To do so, you should:
Launch the desktop application Services.
Locate Web Management Service and Web Deployment Agent Service and, if necessary, right-click any one of them and then select Start.
Enabling Remote Connections
To enable remote connections, you should:
Launch IIS Manager, select the name of your computer in the left column, and then double-click Management Service on the right side.
Launch the Management Service. Click Stop first, select Enable remote connections and then click Apply.
Configuring IIS Users
There are two ways of user configuration, which are configuration of IIS Manager users and configuration of Windows users. Windows users are granted more permissions for publishing an application.
Configuring IIS Manager Users
To configure IIS Manager users, you should:
Double-click IIS Manager Users so that you can go to the IIS Manager Users page.
Add a user and then enter the user name and password.
In IIS Manager, open the server's node in the Connections panel. Right-click the Sites folder. Select Add Website from the context menu.
Provide a Site name and change the Physical path. Provide the Binding configuration and create the website by clicking OK.
Expand the Sites folder. Select the newly created website and then double-click IIS Manager Permissions.
In the IIS Manager Permissions dialog box, click Allow User so that a popup window appears. Choose IIS Manager and then click Select to select a desired user you added previously.
Configuring Windows Users
To configure Windows users, you should:
Right-click the Sites folder in the Connections panel. Select Add Website from the contextual menu.
Provide the Site name and change the Physical path. Provide the Binding configuration and create the website by clicking OK.
Expand the Sites folder. Select the newly created website and double-click IIS Manager Permissions.
On the IIS Manager Permissions page, click Allow User so that a popup window appears. Choose Windows and then click Select to continue.
Specify the object type and location and enter the object name to select. Check the object name after you enter it.
Select Basic Settings.
Choose Connect as > Specific user > Set and then enter the user name and password.
View the result of connection test by clicking Test Settings in step 7.
Click OK to continue if the specified user credentials are valid.
Performing the Publish Operations
Take the following steps to deploy your application:
Right-click the project you create and then select Publish to launch the publish wizard.
Select Web Deploy and enter the corresponding information (including server IP address, site name, user name and password). Note that the user name can be either the IIS Web Deploy user name or the Windows user name.
Click Validate Connection after the information is entered. Note that a green tick will appear if IIS and Web Deploy users are configured correctly.
Click Save to continue.
Check the configuration information and modify if necessary.
Click Publish to publish your application to a local host or a remote server.
Check the output message to see if the publication succeeds.
Troubleshooting
There are some common errors that may appear during server configuration. These errors are listed in the following paragraphs and corresponding solutions are offered.
1. "the site does not exist" error
When the plug-in Web Deploy required for publication is to be installed, the Complete setup type must be installed so that SnapDevelop can successfully publish the application. Otherwise, the "the site does not exist" error will be reported since Web deployment agent service is not enabled in the other setup types of Web Deploy.
Solution:
Uninstall the current version of Web Deploy and then reinstall the Complete version.
2. "The Web server is configured to not list the contents of this directory" error
Solution:
Launch IIS -> select your website -> click Directory Browsing -> click Enable on the top right corner of the page.
3. Issues concerning IIS application pool permission
There is sometimes the situation where data cannot be available after the publication of an application and the error code 500 is returned. This is due to the fact that the IIS application pool does not have permission to log in to the database.
Solution 1:
Change the application pool identifier and select a user who has permission.
Solution 2:
Change stdoutLogEnabled="false" to stdoutLogEnabled="true" in the web.config file that appears after the publication.
4. Error indicating that files are locked when an application is published to a remote site where an application has previously been published
Solution 1:
Close down the site and then launch the site after publication.
Solution 2:
Check the box for Remove additional files at destination when publishing.
5. Runtime error 500.30 with .NET Core 2.2d application published to IIS
Solution:
Change the method: Change InProcess to OutOfProcess in PropertyGroup in the application configuration file and then add ModelName.
Error 502.5 may occur after the change of method. To resolve Error 502.5, you can change the .NET path of Web API as an absolute path and restart your computer.
If Error 502.5 still remains, you can check the event log. If the log indicates that the startup process fails, this error can be caused by the lack of permissions. Change the permissions under the IIS application pool, right-click the website and click Advanced Settings. Choose Identity in Process Model and then check the radio button for the Custom account to enter the local administrator's user name and password.
Publishing a Project with Docker
Understanding Docker Basics
Before you use Docker to publish your projects, you should have mastered the basics of Docker publication.
Concepts Related to Docker
You should first familiarize yourself with a variety of Docker-related concepts that will be used in this tutorial.
Image
An image is a read-only template that contains instructions for creating a Docker container.
Container
A container is an executable instance of an image, and it is used to wrap up an application into its own isolated package. The major difference between an image and a container is that a container contains top readable and writable layers.
Registry
A registry is where Docker images are stored. You can have your own private registry, or just use Docker Hub, a public registry that anyone can use. Docker is configured to automatically look for images on Docker Hub.
When you execute such commends as docker pull or docker run, the required images are pulled from the configured registry. When you execute the docker push command, your image is pushed to the configured registry.
Docker Engine
Docker engine is a client-server application, which primarily consists of the following three components:
A Command Line Interface (CLI) client.
A REST API which specifies interfaces that applications can use to communicate with daemon and instruct it what to do.
A server named daemon.
Docker Daemon
Docker daemon is a server that continuously runs on your host operating system. It listens for Docker API requests and manages such Docker objects as images and containers. You can connect a Docker client to a Docker daemon on the same computer, or to a Docker daemon on a remote computer.
Engine API
The Engine API is an HTTP API served by Docker Engine. It is used by the Docker client to communicate with the Engine. What the Docker client can do can be done with the API.
Docker Host
Docker host refers to a computer that runs the Docker engine.
For detailed information about Docker and its related concepts, please visit Docker’s official website at https://docs.docker.com/engine/docker-overview/.
Benefits of Docker
Docker enjoys a variety of advantages over the other deployment modes:
Isolation; Dependencies in a container are independent of any other container that may be running and will not affect any installations on your computer.
Docker Hub; Docker Hub accommodates a large number of available images that can be pulled very quickly, making the build process fast and simple.
Reproducibility; The various specifications of a Docker container are stored in a Dockerfile. All images built from the same Dockerfile will work identically.
Security; Isolating the various components of a large application into different containers can have security benefits.
Common Docker Commands
The following table lists some common Docker commands that you can run using the Command Prompt tool and explains the meanings of individual commands.
Command | Description |
---|---|
docker images | Views information about images included in Docker. |
docker ps | Views information about the running container. |
docker build | Builds an image from a Dockerfile. |
docker run | Runs a command in a new container. |
docker rmi | Removes an image via image name or image ID. |
docker rm | Removes a container via container name or container ID. |
docker pull | Pulls an image or a repository from a registry. |
docker push | Pushes an image or a repository to a registry. |
docker network | Manages network configuration. |
docker save | Packs an image. |
docker load | Loads an image. |
docker-compose build | Turns services into images. |
docker-compose up | Launches the already available images so that they run as containers. |
docker-compose down | Stops and deletes everything created using the docker-compose up command. |
docker inspect network name | Inspects network details. |
docker attach | Attaches local standard input, output, and error streams to a running container |
Note
You can view all necessary information about docker image or container if you add ‘-a’ to command ‘docker images’ or ‘docker ps’, and you can forcefully delete anything by adding ‘-f’ to command ‘docker rmi’ or ‘docker rm’. For more information about docker commands, please visit Docker’s official website at https://docs.docker.com/engine/reference/commandline/docker/.
Publishing a Project with Docker Engine
When your project is ready for deployment, you can choose to publish the project in a Docker container. To publish with Docker, right-click on the project, select Publish from the context menu, and then select Docker. On the pop-up page, select Start to configure the various settings for Docker publication.
Preparing for Docker Publication
Docker supports publication using:
Local Docker engine;
Remote Docker engine.
You can select either way to publish your project, depending on whether Docker is installed on your local computer.
After you have made a decision on the way of publication, you must then decide where you want to publish your project. Currently Docker supports publication to:
Docker Hub;
Self-hosted registry.
Once you have made all the decisions, you need to make preparations for publication accordingly.
Preparing the Operating System
Windows 10 (64-bit) with Hyper-V enabled (for local computer);
CentOS Linux 7 or later (for remote computer).
Preparing a Docker Engine
You can choose to prepare a local Docker engine or a remote Docker engine, depending on whether you want to install Docker Desktop on your local computer.
Local Docker Engine
To use a local Docker engine to publish your project, you need to:
Sign up for Docker Hub;
Download Docker Desktop;
Install Docker Desktop on your local computer.
Signing up for Docker Hub
Before you can download Docker Desktop, you are required to sign up for Docker Hub first. Go to Docker’s official website (https://www.hub.docker.com) and follow the on-screen instructions to sign up for Docker Hub.
Downloading Docker Desktop
After you have successfully signed up for Docker Hub, you can download Docker Desktop at https://www.docker.com/products/docker-desktop.
Installing Docker Desktop
When you have downloaded Docker Desktop successfully, you need to install Docker Desktop on your local computer.
Remote Docker Engine
If you want to use a remote Docker engine to publish your project, you need to use a remote computer installed with CentOS Linux to:
Install Docker;
Register for a Docker ID (optional);
Enable remote access to Docker;
Generate certificates (optional).
Installing Docker
Refer to Get Docker Engine – Community for CentOS for instructions on how to install Docker.
Registering for a Docker ID (Optional)
If you want to publish your project to Docker Hub, you need to register for a Docker ID. Refer to How do you register for a Docker ID? for instructions on how to register for a Docker ID.
Enabling Remote Access to Docker
Refer to How do I enable the remote API for dockerd for instructions on how to enable remote access to Docker.
Generating Certificates (Optional)
If you want your Docker to be accessible through the network in a safe manner, you can enable TLS by specifying the tlsverify flag and pointing Docker’s tlscacert flag to a trusted CA certificate. Refer to the Create a CA, server and client keys with OpenSSL section in Protect the Docker daemon socket for instructions on how to generate certificates.
Preparing a Docker Registry
After you have installed Docker, you must then decide where you want to publish your project. You can publish your project to Docker Hub, or to a self-hosted Docker registry. Publishing a project to Docker Hub may raise security concerns since Docker Hub is a public registry. If you have such concerns, you can publish your project to a private registry URL.
Self-hosted Docker Registry
To publish your project to a self-hosted Docker registry, you need to:
Pull a Docker registry from Docker Hub;
Start the Docker registry;
Configure Docker daemon;
Configure user name and password for connection to registry.
Pulling Docker Registry
You can use the docker pull or docker run command to pull a registry from Docker Hub, or to load a registry if the registry already exists on your computer.
Run the following command to pull a registry from Docker Hub:
docker pull registry
Run the following command to load a registry from a local computer:
docker load –i
For example, docker load –i\\172.16.0.95\share\docker\linux\registry.rar
Starting Docker Registry
When a registry is successfully pulled or loaded, you need to run the following command to start the registry.
docker run -d -v /registry:/home/docker-registry -p 5000:5000 --restart=always --privileged=true --name registry registry:latest
Configuring Docker Daemon
You need to configure Docker daemon differently, depending on the operating system of the computer installed with Docker.
Configuring Docker Daemon (for Windows 10)
To configure Docker daemon, you need to:
Run Docker Desktop.
Click the Docker icon at the bottom right corner of the desktop and then select Settings.
Select Daemon on the Settings page.
Configure Insecure Registries.
Here, you need to configure the registry URL to which you want to publish your project. For example, you can enter registry.hub.docker.com if you want to publish your project to Docker Hub. For security considerations, it is recommended that you publish your project to a private registry URL. When you pulled a registry to a computer by running the docker pull registry command, the registry URL is the IP of the computer (e.g., 172.16.100.73:5000).
Select Apply to validate daemon configurations.
Configuring Docker Daemon (for CentOS Linux)
Refer to the Configure the Docker daemon section of Configure and troubleshoot the Docker daemon for instructions on how to configure the Docker daemon.
Configuring Docker Proxy
You need to configure Docker proxy because Internet connection is required when you pull images from or push images to the registry, and when you download the NuGet packages on which your project depends.
Note
When your project is built inside the Docker container, Docker needs to download the dependencies of your project, even if these dependencies already exist on your local computer.
Configuring Docker Proxy (for Windows 10)
To configure Docker proxy, you need to:
Run Docker Desktop.
Click the Docker icon at the bottom right corner of the desktop and then select Settings.
Select Proxies on the Settings page.
Configure the Web server proxy.
Select Apply to validate proxy configurations.
Configuring Docker Daemon (for CentOS Linux)
Refer to Configure Docker to use a proxy server for instructions on how to configure the Docker proxy.
Configuring User Name and Password for Connection to Registry
Refer to the Native basic auth section in Deploy a registry server for instructions on how to configure user name and password for connection to your private registry.
Docker Hub
To publish your project to Docker Hub, you need only to configure Docker daemon and Docker proxy.
Configuring Docker Daemon
Refer to the Self-hosted Docker Registry section in this tutorial for information about Docker daemon configuration.
Configuring Docker Proxy
Refer to the Self-hosted Docker Registry section in this tutorial for instructions on how to configure Docker proxy.
Connecting to a Docker Daemon
You can connect to a local Docker daemon or to a remote Docker daemon, depending on whether your local computer is installed with Docker Desktop.
Local Docker
If your local computer is installed with Docker Desktop, you can select the Local Docker radio button to publish your project with the local Docker engine.
Note
Make sure your local Docker Desktop is running before you can continue to configure the various Docker settings.
Remote Docker
If your local computer is not installed with Docker Desktop, you can select the Remote Docker radio button to publish your project with a remote Docker engine.
Likewise, you should make sure the remote Docker is running. In addition, you need to provide the following information: engine API URL, and certificates (optional).
Engine API URL
The engine API URL refers to the IP of the remote computer installed with Docker.
Certificates Folder
Contains the certificates (ca.pem, cert.pem and key.pem) generated in the Remote Docker Engine section for authentication by the remote Docker server.
Connecting to a Docker Registry
After you have connected to a Docker daemon, you can continue to configure the Docker connection settings.
Registry URL
Enter the registry URL (the IP of the computer that hosts the registry, for example, 172.16.100.73:5000). If you want to publish your project to Docker Hub, you can select the default registry URL (registry.hub.docker.com) from the drop-down list.
User Name and Password
Enter the user name and password you have configured in the Self-hosted Docker Registry section . If you use registry.hub.docker.com as the registry URL, you just enter the Docker ID and password you use to sign in.
After you have provided the registry URL and user name and password, you can click Next to verify whether this connection succeeds. If the connection fails, you will see a message box displaying the error message.
In this case, you need to re-configure the Docker connection according to the error message.
If the connection succeeds, you will be able to configure the various Docker settings.
Configuring Publish Settings
When you have successfully connected to a Docker registry, you need then to configure the publish settings, including the mode of configuration, target framework, deployment mode, and target runtime.
Configuration
Specifies the configuration for building your .NET project. The Debug mode is used for debugging the .NET project step by step, while the Release mode is used for the final build of the Assembly file (.dll or .exe).
Target Framework
Specifies the version of the .NET that you want your project to target.
Deployment Mode
Framework-dependent deployment is the default deployment option. It means that you can deploy portable code that is ready to run in any compatible environment, provided .NET Core is installed.
Target Runtime
There are five different target platforms where the application runs:
Portable
Win-x86
Win-x64
Osx-x64
Linux-x64
They are runtime identifiers used by .NET packages to represent platform-specific assets in NuGet packages.
Configuring Docker Settings
After you have configured the publish settings, you need to configure the Docker settings, including the image name, custom tag, and container port(s) to be exposed.
Image Name
Specifies a name for your image.
Tag
Allows you to add a tag for your image to distinguish it from the various other images (if any).
Expose Ports
Allows you to specify one or more container ports that can be exposed to be outside world. Note that container ports must be exposed so that they can be used for port mapping, and the exposed container ports will appear in the Container Port dropdown list. It is recommended that you expose port 80.
Configuring Publish Options
Deleting Intermediate Images
Removes the cached images that can be used for subsequent builds. Examples of intermediate images are images named <none>, and useless images (e.g., 172.16.100.18:5000/smm).
Running the Container after Publishing
Specifies whether to run the container immediately after you deploy your project to the target registry. If you enable this option, you need then to configure port mapping.
By default, the published container does not have any port accessible to the outside world. To enable the container to accept incoming connections, you need to select an exposed container port, and specify a host port to which the container port will map.
Container port: it is the port you exposed in Expose Ports.
Host port: this is the port to be used by the Docker host to access the container. Make sure you specify a port number that has not been assigned to any other service yet.
Note:
If you don’t enable the Run the container after publishing option, when you later run the container manually with the command line arguments, make sure you will specify the port mapping as well. The basic command line syntax is as follows:
docker run -d -p host port:container port --name container name image
For example:
docker run -d -p 8080:80 --name dockertest 172.16.100.73:5000/dockertest:latest
Executing the Publish Operations
When you have properly configured the various Docker settings and then click Finish, you will see the Dockerfile in your project in Solution Explorer. Dockerfile contains all the commands used by a user to assemble the image.
The following table presents a brief introduction to the various commands in the Dockerfile.
Command | Description |
---|---|
FROM | The FROM instruction initializes a new build stage and sets the base image for subsequent instructions. |
: | Marks the version of an image. |
AS | Specifies an alias. |
RUN | The RUN instruction will execute any commands in a new layer on top of the current image and commit the results. The resulting committed image will be used for the next step in the Dockerfile. |
COPY | The COPY instruction copies new files or directories from “ForDockerTest/ForDockerTest.csproj” and adds them to the filesystem of the container at the path “ForDockerTest/”. |
WORKDIR | Sets a working directory for other Dockerfile directives (such as RUN, CMD) and sets up a working directory for running container image instances. |
ENTRYPOINT | An ENTRYPOINT instruction allows you to configure a container that will run as an executable. |
EXPOSE | The EXPOSE instruction informs Docker that the container listens on the specified network ports at runtime. You can specify whether the port listens on TCP or UDP, and the default is TCP if the protocol is not specified. |
Refer to Dockerfile reference for more information about the commands that may be used in the Dockerfile.
When you click Finish, the publication process launches immediately. In the Output pane, you can check if the commands in the Dockerfile are being executed correctly. If an error occurs, you can view the error message and then correct the error accordingly. If no error occurs, it is recommended that you do not interrupt the publication process until the publication succeeds.
If you have enabled the Run the container after publishing option, the Docker host will run the published container, which means that the project will launch on the launchURL configured in the project launchSettings.json file.
For example, if the launchSettings.json file is as follows:
The deployed project in the container will run:
Finally, you can check whether your project is successfully published to the target registry URL.
Publishing and Hosting an ASP.NET Core Application on Linux
In this section, we create a Web API application, publish it using the File System method, and then host the app on Linux CentOS7 operating system following these steps:
In SnapDevelop, publish the Web API application with middleware configured to support reverse proxy
Copy over the Web API application from the local published folder to CentOS server
In CentOS, host Web API application on CentOS with reverse proxy (Apache) configured
For more information on how to set up Apache as a reverse proxy on CentOS 7, you can further read the Microsoft article: Host ASP.NET Core on Linux with Apache.
Prerequisites
- SnapDevelop 2019
- Server running CentOS 7 with a standard sudo user account
- .NET Core Runtime is installed on CentOS 7 with the following instructions
Install .NET Core Runtime on CentOS 7
Before installing .NET Runtime, you need to register the Microsoft key, register the product repository, and install required dependencies. These only need to be done once per machine. Open a terminal and run the following commands:
# Install repository configuration
curl https://packages.microsoft.com/config/rhel/7/prod.repo > ./microsoft-prod.repo
sudo cp ./microsoft-prod.repo /etc/yum.repos.d/
# Install Microsoft's GPG public key
curl https://packages.microsoft.com/keys/microsoft.asc > ./microsoft.asc
sudo rpm --import ./microsoft.asc
Install the latest available updates for the product, then install the .NET Runtime.
In your terminal, run the following commands:
# Install the latest available updates for the product
sudo yum update
# Install the ASP.NET Core 2.1 runtime
sudo yum install aspnetcore-runtime-2.1
The previous command will install the .NET Core Runtime Bundle, which includes the .NET Core runtime and the ASP.NET Core 2.1 runtime. To install just the .NET Core runtime, use the dotnet-runtime-2.1
package.
Publishing an ASP.NET Core Application to Server
Preparation for the Application
In SnapDevelop, select File from the menu bar and then choose New > Project. In the dialog box, select C# > .NET Core and then select ASP.NET Core Web API. Then, fill in the project information to create a .NET Core project named WebAPI1 by clicking OK.
Some configurations for reverse proxy and Kestrel server need to be made before publishing.
Configuration for Forwarded Headers Middleware
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 for diagnostics and error handling middleware. This running order 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:
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
app.UseAuthentication();
If no ForwardedHeadersOptions are specified to the middleware, the default forwarded headers are None
.
Proxies running on loopback addresses (127.0.0.0/8, [::1]), including the standard localhost address (127.0.0.1), are trusted by default. For other trusted proxies or networks within the organization handling requests between the Internet and the web server, add them to the list of KnownProxies or KnownNetworks as options in ForwardedHeadersOptions. The following example adds a trusted proxy server at IP address 10.0.0.100 to the KnownProxies
of Forwarded Headers Middleware in Startup.ConfigureServices
:
services.Configure<ForwardedHeadersOptions>(options =>
{
options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});
For more information, see Configure ASP.NET Core to work with proxy servers and load balancers.
Configuration for Secure (HTTPS) Local Connections
It is important for the application to make secure connections (HTTPS), configure the application to use a certificate for your development using one of the following approaches:
- Replace the default certificate from configuration (Recommended)
- KestrelServerOptions.ConfigureHttpsDefaults
The configuration for the application to listen to the URLs is in applicationUrl
property in the Properties/launchSettings.json file, for example, https://localhost:5001;http://localhost:5000
.
The app runs locally, so it is optional to configure the web server (Kestrel) with secure (HTTPS) local connections. You can remove https://localhost:5001
(if present) from the configuration.
Publishing the Application to a Local Folder
In Solution Explorer, right-click the project and choose Publish.
On the popup window, select File System.
Specify the target location of publication.
Go to Settings tab, change Target Runtime to linux-64.
Note that the application is configured for a framework-dependent deployment by default.
Click Save to continue.
Click Publish, then check the publication status in the Output window.
Copying the Application to the Server
Once the Web API application is published, copy the application from the published folder to the CentOS server using a tool that integrates into the organization's workflow (for example, SCP, SFTP). It's common to locate web applications under the var directory (for example, var/www/WebAPI1).
Hosting ASP.NET Core on CentOS with Apache
Configuring a Proxy Server
A reverse proxy is a common setup for serving dynamic web applications. The reverse proxy terminates the HTTP request and forwards it to the Web API application. In this example, Apache is configured as a reverse proxy, and Kestrel serves the Web API application. Apache forwards client requests to the Web API application running on Kestrel instead of fulfilling requests itself.
Installing Apache
Update CentOS packages to the latest stable versions:
sudo yum update -y
Install the Apache web server on CentOS with a single yum
command:
sudo yum -y install httpd mod_ssl
To verify where Apache is installed, run whereis httpd
from a command prompt.
Configuring Apache
Open the /etc/httpd/conf/httpd.conf
file and set the ServerName directive globally:
sudo nano /etc/httpd/conf/httpd.conf
# Set ServerName in this configuration file
ServerName www.example.com:80
The configuration files for Apache are located in 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 all the necessary configuration files to load modules.
Create a configuration file:
sudo nano /etc/httpd/conf.d/WebAPI1.conf
An example of configuration files for the application:
<VirtualHost *:*>
RequestHeader set "X-Forwarded-Proto" expr=$scheme
</VirtualHost>
<VirtualHost *:80>
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
ServerName www.example.com
ServerAlias *.example.com
ErrorLog /var/log/httpd/WebAPI1-error.log
CustomLog /var/log/httpd/WebAPI1-access.log common
</VirtualHost>
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 www.example.com
is being served, and the *.example.com
alias resolves to the same domain. See Name-based virtual host support for more information. Requests are proxied at the root to port 5000 of the server at 127.0.0.1. For bi-directional communication, ProxyPass
and ProxyPassReverse
are required. To change Kestrel's IP/port, see Kestrel: Endpoint configuration.
Warning: Failure to specify a proper ServerName directive in the VirtualHost block exposes your application to security vulnerabilities. Subdomain wildcard binding (for example, *.example.com
) 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]
.
sudo service httpd configtest
Restart Apache:
sudo systemctl restart httpd
sudo systemctl enable httpd
Monitoring the Application
Apache is now setup to forward requests made to http://localhost:80
to the Web API application running on Kestrel at http://127.0.0.1:5000
. 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 application. systemd is an init system that provides many powerful features for starting, stopping, and managing processes.
Creating the Service File
Create the service definition file:
sudo nano /etc/systemd/system/kestrel-webapi1.service
An example of service files for the application:
[Unit]
Description=Example .NET Web API application running on CentOS 7
[Service]
WorkingDirectory=/var/www/WebAPI1
ExecStart=/usr/share/dotnet /var/www/WebAPI1/WebAPI1.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-example
User=apache
Environment=ASPNETCORE_ENVIRONMENT=Production
[Install]
WantedBy=multi-user.target
If the user apache isn't used by the configuration, the user must be created first and given proper ownership of the files.
Use TimeoutStopSec
to configure the duration of time to wait for the application to shut down after it receives the initial interrupt signal. If the application doesn't shut down in this period, SIGKILL is issued to terminate the application. 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.
# The default value is 90 seconds for most distributions.
TimeoutStopSec=90
Save the file and enable the service:
sudo systemctl enable kestrel-webapi1.service
Start the service and verify that it's running:
# Start the service
sudo systemctl start kestrel-webapi1.service
# Verify the service
sudo systemctl status kestrel-webapi1.service
● kestrel-webapi1.service - Example .NET Web API application running on CentOS 7
Loaded: loaded (/etc/systemd/system/kestrel-webapi1.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2019-08-06 13:46:27 CST; 5s ago
Main PID: 46668 (dotnet)
Tasks: 16
CGroup: /system.slice/kestrel-webapi1.service
└─46668 /usr/share/dotnet/dotnet /var/www/WebAPI1/WebAPI1.dll
With the reverse proxy configured and Kestrel managed through systemd, the web application is fully configured and can be accessed from a browser on a local machine at http://localhost/api/sample/load
. Inspecting the response headers, the Server header indicates that the Web API application is served by Kestrel:
HTTP/1.1 200 OK
Date: Tue, 06 Aug 2019 05:52:17 GMT
Server: Kestrel
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Viewing Logs
Since the web application using Kestrel is managed using systemd, events and processes are logged to a centralized journal. However, this journal includes all of the entries for services and processes managed by systemd. View the specific items of kestrel-webapi1.service
with the following command:
sudo journalctl -fu kestrel-webapi1.service
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 man page for journalctl.
sudo journalctl -fu kestrel-webapi1.service --since "2019-08-06" --until "2019-08-06 23:00"
Configuring 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.
sudo yum install mod_ssl
To enforce HTTPS, install the mod_rewrite
module to enable URL rewriting:
sudo yum install mod_rewrite
Modify the /etc/httpd/conf.d/WebAPI1.conf
file to enable URL rewriting and secure communication on port 443:
<VirtualHost *:*>
RequestHeader set "X-Forwarded-Proto" expr=$scheme
</VirtualHost>
<VirtualHost *:80>
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
</VirtualHost>
<VirtualHost *:443>
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
ErrorLog /var/log/httpd/WebAPI1-error.log
CustomLog /var/log/httpd/WebAPI1-access.log common
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:!RC4+RSA:+HIGH:+MEDIUM:!LOW:!RC4
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
</VirtualHost>
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 present) that was supplied by the certificate authority.
Save the file and test the configuration:
sudo service httpd configtest
Restart Apache:
sudo systemctl restart httpd
After HTTPS is fully configured, the web application can be accessed from a browser on a local machine at https://localhost/api/sample/load
. Please pay attention here, it's https://....
Attribution
The content of this section incorporates some materials from “Host ASP.NET Core on Linux with Apache“ by Shayne Boyer licensed under CC BY 2.0.