content/blog/2021-03-30-vps-web-server.org

e8577d98faff1bed72ba6f2d204b8b44c6827c23
cleberg.net/content/blog/2021-03-30-vps-web-server.org rendered · source · history · blame · raw

412 lines · 14097 bytes

  1#+date:        <2021-03-30 Tue 00:00:00>
  2#+title:       Virtual Private Server (VPS) Web Server Configuration Guide
  3#+description: Instructional outline for setting up and maintaining a VPS environment configured for secure and scalable web hosting applications.
  4#+slug:        vps-web-server
  5#+filetags:    :vps:webserver:setup:
  6
  7* Shared Hosting vs. VPS
  8
  9Choosing a place to host a website is one of the most confusing
 10decisions for beginner web developers. Even for experienced web devs,
 11choosing between different forms of web hosting can be a daunting
 12choice.
 13
 14First, let's take a look at
 15[[https://en.wikipedia.org/wiki/Shared_web_hosting_service][shared web
 16hosting]]. Shared web hosting is a product where you are purchasing a
 17small piece of a web server that is being shared between many websites.
 18As a result, the cost of shared hosting is extremely low. You won't have
 19access to the server itself, which means you can't install your own
 20software on the server, such as Docker. Usually, you are simply allowed
 21to connect your domains to the server, set up domain security, and other
 22small utilities.
 23
 24In contrast, a
 25[[https://en.wikipedia.org/wiki/Virtual_private_server][virtual private
 26server]] (VPS) is a virtual machine that replicates the environment of
 27having a dedicated server to yourself. You are able to control the
 28virtual server's host names, base file system, package manager, etc.
 29Another great upside of a VPS is that since it's virtual, the company
 30providing the VPS can dynamically increase the disk size, RAM size, or
 31number of CPUs at any time. However, the virtual server is still
 32physically located on a server that is shared between multiple virtual
 33servers.
 34
 35The choice between shared hosting and VPS mostly depends on your skill
 36level with system administration. If you're comforting working on a
 37server that is mostly left up to you (or you're willing to learn), then
 38a VPS is usually a better option. However, shared hosting is a fantastic
 39option for people who don't want to have to learn how to manage their
 40server.
 41
 42* My Situation
 43
 44I had used shared hosting for approximately 5 years before trying my
 45first VPS. I manage a homelab and have had success running a server and
 46performing typical sysadmin duties, but I was still hesitant to get a
 47VPS. One fear was that I always struggled to properly set up the
 48networking part of a server - DNS and hostname configurations were not
 49my friend.
 50
 51As a little bit of background, I originally used
 52[[https://www.siteground.com][Siteground]] for my initially shared
 53hosting and stayed on that platform for at least a year. However, the UI
 54was clunky, and I didn't like how they handled certain technical
 55aspects, so I switched to [[https://www.namecheap.com][Namecheap]].
 56Namecheap was great because it is the service I primarily use for
 57purchasing domain names, which made it incredibly easy to link them to
 58my hosting service. However, it was still mediocre shared hosting, and
 59Namecheap is notorious for not letting you use
 60[[https://letsencrypt.org][Let's Encrypt]] to obtain free SSL/TLS
 61certificates; Namecheap wants to make you purchase certificates through
 62their store.
 63
 64Finally, I settled down with [[https://www.iwebfusion.net][iWebFusion]]
 65for about the last year of my shared hosting. This service was pretty
 66great, came with free SSL/TLS, and I never had any complaints.
 67
 68However, I finally grew tired of not being able to install software on
 69my own web server. I wanted to be able to try out things like
 70[[https://postmill.xyz][Postmill]] or [[https://matrix.org][Matrix]].
 71This is possible with a VPS, so I decided to grab a new domain name to
 72try it out.
 73
 74* Getting Started: Buying a VPS
 75
 76The first step to moving over to a VPS is (you guessed it): finding a
 77VPS provider. For my VPSs, I use [[https://1984hosting.com][1984]] and
 78prefer their services much more than any alternative, due to their
 79location (Iceland), their [[https://1984hosting.com/GDPR/][privacy
 80policy]], their respect for GDPR, and the ability to remain anonymous if
 81you pay in Bitcoin or Monero.
 82
 83[[https://njal.la][Njalla]] is another good, privacy-oriented option for
 84VPS services.
 85
 86You'll have to decide what specifications you want on your VPS. For me,
 87I only build and deploy low-resource HTML, PHP, and Python websites.
 88This means I can survive on the smallest VPS: 1 CPU, 1GB of RAM, and
 8925GB SSD for $5.00 per month.
 90
 91As noted above, the great thing about a VPS is you can request your
 92provider to increase the resources at any time.
 93
 94* Configuring DNS Settings
 95
 96Okay, so now let's get into some actual work that has to be done to get
 97content moved from a shared host to a VPS. At this point, I'm assuming
 98you have a shared host with website content that you can still access,
 99and you've purchased a new VPS and can SSH into that server.
100
101The first change is minor, but it should be done immediately in order to
102get things moving: DNS settings. Go to wherever your DNS settings are
103handled. If your shared host also managed your DNS settings, you'll need
104to first move that DNS over to your new VPS provider. For me, I route my
105DNS through [[https://www.gandi.net][Gandi]].
106
107Once you know where your DNS settings are, go ahead and update the =A=
108records to match the public IP address of your VPS. For example:
109
110#+begin_src txt
111A         example.com     xxx.xxx.xxx.xxx
112A         subdomain       xxx.xxx.xxx.xxx
113CNAME     www             example.com.
114#+end_src
115
116If you have any other records that require updates, such as MX or TXT
117records for a mail server, be sure to update those accordingly.
118Personally, I don't host my own mail server. I route all mail on my
119custom domains to [[https://www.migadu.com][Migadu]]. Hosting your own
120email server can become complex quickly and is not for beginners.
121
122DNS changes can take up to 48 hours to propagate, so be sure to give it
123some time before assuming you've made an error.
124
125* Server Updates and Packages
126
127Now that the DNS settings have been changed, let's set up our server
128while we wait for the DNS to propagate. First up is to ssh into your
129server. If you've signed up with a service like DigitalOcean, you can
130add your SSH key to your account and to your VPS droplet so that you
131don't need a password in order to SSH.
132
133#+begin_src sh
134ssh root@xxx.xxx.xxx.xxx
135#+end_src
136
137The VPS that is used in this blog post runs Ubuntu 20.04 with an Apache
138web server. If you're working on a different operating system (OS) or
139want a different web server, such as Nginx, you'll have to use different
140commands to set it up.
141
142First, let's update and upgrade our server.
143
144*NOTE:* Since we have logged in to the server as =root= for now, we
145don't need to use the =sudo= modifier before our commands.
146
147#+begin_src sh
148apt update && apt upgrade -y
149#+end_src
150
151* Create A User Account
152
153While being able to use =root= can be beneficial at times, you shouldn't
154use =root= unless you have to.
155
156So let's set up a new user in our system. The =-m= option below tells
157the OS to create a home directory for the new user.
158
159#+begin_src sh
160adduser USERNAME
161#+end_src
162
163Now, create a password for that user.
164
165#+begin_src sh
166passwd USERNAME
167#+end_src
168
169Finally, add the user to the sudoers file, so they can perform
170priveleged commands.
171
172#+begin_src sh
173usermod -a -G sudo USERNAME
174#+end_src
175
176If you are using SSH keys and not passwords, you'll need to copy your
177SSH key from your local machine to the VPS. If you haven't disabled
178password-based SSH yet, the easiest way to do this is =ssh-copy-id= from
179your local computer (not from the VPS):
180
181#+begin_src sh
182ssh-copy-id testuser@xxx.xxx.xxx.xxx
183#+end_src
184
185If you've disabled password-based SSH, you'll need to manually copy your
186SSH key into the =~/.ssh/authorized_keys= file.
187
188* Install Software
189
190Our goal here is to host a web server, so the next step is to install
191the Apache web server and any other packages we need.
192
193From this point on, I will be logged in as a user (not =root=) and will
194need to use the =sudo= modifier for most commands.
195
196#+begin_src sh
197sudo apt update; sudo apt upgrade -y; sudo apt autoremove -y
198sudo apt install apache2
199#+end_src
200
201If you need other language support, such as PHP, you'll need to install
202that too.
203
204#+begin_src sh
205sudo apt install libapache2-mod-php php-dom
206sudo a2enmod php
207sudo systemctl restart apache2
208#+end_src
209
210* Website Files & Folders
211
212Next up is to create the directories for the domain(s) we want to be
213hosted on this web server.
214
215#+begin_src sh
216cd /var/www
217sudo mkdir example.com
218#+end_src
219
220We have a folder for =example.com= now, so let's add an =index.html=
221file and put it within a specific =public_html= folder. You don't need
222this =public_html= if you don't want it, but it helps with organizing
223items related to =example.com= that you don't want to publish to the
224internet.
225
226#+begin_src sh
227cd example.com
228sudo mkdir public_html && cd public_html
229sudo nano index.html
230#+end_src
231
232You can put anything you want in this =index.html= file. If you can't
233think of anything, paste this in there:
234
235#+begin_src html
236<!DOCTYPE html>
237<html lang="en">
238    <head>
239        <meta charset="utf-8" />
240        <meta name="viewport" content="width=device-width, initial-scale=1" />
241        <title>Hello, world!</title>
242    </head>
243    <body>
244        <h1>Hello, world!</h1>
245    </body>
246</html>
247#+end_src
248
249If you want something to be served at =example.com/page01/file.txt=,
250you'll have to create the =page01= directory under the =example.com=
251directory. For example:
252
253#+begin_src sh
254cd /var/www/example.com/public_html
255sudo mkdir page01
256sudo nano file.txt
257#+end_src
258
259* Apache Configuration
260
261Now, let's set up the files that will tell the server where to find the
262files for =example.com=. We will copy the default configuration file and
263create our own.
264
265#+begin_src sh
266cd /etc/apache2/sites-available
267sudo cp 000-default.conf example.com.conf
268sudo nano example.com.conf
269#+end_src
270
271This configuration file will have a few default lines, but you'll need
272to edit it to look similar to this (settings may change based on your
273personal needs):
274
275#+begin_src config
276<VirtualHost *:80>
277    ServerAdmin your-email@email-provider.com
278    ServerName example.com
279    ServerAlias www.example.com
280    DocumentRoot /var/www/example.com/public_html
281    ErrorLog ${APACHE_LOG_DIR}/error.log
282    CustomLog ${APACHE_LOG_DIR}/access.log combined
283</VirtualHost>
284#+end_src
285
286Now, enable the configuration for your new site, disable the default
287configuration, and reload the web server.
288
289#+begin_src sh
290sudo a2ensite example.com.conf
291sudo a2dissite 000-default.conf
292sudo systemctl reload apache2
293#+end_src
294
295You can always run a test to make sure no errors or warnings are found
296in your configuration files.
297
298#+begin_src sh
299sudo apache2ctl configtest
300#+end_src
301
302Now, restart the web server entirely. After this, you should be able to
303browse to =http://example.com= and see the HTML content you provided
304earlier. Note that SSL/TLS has not been enabled yet, so you won't be
305able to use the secure version yet (=https://example.com=).
306
307#+begin_src sh
308sudo systemctl restart apache2
309#+end_src
310
311You can repeat this for as many websites as you need. Just create the
312domain folders in =/var/www/=, add the configuration file, enable the
313configuration, and restart =apache2=.
314
315* SSL/TLS Certificates: Serve Websites Over HTTPS
316
317In order to serve secure content, you'll need to obtain SSL/TLS
318certificates. Luckily, there's a free tool called
319[[https://certbot.eff.org][Certbot]] that helps us with the process.
320
321The first step is to install =snapd= and =core= for Ubuntu.
322
323#+begin_src sh
324sudo apt install snapd
325sudo snap install core
326sudo snap refresh core
327#+end_src
328
329Next, install the =certbot= snap package.
330
331#+begin_src sh
332sudo snap install --classic certbot
333#+end_src
334
335Execute the following command to ensure that the =certbot= command can
336be run.
337
338#+begin_src sh
339sudo ln -s /snap/bin/certbot /usr/bin/certbot
340#+end_src
341
342Finally, you can run =certbot= one of two ways:
343
3441. run it and let it alter your Apache configuration files automatically
345   to enable HTTPS redirects.
3462. run it and only allow it to create certificates. You'll need to
347   manually alter the config files to enable HTTPS redirects.
348
349Run certbot and allow automatic config changes:
350
351#+begin_src sh
352sudo certbot --apache
353#+end_src
354
355Run certbot for certificates only and don't allow it to alter config
356files:
357
358#+begin_src sh
359sudo certbot certonly --apache
360#+end_src
361
362The Certbot packages on your system come with a cron job or systemd
363timer that will renew your certificates automatically before they
364expire. You will not need to run Certbot again unless you change your
365configuration. You can test automatic renewal for your certificates by
366running this command:
367
368#+begin_src sh
369sudo certbot renew --dry-run
370#+end_src
371
372Now, test your domains by going to =https://example.com=.
373
374* Firewall Security
375
376To enable better security on your server, you'll need to enable a basic
377firewall. For Ubuntu, we'll use
378[[../secure-your-network-with-the-uncomplicated-firewall/][the
379uncomplicated firewall]].
380
381Now, add the following rules to the firewall allow SSH, Apache, and
382HTTP(S) connections. If you need to, you can enable different ports for
383specifics applications, SFTP, etc.
384
385#+begin_src sh
386sudo ufw default deny incoming
387sudo ufw default allow outgoing
388sudo ufw allow OpenSSH
389sudo ufw allow Apache
390sudo ufw allow proto tcp from any to any port 80,443
391#+end_src
392
393Once you've added all the rules you need, enable the firewall.
394
395#+begin_src sh
396sudo ufw enable
397#+end_src
398
399* Troubleshooting
400
401If you run into any issues during your VPS set-up, be sure to walk back
402through your actions and make sure you didn't miss any steps.
403
404Many websites have fantastic guides to setting up various web servers.
405This is one of the areas
406[[https://www.digitalocean.com/community/tutorials][where DigitalOcean
407shines]]. For simpler or more Linux-oriented questions, I suggest using
408[Linuxize] ([[https://linuxize.com]]).
409
410If you're getting certain errors (e.g. =500 Internal Server Error=) and
411need to debug locally, you can view the =access.log= and =error.log=
412files in the =/var/log/apache/= directory.