From d5abf3541632c876d6121b3b1719d87740d3ee1e Mon Sep 17 00:00:00 2001
From: Martin Goik <goik@hdm-stuttgart.de>
Date: Tue, 4 Jun 2024 11:41:59 +0200
Subject: [PATCH] Base server creation enhancements

---
 Doc/Sdi/CloudProvider/gettingStarted.xml | 344 +++++++++++++++--------
 1 file changed, 221 insertions(+), 123 deletions(-)

diff --git a/Doc/Sdi/CloudProvider/gettingStarted.xml b/Doc/Sdi/CloudProvider/gettingStarted.xml
index 12d8f940..f1058eb3 100644
--- a/Doc/Sdi/CloudProvider/gettingStarted.xml
+++ b/Doc/Sdi/CloudProvider/gettingStarted.xml
@@ -137,8 +137,8 @@
                 like /, * and others do not work as expected. First try
                 finding the <quote>-</quote> symbol which might be tied to the
                 <quote>ß</quote> on a German keyboard. Keep in mind
-                <quote>z</quote> and <quote>y</quote> are probably swapped as
-                well. Overcoming all these obstacles enter:</para>
+                <quote>z</quote> and <quote>y</quote> keys are probably
+                swapped as well. Overcoming all these obstacles enter:</para>
 
                 <screen>dpkg-reconfigure keyboard-configuration</screen>
 
@@ -299,13 +299,22 @@
                 expected.</para>
               </listitem>
 
+              <listitem>
+                <para>ping your server and access it by <xref
+                linkend="glo_ssh"/> / password login rather than just using
+                the <orgname>Hetzner</orgname> GUI console. </para>
+              </listitem>
+
               <listitem>
                 <para>Congrats: Your first server is up and running. Do
-                whatever you feel so inclined.</para>
+                whatever else you feel so inclined.</para>
+              </listitem>
 
-                <para><emphasis role="red">Then delete it avoiding 10€ / Month
-                being billed to our department!</emphasis> You may re-create
-                it any time you like.</para>
+              <listitem>
+                <para><emphasis role="red">Finally delete your server avoiding
+                10€ / Month being billed to our department!</emphasis></para>
+
+                <para>(You may re-create it any time you like.)</para>
               </listitem>
             </orderedlist>
           </question>
@@ -359,143 +368,205 @@ Your public key has been saved in /home/sdiuser/.ssh/id_ed25519.pub <co
           <note>
             <para>Different implementations like e.g. <command
             xlink:href="https://www.putty.org">putty</command> may use
-            different key storage formats.</para>
+            different key storage formats being incompatible with <productname
+            xlink:href="https://www.openssh.com">Openssh</productname>
+            implementations. You require a conversion step.</para>
           </note>
         </callout>
       </calloutlist>
     </figure>
 
-    <figure xml:id="sdi_cloudProvider_webAdminGui_">
-      <title>Create a server</title>
+    <figure xml:id="sdi_cloudProvider_minimalServerIssues">
+      <title>Current server security flaws</title>
 
-      <informaltable border="0">
-        <tr>
-          <td valign="top"><orderedlist>
-              <listitem>
-                <para>Create a default firewall allowing <command
-                xlink:href="https://linux.die.net/man/8/ping">ping</command>
-                and <command
-                xlink:href="https://linux.die.net/man/1/ssh">ssh</command></para>
-              </listitem>
+      <itemizedlist>
+        <listitem>
+          <para>No updates, just (likely) outdated installation image</para>
+        </listitem>
 
-              <listitem>
-                <para><productname>Debian</productname> latest</para>
-              </listitem>
+        <listitem>
+          <para>Password based logins being notoriously prone to
+          attacks.</para>
 
-              <listitem>
-                <para>Shared vCPU / x86 / CX11 (<link
-                xlink:href="https://www.hetzner.com/cloud/#pricing">the
-                cheapest</link>)</para>
-              </listitem>
+          <para>Solution: Use public/private key based <xref
+          linkend="glo_ssh"/> login.</para>
+        </listitem>
+
+        <listitem>
+          <para>There is no firewall yet restricting network access.
+          Insecurely configured supplementary software components
+          <abbrev>e.g.</abbrev> database servers may lead to disaster.</para>
 
