Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Building an ASP.NET Core web app for a Linux VPS: Part 1

0.00/5 (No votes)
11 Jul 2016 1  
A quick Windows programmers' guide to building a secure .NET Core web app for a Linux VPS and NGINX

Introduction

With .NET Core 1.0 fresh off the press, the Windows developer in me that has a decade-long experience with C# is thrilled by the new cross-platform opportunities. In this series of articles I'm putting on the hat of a full-stack web developer and lay the groundwork for a tiny open-source web application. Along the way I'll show you how to:

  • get started with a Debian Virtual Private Server (VPS) and run your first .NET program;
  • get the Linux environment ready for the real world;
  • build your first .NET Core web app;
  • configure a free domain name;
  • set up NGINX for use as a reverse proxy;
  • code and build in Visual Studio 2015 and publish on Linux;
  • enable HTTPS with a free certificate from Let's Encrypt
  • architect a simple single-page app with jQuery and AJAX
  • add a database to the mix

There is enough stuff here for several articles, so let's get started!

Get your VPS

Virtual Private Servers are the coolest kid on the block. With a bit of research you can find several providers that allow you to get your own Linux server up and running in a matter of minutes and operate it for as little as five bucks a month. I find this thrilling because of the freedom it gives you over the usual hosting plans with very narrow options to configure a site under IIS. The coolness of .NET Core 1.0 is that it allows you to use your C# and Windows skillset and run your web app in a cheap, instant Linux VPS.

So go get your very own VPS.

Are you done? Then your provider will have given you an IP address and an initial root password. Let's put them to good use. Throughout this series I'll be using Debian 8.5; your mileage may vary slightly depending on your particular flavor of 'nux.

Caution
At the time of writing, .NET Core binaries are only available for x64 Linux distros. Do yourself a favor and make sure you get a 64-bit system, even though for anything with less than 4 gigs of RAM, 32-bit makes a lot more sense - and we're after a tiny VPS here. More on this in the last section of this article.

E.T. on the phone: PuTTY and WinSCP

If you're using these two tools every day, skip right through to the next section. Otherwise, read on.

Download and install PuTTY and WinSCP from here:
http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
https://winscp.net/eng/download.php

PuTTY gives you a terminal console into the Linux system over a secure SSL connection. It's a mind-bogglingly simple tool, but here are two useful tweaks.

1: Save a session. All this means in practice is that you enter your server's IP address (or domain name once you've obtained one), give it a name, and hit the Save button. That adds it to the list so you can simply double-click later to connect.

Image 1

2: Make the console bigger. By default, every time you connect, PuTTY will give you an 80x24 character screen, which is way too small for any practical purpose. Load an existing session; go to Window on the left; put in your favorite size (for me the sweet spot is at 100x38); head back to Session and save. Happy connecting ever after.

Image 2

WinSCP is what self-respecting people really mean when they say FTP. It allows you to upload and download files over a secure connection, without broadcasting passwords and data in plain, unencrypted form - to the great delight of all the script kids lurking around. WinSCP has the same, familiar two-column layout as Norton Commander or its later sibling, FAR Manager. (And FAR Manager is the first tool you always install after Windows, right?)

First login

Fire up PuTTY and connect. Your Linux system will initially only have a "root" account. With my provider, I chose to get an initial root password instead of setting up an SSH key, so the first time I log in I must change that password right away:

login as: root
root@46.101.122.226's password:
You are required to change your password immediately (root enforced)

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Changing password for root.
(current) UNIX password:
Enter new UNIX password:
Retype new UNIX password:
_____________________________________________________________________
WARNING! Your environment specifies an invalid locale.
 This can affect your user experience significantly, including the
 ability to manage packages. You may install the locales by running:

WARNING: 'False' is an invalid locale
To see all available language packs, run:
   apt-cache search "^language-pack-[a-z][a-z]$"
To disable this message for all users, run:
   sudo touch /var/lib/cloud/instance/locale-check.skip
_____________________________________________________________________
<o:p>This may or may not be the same in your case, but this system throws a threat right at me about the system's invalid locale, so let's get that out of the way real quick. That goes hand in hand with the default character set, where UTF-8 is a no-brainer, so the incantations look like this:
root@debian-512mb-fra1-02:~# locale
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
LANG=False
LANGUAGE=
LC_CTYPE="False"
LC_NUMERIC="False"
LC_TIME="False"
LC_COLLATE="False"
LC_MONETARY="False"
LC_MESSAGES="False"
LC_PAPER="False"
LC_NAME="False"
LC_ADDRESS="False"
LC_TELEPHONE="False"
LC_MEASUREMENT="False"
LC_IDENTIFICATION="False"
LC_ALL=
root@debian-512mb-fra1-02:~# locale-gen en_US.UTF8
Generating locales (this might take a while)...
  en_US.UTF-8... done
Generation complete.
root@debian-512mb-fra1-02:~# localectl set-locale LANG=en_US.UTF-8

