clone url: git://


1 <!DOCTYPE html>
2 <html xmlns="" lang="en" xml:lang="en">
3 <head>
4 <meta charset="utf-8" />
5 <meta name="generator" content="pandoc" />
6 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
7 <title>Home hosting</title>
8 <style>
9 code{white-space: pre-wrap;}
10 span.smallcaps{font-variant: small-caps;}
11 span.underline{text-decoration: underline;}
12 div.column{display: inline-block; vertical-align: top; width: 50%;}
13 div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
14 ul.task-list{list-style: none;}
15 </style>
16 <link rel="stylesheet" href="/assets/archive.css">
17 </head>
18 <body>
19 <main>
20 <h2 id="home-hosting">Home-hosting</h2>
21 <p>2021-02-12 00:00</p>
22 <aside class="border">
23 <p>
24 <strong>Notice</strong>: I just read up on my ISP’s Terms of Use page, and it prohibits the following:
25 </p>
26 <blockquote>
27 operate a server in connection with the Services, including, without limitation, mail, news, file, gopher, telnet, chat, Web, or host configuration servers, multimedia streamers or multi-user interactive forums;
28 </blockquote>
29 <p>
30 Because of this, I have moved back to DigitalOcean as my host.
31 </p>
32 </aside>
33 <p>Okay, I don’t think the term “home-hosting” actually exists, so I’m just going to be using it here to refer to act of hosting a server on a machine in your home that publicly faces the internet.</p>
34 <p>Anyway! I’m super happy right now, mostly happy at the fact that I’ve done something this technical, well, technical for me! I’ve managed to move my server hosting from DigitalOcean to my home. This means what you are reading right now is actually coming from an old 2008 Macbook Pro with a broken screen from the basement of my house!</p>
35 <p>I have nothing against DigitalOcean, they are great, super friendly, and the support was awesome when I had questions. I would definitely recommend them to anyone who is starting out with their first virtual private server. Especially if you don’t want to deal with port-forwarding!</p>
36 <p>I haven’t removed the virtual private server (VPS) from DigitalOcean yet, because I want to let my home-hosted server run for about a week or two to test the stability of it. After that, it should be safe to remove the VPS, and if anything becomes unstable, then I’ll probably move back to DigitalOcean for hosting again.</p>
37 <h3 id="page-contents">Page contents</h3>
38 <!-- vim-markdown-toc GFM -->
39 <ul>
40 <li><a href="#choosing-a-linux-distribution">Choosing a Linux distribution</a></li>
41 <li><a href="#dealing-with-the-broken-backlight">Dealing with the broken backlight</a></li>
42 <li><a href="#installing-debian">Installing Debian</a></li>
43 <li><a href="#connecting-to-the-server-from-my-home-network">Connecting to the server from my home network</a></li>
44 <li><a href="#dealing-with-server-hibernation-and-disconnects">Dealing with server hibernation and disconnects</a></li>
45 <li><a href="#dealing-with-the-servers-loud-fan-and-high-temperature">Dealing with the server’s loud fan and high temperature</a></li>
46 <li><a href="#making-system-administration-convenient">Making system administration convenient</a></li>
47 <li><a href="#allowing-ports-with-ufw">Allowing ports with ufw</a></li>
48 <li><a href="#disabling-password-logins-over-ssh">Disabling password logins over SSH</a></li>
49 <li><a href="#hardening-ssh">Hardening SSH</a></li>
50 <li><a href="#setup-a-web-server">Setup a web server</a></li>
51 <li><a href="#configuring-the-router">Configuring the router</a></li>
52 <li><a href="#pointing-my-domain-name-to-my-servers-ip-address">Pointing my domain name to my server’s IP address</a></li>
53 <li><a href="#writing-a-script-to-update-my-dns-records">Writing a script to update my DNS records</a></li>
54 <li><a href="#getting-a-valid-tlsssl-certificate-for-https-access">Getting a valid TLS/SSL certificate for HTTPS access</a></li>
55 </ul>
56 <!-- vim-markdown-toc -->
57 <h3 id="choosing-a-linux-distribution">Choosing a Linux distribution</h3>
58 <p>Back when I was on DigitalOcean, I chose Ubuntu 20.04 because there were so many guides on Ubuntu for doing various tasks. Since, then, I’ve learned a lot about getting a server up and running. I probably wouldn’t be able to pull off some enterprise network infrastructure, but I don’t need that kind of setup. I just wanted to start off simple by getting a web server going, and serving that from my basement to the internet.</p>
59 <p>I decided to switch it up and go out of my comfort zone a bit, well, kind of… For servers, I always went with a Ubuntu server, again, because of all of the guides. I figured I would try out Debian, since that’s what Ubuntu is based on, and more importantly, it’s because I use Debian as my daily-driver on my personal laptop.</p>
60 <p>I figured Debian would be fine for a server because it’s focus is on stability, and when I’m not home, I don’t want to have to worry about my server crapping out, so Debian it was!</p>
61 <h3 id="dealing-with-the-broken-backlight">Dealing with the broken backlight</h3>
62 <p>Usually, when I install Linux on a machine, I have the luxury of seeing what I’m configuring and what options I’m choosing during the installation process. With a broken backlight, this is a little harder. At first, I tried connecting the laptop to a TV through an HMDI cable, but nothing was coming up. As a test, I tried a Ubuntu live USB to test if a desktop environment would work with the TV, and it did. I wasn’t sure why Debian’s graphical or command-line installer wasn’t showing up on the TV, so I decided to pull out my phone’s flashlight!</p>
63 <p>Before any actual “flashlighting” happened, I plugged my ethernet cable and a Debian installation USB stick into the server. Since the server is running on a 2008 Macbook Pro, I had to hold the “Option” key during the bootup to access the device selection screen. This is where my phone’s flashlight came in.</p>
64 <p>I flashed the screen with the flashlight, which is only bright enough to show about 5cm of the screen, so it was really hard to see, and even the lit-up part was still very dim. I’m thankful I have good eye sight. I noticed two icons show up on what looked like a light background. One was a grey hard drive icon with the name of my Macbook Pro’s hard drive, and the other icon was this yellow or orange icon that resembled some kind of external hard drive or USB, with the name “EFI … something”. I honestly forget what it said after “EFI”, so we’ll call it “EFI something” from now on haha. I’m also not sure if this is what Apple considers a BIOS, but whatever, it allowed me to choose bootup devices using the arrow keys and the “Enter” key.</p>
65 <h3 id="installing-debian">Installing Debian</h3>
66 <p>After selecting a boot device, I noticed the familiar Debian setup, so I knew all was good. Everything was normal, except for setting up an encrypted LVM. I have my personal laptop encrypted if it’s stolen, but for the server, I couldn’t do this, because I wanted to be able to restart the server remotely, and LVM encryption would require me to type in a decryption password before starting the server, which wouldn’t work, because I would need to decrypt the server before anything could connect to it. Because of this, I’ve decided to not keep anything overly-personal or sensitive on it, just in case of a burglary, and so I could restart the server after security updates.</p>
67 <p>After I got to the final screen, which asks you which desktop environment you want, if you want a print server, or if you want an SSH server setup after the installation. I think, under the hood, this is the Linux program <code>tasksel</code>, but I might be wrong.</p>
68 <p>I ended up not installing a desktop environment, unchecking the printing server option, and checking off the SSH server option.</p>
69 <h3 id="connecting-to-the-server-from-my-home-network">Connecting to the server from my home network</h3>
70 <p>Before I forwarded my ports, I wanted to see if I could just SSH into the server to set it up. I opened my router’s configuration page and logged into my router. I looked for any new devices on my network, and found the local IP address of the server.</p>
71 <p>On my personal laptop, I tried to SSH into the server using <code>ssh</code> on a whim, where <code>m455</code> was my under-privileged, regular user account on the server, and <code></code> was the server’s local IP address. To my success, I was prompted with a password for the <code>m455</code> user! I put in the password, and saw that my Bash prompt’s host changed! I was now SSHed into the server, and able to set it up remotely and didn’t need to drain my poor phone’s battery from all of the flashlight usage haha!</p>
72 <h3 id="dealing-with-server-hibernation-and-disconnects">Dealing with server hibernation and disconnects</h3>
73 <p>The first thing that happened while I was reading Debian’s documentation was being disconnected from my server. I was kind of disappointed, but realized it wasn’t because of connection instability, it was because the laptop went to sleep! I totally thought it would only go to sleep if I had some kind of graphical power manager, but it turns out systemd systems have a sleep, suspend, hibernate, and a few other services that run at startup that cause your system to sleep when inactive.</p>
74 <p>After a bit of internet-searching, I found out I can turn off various services with <code>systemctl mask x</code>, where mask is a service. I forget exactly what this does, but it points to <code>/dev/null</code> somewhere, and … something, something. Okay, I totally forgot how it works, but I do know it disables things, and that’s all I needed to know!</p>
75 <p>The following command stopped the server from sleeping, hibernated, suspending, or whatever it was doing:</p>
76 <pre><code>systemctl mask</code></pre>
77 <p>After doing this, I stepped away from the SSH connection and made some coffee, I came back 10 minutes later, and the connection was still there, so I knew the command worked.</p>
78 <h3 id="dealing-with-the-servers-loud-fan-and-high-temperature">Dealing with the server’s loud fan and high temperature</h3>
79 <p>One thing I noticed, though, was that the server fan was really loud, and pretty hot. I ran <code>htop</code> to see if anything was peaking CPU-wise, but the server was only using ~150mb of RAM, so that didn’t make sense.</p>
80 <p>After some more internet-searching, I found out that the loud fans and high temperatures were a common issue with Macbook Pros running Linux. Conveniently, I had learned that someone had written software called <a href="">mbpfan</a> to fix this issue, and that <code>mbpfan</code> was available in Debian’s repositories, so I <code>apt install</code>ed <code>mbpfan</code>, and successfully installed it.</p>
81 <p>I wasn’t sure how to use it, so I took a look at <a href="">mbpfan’s GitHub repository</a> page, and soon found out that all I had to do was add the <code>mbpfan.service</code> file from that repository to my systemctl startup services, and add the following kernel modules to <code>/etc/modules</code>:</p>
82 <ul>
83 <li><code>coretemp</code></li>
84 <li><code>applesmc</code></li>
85 </ul>
86 <p>I then ran <code>systemctl enable mbpfan.service</code>, <code>systemctl daemon-reload</code>, <code>systemctl start mbpfan.service</code>, and then <code>systemctl reboot</code>, just in case kernel modules require system reboots.</p>
87 <p>To my luck, the laptop/server was super quite, and wasn’t running hot like it was before! Thanks <code>mbpfan</code>’s developers!</p>
88 <p>I SSHed back into the server using my username and password, and continued the setup.</p>
89 <h3 id="making-system-administration-convenient">Making system administration convenient</h3>
90 <p>Now that the hardware and the connection were behaving the way I wanted, I installed a few packages I knew I would need for security, convenience, and text-editing when doing administrative tasks with the following commands as root:</p>
91 <pre><code>apt update
92 apt upgrade
93 apt install sendmail mutt vim curl htop rsync nginx ufw fail2ban</code></pre>
94 <p>Because I am running this server from home, I wanted some extra security, so <code>ufw</code> and <code>fail2ban</code> seemed like good candidates. <code>ufw</code> would act as a firewall to only allow specific ports to be open, and <code>fail2ban</code> would prevent repetitive, password-guessing or brute force attacks on my service, by denying connections for a period of time after x failed attempts.</p>
95 <p>To make things more convenient, while doing system administration as root, I added the following line to my <code>root</code> user’s <code>~/.bashrc</code>:</p>
96 <pre><code>export PATH=&quot;$PATH:/usr/local/bin:/usr/local/sbin:/usr/sbin:/usr/bin&quot;</code></pre>
97 <h3 id="allowing-ports-with-ufw">Allowing ports with ufw</h3>
98 <p>In case of a disconnect, I wanted to make sure <code>ufw</code> didn’t lock me out of the server remotely, so I ran the following command:</p>
99 <pre><code>ufw allow 22</code></pre>
100 <p>After this, I figured I’m going to be running this as a web server, so I should add HTTP and HTTPS ports as well:</p>
101 <pre><code>ufw allow 80
102 ufw allow 443</code></pre>
103 <p>Then to enable these settings, and have them applied on system reboots, I ran the following commands:</p>
104 <pre><code>systemctl enable ufw
105 systemctl start ufw
106 ufw enable</code></pre>
107 <p>I am honestly not sure if the <code>ufw enable</code> is necessary here with the <code>systemctl enable ufw</code> command already being ran, but I did it just in case.</p>
108 <h3 id="disabling-password-logins-over-ssh">Disabling password logins over SSH</h3>
109 <p>Next, I didn’t want to have to put in my password every time, so I began to setup SSH key authentication by creating an <code>authorized_keys</code> file in my <code>~/.ssh</code> directory, where my public SSH keys would be stored on the server:</p>
110 <pre><code>mkdir ~/.ssh
111 touch ~/.ssh/authorized_keys
112 chmod 700 ~/.ssh
113 chmod 600 ~/.ssh/authorized_keys</code></pre>
114 <p>On my local machine, I then generated an SSH key with the following command:</p>
115 <pre><code>ssh-keygen -b 4096 -t rsa -f ~/.ssh/home-server</code></pre>
116 <p>And sent the public key to my server using:</p>
117 <pre><code>scp -i ~/.ssh/ m455@local-ip:~/</code></pre>
118 <p>After doing this, I logged back into the server, and moved the contents of the <code></code> file to the <code>~/.ssh/authorized_keys</code> file I made earlier using the following commands on the server:</p>
119 <pre><code>cat &gt;&gt; ~/.ssh/authorized_keys
120 rm</code></pre>
121 <p>The reason I did this, is because SSH compares keys in <code>~/.ssh/authorized_keys</code> when you try to log into a server using <a href="">asymmetric key authentication</a>.</p>
122 <p>Before disabling password logins over SSH, I needed to test the key authentication, so I didn’t lock myself out of my server. I did this by specifying the private key to use when logging into the server using the following command:</p>
123 <pre><code>ssh -i ~/.ssh/home-server</code></pre>
124 <p>If everything went well, it shouldn’t prompt me for a password, which it didn’t! Perfect! Now I knew I could go and secure SSH more.</p>
125 <h3 id="hardening-ssh">Hardening SSH</h3>
126 <p>After reading several articles related to SSH hardening, I found some settings in <code>/etc/ssh/sshd_config</code> that I needed to change, and looked up what each of them do. The GSSAPIAuthentication and KerberosAuthentication were the only two settings that I am still fuzzy about haha:</p>
127 <pre><code>PasswordAuthentication no
128 PermitEmptyPasswords no
129 ChallengeResponseAuthentication no
130 KerberosAuthentication no
131 GSSAPIAuthentication no
132 X11Forwarding no
133 PermitUserEnvironment no
134 LoginGraceTime 20
135 PermitRootLogin no
136 MaxAuthTries 3
137 AllowUsers m455</code></pre>
138 <p>I also commented out any <code>#AcceptEnv ...</code>, because I set <code>PermitUserEnvironment</code> to <code>no</code>.</p>
139 <p>Then to bring these changes into action, I ran <code>systemctl restart SSH</code></p>
140 <p>Next step was <code>fail2ban</code>. By default, <code>fail2ban</code> has some defaults for hardening SSH, but I added another rule by adding the following to <code>/etc/fail2ban/jail.d/jail-debian.local</code>:</p>
141 <pre><code>[sshd]
142 port = 22
143 maxretry =3</code></pre>
144 <p>To enable this, I restarted <code>fail2ban</code> using the following command:</p>
145 <pre><code>systemctl restart fail2ban</code></pre>
146 <p>This little addition to <code>fail2ban</code> blocks attacker’s IP addresses from connecting to my server after three failed login attempts over ssh.</p>
147 <p>I found some information on the internet about being able to randomize ban time lengths, but they mentioned that you could just uncomment a few things to enable those kinds of bans. Unfortunately, on Debian, I don’t see those settings, so I didn’t add them in case I’m using an older version of fail2ban on Debian. I’ll probably have to look those up later.</p>
148 <h3 id="setup-a-web-server">Setup a web server</h3>
149 <p>The next step is actually getting something visible from the internet up, a web server! Well… it won’t be visible yet, because I haven’t gotten to port forwarding yet. For my setup, I am using nginx.</p>
150 <p>First I create the required directories as root for my <code>m455</code> user:</p>
151 <pre><code>mkdir -p /var/www/
152 chown -R m455:m455 /var/www/
153 chmod -R 755 /var/www/</code></pre>
154 <p>Then I add a test website at <code>/var/www/</code> as the <code>m455</code> user.</p>
155 <p>I then make an nginx server block (I think that’s what these things are called?) for the website in <code>/etc/nginx/sites-available/</code> with the following contents:</p>
156 <pre><code>server {
157 root /var/www/;
158 index index.html index.htm index.nginx-debian.html;
160 server_name;
162 location / {
163 try_files $uri $uri/ =404;
164 }
165 }</code></pre>
166 <p>I guess the <code>index.htm</code> and <code>index.nginx-debian.html</code> are optional, but I throw them in there anyway.</p>
167 <p>Next I enable the server block with the following command:</p>
168 <pre><code>ln -s /etc/nginx/sites-available/ /etc/nginx/sites-enabled/</code></pre>
169 <p>After this, I uncomment the following command from <code>/etc/nginx/nginx.conf</code>, which I don’t full understand, but apparently it fixes several caching problems? haha:</p>
170 <pre><code>server_names_hash_bucket_size 64;</code></pre>
171 <p>I also stop nginx from showing the its version number on 404s as an extra security measure by uncommenting the following in <code>/etc/nginx.conf</code>:</p>
172 <pre><code>server_tokens off</code></pre>
173 <p>Basically, if there are any zero-day vulnerabilities, this will hide what version I’m on if I was using an vulnerable version of nginx.</p>
174 <p>Run <code>nginx -t</code> to test my nginx configuration, and if there aren’t any issues, I restart nginx with <code>systemctl restart nginx</code>.</p>
175 <p>Next, to see if my website is actually working, I find the local/internal IP address of the server on my network, and type it into my browser. The test page we made earlier should be visible.</p>
176 <h3 id="configuring-the-router">Configuring the router</h3>
177 <p>Before I could try to view the test page from an external IP address, we have to forward ports. This took me a while to figure out, because I didn’t realize we were behind a double NAT.</p>
178 <p>This took several tries and a bit of reading to understand what was going on, but basically I had to forward port connections from my most-external router, to an internal router, and finally to the server.</p>
179 <p>Specifically, I had to:</p>
180 <ul>
181 <li>Forward external connections to my outer-most router on port 3222 to port 22 on my inner-most router, then from my inner-most router, I forward connections on port 22 to port 22 on my server.</li>
182 <li>Forward external connections to my outer-most router on port 443 to port 1443 on my inner-most router, then from my inner-most router, I forward connections on port 1443 to port 443 on my server.</li>
183 <li>Forward external connections to my outer-most router on port 80 to port 1080 on my inner-most router, then from my inner-most router, I forward connections on port 1080 to port 80 on my server.</li>
184 </ul>
185 <p>The reason I had to change to ports 1443 and 1080 mid-way through the port-fowarding for connections on ports 80 and 443 are because ports 80 and 443 on my internal router point to my router login page, which causes things to break. To avoid confusing configurations on my server, and allow myself to use regular ports like 22, 443, and 80, I just changed changed the internal router’s interpal port mapping to change the port numbers back to normal when they point back to my server.</p>
186 <p>If I were to make an awful diagram, it would look like this:</p>
187 <pre><code> ___
188 ___( )_
189 ___( )_
190 ( interwebz )
191 ---------------
192 |
193 connects through ports
194 3222 443 80
195 |
196 V
197 +--------------+
198 | first router |
199 +--------------+
200 |
201 first router forwards ports
202 3222 443 80
203 |
204 as
205 |
206 22 1433 1080
207 |
208 V
209 +---------------+
210 | second router |
211 +---------------+
212 |
213 second router forwards ports
214 22 1433 1080
215 |
216 as
217 |
218 22 443 80
219 |
220 V
221 +--------------+
222 | my server |
223 +--------------+</code></pre>
224 <p>In case you couldn’t tell, the interwebz shape is a cloud.</p>
225 <p>After doing this, I was able to go to a website like <a href=""></a> to look up my external IP address. I then took the external IP address, and tried to visit it in my browser. To my happy surprised, it worked! I could see the test HTML page I made at <code>/var/www/</code> earlier!</p>
226 <h3 id="pointing-my-domain-name-to-my-servers-ip-address">Pointing my domain name to my server’s IP address</h3>
227 <p>Next was to make my <code></code> domain point to my IP address!</p>
228 <p>… but wait! I have a dynamic IP address that changes all the time! How the hell am I going to do that?</p>
229 <p>Well let me tell you! We are going to make my server contact my domain name registrar, <a href=""></a> every 5 minutes to tell it my IP address!</p>
230 <p>Luckily Namecheap had <a href="">a handy article</a> on how to update your IP address from a browser, which means all we need to do is an HTTP request. The command-line tool <code>curl</code> can do that, because I download webpages and websites with it all the time!</p>
231 <p>First I had to go to the Namecheap dashboard, and click the “Domain List” button from the sidebar. Then I clicked “MANAGE” beside my <code></code> domain name.</p>
232 <p>From there, I had to go down to the “NAMESERVERS” section and change it to “Namecheap BasicDNS”, instead of the “Custom DNS” option I had selected that had allowed me to point to DigitalOcean’s name servers.</p>
233 <p>I then clicked the “Advanced DNS” button at the top of the webpage where I could add DNS records.</p>
234 <p>Here, I added the following entries:</p>
235 <ul>
236 <li>An “A + Dynamic DNS” record with the “Host” <code>@</code>, and the value <code></code>, and I left the TTL as “Automatic”.</li>
237 <li>I also added an “A + Dynamic DNS” record with the “Host” <code>*</code>, and the value <code></code> for any subdomains I wanted to add in the future.</li>
238 </ul>
239 <p>The reason I chose <code></code> as the “Value” for the records is because this value will be overwritten by my server’s external IP address later.</p>
240 <p>After adding each entry, Namecheap will show you a “Dynamic DNS Password” in the “DYNAMIC DNS” section. I found this section by scrolling down below the DNS record-setting section. Oh yeah, I had to switch the slide bar beside “Status” to turn on Dynamic DNS so I could set the records above.</p>
241 <h3 id="writing-a-script-to-update-my-dns-records">Writing a script to update my DNS records</h3>
242 <p>Okay, so, to make a script to update my DNS records with my current IP address, I SSHed into my server using its local IP address for now.</p>
243 <p>In my <code>m455</code> user’s home directory, I made a script called <code></code> with the following contents:</p>
244 <pre><code>#!/bin/sh
247 password=that-weird-long-dns-password-namecheap-gave-me
249 curl -s &quot;;domain=$domain&amp;password=$password&amp;&quot;
250 curl -s &quot;*&amp;domain=$domain&amp;password=$password&amp;&quot;</code></pre>
251 <p>Next, I had to make this run every 5 minutes, because I honestly don’t know how often my IP address changes, and 5 minutes of downtime doesn’t seem to bad if it ever wasn’t in sync. Plus, I don’t want to spam too much with excessive <code>curl</code> requests haha.</p>
252 <p>To do this, I ran <code>crontab -e</code> as my <code>m455</code> user to open its cronjobs. Cronjobs allow you to run things at specific intervals, and in my case, I wanted to run that <code></code> script every 5 minutes. To do this, I add the following contents to my <code>m455</code> user’s cronjobs:</p>
253 <pre><code># Update Namecheap with my current IP every 5 minutes
254 */5 * * * * /home/m455/ &gt;/dev/null 2&gt;&amp;1</code></pre>
255 <p>The reason I have <code>&gt;/dev/null 2&gt;&amp;1</code> there is so my system doesn’t send me local mail to my <code>m455</code> user about the output of the command every 5 minutes.</p>
256 <p>I then saved the <code>crontab</code> file, and exited. For fun, I ran the script with <code>./</code>, and went to check my DNS records on Namecheap to see if the <code></code>s were replaced with a new IP address, and they were! I was so happy, but I was also super sad quickly after, because when I went to <code></code> in my browser, it said the page didn’t exist.</p>
257 <p>After a bit of researching and asking friends, I learned that it takes time for DNS records to propagate to other internet service providers. I also found a little excerpt on that mentioned it can take up to one or two days to propagate.</p>
258 <p>I ended up checking my page every 10 minutes to see if anything on <code></code> would show up, but nothing did. I think all I added was a <code>&lt;h1&gt;hello there&lt;/h1&gt;</code> in the <code>index.html</code>, so it wouldn’t be hard to notice!</p>
259 <p>About 45 minutes passed by, and I grew impatient, and finally, around the 45-minute mark, I saw my silly <code>&lt;h1&gt;hello there&lt;/h1&gt;</code>! I was actually doing it! Serving a website from a computer in my home!</p>
260 <h3 id="getting-a-valid-tlsssl-certificate-for-https-access">Getting a valid TLS/SSL certificate for HTTPS access</h3>
261 <p>Next, I eagerly added <code></code> to my SSH <code>~/.ssh/config</code> file so I could just run <code>ssh</code>, instead of <code>ssh -i ~/.ssh/my-identity-file -p 3222</code>.</p>
262 <p>I then tried running <code>ssh</code>, and was greeted by Debian’s MOTD on my server! I was so happy I managed to do all of this.</p>
263 <p>All I had to do now was setup Let’s Encrypts <code>certbot</code> by running the following command on my Debian server as root to get the <code>certbot</code> tool:</p>
264 <pre><code>apt install python3-acme python3-certbot python3-mock python3-openssl python3-pkg-resources python3-pyparsing python3-zope.interface python3-certbot-nginx</code></pre>
265 <p>Then I ran the following command to setup certificates for my domain with the following command as root:</p>
266 <pre><code>certbot --nginx -d</code></pre>
267 <p>I actually got the information on how to do this from a <a href="">DigitalOcean guide</a>. Thank you again, DigitalOcean!</p>
268 <p>I then tried visiting <code></code> in a private browser tab, so it didn’t have the cache from when I tried to visit <code></code> in my browser early, and the good ol’ lock in my browser’s address bar was green! The certificate worked!</p>
269 <p>That’s my story of how I learned how to “home-host”. I hope you enjoyed that little adventure. I had fun writing it! A little too much fun… I should go back and edit this post later to check for mistakes haha. For now, I’ll post it for your enjoyment. Mistakes and all!</p>
270 </main>
271 </body>
272 </html>