+          <para>Two choices:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para> Cloud provider level <link
+              xlink:href="https://docs.hetzner.com/cloud/firewalls">centralized
+              firewall</link>.</para>
+            </listitem>
+
+            <listitem>
+              <para>Host local firewall, e.g. <productname
+              xlink:href="https://wiki.ubuntu.com/UncomplicatedFirewall">Ufw</productname>.</para>
+            </listitem>
+          </itemizedlist>
+        </listitem>
+      </itemizedlist>
+    </figure>
+
+    <qandaset defaultlabel="qanda"
+              xml:id="sdi_cloudProvider_webAdminGui_quandaServerImproved">
+      <title>Improve your server!</title>
+
+      <qandadiv>
+        <qandaentry>
+          <question>
+            <para>Re-create your <xref
+            linkend="sdi_cloudProvider_webAdminGui_quandaFirstServer"/> server
+            solving (some of) its security flaws.</para>
+
+            <orderedlist>
               <listitem>
-                <para>Add your personal <command>ssh</command> public key from
-                <xref
-                linkend="sdi_cloudProvider_webAdminGui_createSshKeyPair"/></para>
+                <para>Create a firewall using the <orgname>Hetzner</orgname>
+                GUI accepting just the two default <xref linkend="glo_ssh"/>
+                and <acronym>ICMP</acronym> inbound access rules.</para>
               </listitem>
-            </orderedlist></td>
 
-          <td valign="top"><orderedlist continuation="continues">
               <listitem>
-                <para>Omit volume, labels and cloud configuration</para>
+                <para>Transfer your <link
+                linkend="sdi_cloudProvider_webAdminGui_createSshKeyPair">public
+                <acronym>ssh</acronym> key</link> to your
+                <orgname>Hetzner</orgname> account marking it as
+                <quote>default</quote>.</para>
               </listitem>
 
               <listitem>
-                <para>Note the <guimenuitem>Networking</guimenuitem> /
-                <guisubmenu>Public IPv4</guisubmenu> address for later
-                reference</para>
+                <para>Select both your newly created firewall and your <xref
+                linkend="glo_ssh"/> key during server creation. The subsequent
+                examples assumes a <emphasis
+                role="red">167.235.54.109</emphasis> server IP.</para>
               </listitem>
 
               <listitem>
-                <para>Click »Create &amp; Buy now«</para>
+                <para>Try to ping your server:</para>
+
+                <screen>$ <emphasis role="red">ping 167.235.54.109</emphasis>
+PING 167.235.54.109 (167.235.54.109) 56(84) bytes of data.
+64 bytes from 167.235.54.109: icmp_seq=1 ttl=54 time=13.2 ms
+64 bytes from 167.235.54.109: icmp_seq=2 ttl=54 time=12.3 ms
+^C
+--- 167.235.54.109 ping statistics ---
+2 packets transmitted, 2 received, 0% packet loss, time 1001ms
+rtt min/avg/max/mdev = 12.325/12.749/13.173/0.424 ms</screen>
               </listitem>
-            </orderedlist></td>
-        </tr>
-      </informaltable>
-    </figure>
-
-    <figure xml:id="sdi_cloudProvider_webAdminGui_accessServer">
-      <title>Access your server</title>
-
-      <itemizedlist>
-        <listitem>
-          <para>Ping your server:</para>
 
-          <note>
-            <para>The IP 91.107.232.156 serves just as a sample value
-            irrespective of your individual actual server IP.</para>
-          </note>
-
-          <screen>sdiuser:~$ ping 91.107.232.156
-PING 91.107.232.156 (91.107.232.156) 56(84) bytes of data.
-64 bytes from 91.107.232.156: icmp_seq=1 ttl=49 time=18.3 ms
-64 bytes from 91.107.232.156 ...</screen>
-        </listitem>
+              <listitem>
+                <para><xref linkend="glo_ssh"/> passwordless access should
+                work:</para>
 
-        <listitem>
-          <para>Login via <command>ssh</command>:</para>
+                <screen>$ <emphasis role="red">ssh root@167.235.54.109</emphasis>
+Linux gtest3 6.1.0-21-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.90-1 (2024-05-03) x86_64
 
-          <screen>ssh root@91.107.232.156</screen>
-        </listitem>
-      </itemizedlist>
-    </figure>
+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.
 
-    <figure xml:id="sdi_cloudProvider_webAdminGui_updateServer">
-      <title>Update and reboot</title>
+Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
+permitted by applicable law.
+Last login: Tue Jun  4 08:15:42 2024 from 217.245.243.187
 
-      <orderedlist>
-        <listitem>
-          <para>apt update</para>
-        </listitem>
+root@gtest3:~# <emphasis role="red">hostname</emphasis>
+gtest3</screen>
+              </listitem>
 