(I highlighted the incantations in bold so they stand out from all the French that Linux throws back at you. I'll do this in every subsequent shell sample.)

Your top priority right now is to stop being root. It's terribly easy to mess up a single character in a Linux incantation and end up with one that has tragic consequences; and root has the powers to do it all. One slip of the keyboard and the dementors will do Horrible Things to your system. Below I'll create a user called gabor that's an ordinary citizen except he can pretend to be root for a single incantation at a time, by prepending the magic word sudo. Do this, leave stage with exit, and log right back in as your less dangerous self. Here's how it goes.

root@debian-512mb-fra1-02:~# adduser gabor
Adding user `gabor' ...
Adding new group `gabor' (1000) ...
Adding new user `gabor' (1000) with group `gabor' ...
Creating home directory `/home/gabor' ...
Copying files from `/etc/skel' ...
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for gabor
Enter the new value, or press ENTER for the default
        Full Name []:
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
Is the information correct? [Y/n] Y
root@debian-512mb-fra1-02:~# apt-get install sudo
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  sudo
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 860 kB of archives.
After this operation, 2,488 kB of additional disk space will be used.
Get:1 http://mirrors.digitalocean.com/debian/ jessie/main sudo i386 1.8.10p3-1+deb8u3 [860 kB]
Fetched 860 kB in 0s (4,512 kB/s)
Selecting previously unselected package sudo.
(Reading database ... 35512 files and directories currently installed.)
Preparing to unpack .../sudo_1.8.10p3-1+deb8u3_i386.deb ...
Unpacking sudo (1.8.10p3-1+deb8u3) ...
Processing triggers for man-db (2.7.0.2-5) ...
Processing triggers for systemd (215-17+deb8u4) ...
Setting up sudo (1.8.10p3-1+deb8u3) ...
Processing triggers for systemd (215-17+deb8u4) ...
root@debian-512mb-fra1-02:~# visudo

The trick here is the very last command, visudo. That opens a magic file with the default editor:

Image 3

So you can append a line under the one for "root" like so:

# User privilege specification
root    ALL=(ALL:ALL) ALL
gabor   ALL=(ALL:ALL) ALL

Save your edit and exit the console with exit. Log back in as yourself.

Get .NET!

Back as yourself? Good. Time for magic: we shall now install .NET on this Linux box.
Official instructions: https://www.microsoft.com/net/core#debian

gabor@debian-512mb-fra1-02:~$ sudo apt-get install curl libunwind8 gettext
Reading package lists... Done
#
# Omitted many-many lines of output
#
gabor@debian-512mb-fra1-02:~$ curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?LinkID=809130
gabor@debian-512mb-fra1-02:~$ sudo mkdir -p /opt/dotnet && sudo tar zxf dotnet.tar.gz -C /opt/dotnet
gabor@debian-512mb-fra1-02:~$ sudo ln -s /opt/dotnet/dotnet /usr/local/bin

Now let's unwrap things here a bit.

  • apt-get install is the Linux equivalent of "download these packages and install them."
  • The curl command downloads a file from the Microsoft link and saves it in the current folder, which is your user's home folder right after login.
  • The next sudo'd command creates a directory under /opt and unpacks the downloaded file right into it. /opt is one of the standard places on Linux to install custom applications.
  • ln -s creates a symlink to the dotnet executable in /usr/local/bin, which is the directory for system-wide commands. In other words, anyone can now say dotnet and the system will dotnet for them.
  • The syntax for the symlink command is ln -s actualfile symlink. This will come in handy later.

You might as well delete the downloaded file from your home folder now. del will not work. The command is rm.

Say hello to the world

You say you got .NET on Linux? I still don't believe it. I want to see a Hello, world! program run. Let's create a subdirectory for this and tell .NET to create a new project - which will be, precisely, a Hello, world.

gabor@debian-512mb-fra1-02:~$ mkdir work
gabor@debian-512mb-fra1-02:~$ mkdir hwapp
gabor@debian-512mb-fra1-02:~$ cd hwapp/
gabor@debian-512mb-fra1-02:~/hwapp$ dotnet new
-bash: /usr/local/bin/dotnet: cannot execute binary file: Exec format error

Almost good. If you followed my advice from the beginning and made sure you got yourself a 64-bit system, you are now seeing Hello, world! at the end. If, like me, you naïvely thought a 512MB instance is perfectly fine with 32 bits, you're seeing the above. In that case, destroy your VPS and start again from scratch.

Conclusion

So what did we achieve here? We haven't actually built anything yet, just murmured a bunch of magic words at the command line. And did the impossible: compiled and built a C# program, natively, on Linux.

Check back for the next article in my series, where we'll point a domain name at our freshly minted VPS, harden the system to the minimum required extent expected for a machine out in the wild, and get a real website powered by ASP.NET Core greeting unspecified sailors.

History

07/11/2016 - Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here