-        <listitem>
-          <para>apt upgrade</para>
-        </listitem>
+              <listitem>
+                <para>Update and reboot your server:</para>
 
-        <listitem>
-          <para>reboot</para>
-        </listitem>
-      </orderedlist>
-    </figure>
+                <screen># <emphasis role="red">apt update &amp;&amp; apt upgrade</emphasis>
+Get:1 http://mirror.hetzner.com/debian/packages bookworm InRelease [151 kB]
+Get:2 http://deb.debian.org/debian bookworm InRelease [151 kB]                                                        
+Get:3 http://deb.debian.org/debian bookworm-updates InRelease [55.4 kB] 
+...           </screen>
+              </listitem>
 
-    <figure xml:id="sdi_cloudProvider_webAdminGui_installNginx">
-      <title>Install a web server</title>
+              <listitem>
+                <para>Install the <productname
+                xlink:href="https://docs.nginx.com/nginx/admin-guide/web-server">nginx</productname>
+                webserver:</para>
 
-      <screen>root@topsy:~# apt install nginx</screen>
-    </figure>
+                <screen># <emphasis role="red">apt install nginx</emphasis>
+Reading package lists... Done
+Building dependency tree... Done
+...
+Do you want to continue? [Y/n] y
+Get:1 http://deb.debian.org/debian bookworm/main amd64 nginx-common all 1.22.1-9 [112 kB]
+Get:2 http://deb.debian.org/debian bookworm/main amd64 nginx amd64 1.22.1-9 [527 kB]
+...
+Processing triggers for man-db (2.11.2-2) ...</screen>
+
+                <para>Check for the running process:</para>
+
+                <screen># <emphasis role="red">systemctl status nginx</emphasis>
+● nginx.service - A high performance web server and a reverse proxy server
+     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
+     Active: active (running) since Tue 2024-06-04 08:24:57 UTC; 1min 31s ago
+       Docs: man:nginx(8)
+    Process: 1558 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
+    Process: 1559 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
+   Main PID: 1582 (nginx)
+      Tasks: 2 (limit: 2251)
+     Memory: 1.8M
+        CPU: 22ms
+     CGroup: /system.slice/nginx.service
+             ├─1582 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
+             └─1583 "nginx: worker process"</screen>
+              </listitem>
 
-    <figure xml:id="sdi_cloudProvider_webAdminGui_localHttpAccess">
-      <title>Check local <acronym>http</acronym> web access</title>
+              <listitem>
+                <para>Use <command
+                xlink:href="https://linux.die.net/man/1/wget">wget</command>
+                for locally accessing <emphasis
+                role="red">http://167.235.54.109</emphasis> verifying <xref
+                linkend="glo_HTTP"/> (port 80) accessibility from your host
+                machine:</para>
+
+                <screen># <emphasis role="red">wget -O - http://167.235.54.109</emphasis>
+--2024-06-04 09:02:41--  http://167.235.54.109/
+Connecting to 167.235.54.109:80... connected.
+HTTP request sent, awaiting response... 200 OK
+Length: 615 [text/html]
+Saving to: ‘STDOUT’
 
-      <screen>root@topsy:~# wget -O - 91.107.232.156
---2024-04-07 18:59:13--  http://91.107.232.156/
-Connecting to 91.107.232.156:80... connected.
 &lt;html&gt;
 &lt;head&gt;
-&lt;title&gt;Welcome to nginx!&lt;/title&gt; ...</screen>
-    </figure>
-
-    <figure xml:id="sdi_cloudProvider_cloudAdminGui_externHttp">
-      <title>External <acronym>http</acronym> web access</title>
-
-      <para>Point your browser to http://91.107.232.156.</para>
-
-      <screen>sdiuser:~$ telnet 91.107.232.156 80
-Trying 91.107.232.156...</screen>
-
-      <para>Why is there no answer?</para>
-    </figure>
+&lt;title&gt;Welcome to nginx!&lt;/title&gt;
+            ...
+&lt;p&gt;&lt;em&gt;Thank you for using nginx.&lt;/em&gt;&lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;</screen>
+              </listitem>
 
-    <figure xml:id="sdi_cloudProvider_cloudAdminGui_allowHttp">
-      <title>Add port 80 / <acronym>http</acronym> firewall rule</title>
+              <listitem>
+                <para>Try external access using <emphasis
+                role="red">http://167.235.54.109</emphasis> again in your
+                browser of choice.</para>
 
-      <screen>sdiuser:~$ telnet 91.107.232.156 80
-Trying 91.107.232.156...
-Connected to 91.107.232.156.
-Escape character is '^]'</screen>
+                <para>Why does external access fail although local access
+                works? </para>
+              </listitem>
 
-      <para>Congrats: External Browser access is working now!</para>
-    </figure>
+              <listitem>
+                <para>Modify your firewall adding an inbound <xref
+                linkend="glo_HTTP"/> traffic rule and repeat accessing
+                <emphasis role="red">http://167.235.54.109</emphasis> in your
+                browser.</para>
+              </listitem>
+            </orderedlist>
+          </question>
+        </qandaentry>
+      </qandadiv>
+    </qandaset>
 
     <figure xml:id="sdi_cloudProvider_cloudAdminGui_cleanUp">
       <title>Cleaning up!</title>
@@ -511,7 +582,7 @@ Escape character is '^]'</screen>
         </listitem>
 
         <listitem>
-          <para>You may delete your firewall</para>
+          <para>You may optionally delete your firewall.</para>
         </listitem>
       </itemizedlist>
     </figure>
@@ -601,7 +672,7 @@ provider "hcloud" {
 }
 
 # Create a server
-resource "hcloud_server" "helloServer" {
+resource "hcloud_server" "<emphasis role="red">helloServer</emphasis>" {
   name         = "hello"
   image        =  "debian-12"
   server_type  =  "cx11"   
@@ -612,7 +683,7 @@ resource "hcloud_server" "helloServer" {
       <title><productname>Terraform</productname> <command
       xlink:href="https://developer.hashicorp.com/terraform/cli/commands/init">init</command></title>
 
-      <programlisting language="terraform">$ terraform <command
+      <screen language="terraform">$ <emphasis role="red">terraform</emphasis> <command
           xlink:href="https://developer.hashicorp.com/terraform/cli/commands/init">init</command>
 
 Initializing the backend...
@@ -624,14 +695,14 @@ Initializing provider plugins...
 
 ...
 Terraform has created a lock file .terraform.lock.hcl to record the provider
-selections it made above.  ...</programlisting>
+selections it made above.  ...</screen>
     </figure>
 
     <figure xml:id="sdi_cloudProvider_terra_plan">
       <title><productname>Terraform</productname> <command
       xlink:href="https://developer.hashicorp.com/terraform/cli/commands/plan">plan</command></title>
 
-      <programlisting language="terraform">$ terraform <command
+      <screen language="terraform">$ <emphasis role="red">terraform</emphasis> <command
           xlink:href="https://developer.hashicorp.com/terraform/cli/commands/plan">plan</command>
 
 Terraform used the selected providers to generate the following execution plan. Resource actions ...
@@ -646,14 +717,14 @@ Terraform will perform the following actions:
   ...
     }
 
-Plan: 1 to add, 0 to change, 0 to destroy.</programlisting>
+Plan: 1 to add, 0 to change, 0 to destroy.</screen>
     </figure>
 
     <figure xml:id="sdi_cloudProvider_terra_apply">
       <title><productname>Terraform</productname> <command
       xlink:href="https://developer.hashicorp.com/terraform/cli/commands/apply">apply</command></title>
 
-      <programlisting language="terraform">$ terraform <command
+      <screen language="terraform">$ <emphasis role="red">terraform</emphasis> <command
           xlink:href="https://developer.hashicorp.com/terraform/cli/commands/apply">apply</command>
 ...
 Plan: 1 to add, 0 to change, 0 to destroy.
@@ -668,7 +739,7 @@ hcloud_server.helloServer: Creating...
 hcloud_server.helloServer: Still creating... [10s elapsed]
 hcloud_server.helloServer: Creation complete after 14s [id=45822789]
 
-Apply complete! Resources: 1 added, 0 changed, 0 destroyed.</programlisting>
+Apply complete! Resources: 1 added, 0 changed, 0 destroyed.</screen>
     </figure>
 
     <figure xml:id="sdi_cloudProvider_terra_hello_email">
@@ -764,6 +835,9 @@ resource "hcloud_server" "helloServer" {
               ...
   ssh_keys     = [hcloud_ssh_key.<emphasis role="red">loginUser</emphasis>.id]
 }</programlisting>
+
+      <para>Note: Remove any conflicting manually installed keys
+      beforehand.</para>
     </figure>
 
     <figure xml:id="sdi_cloudProvider_terra_hello_sshApply">
@@ -771,7 +845,8 @@ resource "hcloud_server" "helloServer" {
       xlink:href="https://linux.die.net/man/1/ssh">ssh</command> key
       access</title>
 
-      <screen>$ terraform apply
+      <screen>$ <emphasis role="red">terraform</emphasis> <command
+          xlink:href="https://developer.hashicorp.com/terraform/cli/commands/apply">apply</command>
 
   # hcloud_firewall.sshFw will be created
   + resource "hcloud_firewall" "sshFw" {
@@ -812,13 +887,15 @@ output "hello_datacenter" {
   description = "The server's datacenter"
 }</programlisting></td>
 
-          <td valign="top"><screen language="properties">$ <command>terraform</command> output
+          <td valign="top"><screen language="properties">$ <command>terraform</command> <command
+                xlink:href="https://developer.hashicorp.com/terraform/cli/commands/output">output</command>
 hello_datacenter = "nbg1-dc3"
 hello_ip_addr = "159.69.152.37"</screen></td>
         </tr>
 
         <tr>
-          <td valign="top"><screen language="properties">$ <command>terraform</command> output hello_ip_addr
+          <td valign="top"><screen language="properties">$ <command>terraform</command> <command
+                xlink:href="https://developer.hashicorp.com/terraform/cli/commands/output">output</command> hello_ip_addr
 "159.69.152.37"</screen></td>
         </tr>
       </informaltable>
@@ -895,8 +972,8 @@ provider "hcloud" { token = "<emphasis role="red">xdaGfz9LmwO8SWkg ... </emphasi
       </itemizedlist>
     </figure>
 
-    <figure xml:id="sdi_cloudProvider_terra_hello_sshProblemApiTokenSolve">
-      <title>Solution</title>
+    <figure xml:id="sdi_cloudProvider_terra_hello_sshProblemApiTokenSolveVariable">
+      <title>Solution by variable</title>
 
       <informaltable border="0">
         <tr>
@@ -921,13 +998,33 @@ provider "hcloud" { token = "<emphasis role="red">xdaGfz9LmwO8SWkg ... </emphasi
           language="terraform">provider "hcloud" { token = var.<emphasis
                 role="red">hcloud_token</emphasis> }</programlisting></td>
 
-          <td valign="top"><para>Example in
+          <td valign="top"><para>Template file
           <filename>secrets.auto.tfvars.template:</filename></para><programlisting
           language="terraform"><emphasis role="red">hcloud_token</emphasis>="your_api_token_goes_here"</programlisting></td>
         </tr>
       </informaltable>
     </figure>
 
+    <figure xml:id="sdi_cloudProvider_terra_hello_sshProblemApiTokenSolveFile">
+      <title>Solution by file</title>
+
+      <informaltable border="0">
+        <tr>
+          <td valign="top"><programlisting language="terraform"># Configure the Hetzner Cloud API token
+provider "hcloud" {
+  token = file("../providertoken.key")
+}</programlisting></td>
+
+          <td valign="top"><para>Content of file
+          <filename>providertoken.key</filename>:</para><programlisting
+          language="terraform">xdaGfz9LmwO8SWkg ...</programlisting><para>Content
+          of file
+          <filename>providertoken.key.template</filename>:</para><programlisting
+          language="terraform">your_api_token_goes_here</programlisting></td>
+        </tr>
+      </informaltable>
+    </figure>
+
     <qandaset defaultlabel="qanda"
               xml:id="sdi_cloudProvider_terra_qandaBasicSystem">
       <title>Incrementally creating a base system</title>
@@ -958,7 +1055,7 @@ provider "hcloud" { token = "<emphasis role="red">xdaGfz9LmwO8SWkg ... </emphasi
                 previous <xref linkend="glo_Terraform"/> configuration might
                 expose your cloud provider's API token. Circumvent this
                 problem by following the steps outlined in <xref
-                linkend="sdi_cloudProvider_terra_hello_sshProblemApiTokenSolve"/>.</para>
+                linkend="sdi_cloudProvider_terra_hello_sshProblemApiTokenSolveFile"/>.</para>
               </listitem>
 
               <listitem>
@@ -994,7 +1091,8 @@ provider "hcloud" { token = "<emphasis role="red">xdaGfz9LmwO8SWkg ... </emphasi
                 xlink:href="https://developer.hashicorp.com/terraform/cli/commands/apply">terraform
                 apply</command> you should see something like:</para>
 
-                <screen>terraform apply
+                <screen><emphasis role="red">terraform</emphasis> <command
+                    xlink:href="https://developer.hashicorp.com/terraform/cli/commands/apply">apply</command>
 ...
 hcloud_server.helloServer: Still creating... [10s elapsed]
 hcloud_server.helloServer: Creation complete after 14s [id=46961197]
-- 
GitLab