diff --git a/LateX/main.aux b/LateX/main.aux index 26649f1..f152d12 100644 --- a/LateX/main.aux +++ b/LateX/main.aux @@ -10,108 +10,260 @@ \babel@aux{ngerman}{} \BKM@entry{id=1,dest={73656374696F6E2E31},srcline={5}}{5C3337365C3337375C303030535C303030655C303030725C303030765C303030655C303030725C3030302D5C303030415C303030625C303030735C303030695C303030635C303030685C303030655C303030725C303030755C3030306E5C303030675C3030305C3034305C3030305C3035305C303030555C303030625C303030755C3030306E5C303030745C303030755C3030305C3034305C303030325C303030345C3030302E5C303030305C303030345C3030305C3034305C303030615C303030755C303030665C3030305C3034305C303030435C3030306F5C3030306E5C303030745C303030615C303030625C3030306F5C3030305C3034305C303030565C303030505C303030535C3030305C303531} \BKM@entry{id=2,dest={73756273656374696F6E2E312E31},srcline={28}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030315C3030303A5C3030305C3034305C303030535C303030535C303030485C3030302D5C303030565C303030655C303030725C303030625C303030695C3030306E5C303030645C303030755C3030306E5C303030675C3030305C3034305C303030745C303030655C303030735C303030745C303030655C3030306E} -\@writefile{toc}{\contentsline {section}{\numberline {1}Server-Absicherung (Ubuntu 24.04 auf Contabo VPS)}{3}{section.1}\protected@file@percent } -\newlabel{sec:step01}{{1}{3}{Server-Absicherung (Ubuntu 24.04 auf Contabo VPS)}{section.1}{}} -\@writefile{toc}{\contentsline {subsection}{\numberline {1.1}Schritt 1: SSH-Verbindung testen}{3}{subsection.1.1}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {1}SSH-Verbindung zum Server aufbauen}{3}{lstlisting.1}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {2}WARNUNG: REMOTE HOST IDENTIFICATION HAS CHANGED}{3}{lstlisting.2}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {1}Server-Absicherung (Ubuntu 24.04 auf Contabo VPS)}{4}{section.1}\protected@file@percent } +\newlabel{sec:step01}{{1}{4}{Server-Absicherung (Ubuntu 24.04 auf Contabo VPS)}{section.1}{}} +\@writefile{toc}{\contentsline {subsection}{\numberline {1.1}Schritt 1: SSH-Verbindung testen}{4}{subsection.1.1}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {1}SSH-Verbindung zum Server aufbauen}{4}{lstlisting.1}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {2}WARNUNG: REMOTE HOST IDENTIFICATION HAS CHANGED}{4}{lstlisting.2}\protected@file@percent } \BKM@entry{id=3,dest={73756273656374696F6E2E312E32},srcline={67}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030325C3030303A5C3030305C3034305C303030535C303030795C303030735C303030745C303030655C3030306D5C3030302D5C303030555C303030705C303030645C303030615C303030745C303030655C30303073} \BKM@entry{id=4,dest={73756273656374696F6E2E312E33},srcline={88}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030335C3030303A5C3030305C3034305C303030535C303030535C303030485C3030302D5C3030304B5C303030655C303030795C3030302D5C303030415C303030755C303030745C303030685C303030655C3030306E5C303030745C303030695C303030665C303030695C3030307A5C303030695C303030655C303030725C303030755C3030306E5C30303067} -\@writefile{lol}{\contentsline {lstlisting}{\numberline {3}Alten SSH-Fingerabdruck entfernen}{4}{lstlisting.3}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {1.2}Schritt 2: System-Updates}{4}{subsection.1.2}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {4}System-Updates ausführen}{4}{lstlisting.4}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {1.3}Schritt 3: SSH-Key-Authentifizierung}{4}{subsection.1.3}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {5}SSH-Key generieren}{4}{lstlisting.5}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {3}Alten SSH-Fingerabdruck entfernen}{5}{lstlisting.3}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {1.2}Schritt 2: System-Updates}{5}{subsection.1.2}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {4}System-Updates ausführen}{5}{lstlisting.4}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {1.3}Schritt 3: SSH-Key-Authentifizierung}{5}{subsection.1.3}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {5}SSH-Key generieren}{5}{lstlisting.5}\protected@file@percent } \BKM@entry{id=5,dest={73756273656374696F6E2E312E34},srcline={132}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030345C3030303A5C3030305C3034305C303030535C303030535C303030485C3030302D5C303030435C3030306C5C303030695C303030655C3030306E5C303030745C3030302D5C3030304B5C3030306F5C3030306E5C303030665C303030695C303030675C303030755C303030725C303030615C303030745C303030695C3030306F5C3030306E5C3030305C3034305C3030305C3035305C303030415C3030306C5C303030695C303030615C303030735C3030305C303531} \BKM@entry{id=6,dest={73756273656374696F6E2E312E35},srcline={169}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030355C3030303A5C3030305C3034305C303030535C303030535C303030485C3030302D5C303030545C303030695C3030306D5C303030655C3030306F5C303030755C303030745C3030305C3034305C303030615C303030755C303030665C3030305C3034305C303030325C303030305C3030305C3034305C3030304D5C303030695C3030306E5C303030755C303030745C303030655C3030306E} -\@writefile{lol}{\contentsline {lstlisting}{\numberline {6}Public Key auf den Server übertragen}{5}{lstlisting.6}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {7}Login ohne Passwort testen}{5}{lstlisting.7}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {1.4}Schritt 4: SSH-Client-Konfiguration (Alias)}{5}{subsection.1.4}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {8}SSH-Konfiguration bearbeiten}{5}{lstlisting.8}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {9}Inhalt von \textasciitilde /.ssh/config}{5}{lstlisting.9}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {10}Mit Alias verbinden}{5}{lstlisting.10}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {6}Public Key auf den Server übertragen}{6}{lstlisting.6}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {7}Login ohne Passwort testen}{6}{lstlisting.7}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {1.4}Schritt 4: SSH-Client-Konfiguration (Alias)}{6}{subsection.1.4}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {8}SSH-Konfiguration bearbeiten}{6}{lstlisting.8}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {9}Inhalt von \textasciitilde /.ssh/config}{6}{lstlisting.9}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {10}Mit Alias verbinden}{6}{lstlisting.10}\protected@file@percent } \BKM@entry{id=7,dest={73756273656374696F6E2E312E36},srcline={203}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030365C3030303A5C3030305C3034305C303030465C303030615C303030695C3030306C5C303030325C303030425C303030615C3030306E5C3030305C3034305C3030305C3035305C303030425C303030725C303030755C303030745C303030655C303030665C3030306F5C303030725C303030635C303030655C3030302D5C303030535C303030635C303030685C303030755C303030745C3030307A5C3030305C303531} -\@writefile{toc}{\contentsline {subsection}{\numberline {1.5}Schritt 5: SSH-Timeout auf 20 Minuten}{6}{subsection.1.5}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {11}SSH-Server-Konfiguration bearbeiten}{6}{lstlisting.11}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {12}Timeout-Konfiguration}{6}{lstlisting.12}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {13}SSH-Dienst neustarten}{6}{lstlisting.13}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {1.6}Schritt 6: Fail2Ban (Bruteforce-Schutz)}{6}{subsection.1.6}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {1.5}Schritt 5: SSH-Timeout auf 20 Minuten}{7}{subsection.1.5}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {11}SSH-Server-Konfiguration bearbeiten}{7}{lstlisting.11}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {12}Timeout-Konfiguration}{7}{lstlisting.12}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {13}SSH-Dienst neustarten}{7}{lstlisting.13}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {1.6}Schritt 6: Fail2Ban (Bruteforce-Schutz)}{7}{subsection.1.6}\protected@file@percent } \BKM@entry{id=8,dest={73756273656374696F6E2E312E37},srcline={258}}{5C3337365C3337375C3030305A5C303030755C303030735C303030615C3030306D5C3030306D5C303030655C3030306E5C303030665C303030615C303030735C303030735C303030755C3030306E5C30303067} \BKM@entry{id=9,dest={73656374696F6E2E32},srcline={5}}{5C3337365C3337375C303030465C303030695C303030725C303030655C303030775C303030615C3030306C5C3030306C5C3030305C3034305C3030306D5C303030695C303030745C3030305C3034305C303030555C303030465C303030575C3030305C3034305C303030655C303030695C3030306E5C303030725C303030695C303030635C303030685C303030745C303030655C3030306E} \BKM@entry{id=10,dest={73756273656374696F6E2E322E31},srcline={10}}{5C3337365C3337375C303030575C303030615C303030735C3030305C3034305C303030695C303030735C303030745C3030305C3034305C303030655C303030695C3030306E5C303030655C3030305C3034305C303030465C303030695C303030725C303030655C303030775C303030615C3030306C5C3030306C5C3030305C3034305C303030755C3030306E5C303030645C3030305C3034305C303030775C303030615C303030725C303030755C3030306D5C3030305C3034305C303030625C303030725C303030615C303030755C303030635C303030685C303030655C3030306E5C3030305C3034305C303030775C303030695C303030725C3030305C3034305C303030735C303030695C303030655C3030303F} -\@writefile{lol}{\contentsline {lstlisting}{\numberline {14}Beispiel: /etc/fail2ban/jail.local}{7}{lstlisting.14}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {15}Fail2Ban installieren}{7}{lstlisting.15}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {16}Fail2Ban aktivieren und starten}{7}{lstlisting.16}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {17}Fail2Ban-Status abfragen}{7}{lstlisting.17}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {18}Erfolgreiche Ausgabe}{7}{lstlisting.18}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {1.7}Zusammenfassung}{7}{subsection.1.7}\protected@file@percent } -\@writefile{toc}{\contentsline {section}{\numberline {2}Firewall mit UFW einrichten}{7}{section.2}\protected@file@percent } -\newlabel{sec:step02}{{2}{7}{Firewall mit UFW einrichten}{section.2}{}} +\@writefile{lol}{\contentsline {lstlisting}{\numberline {14}Beispiel: /etc/fail2ban/jail.local}{8}{lstlisting.14}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {15}Fail2Ban installieren}{8}{lstlisting.15}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {16}Fail2Ban aktivieren und starten}{8}{lstlisting.16}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {17}Fail2Ban-Status abfragen}{8}{lstlisting.17}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {18}Erfolgreiche Ausgabe}{8}{lstlisting.18}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {1.7}Zusammenfassung}{8}{subsection.1.7}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {2}Firewall mit UFW einrichten}{8}{section.2}\protected@file@percent } +\newlabel{sec:step02}{{2}{8}{Firewall mit UFW einrichten}{section.2}{}} \BKM@entry{id=11,dest={73756273656374696F6E2E322E32},srcline={21}}{5C3337365C3337375C303030445C303030695C303030655C3030305C3034305C303030365C303030355C3030302E5C303030355C303030335C303030355C3030305C3034305C303030505C3030306F5C303030725C303030745C303030735C3030303A5C3030305C3034305C303030455C303030695C3030306E5C3030305C3034305C3030306B5C303030755C303030725C3030307A5C303030655C303030725C3030305C3034305C3030305C3333345C303030625C303030655C303030725C303030625C3030306C5C303030695C303030635C3030306B} \BKM@entry{id=12,dest={73756273656374696F6E2E322E33},srcline={52}}{5C3337365C3337375C303030445C303030695C303030655C3030305C3034305C303030645C303030725C303030655C303030695C3030305C3034305C303030505C3030306F5C303030725C303030745C303030735C3030302C5C3030305C3034305C303030645C303030695C303030655C3030305C3034305C303030775C303030695C303030725C3030305C3034305C3030305C3336365C303030665C303030665C3030306E5C303030655C3030306E} \BKM@entry{id=13,dest={73756273656374696F6E2E322E34},srcline={70}}{5C3337365C3337375C303030575C303030615C303030725C303030755C3030306D5C3030305C3034305C303030485C303030545C303030545C303030505C303030535C3030305C3034305C303030665C3030305C3337345C303030725C3030305C3034305C303030505C303030575C303030415C303030735C3030305C3034305C303030505C303030665C3030306C5C303030695C303030635C303030685C303030745C3030305C3034305C303030695C303030735C30303074} -\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Was ist eine Firewall und warum brauchen wir sie?}{8}{subsection.2.1}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Die 65.535 Ports: Ein kurzer Überblick}{8}{subsection.2.2}\protected@file@percent } -\@writefile{lot}{\contentsline {table}{\numberline {1}{\ignorespaces Bekannte Ports und ihre Dienste}}{8}{table.1}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {2.3}Die drei Ports, die wir öffnen}{8}{subsection.2.3}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {2.4}Warum HTTPS für PWAs Pflicht ist}{8}{subsection.2.4}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Was ist eine Firewall und warum brauchen wir sie?}{9}{subsection.2.1}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Die 65.535 Ports: Ein kurzer Überblick}{9}{subsection.2.2}\protected@file@percent } +\@writefile{lot}{\contentsline {table}{\numberline {1}{\ignorespaces Bekannte Ports und ihre Dienste}}{9}{table.1}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {2.3}Die drei Ports, die wir öffnen}{9}{subsection.2.3}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {2.4}Warum HTTPS für PWAs Pflicht ist}{9}{subsection.2.4}\protected@file@percent } \BKM@entry{id=14,dest={73756273656374696F6E2E322E35},srcline={82}}{5C3337365C3337375C303030445C303030755C303030725C303030635C303030685C303030665C3030305C3337345C303030685C303030725C303030755C3030306E5C30303067} \BKM@entry{id=15,dest={73756273756273656374696F6E2E322E352E31},srcline={84}}{5C3337365C3337375C303030535C303030745C303030615C3030306E5C303030645C303030615C303030725C303030645C303030725C303030695C303030635C303030685C303030745C3030306C5C303030695C3030306E5C303030695C303030655C3030306E5C3030305C3034305C303030735C303030655C303030745C3030307A5C303030655C3030306E} -\@writefile{lot}{\contentsline {table}{\numberline {2}{\ignorespaces Geöffnete Ports und ihre Begründung}}{9}{table.2}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {2.5}Durchführung}{9}{subsection.2.5}\protected@file@percent } -\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.5.1}Standardrichtlinien setzen}{9}{subsubsection.2.5.1}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {19}Firewall-Standardregeln definieren}{9}{lstlisting.19}\protected@file@percent } +\@writefile{lot}{\contentsline {table}{\numberline {2}{\ignorespaces Geöffnete Ports und ihre Begründung}}{10}{table.2}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {2.5}Durchführung}{10}{subsection.2.5}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.5.1}Standardrichtlinien setzen}{10}{subsubsection.2.5.1}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {19}Firewall-Standardregeln definieren}{10}{lstlisting.19}\protected@file@percent } \BKM@entry{id=16,dest={73756273756273656374696F6E2E322E352E32},srcline={105}}{5C3337365C3337375C303030425C303030655C3030306E5C3030305C3336365C303030745C303030695C303030675C303030745C303030655C3030305C3034305C303030505C3030306F5C303030725C303030745C303030735C3030305C3034305C3030305C3336365C303030665C303030665C3030306E5C303030655C3030306E} \BKM@entry{id=17,dest={73756273756273656374696F6E2E322E352E33},srcline={125}}{5C3337365C3337375C303030465C303030695C303030725C303030655C303030775C303030615C3030306C5C3030306C5C3030305C3034305C303030615C3030306B5C303030745C303030695C303030765C303030695C303030655C303030725C303030655C3030306E} \BKM@entry{id=18,dest={73756273756273656374696F6E2E322E352E34},srcline={141}}{5C3337365C3337375C3030304B5C3030306F5C3030306E5C303030665C303030695C303030675C303030755C303030725C303030615C303030745C303030695C3030306F5C3030306E5C3030305C3034305C3030305C3337345C303030625C303030655C303030725C303030705C303030725C3030305C3337345C303030665C303030655C3030306E} -\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.5.2}Benötigte Ports öffnen}{10}{subsubsection.2.5.2}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {20}Ports 22, 80, 443 für TCP freigeben}{10}{lstlisting.20}\protected@file@percent } -\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.5.3}Firewall aktivieren}{10}{subsubsection.2.5.3}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {21}Firewall aktivieren}{10}{lstlisting.21}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.5.2}Benötigte Ports öffnen}{11}{subsubsection.2.5.2}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {20}Ports 22, 80, 443 für TCP freigeben}{11}{lstlisting.20}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.5.3}Firewall aktivieren}{11}{subsubsection.2.5.3}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {21}Firewall aktivieren}{11}{lstlisting.21}\protected@file@percent } \BKM@entry{id=19,dest={73756273656374696F6E2E322E36},srcline={179}}{5C3337365C3337375C3030305A5C303030755C303030735C303030615C3030306D5C3030306D5C303030655C3030306E5C303030665C303030615C303030735C303030735C303030755C3030306E5C30303067} \BKM@entry{id=20,dest={73656374696F6E2E33},srcline={5}}{5C3337365C3337375C303030445C3030306F5C303030635C3030306B5C303030655C303030725C3030302D5C303030495C3030306D5C303030615C303030675C303030655C303030735C3030305C3034305C303030625C303030615C303030755C303030655C3030306E5C3030305C3034305C303030755C3030306E5C303030645C3030305C3034305C303030415C303030705C303030705C3030305C3034305C303030645C303030655C303030705C3030306C5C3030306F5C303030795C303030655C3030306E} -\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.5.4}Konfiguration überprüfen}{11}{subsubsection.2.5.4}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {22}Firewall-Status mit Details anzeigen}{11}{lstlisting.22}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {23}Erwartete Firewall-Ausgabe (gekürzt)}{11}{lstlisting.23}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {2.6}Zusammenfassung}{11}{subsection.2.6}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.5.4}Konfiguration überprüfen}{12}{subsubsection.2.5.4}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {22}Firewall-Status mit Details anzeigen}{12}{lstlisting.22}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {23}Erwartete Firewall-Ausgabe (gekürzt)}{12}{lstlisting.23}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {2.6}Zusammenfassung}{12}{subsection.2.6}\protected@file@percent } \BKM@entry{id=21,dest={73756273656374696F6E2E332E31},srcline={10}}{5C3337365C3337375C303030575C303030615C303030735C3030305C3034305C303030695C303030735C303030745C3030305C3034305C303030445C3030306F5C303030635C3030306B5C303030655C303030725C3030305C3034305C303030755C3030306E5C303030645C3030305C3034305C303030775C303030615C303030725C303030755C3030306D5C3030305C3034305C3030306E5C303030755C303030745C3030307A5C303030655C3030306E5C3030305C3034305C303030775C303030695C303030725C3030305C3034305C303030655C303030735C3030303F} \BKM@entry{id=22,dest={73756273656374696F6E2E332E32},srcline={27}}{5C3337365C3337375C303030445C303030695C303030655C3030305C3034305C303030645C303030725C303030655C303030695C3030305C3034305C303030445C3030306F5C303030635C3030306B5C303030655C303030725C303030665C303030695C3030306C5C303030655C303030735C3030305C3034305C303030695C3030306D5C3030305C3034305C303030445C303030655C303030745C303030615C303030695C3030306C} \BKM@entry{id=23,dest={73756273756273656374696F6E2E332E322E31},srcline={29}}{5C3337365C3337375C303030425C303030615C303030635C3030306B5C303030655C3030306E5C303030645C3030302D5C303030445C3030306F5C303030635C3030306B5C303030655C303030725C303030665C303030695C3030306C5C303030655C3030303A5C3030305C3034305C303030615C303030705C303030705C303030735C3030302F5C303030615C303030705C303030695C3030302F5C303030445C3030306F5C303030635C3030306B5C303030655C303030725C303030665C303030695C3030306C5C30303065} -\@writefile{toc}{\contentsline {section}{\numberline {3}Docker-Images bauen und App deployen}{12}{section.3}\protected@file@percent } -\newlabel{sec:step03}{{3}{12}{Docker-Images bauen und App deployen}{section.3}{}} -\@writefile{toc}{\contentsline {subsection}{\numberline {3.1}Was ist Docker und warum nutzen wir es?}{12}{subsection.3.1}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {3.2}Die drei Dockerfiles im Detail}{12}{subsection.3.2}\protected@file@percent } -\@writefile{toc}{\contentsline {subsubsection}{\numberline {3.2.1}Backend-Dockerfile: \texttt {apps/api/Dockerfile}}{12}{subsubsection.3.2.1}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {24}Dockerfile für das .NET Backend}{12}{lstlisting.24}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {3}Docker-Images bauen und App deployen}{13}{section.3}\protected@file@percent } +\newlabel{sec:step03}{{3}{13}{Docker-Images bauen und App deployen}{section.3}{}} +\@writefile{toc}{\contentsline {subsection}{\numberline {3.1}Was ist Docker und warum nutzen wir es?}{13}{subsection.3.1}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {3.2}Die drei Dockerfiles im Detail}{13}{subsection.3.2}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {3.2.1}Backend-Dockerfile: \texttt {apps/api/Dockerfile}}{13}{subsubsection.3.2.1}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {24}Dockerfile für das .NET Backend}{13}{lstlisting.24}\protected@file@percent } \BKM@entry{id=24,dest={73756273756273656374696F6E2E332E322E32},srcline={64}}{5C3337365C3337375C303030465C303030725C3030306F5C3030306E5C303030745C303030655C3030306E5C303030645C3030302D5C303030445C3030306F5C303030635C3030306B5C303030655C303030725C303030665C303030695C3030306C5C303030655C3030303A5C3030305C3034305C303030615C303030705C303030705C303030735C3030302F5C303030775C303030655C303030625C3030302F5C303030445C3030306F5C303030635C3030306B5C303030655C303030725C303030665C303030695C3030306C5C30303065} -\@writefile{toc}{\contentsline {subsubsection}{\numberline {3.2.2}Frontend-Dockerfile: \texttt {apps/web/Dockerfile}}{13}{subsubsection.3.2.2}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {25}Dockerfile für das React Frontend}{13}{lstlisting.25}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {3.2.2}Frontend-Dockerfile: \texttt {apps/web/Dockerfile}}{14}{subsubsection.3.2.2}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {25}Dockerfile für das React Frontend}{14}{lstlisting.25}\protected@file@percent } \BKM@entry{id=25,dest={73756273756273656374696F6E2E332E322E33},srcline={99}}{5C3337365C3337375C3030304E5C303030675C303030695C3030306E5C303030785C3030302D5C3030304B5C3030306F5C3030306E5C303030665C303030695C303030675C303030755C303030725C303030615C303030745C303030695C3030306F5C3030306E5C3030303A5C3030305C3034305C303030615C303030705C303030705C303030735C3030302F5C303030775C303030655C303030625C3030302F5C3030306E5C303030675C303030695C3030306E5C303030785C3030302E5C303030635C3030306F5C3030306E5C30303066} \BKM@entry{id=26,dest={73756273656374696F6E2E332E33},srcline={130}}{5C3337365C3337375C303030445C303030615C303030735C3030305C3034305C303030425C303030615C303030635C3030306B5C303030655C3030306E5C303030645C3030303A5C3030305C3034305C303030505C303030725C3030306F5C303030675C303030725C303030615C3030306D5C3030302E5C303030635C303030735C3030305C3034305C303030695C3030306D5C3030305C3034305C303030445C303030655C303030745C303030615C303030695C3030306C} -\@writefile{toc}{\contentsline {subsubsection}{\numberline {3.2.3}Nginx-Konfiguration: \texttt {apps/web/nginx.conf}}{14}{subsubsection.3.2.3}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {26}Nginx-Konfiguration mit Reverse Proxy}{14}{lstlisting.26}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {3.3}Das Backend: Program.cs im Detail}{15}{subsection.3.3}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {27}Vollständige Program.cs}{15}{lstlisting.27}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {3.2.3}Nginx-Konfiguration: \texttt {apps/web/nginx.conf}}{15}{subsubsection.3.2.3}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {26}Nginx-Konfiguration mit Reverse Proxy}{15}{lstlisting.26}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {3.3}Das Backend: Program.cs im Detail}{16}{subsection.3.3}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {27}Vollständige Program.cs}{16}{lstlisting.27}\protected@file@percent } \BKM@entry{id=27,dest={73756273656374696F6E2E332E34},srcline={186}}{5C3337365C3337375C303030445C303030655C303030725C3030305C3034305C303030415C303030505C303030495C3030302D5C303030435C3030306C5C303030695C303030655C3030306E5C303030745C3030303A5C3030305C3034305C303030635C3030306C5C303030695C303030655C3030306E5C303030745C3030302E5C303030745C303030735C3030305C3034305C303030695C3030306D5C3030305C3034305C303030445C303030655C303030745C303030615C303030695C3030306C} \BKM@entry{id=28,dest={73756273656374696F6E2E332E35},srcline={226}}{5C3337365C3337375C303030445C303030615C303030735C3030305C3034305C303030465C303030725C3030306F5C3030306E5C303030745C303030655C3030306E5C303030645C3030303A5C3030305C3034305C303030415C303030705C303030705C3030302E5C303030745C303030735C303030785C3030305C3034305C303030695C3030306D5C3030305C3034305C303030445C303030655C303030745C303030615C303030695C3030306C} -\@writefile{toc}{\contentsline {subsection}{\numberline {3.4}Der API-Client: client.ts im Detail}{16}{subsection.3.4}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {28}Manueller API-Client}{16}{lstlisting.28}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {3.5}Das Frontend: App.tsx im Detail}{16}{subsection.3.5}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {29}Hauptkomponente mit Workout-Liste und Formular}{16}{lstlisting.29}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {3.4}Der API-Client: client.ts im Detail}{17}{subsection.3.4}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {28}Manueller API-Client}{17}{lstlisting.28}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {3.5}Das Frontend: App.tsx im Detail}{17}{subsection.3.5}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {29}Hauptkomponente mit Workout-Liste und Formular}{17}{lstlisting.29}\protected@file@percent } \BKM@entry{id=29,dest={73756273656374696F6E2E332E36},srcline={265}}{5C3337365C3337375C303030495C3030306D5C303030615C303030675C303030655C303030735C3030305C3034305C303030625C303030615C303030755C303030655C3030306E} -\@writefile{toc}{\contentsline {subsection}{\numberline {3.6}Images bauen}{17}{subsection.3.6}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {3.6}Images bauen}{18}{subsection.3.6}\protected@file@percent } \BKM@entry{id=30,dest={73756273656374696F6E2E332E37},srcline={287}}{5C3337365C3337375C303030495C3030306D5C303030615C303030675C303030655C303030735C3030305C3034305C303030655C303030785C303030705C3030306F5C303030725C303030745C303030695C303030655C303030725C303030655C3030306E5C3030305C3034305C303030755C3030306E5C303030645C3030305C3034305C303030615C303030755C303030665C3030305C3034305C303030645C303030655C3030306E5C3030305C3034305C303030535C303030655C303030725C303030765C303030655C303030725C3030305C3034305C3030306B5C3030306F5C303030705C303030695C303030655C303030725C303030655C3030306E} \BKM@entry{id=31,dest={73756273656374696F6E2E332E38},srcline={311}}{5C3337365C3337375C303030435C3030306F5C3030306E5C303030745C303030615C303030695C3030306E5C303030655C303030725C3030305C3034305C303030615C303030755C303030665C3030305C3034305C303030645C303030655C3030306D5C3030305C3034305C303030535C303030655C303030725C303030765C303030655C303030725C3030305C3034305C303030735C303030745C303030615C303030725C303030745C303030655C3030306E} -\@writefile{toc}{\contentsline {subsection}{\numberline {3.7}Images exportieren und auf den Server kopieren}{18}{subsection.3.7}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {30}Images exportieren und kopieren}{18}{lstlisting.30}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {3.8}Container auf dem Server starten}{18}{subsection.3.8}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{\numberline {31}Docker-Netzwerk, Volume und Container anlegen}{18}{lstlisting.31}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {3.7}Images exportieren und auf den Server kopieren}{19}{subsection.3.7}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {30}Images exportieren und kopieren}{19}{lstlisting.30}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {3.8}Container auf dem Server starten}{19}{subsection.3.8}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {31}Docker-Netzwerk, Volume und Container anlegen}{19}{lstlisting.31}\protected@file@percent } \BKM@entry{id=32,dest={73756273656374696F6E2E332E39},srcline={345}}{5C3337365C3337375C303030415C303030755C303030665C303030675C303030655C303030745C303030725C303030655C303030745C303030655C3030306E5C303030655C3030305C3034305C303030505C303030725C3030306F5C303030625C3030306C5C303030655C3030306D5C303030655C3030305C3034305C303030755C3030306E5C303030645C3030305C3034305C3030304C5C3030305C3336365C303030735C303030755C3030306E5C303030675C303030655C3030306E} \BKM@entry{id=33,dest={73756273656374696F6E2E332E3130},srcline={372}}{5C3337365C3337375C3030305A5C303030755C303030735C303030615C3030306D5C3030306D5C303030655C3030306E5C303030665C303030615C303030735C303030735C303030755C3030306E5C30303067} -\@writefile{toc}{\contentsline {subsection}{\numberline {3.9}Aufgetretene Probleme und Lösungen}{19}{subsection.3.9}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {3.10}Zusammenfassung}{20}{subsection.3.10}\protected@file@percent } -\global\@namedef{scr@dte@section@lastmaxnumwidth}{11.00392pt} +\@writefile{toc}{\contentsline {subsection}{\numberline {3.9}Aufgetretene Probleme und Lösungen}{20}{subsection.3.9}\protected@file@percent } +\BKM@entry{id=34,dest={73656374696F6E2E34},srcline={5}}{5C3337365C3337375C303030445C3030306F5C3030306D5C303030615C303030695C3030306E5C3030305C3034305C3030306B5C303030615C303030755C303030665C303030655C3030306E5C3030305C3034305C303030755C3030306E5C303030645C3030305C3034305C303030445C3030304E5C303030535C3030305C3034305C3030306B5C3030306F5C3030306E5C303030665C303030695C303030675C303030755C303030725C303030695C303030655C303030725C303030655C3030306E} +\BKM@entry{id=35,dest={73756273656374696F6E2E342E31},srcline={10}}{5C3337365C3337375C303030575C303030615C303030725C303030755C3030306D5C3030305C3034305C303030655C303030695C3030306E5C303030655C3030305C3034305C303030655C303030695C303030675C303030655C3030306E5C303030655C3030305C3034305C303030445C3030306F5C3030306D5C303030615C303030695C3030306E5C3030303F} +\BKM@entry{id=36,dest={73756273656374696F6E2E342E32},srcline={21}}{5C3337365C3337375C303030475C303030725C303030755C3030306E5C303030645C3030306C5C303030615C303030675C303030655C3030306E5C3030303A5C3030305C3034305C303030575C303030695C303030655C3030305C3034305C303030665C303030755C3030306E5C3030306B5C303030745C303030695C3030306F5C3030306E5C303030695C303030655C303030725C303030745C3030305C3034305C303030645C303030615C303030735C3030305C3034305C303030445C3030304E5C303030535C3030303F} +\@writefile{toc}{\contentsline {subsection}{\numberline {3.10}Zusammenfassung}{21}{subsection.3.10}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {4}Domain kaufen und DNS konfigurieren}{21}{section.4}\protected@file@percent } +\newlabel{sec:step04}{{4}{21}{Domain kaufen und DNS konfigurieren}{section.4}{}} +\@writefile{toc}{\contentsline {subsection}{\numberline {4.1}Warum eine eigene Domain?}{21}{subsection.4.1}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {4.2}Grundlagen: Wie funktioniert das DNS?}{21}{subsection.4.2}\protected@file@percent } +\BKM@entry{id=37,dest={73756273656374696F6E2E342E33},srcline={54}}{5C3337365C3337375C303030575C303030615C303030735C3030305C3034305C303030695C303030735C303030745C3030305C3034305C303030445C3030304E5C303030535C3030302D5C303030505C303030725C3030306F5C303030705C303030615C303030675C303030615C303030745C303030695C3030306F5C3030306E5C3030303F} +\BKM@entry{id=38,dest={73756273656374696F6E2E342E34},srcline={66}}{5C3337365C3337375C303030445C3030306F5C3030306D5C303030615C303030695C3030306E5C3030302D5C3030304B5C303030615C303030755C303030665C3030305C3034305C303030625C303030655C303030695C3030305C3034305C303030435C3030306F5C3030306E5C303030745C303030615C303030625C3030306F} +\BKM@entry{id=39,dest={73756273756273656374696F6E2E342E342E31},srcline={68}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030315C3030303A5C3030305C3034305C303030455C303030695C3030306E5C3030306C5C3030306F5C303030675C303030675C303030655C3030306E5C3030305C3034305C303030695C3030306E5C303030735C3030305C3034305C3030304B5C303030755C3030306E5C303030645C303030655C3030306E5C303030635C303030655C3030306E5C303030745C303030655C30303072} +\BKM@entry{id=40,dest={73756273756273656374696F6E2E342E342E32},srcline={71}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030325C3030303A5C3030305C3034305C303030445C3030306F5C3030306D5C303030615C303030695C3030306E5C3030305C3034305C303030625C303030655C303030735C303030745C303030655C3030306C5C3030306C5C303030655C3030306E} +\@writefile{lot}{\contentsline {table}{\numberline {3}{\ignorespaces DNS-Record-Typen und ihre Funktion}}{22}{table.3}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {4.3}Was ist DNS-Propagation?}{22}{subsection.4.3}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {4.4}Domain-Kauf bei Contabo}{22}{subsection.4.4}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.4.1}Schritt 1: Einloggen ins Kundencenter}{22}{subsubsection.4.4.1}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.4.2}Schritt 2: Domain bestellen}{22}{subsubsection.4.4.2}\protected@file@percent } +\BKM@entry{id=41,dest={73756273756273656374696F6E2E342E342E33},srcline={79}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030335C3030303A5C3030305C3034305C303030445C3030306F5C3030306D5C303030615C303030695C3030306E5C3030302D5C303030485C303030615C3030306E5C303030645C3030306C5C303030655C303030735C3030305C3034305C3030306B5C3030306F5C3030306E5C303030665C303030695C303030675C303030755C303030725C303030695C303030655C303030725C303030655C3030306E} +\BKM@entry{id=42,dest={73756273756273656374696F6E2E342E342E34},srcline={91}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030345C3030303A5C3030305C3034305C3030304E5C303030615C3030306D5C303030655C303030735C303030655C303030725C303030765C303030655C303030725C3030305C3034305C303030665C303030655C303030735C303030745C3030306C5C303030655C303030675C303030655C3030306E} +\BKM@entry{id=43,dest={73756273756273656374696F6E2E342E342E35},srcline={99}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030355C3030303A5C3030305C3034305C303030495C303030505C3030302D5C303030415C303030645C303030725C303030655C303030735C303030735C303030655C3030305C3034305C303030615C303030755C303030735C303030775C3030305C3334345C303030685C3030306C5C303030655C3030306E} +\BKM@entry{id=44,dest={73756273756273656374696F6E2E342E342E36},srcline={109}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030365C3030303A5C3030305C3034305C303030425C303030655C303030735C303030745C303030655C3030306C5C3030306C5C303030755C3030306E5C303030675C3030305C3034305C303030615C303030625C303030735C303030635C303030685C3030306C5C303030695C303030655C3030305C3333375C303030655C3030306E} +\BKM@entry{id=45,dest={73756273656374696F6E2E342E35},srcline={112}}{5C3337365C3337375C303030445C3030304E5C303030535C3030302D5C303030455C303030695C3030306E5C303030745C303030725C3030305C3334345C303030675C303030655C3030305C3034305C303030665C3030305C3337345C303030725C3030305C3034305C303030645C303030695C303030655C3030305C3034305C303030445C3030306F5C3030306D5C303030615C303030695C3030306E5C3030305C3034305C303030655C303030695C3030306E5C303030725C303030695C303030635C303030685C303030745C303030655C3030306E} +\BKM@entry{id=46,dest={73756273756273656374696F6E2E342E352E31},srcline={116}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030315C3030303A5C3030305C3034305C303030445C3030304E5C303030535C3030305C3034305C3030305A5C3030306F5C3030306E5C303030655C3030305C3034305C3030304D5C303030615C3030306E5C303030615C303030675C303030655C3030306D5C303030655C3030306E5C303030745C3030305C3034305C3030305C3336365C303030665C303030665C3030306E5C303030655C3030306E} +\BKM@entry{id=47,dest={73756273756273656374696F6E2E342E352E32},srcline={119}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030325C3030303A5C3030305C3034305C3030304E5C3030306F5C303030745C303030775C303030655C3030306E5C303030645C303030695C303030675C303030655C3030305C3034305C303030415C3030302D5C303030525C303030655C303030635C3030306F5C303030725C303030645C303030735C3030305C3034305C303030615C3030306E5C3030306C5C303030655C303030675C303030655C3030306E} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.4.3}Schritt 3: Domain-Handles konfigurieren}{23}{subsubsection.4.4.3}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.4.4}Schritt 4: Nameserver festlegen}{23}{subsubsection.4.4.4}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.4.5}Schritt 5: IP-Adresse auswählen}{23}{subsubsection.4.4.5}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.4.6}Schritt 6: Bestellung abschließen}{23}{subsubsection.4.4.6}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {4.5}DNS-Einträge für die Domain einrichten}{23}{subsection.4.5}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.5.1}Schritt 1: DNS Zone Management öffnen}{23}{subsubsection.4.5.1}\protected@file@percent } +\BKM@entry{id=48,dest={73756273656374696F6E2E342E36},srcline={155}}{5C3337365C3337375C303030445C3030304E5C303030535C3030302D5C303030505C303030725C3030306F5C303030705C303030615C303030675C303030615C303030745C303030695C3030306F5C3030306E5C3030305C3034305C303030705C303030725C3030305C3337345C303030665C303030655C3030306E5C3030305C3034305C303030755C3030306E5C303030645C3030305C3034305C303030625C303030655C303030735C303030635C303030685C3030306C5C303030655C303030755C3030306E5C303030695C303030675C303030655C3030306E} +\BKM@entry{id=49,dest={73756273756273656374696F6E2E342E362E31},srcline={157}}{5C3337365C3337375C303030445C303030695C303030725C303030655C3030306B5C303030745C3030305C3034305C303030625C303030655C303030695C3030306D5C3030305C3034305C3030304E5C303030615C3030306D5C303030655C303030735C303030655C303030725C303030765C303030655C303030725C3030305C3034305C303030705C303030725C3030305C3337345C303030665C303030655C3030306E} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.5.2}Schritt 2: Notwendige A-Records anlegen}{24}{subsubsection.4.5.2}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {4.6}DNS-Propagation prüfen und beschleunigen}{24}{subsection.4.6}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.6.1}Direkt beim Nameserver prüfen}{24}{subsubsection.4.6.1}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {32}DNS direkt bei Contabo abfragen}{24}{lstlisting.32}\protected@file@percent } +\BKM@entry{id=50,dest={73756273756273656374696F6E2E342E362E32},srcline={173}}{5C3337365C3337375C3030304C5C3030306F5C3030306B5C303030615C3030306C5C303030655C3030306E5C3030305C3034305C303030445C3030304E5C303030535C3030302D5C303030435C303030615C303030635C303030685C303030655C3030305C3034305C3030306C5C303030655C303030655C303030725C303030655C3030306E} +\BKM@entry{id=51,dest={73756273756273656374696F6E2E342E362E33},srcline={180}}{5C3337365C3337375C303030535C303030655C303030725C303030765C303030655C303030725C3030305C3034305C303030645C303030695C303030725C303030655C3030306B5C303030745C3030305C3034305C3030305C3337345C303030625C303030655C303030725C3030305C3034305C303030495C303030505C3030305C3034305C303030705C303030725C3030305C3337345C303030665C303030655C3030306E} +\BKM@entry{id=52,dest={73756273756273656374696F6E2E342E362E34},srcline={197}}{5C3337365C3337375C3030304F5C3030306E5C3030306C5C303030695C3030306E5C303030655C3030305C3034305C303030445C3030304E5C303030535C3030302D5C303030435C303030685C303030655C303030635C3030306B5C303030655C303030725C3030305C3034305C303030765C303030655C303030725C303030775C303030655C3030306E5C303030645C303030655C3030306E} +\BKM@entry{id=53,dest={73756273656374696F6E2E342E37},srcline={200}}{5C3337365C3337375C3030305A5C303030755C303030735C303030615C3030306D5C3030306D5C303030655C3030306E5C303030665C303030615C303030735C303030735C303030755C3030306E5C30303067} +\BKM@entry{id=54,dest={73656374696F6E2E35},srcline={2}}{5C3337365C3337375C303030485C303030545C303030545C303030505C303030535C3030305C3034305C3030306D5C303030695C303030745C3030305C3034305C3030306E5C303030675C303030695C3030306E5C303030785C3030302D5C303030705C303030725C3030306F5C303030785C303030795C3030305C3034305C303030755C3030306E5C303030645C3030305C3034305C3030304C5C303030655C303030745C303030275C303030735C3030305C3034305C303030455C3030306E5C303030635C303030725C303030795C303030705C30303074} +\@writefile{lol}{\contentsline {lstlisting}{\numberline {33}Erwartete Ausgabe}{25}{lstlisting.33}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.6.2}Lokalen DNS-Cache leeren}{25}{subsubsection.4.6.2}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {34}DNS-Cache leeren unter Linux mit systemd-resolved}{25}{lstlisting.34}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.6.3}Server direkt über IP prüfen}{25}{subsubsection.4.6.3}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {35}Server direkt über IP testen}{25}{lstlisting.35}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {36}Server antwortet korrekt}{25}{lstlisting.36}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.6.4}Online DNS-Checker verwenden}{25}{subsubsection.4.6.4}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {4.7}Zusammenfassung}{25}{subsection.4.7}\protected@file@percent } +\BKM@entry{id=55,dest={73756273656374696F6E2E352E31},srcline={7}}{5C3337365C3337375C303030575C303030615C303030725C303030755C3030306D5C3030305C3034305C303030625C303030725C303030615C303030755C303030635C303030685C303030655C3030306E5C3030305C3034305C303030775C303030695C303030725C3030305C3034305C303030485C303030545C303030545C303030505C303030535C3030303F} +\BKM@entry{id=56,dest={73756273656374696F6E2E352E32},srcline={18}}{5C3337365C3337375C303030575C303030695C303030655C3030305C3034305C303030665C303030755C3030306E5C3030306B5C303030745C303030695C3030306F5C3030306E5C303030695C303030655C303030725C303030745C3030305C3034305C303030645C303030615C303030735C3030305C3034305C303030535C303030535C3030304C5C3030302D5C3030305A5C303030655C303030725C303030745C303030695C303030665C303030695C3030306B5C303030615C303030745C3030305C3034305C303030765C3030306F5C3030306E5C3030305C3034305C3030304C5C303030655C303030745C303030275C303030735C3030305C3034305C303030455C3030306E5C303030635C303030725C303030795C303030705C303030745C3030303F} +\BKM@entry{id=57,dest={73756273656374696F6E2E352E33},srcline={33}}{5C3337365C3337375C303030445C3030304E5C303030535C3030302D5C303030505C303030725C3030306F5C303030705C303030615C303030675C303030615C303030745C303030695C3030306F5C3030306E5C3030303A5C3030305C3034305C303030575C303030695C303030655C3030305C3034305C3030306C5C303030615C3030306E5C303030675C303030655C3030305C3034305C303030645C303030615C303030755C303030655C303030725C303030745C3030305C3034305C303030655C303030735C3030303F} +\@writefile{toc}{\contentsline {section}{\numberline {5}HTTPS mit nginx-proxy und Let's Encrypt}{26}{section.5}\protected@file@percent } +\newlabel{sec:step05}{{5}{26}{HTTPS mit nginx-proxy und Let's Encrypt}{section.5}{}} +\@writefile{toc}{\contentsline {subsection}{\numberline {5.1}Warum brauchen wir HTTPS?}{26}{subsection.5.1}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {5.2}Wie funktioniert das SSL-Zertifikat von Let's Encrypt?}{26}{subsection.5.2}\protected@file@percent } +\BKM@entry{id=58,dest={73756273656374696F6E2E352E34},srcline={60}}{5C3337365C3337375C303030415C303030725C303030635C303030685C303030695C303030745C303030655C3030306B5C303030745C303030755C303030725C3030303A5C3030305C3034305C303030575C303030695C303030655C3030305C3034305C303030685C3030305C3334345C3030306E5C303030675C303030655C3030306E5C3030305C3034305C303030645C303030695C303030655C3030305C3034305C303030435C3030306F5C3030306E5C303030745C303030615C303030695C3030306E5C303030655C303030725C3030305C3034305C3030307A5C303030755C303030735C303030615C3030306D5C3030306D5C303030655C3030306E5C3030303F} +\@writefile{toc}{\contentsline {subsection}{\numberline {5.3}DNS-Propagation: Wie lange dauert es?}{27}{subsection.5.3}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {37}DNS-Auflösung lokal prüfen}{27}{lstlisting.37}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {5.4}Architektur: Wie hängen die Container zusammen?}{27}{subsection.5.4}\protected@file@percent } +\BKM@entry{id=59,dest={73756273656374696F6E2E352E35},srcline={86}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030302D5C303030665C3030305C3337345C303030725C3030302D5C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030303A5C3030305C3034305C303030485C303030545C303030545C303030505C303030535C3030305C3034305C303030655C303030695C3030306E5C303030725C303030695C303030635C303030685C303030745C303030655C3030306E} +\BKM@entry{id=60,dest={73756273756273656374696F6E2E352E352E31},srcline={88}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030315C3030303A5C3030305C3034305C303030425C303030655C303030735C303030745C303030655C303030685C303030655C3030306E5C303030645C303030655C3030305C3034305C303030435C3030306F5C3030306E5C303030745C303030615C303030695C3030306E5C303030655C303030725C3030305C3034305C303030735C303030745C3030306F5C303030705C303030705C303030655C3030306E5C3030305C3034305C303030755C3030306E5C303030645C3030305C3034305C3030306C5C3030305C3336365C303030735C303030635C303030685C303030655C3030306E} +\BKM@entry{id=61,dest={73756273756273656374696F6E2E352E352E32},srcline={98}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030325C3030303A5C3030305C3034305C303030565C303030655C303030725C3030307A5C303030655C303030695C303030635C303030685C3030306E5C303030695C303030735C3030305C3034305C303030665C3030305C3337345C303030725C3030305C3034305C303030645C3030306F5C303030635C3030306B5C303030655C303030725C3030302D5C303030635C3030306F5C3030306D5C303030705C3030306F5C303030735C303030655C3030305C3034305C303030615C3030306E5C3030306C5C303030655C303030675C303030655C3030306E} +\BKM@entry{id=62,dest={73756273756273656374696F6E2E352E352E33},srcline={105}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030335C3030303A5C3030305C3034305C303030645C3030306F5C303030635C3030306B5C303030655C303030725C3030302D5C303030635C3030306F5C3030306D5C303030705C3030306F5C303030735C303030655C3030302E5C303030795C3030306D5C3030306C5C3030305C3034305C303030655C303030725C303030735C303030745C303030655C3030306C5C3030306C5C303030655C3030306E} +\@writefile{toc}{\contentsline {subsection}{\numberline {5.5}Schritt-für-Schritt: HTTPS einrichten}{28}{subsection.5.5}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.1}Schritt 1: Bestehende Container stoppen und löschen}{28}{subsubsection.5.5.1}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {38}Alte Container stoppen und löschen}{28}{lstlisting.38}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.2}Schritt 2: Verzeichnis für docker-compose anlegen}{28}{subsubsection.5.5.2}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {39}Projektverzeichnis auf dem Server}{28}{lstlisting.39}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.3}Schritt 3: docker-compose.yml erstellen}{28}{subsubsection.5.5.3}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {40}Vollständige docker-compose.yml}{28}{lstlisting.40}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{\nonumberline nginx-proxy}{30}{paragraph*.3}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{\nonumberline acme-companion}{30}{paragraph*.5}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{\nonumberline frontend (entscheidende Umgebungsvariablen!)}{30}{paragraph*.7}\protected@file@percent } +\BKM@entry{id=63,dest={73756273756273656374696F6E2E352E352E34},srcline={228}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030345C3030303A5C3030305C3034305C303030435C3030306F5C3030306E5C303030745C303030615C303030695C3030306E5C303030655C303030725C3030305C3034305C303030735C303030745C303030615C303030725C303030745C303030655C3030306E} +\BKM@entry{id=64,dest={73756273756273656374696F6E2E352E352E35},srcline={237}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030355C3030303A5C3030305C3034305C303030535C303030745C303030615C303030745C303030755C303030735C3030305C3034305C303030705C303030725C3030305C3337345C303030665C303030655C3030306E} +\BKM@entry{id=65,dest={73756273756273656374696F6E2E352E352E36},srcline={245}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030365C3030303A5C3030305C3034305C3030304C5C3030306F5C303030675C303030735C3030305C3034305C303030645C303030655C303030735C3030305C3034305C303030615C303030635C3030306D5C303030655C3030302D5C303030635C3030306F5C3030306D5C303030705C303030615C3030306E5C303030695C3030306F5C3030306E5C3030305C3034305C303030705C303030725C3030305C3337345C303030665C303030655C3030306E} +\BKM@entry{id=66,dest={73756273656374696F6E2E352E36},srcline={258}}{5C3337365C3337375C303030485C3030305C3334345C303030755C303030665C303030695C303030675C303030655C3030305C3034305C303030465C303030655C303030685C3030306C5C303030655C303030725C3030305C3034305C303030755C3030306E5C303030645C3030305C3034305C303030695C303030685C303030725C303030655C3030305C3034305C303030425C303030655C303030685C303030655C303030625C303030755C3030306E5C30303067} +\BKM@entry{id=67,dest={73756273756273656374696F6E2E352E362E31},srcline={260}}{5C3337365C3337375C303030465C303030655C303030685C3030306C5C303030655C303030725C3030305C3034305C303030315C3030303A5C3030305C3034305C303030275C303030275C303030635C303030615C3030306E5C303030275C303030745C3030305C3034305C303030675C303030655C303030745C3030305C3034305C3030306E5C303030675C303030695C3030306E5C303030785C3030302D5C303030705C303030725C3030306F5C303030785C303030795C3030305C3034305C303030635C3030306F5C3030306E5C303030745C303030615C303030695C3030306E5C303030655C303030725C3030305C3034305C303030495C303030445C303030275C30303027} +\BKM@entry{id=68,dest={73756273756273656374696F6E2E352E362E32},srcline={266}}{5C3337365C3337375C303030465C303030655C303030685C3030306C5C303030655C303030725C3030305C3034305C303030325C3030303A5C3030305C3034305C303030275C303030275C303030635C3030306F5C3030306E5C303030745C303030615C303030635C303030745C3030305C3034305C303030655C3030306D5C303030615C303030695C3030306C5C3030305C3034305C303030685C303030615C303030735C3030305C3034305C303030665C3030306F5C303030725C303030625C303030695C303030645C303030645C303030655C3030306E5C3030305C3034305C303030645C3030306F5C3030306D5C303030615C303030695C3030306E5C303030275C30303027} +\BKM@entry{id=69,dest={73756273756273656374696F6E2E352E362E33},srcline={272}}{5C3337365C3337375C303030465C303030655C303030685C3030306C5C303030655C303030725C3030305C3034305C303030335C3030303A5C3030305C3034305C303030275C303030275C303030445C3030304E5C303030535C3030305C3034305C303030705C303030725C3030306F5C303030625C3030306C5C303030655C3030306D5C3030303A5C3030305C3034305C3030304E5C303030585C303030445C3030304F5C3030304D5C303030415C303030495C3030304E5C303030275C30303027} +\@writefile{toc}{\contentsline {paragraph}{\nonumberline Docker Volumes}{31}{paragraph*.9}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.4}Schritt 4: Container starten}{31}{subsubsection.5.5.4}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {41}Alle Container im Hintergrund starten}{31}{lstlisting.41}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.5}Schritt 5: Status prüfen}{31}{subsubsection.5.5.5}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {42}Laufende Container anzeigen}{31}{lstlisting.42}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.6}Schritt 6: Logs des acme-companion prüfen}{31}{subsubsection.5.5.6}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {43}SSL-Zertifikatserstellung verfolgen}{31}{lstlisting.43}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {44}Erfolgreiche Ausgabe}{31}{lstlisting.44}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {5.6}Häufige Fehler und ihre Behebung}{31}{subsection.5.6}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.6.1}Fehler 1: ''can't get nginx-proxy container ID''}{31}{subsubsection.5.6.1}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.6.2}Fehler 2: ''contact email has forbidden domain''}{31}{subsubsection.5.6.2}\protected@file@percent } +\BKM@entry{id=70,dest={73756273656374696F6E2E352E37},srcline={282}}{5C3337365C3337375C303030575C303030695C303030655C3030305C3034305C303030665C3030305C3337345C303030675C303030655C3030305C3034305C303030695C303030635C303030685C3030305C3034305C303030735C303030705C3030305C3334345C303030745C303030655C303030725C3030305C3034305C303030775C303030655C303030695C303030745C303030655C303030725C303030655C3030305C3034305C303030535C303030755C303030625C303030645C3030306F5C3030306D5C303030615C303030695C3030306E5C303030735C3030305C3034305C303030685C303030695C3030306E5C3030307A5C303030755C3030303F} +\BKM@entry{id=71,dest={73756273656374696F6E2E352E38},srcline={294}}{5C3337365C3337375C303030575C303030695C303030655C3030305C3034305C303030665C303030755C3030306E5C3030306B5C303030745C303030695C3030306F5C3030306E5C303030695C303030655C303030725C303030745C3030305C3034305C303030645C303030655C303030725C3030305C3034305C303030525C303030655C303030765C303030655C303030725C303030735C303030655C3030305C3034305C303030505C303030725C3030306F5C303030785C303030795C3030305C3034305C303030695C3030306D5C3030305C3034305C303030445C303030655C303030745C303030615C303030695C3030306C5C3030303F} +\BKM@entry{id=72,dest={73756273656374696F6E2E352E39},srcline={311}}{5C3337365C3337375C3030305A5C303030755C303030735C303030615C3030306D5C3030306D5C303030655C3030306E5C303030665C303030615C303030735C303030735C303030755C3030306E5C30303067} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.6.3}Fehler 3: ''DNS problem: NXDOMAIN''}{32}{subsubsection.5.6.3}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {45}Zertifikatserstellung erneut anstoßen}{32}{lstlisting.45}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {5.7}Wie füge ich später weitere Subdomains hinzu?}{32}{subsection.5.7}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {5.8}Wie funktioniert der Reverse Proxy im Detail?}{32}{subsection.5.8}\protected@file@percent } +\BKM@entry{id=73,dest={73656374696F6E2E36},srcline={5}}{5C3337365C3337375C303030475C303030695C303030745C303030655C303030615C3030305C3034305C303030495C3030306E5C303030735C303030745C303030615C3030306C5C3030306C5C303030615C303030745C303030695C3030306F5C3030306E5C3030305C3034305C303030755C3030306E5C303030645C3030305C3034305C303030535C303030655C303030725C303030765C303030655C303030725C3030302D5C3030305C3333345C303030625C303030655C303030725C303030735C303030695C303030635C303030685C30303074} +\BKM@entry{id=74,dest={73756273656374696F6E2E362E31},srcline={10}}{5C3337365C3337375C303030575C303030615C303030725C303030755C3030306D5C3030305C3034305C303030655C303030695C3030306E5C3030305C3034305C303030655C303030695C303030675C303030655C3030306E5C303030655C303030725C3030305C3034305C303030475C303030695C303030745C3030302D5C303030535C303030655C303030725C303030765C303030655C303030725C3030303F} +\BKM@entry{id=75,dest={73756273656374696F6E2E362E32},srcline={21}}{5C3337365C3337375C3030304F5C3030306E5C303030655C303030445C303030655C303030765C3030303A5C3030305C3034305C303030445C303030655C303030725C3030305C3034305C303030675C303030655C303030735C303030635C303030685C303030655C303030695C303030745C303030655C303030725C303030745C303030655C3030305C3034305C303030565C303030655C303030725C303030735C303030755C303030635C30303068} +\BKM@entry{id=76,dest={73756273756273656374696F6E2E362E322E31},srcline={25}}{5C3337365C3337375C303030495C3030306E5C303030735C303030745C303030615C3030306C5C3030306C5C303030615C303030745C303030695C3030306F5C3030306E5C303030735C303030765C303030655C303030725C303030735C303030755C303030635C303030685C3030305C3034305C3030306D5C303030695C303030745C3030305C3034305C303030445C3030306F5C303030635C3030306B5C303030655C303030725C3030305C3034305C3030305C3035305C303030565C303030655C303030725C303030735C303030695C3030306F5C3030306E5C3030305C3034305C303030315C303030645C303030655C303030765C3030302F5C303030735C303030655C303030725C303030765C303030655C303030725C3030303A5C3030306C5C303030615C303030745C303030655C303030735C303030745C3030305C303531} +\@writefile{toc}{\contentsline {subsection}{\numberline {5.9}Zusammenfassung}{33}{subsection.5.9}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {6}Gitea Installation und Server-Übersicht}{33}{section.6}\protected@file@percent } +\newlabel{sec:step06}{{6}{33}{Gitea Installation und Server-Übersicht}{section.6}{}} +\@writefile{toc}{\contentsline {subsection}{\numberline {6.1}Warum ein eigener Git-Server?}{33}{subsection.6.1}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {6.2}OneDev: Der gescheiterte Versuch}{33}{subsection.6.2}\protected@file@percent } +\BKM@entry{id=77,dest={73756273656374696F6E2E362E33},srcline={64}}{5C3337365C3337375C303030475C303030695C303030745C303030655C303030615C3030303A5C3030305C3034305C303030445C303030695C303030655C3030305C3034305C303030735C303030635C303030685C3030306C5C303030615C3030306E5C3030306B5C303030655C3030305C3034305C303030415C3030306C5C303030745C303030655C303030725C3030306E5C303030615C303030745C303030695C303030765C30303065} +\BKM@entry{id=78,dest={73756273656374696F6E2E362E34},srcline={85}}{5C3337365C3337375C303030475C303030695C303030745C303030655C303030615C3030305C3034305C3030306D5C303030695C303030745C3030305C3034305C303030445C3030306F5C303030635C3030306B5C303030655C303030725C3030305C3034305C303030695C3030306E5C303030735C303030745C303030615C3030306C5C3030306C5C303030695C303030655C303030725C303030655C3030306E} +\BKM@entry{id=79,dest={73756273756273656374696F6E2E362E342E31},srcline={87}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030315C3030303A5C3030305C3034305C3030304F5C3030306E5C303030655C303030445C303030655C303030765C3030305C3034305C303030725C3030305C3337345C303030635C3030306B5C303030735C303030745C303030615C3030306E5C303030645C303030735C3030306C5C3030306F5C303030735C3030305C3034305C303030655C3030306E5C303030745C303030665C303030655C303030725C3030306E5C303030655C3030306E} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.2.1}Installationsversuch mit Docker (Version \texttt {1dev/server:latest})}{34}{subsubsection.6.2.1}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {46}docker-compose.yml für OneDev}{34}{lstlisting.46}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {47}Kritischer Fehler beim OneDev-Start}{34}{lstlisting.47}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {6.3}Gitea: Die schlanke Alternative}{34}{subsection.6.3}\protected@file@percent } +\BKM@entry{id=80,dest={73756273756273656374696F6E2E362E342E32},srcline={107}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030325C3030303A5C3030305C3034305C303030475C303030695C303030745C303030655C303030615C3030302D5C303030565C303030655C303030725C3030307A5C303030655C303030695C303030635C303030685C3030306E5C303030695C303030735C3030305C3034305C303030755C3030306E5C303030645C3030305C3034305C303030645C3030306F5C303030635C3030306B5C303030655C303030725C3030302D5C303030635C3030306F5C3030306D5C303030705C3030306F5C303030735C303030655C3030302E5C303030795C3030306D5C3030306C5C3030305C3034305C303030615C3030306E5C3030306C5C303030655C303030675C303030655C3030306E} +\@writefile{lot}{\contentsline {table}{\numberline {4}{\ignorespaces Vergleich OneDev vs. Gitea}}{35}{table.4}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {6.4}Gitea mit Docker installieren}{35}{subsection.6.4}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.4.1}Schritt 1: OneDev rückstandslos entfernen}{35}{subsubsection.6.4.1}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {48}OneDev komplett löschen}{35}{lstlisting.48}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.4.2}Schritt 2: Gitea-Verzeichnis und docker-compose.yml anlegen}{35}{subsubsection.6.4.2}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {49}Gitea-Verzeichnis vorbereiten}{35}{lstlisting.49}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {50}docker-compose.yml für Gitea}{35}{lstlisting.50}\protected@file@percent } +\BKM@entry{id=81,dest={73756273756273656374696F6E2E362E342E33},srcline={141}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030335C3030303A5C3030305C3034305C303030435C3030306F5C3030306E5C303030745C303030615C303030695C3030306E5C303030655C303030725C3030305C3034305C303030735C303030745C303030615C303030725C303030745C303030655C3030306E} +\BKM@entry{id=82,dest={73756273756273656374696F6E2E362E342E34},srcline={157}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030345C3030303A5C3030305C3034305C303030465C303030695C303030725C303030655C303030775C303030615C3030306C5C3030306C5C3030305C3034305C3030305C3336365C303030665C303030665C3030306E5C303030655C3030306E} +\BKM@entry{id=83,dest={73756273756273656374696F6E2E362E342E35},srcline={163}}{5C3337365C3337375C303030535C303030635C303030685C303030725C303030695C303030745C303030745C3030305C3034305C303030355C3030303A5C3030305C3034305C303030475C303030695C303030745C303030655C303030615C3030305C3034305C303030695C3030306D5C3030305C3034305C303030425C303030725C3030306F5C303030775C303030735C303030655C303030725C3030305C3034305C303030655C303030695C3030306E5C303030725C303030695C303030635C303030685C303030745C303030655C3030306E} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.4.3}Schritt 3: Container starten}{36}{subsubsection.6.4.3}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {51}Gitea starten}{36}{lstlisting.51}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {52}Erfolgreicher Start}{36}{lstlisting.52}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.4.4}Schritt 4: Firewall öffnen}{36}{subsubsection.6.4.4}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {53}Port 3000 freigeben}{36}{lstlisting.53}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.4.5}Schritt 5: Gitea im Browser einrichten}{36}{subsubsection.6.4.5}\protected@file@percent } +\BKM@entry{id=84,dest={73756273656374696F6E2E362E35},srcline={188}}{5C3337365C3337375C303030565C3030306F5C3030306C5C3030306C5C303030735C303030745C3030305C3334345C3030306E5C303030645C303030695C303030675C303030655C3030305C3034305C303030535C303030655C303030725C303030765C303030655C303030725C3030302D5C3030305C3333345C303030625C303030655C303030725C303030735C303030695C303030635C303030685C30303074} +\BKM@entry{id=85,dest={73756273756273656374696F6E2E362E352E31},srcline={192}}{5C3337365C3337375C3030304C5C303030615C303030755C303030665C303030655C3030306E5C303030645C303030655C3030305C3034305C303030445C3030306F5C303030635C3030306B5C303030655C303030725C3030302D5C303030435C3030306F5C3030306E5C303030745C303030615C303030695C3030306E5C303030655C30303072} +\BKM@entry{id=86,dest={73756273756273656374696F6E2E362E352E32},srcline={210}}{5C3337365C3337375C303030445C3030306F5C303030635C3030306B5C303030655C303030725C3030302D5C303030565C3030306F5C3030306C5C303030755C3030306D5C303030655C303030735C3030305C3034305C3030305C3035305C303030705C303030655C303030725C303030735C303030695C303030735C303030745C303030655C3030306E5C303030745C303030655C3030305C3034305C303030445C303030615C303030745C303030655C3030306E5C303030735C303030705C303030655C303030695C303030635C303030685C303030655C303030725C3030305C303531} +\BKM@entry{id=87,dest={73756273756273656374696F6E2E362E352E33},srcline={229}}{5C3337365C3337375C303030465C303030695C303030725C303030655C303030775C303030615C3030306C5C3030306C5C3030305C3034305C3030305C3035305C3030306E5C303030755C303030725C3030305C3034305C303030645C303030695C303030655C303030735C303030655C3030305C3034305C303030505C3030306F5C303030725C303030745C303030735C3030305C3034305C303030735C303030695C3030306E5C303030645C3030305C3034305C3030306F5C303030665C303030665C303030655C3030306E5C303030215C3030305C303531} +\BKM@entry{id=88,dest={73756273756273656374696F6E2E362E352E34},srcline={246}}{5C3337365C3337375C303030495C3030306E5C303030735C303030745C303030615C3030306C5C3030306C5C303030695C303030655C303030725C303030745C303030655C3030305C3034305C303030535C303030795C303030735C303030745C303030655C3030306D5C303030705C303030615C3030306B5C303030655C303030745C30303065} +\@writefile{toc}{\contentsline {subsection}{\numberline {6.5}Vollständige Server-Übersicht}{37}{subsection.6.5}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.5.1}Laufende Docker-Container}{37}{subsubsection.6.5.1}\protected@file@percent } +\@writefile{lot}{\contentsline {table}{\numberline {5}{\ignorespaces Alle laufenden Container auf dem Server}}{37}{table.5}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.5.2}Docker-Volumes (persistente Datenspeicher)}{37}{subsubsection.6.5.2}\protected@file@percent } +\@writefile{lot}{\contentsline {table}{\numberline {6}{\ignorespaces Volumes und ihre Inhalte}}{37}{table.6}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.5.3}Firewall (nur diese Ports sind offen!)}{37}{subsubsection.6.5.3}\protected@file@percent } +\@writefile{lot}{\contentsline {table}{\numberline {7}{\ignorespaces Geöffnete Ports}}{37}{table.7}\protected@file@percent } +\BKM@entry{id=89,dest={73756273756273656374696F6E2E362E352E35},srcline={256}}{5C3337365C3337375C303030565C303030655C303030725C3030307A5C303030655C303030695C303030635C303030685C3030306E5C303030695C303030735C303030735C303030745C303030725C303030755C3030306B5C303030745C303030755C303030725C3030305C3034305C303030755C3030306E5C303030745C303030655C303030725C3030305C3034305C3030302F5C3030306F5C303030705C30303074} +\BKM@entry{id=90,dest={73756273656374696F6E2E362E36},srcline={267}}{5C3337365C3337375C303030575C303030695C303030655C3030305C3034305C303030475C303030695C303030745C303030655C303030615C3030305C3034305C303030695C3030306E5C3030305C3034305C303030645C303030695C303030655C3030305C3034305C303030495C3030306E5C303030665C303030725C303030615C303030735C303030745C303030725C303030755C3030306B5C303030745C303030755C303030725C3030305C3034305C303030705C303030615C303030735C303030735C30303074} +\BKM@entry{id=91,dest={73756273656374696F6E2E362E37},srcline={297}}{5C3337365C3337375C3030305A5C303030755C303030735C303030615C3030306D5C3030306D5C303030655C3030306E5C303030665C303030615C303030735C303030735C303030755C3030306E5C30303067} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.5.4}Installierte Systempakete}{38}{subsubsection.6.5.4}\protected@file@percent } +\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.5.5}Verzeichnisstruktur unter /opt}{38}{subsubsection.6.5.5}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {54}Projektverzeichnisse auf dem Server}{38}{lstlisting.54}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {6.6}Wie Gitea in die Infrastruktur passt}{38}{subsection.6.6}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {6.7}Zusammenfassung}{39}{subsection.6.7}\protected@file@percent } +\@writefile{lol}{\contentsline {lstlisting}{\numberline {55}Server-Cockpit – wichtige Befehle}{39}{lstlisting.55}\protected@file@percent } +\global\@namedef{scr@dte@section@lastmaxnumwidth}{11.59192pt} \global\@namedef{scr@dte@subsection@lastmaxnumwidth}{24.81589pt} -\global\@namedef{scr@dte@subsubsection@lastmaxnumwidth}{28.41586pt} +\global\@namedef{scr@dte@subsubsection@lastmaxnumwidth}{29.13585pt} \@writefile{toc}{\providecommand\tocbasic@end@toc@file{}\tocbasic@end@toc@file} -\gdef \@abspage@last{20} +\gdef \@abspage@last{39} diff --git a/LateX/main.fdb_latexmk b/LateX/main.fdb_latexmk index 5565f6d..ddfb947 100644 --- a/LateX/main.fdb_latexmk +++ b/LateX/main.fdb_latexmk @@ -1,7 +1,7 @@ # Fdb version 4 -["pdflatex"] 1778081248.77398 "/home/computer/projects/fitness-app/LateX/main.tex" "main.pdf" "main" 1778081251.03276 0 +["pdflatex"] 1778244769.05929 "/home/computer/projects/fitness-app/LateX/main.tex" "main.pdf" "main" 1778244771.97073 0 "/etc/texmf/web2c/texmf.cnf" 1776891072.07073 475 c0e671620eb5563b2130f56340a5fde8 "" - "/home/computer/projects/fitness-app/LateX/main.tex" 1778081236.97865 8413 41aad5c5d32e893cafb487728bf379a6 "" + "/home/computer/projects/fitness-app/LateX/main.tex" 1778244681.19007 8476 4f7793f213e99c2fab6230bc8d2163a2 "" "/usr/share/texlive/texmf-dist/fonts/enc/dvips/fira/fir_d4q673.enc" 1570828436 2978 6d777d1174162fa94ff58f36782f4570 "" "/usr/share/texlive/texmf-dist/fonts/enc/dvips/fira/fir_d67aat.enc" 1570828436 3385 21a7e8c8dac3c39de5acda2c56e7bd7e "" "/usr/share/texlive/texmf-dist/fonts/enc/dvips/fira/fir_iln36p.enc" 1570828436 3071 cfa92ee28d698dd9275559d9d1c3a233 "" @@ -134,13 +134,16 @@ "/usr/share/texmf/web2c/texmf.cnf" 1707919699 40399 f2c302f7d2af602abb742093540a5834 "" "/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map" 1776891108.46284 5472669 54eaf61a88b6b7896ebd0dac973cb29c "" "/var/lib/texmf/web2c/pdftex/pdflatex.fmt" 1776891271 8211336 7fc26d317f030a4855527787ba3b41d3 "" - "main.aux" 1778081250.91843 23846 804a4d87b04ab7403c0abdcb70108b86 "pdflatex" - "main.out" 1778081250.30135 0 d41d8cd98f00b204e9800998ecf8427e "pdflatex" - "main.tex" 1778081236.97865 8413 41aad5c5d32e893cafb487728bf379a6 "" - "main.toc" 1778081250.92443 3404 2187def0eadc57fc64da16e547916901 "pdflatex" + "main.aux" 1778244771.83832 63855 4c52e1a5c85714f95fa215552b7321a7 "pdflatex" + "main.out" 1778244770.69833 0 d41d8cd98f00b204e9800998ecf8427e "pdflatex" + "main.tex" 1778244681.19007 8476 4f7793f213e99c2fab6230bc8d2163a2 "" + "main.toc" 1778244771.85532 9953 4cb30a3bd0faa13d5f22ee47f5497472 "pdflatex" "step_01.tex" 1778074119.30934 10807 dd7fc11a20ecebed2f07638ceddcf838 "" "step_02.tex" 1778074524.52004 9161 30219f0c68c4ae118067f27c09a123fb "" - "step_03.tex" 1778081246.2535 17575 0dde7ed301abaec40a3b2d19357b160b "" + "step_03.tex" 1778081256.10834 17575 0dde7ed301abaec40a3b2d19357b160b "" + "step_04.tex" 1778147404.27552 9769 0e1ed5ae9f963eb62f6fdf40c18f679b "" + "step_05.tex" 1778150659.56577 15313 3aba6a4bbc80c2ab38e2b98b51ace552 "" + "step_06.tex" 1778244768.71735 12776 e41d6e861e6c9823eb02364956f8b671 "" (generated) "main.aux" "main.log" diff --git a/LateX/main.fls b/LateX/main.fls index 873f3b5..193d90c 100644 --- a/LateX/main.fls +++ b/LateX/main.fls @@ -234,7 +234,6 @@ INPUT /usr/share/texlive/texmf-dist/tex/latex/fira/T1FiraMono-TOsF.fd INPUT /usr/share/texlive/texmf-dist/tex/latex/fira/T1FiraMono-TOsF.fd INPUT /usr/share/texlive/texmf-dist/tex/latex/fira/T1FiraMono-TOsF.fd INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/fira/FiraMono-Regular-tosf-t1.tfm -OUTPUT main.toc INPUT /usr/share/texlive/texmf-dist/fonts/vf/public/fira/FiraSans-Bold-osf-t1.vf INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/fira/FiraSans-Bold-osf-t1--base.tfm INPUT /usr/share/texlive/texmf-dist/fonts/vf/public/fira/FiraSans-Regular-osf-t1.vf @@ -242,6 +241,7 @@ INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/fira/FiraSans-Regular-osf-t INPUT /usr/share/texlive/texmf-dist/fonts/vf/public/fira/FiraMono-Regular-tosf-t1.vf INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/fira/FiraMono-Regular-tosf-t1--base.tfm INPUT /usr/share/texlive/texmf-dist/fonts/enc/dvips/fira/fir_d4q673.enc +OUTPUT main.toc INPUT ./step_01.tex INPUT ./step_01.tex INPUT step_01.tex @@ -273,6 +273,15 @@ INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/fira/FiraMono-Bold-tosf-t1- INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/fira/FiraMono-Oblique-tosf-t1.tfm INPUT /usr/share/texlive/texmf-dist/fonts/vf/public/fira/FiraMono-Oblique-tosf-t1.vf INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/fira/FiraMono-Oblique-tosf-t1--base.tfm +INPUT ./step_04.tex +INPUT ./step_04.tex +INPUT step_04.tex +INPUT ./step_05.tex +INPUT ./step_05.tex +INPUT step_05.tex +INPUT ./step_06.tex +INPUT ./step_06.tex +INPUT step_06.tex INPUT main.aux INPUT ./main.out INPUT ./main.out diff --git a/LateX/main.log b/LateX/main.log index 4dbf3a0..5874b57 100644 --- a/LateX/main.log +++ b/LateX/main.log @@ -1,4 +1,4 @@ -This is pdfTeX, Version 3.141592653-2.6-1.40.25 (TeX Live 2023/Debian) (preloaded format=pdflatex 2026.4.22) 6 MAY 2026 17:27 +This is pdfTeX, Version 3.141592653-2.6-1.40.25 (TeX Live 2023/Debian) (preloaded format=pdflatex 2026.4.22) 8 MAY 2026 14:52 entering extended mode restricted \write18 enabled. file:line:error style messages enabled. @@ -628,13 +628,13 @@ Package microtype Info: Loading generic protrusion settings for font family (microtype) `FiraMono-TOsF' (encoding: T1). (microtype) For optimal results, create family-specific settings. (microtype) See the microtype manual for details. -) + [2 + +{/usr/share/texlive/texmf-dist/fonts/enc/dvips/fira/fir_d4q673.enc}]) \tf@toc=\write4 \openout4 = `main.toc'. - [2 - -{/usr/share/texlive/texmf-dist/fonts/enc/dvips/fira/fir_d4q673.enc}] (./step_01.tex + [3] (./step_01.tex LaTeX Font Info: Trying to load font information for TS1+FiraSans-OsF on input line 21. (/usr/share/texlive/texmf-dist/tex/latex/fira/TS1FiraSans-OsF.fd File: TS1FiraSans-OsF.fd 2019/10/10 (autoinst) Font definitions for TS1/FiraSans-OsF. @@ -656,18 +656,18 @@ LaTeX Font Info: Font shape `T1/FiraSans-OsF/m/n' in size <10> not available (Font) Font shape `T1/FiraSans-OsF/regular/n' tried instead on input line 36. LaTeX Font Info: Font shape `T1/FiraSans-OsF/regular/n' will be (Font) scaled to size 10.0pt on input line 36. - [3 + [4 -{/usr/share/texlive/texmf-dist/fonts/enc/dvips/fira/fir_d67aat.enc}] [4] +{/usr/share/texlive/texmf-dist/fonts/enc/dvips/fira/fir_d67aat.enc}] [5] LaTeX Font Info: Font shape `T1/FiraMono-TOsF/b/n' in size <10> not available (Font) Font shape `T1/FiraMono-TOsF/bold/n' tried instead on input line 140. LaTeX Font Info: Font shape `T1/FiraMono-TOsF/bold/n' will be (Font) scaled to size 8.99994pt on input line 140. - [5] + [6] Package Listings Warning: Text dropped after begin of listing on input line 221. -[6]) (./step_02.tex [7] +[7]) (./step_02.tex [8] Underfull \hbox (badness 10000) in paragraph at lines 63--64 []|\T1/FiraSans-OsF/regular/n/12 (+20) Unser \T1/FiraSans-OsF/bold/n/12 (+20) ein-zi-ger Ver-wal- [] @@ -705,17 +705,17 @@ Underfull \hbox (badness 3612) in paragraph at lines 65--66 LaTeX Warning: `h' float specifier changed to `ht'. -[8] +[9] Overfull \hbox (3.891pt too wide) in paragraph at lines 77--78 []\T1/FiraSans-OsF/regular/n/12 (-20) HTTP-Verbindungen kön-nen von An-grei-fern ver-än-dert wer-den (Man-in-the-Middle) [] -[9] [10]) (./step_03.tex [11] +[10] [11]) (./step_03.tex [12] LaTeX Font Info: Font shape `T1/FiraMono-TOsF/b/n' in size <12> not available (Font) Font shape `T1/FiraMono-TOsF/bold/n' tried instead on input line 29. LaTeX Font Info: Font shape `T1/FiraMono-TOsF/bold/n' will be (Font) scaled to size 10.79993pt on input line 29. - [12] [13] + [13] [14] Overfull \hbox (74.52446pt too wide) in paragraph at lines 125--126 []\T1/FiraMono-TOsF/regular/n/12 location / \T1/FiraSans-OsF/regular/n/12 (-20) ^^U An-fra-gen an die Haupt-sei-te $\OMS/cmsy/m/n/12 !$ \T1/FiraSans-OsF/regular/n/12 (-20) lie-fert React-Dateien aus \T1/FiraMono-TOsF/regular/n/12 /usr/share/nginx/html [] @@ -725,7 +725,7 @@ Overfull \hbox (36.2292pt too wide) in paragraph at lines 126--127 []\T1/FiraMono-TOsF/regular/n/12 location /api/ \T1/FiraSans-OsF/regular/n/12 (-20) ^^U An-fra-gen an \T1/FiraMono-TOsF/regular/n/12 /api/* $\OMS/cmsy/m/n/12 !$ \T1/FiraSans-OsF/regular/n/12 (-20) lei-tet sie an das Ba-ckend (\T1/FiraMono-TOsF/regular/n/12 fitness-api:5000\T1/FiraSans-OsF/regular/n/12 (-20) ) [] -[14] [15] +[15] [16] LaTeX Font Info: Font shape `T1/FiraMono-TOsF/m/it' in size <10> not available (Font) Font shape `T1/FiraMono-TOsF/regular/it' tried instead on input line 214. LaTeX Font Info: Font shape `T1/FiraMono-TOsF/regular/it' in size <10> not available @@ -737,7 +737,7 @@ Overfull \hbox (5.87708pt too wide) in paragraph at lines 220--221 []\T1/FiraMono-TOsF/regular/n/12 API_BASE = \T1/FiraSans-OsF/regular/n/12 (-20) ^^U Kei-ne ab-so-lu-te URL! Statt-des-sen re-la-ti-ve Pfa-de wie \T1/FiraMono-TOsF/regular/n/12 /api/workouts\T1/FiraSans-OsF/regular/n/12 (-20) . [] -[16] [17] [18] +[17] [18] [19] Overfull \hbox (10.69511pt too wide) in paragraph at lines 341--342 []\T1/FiraMono-TOsF/regular/n/12 -v fitness-data:/app/data \T1/FiraSans-OsF/regular/n/12 (-20) ^^U Bin-det das Vo-lu-me \T1/FiraMono-TOsF/regular/n/12 fitness-data \T1/FiraSans-OsF/regular/n/12 (-20) in den Container- [] @@ -747,7 +747,63 @@ Overfull \hbox (0.99844pt too wide) in paragraph at lines 361--362 []\T1/FiraSans-OsF/regular/n/12 (-20) Ursache: Im Cli-ent stand \T1/FiraMono-TOsF/regular/n/12 const API_BASE = "http://192.168.178.189:5107"\T1/FiraSans-OsF/regular/n/12 (-20) . [] -[19]) [20] (./main.aux) +[20]) (./step_04.tex +Underfull \hbox (badness 2197) in paragraph at lines 35--36 +[]|\T1/FiraSans-OsF/regular/n/12 (+20) Wie A-Record, aber für IPv6- + [] + + +Underfull \hbox (badness 2150) in paragraph at lines 38--39 +[]|\T1/FiraSans-OsF/regular/n/12 (+20) Definiert, wel-che Na-me-ser-ver + [] + + +LaTeX Warning: `h' float specifier changed to `ht'. + +[21] [22] [23] +Overfull \hbox (38.17029pt too wide) in paragraph at lines 152--153 +[]\T1/FiraMono-TOsF/regular/n/12 *.robre.de \T1/FiraSans-OsF/regular/n/12 (-20) ^^U fängt al-le zu-künf-ti-gen Sub-do-mains ab (z. B. \T1/FiraMono-TOsF/regular/n/12 app.robre.de\T1/FiraSans-OsF/regular/n/12 (-20) , \T1/FiraMono-TOsF/regular/n/12 api.robre.de\T1/FiraSans-OsF/regular/n/12 (-20) ), + [] + +[24]) (./step_05.tex +Overfull \hbox (16.09901pt too wide) in paragraph at lines 5--6 +\T1/FiraMono-TOsF/regular/n/12 https://robre.de \T1/FiraSans-OsF/regular/n/12 (-20) er-reich-bar und er-füllt al-le Vor-aus-set-zun-gen für die PWA-Installation. + [] + +[25] +Overfull \hbox (74.09863pt too wide) in paragraph at lines 26--27 +[]\T1/FiraSans-OsF/regular/n/12 (-20) Let's En-crypt prüft, ob die-se Da-tei un-ter \T1/FiraMono-TOsF/regular/n/12 http://robre.de/.well-known/acme-challenge/... + [] + +[26] [27] [28] [29] +Overfull \hbox (12.23381pt too wide) in paragraph at lines 205--206 +[]\T1/FiraMono-TOsF/regular/n/12 certs:/etc/nginx/certs \T1/FiraSans-OsF/regular/n/12 (-20) ^^U Hier spei-chert der acme-companion die SSL-Zertifikate. + [] + + +Overfull \hbox (26.42038pt too wide) in paragraph at lines 224--225 +[]\T1/FiraMono-TOsF/regular/n/12 certs, vhost, html, acme \T1/FiraSans-OsF/regular/n/12 (-20) ^^U Spei-chern SSL-Zertifikate, Kon-fi-gu-ra-ti-on und Challenge- + [] + +[30] [31] +Overfull \hbox (118.71225pt too wide) in paragraph at lines 288--289 +[]\T1/FiraSans-OsF/bold/n/12 (-20) Docker-Container: \T1/FiraSans-OsF/regular/n/12 (-20) Einen neu-en Con-tai-ner mit den Um-ge-bungs-va-ria-blen \T1/FiraMono-TOsF/regular/n/12 VIRTUAL_HOST=todo.robre.de + [] + +[32]) (./step_06.tex [33] +Overfull \hbox (44.70439pt too wide) in paragraph at lines 51--52 +[]\T1/FiraSans-OsF/bold/n/12 (-20) Datenbank-Fehler: \T1/FiraSans-OsF/regular/n/12 (-20) Die ent-schei-den-de Feh-ler-mel-dung in \T1/FiraMono-TOsF/regular/n/12 /opt/onedev/logs/server.log\T1/FiraSans-OsF/regular/n/12 (-20) : + [] + + +LaTeX Warning: `h' float specifier changed to `ht'. + +[34] [35] [36] +Overfull \hbox (70.29362pt too wide) in paragraph at lines 197--208 + [][] + [] + +[37] [38]) [39] (./main.aux) *********** LaTeX2e <2023-11-01> patch level 1 L3 programming layer <2024-01-22> @@ -756,18 +812,18 @@ Package rerunfilecheck Info: File `main.out' has not changed. (rerunfilecheck) Checksum: D41D8CD98F00B204E9800998ECF8427E;0. ) Here is how much of TeX's memory you used: - 19894 strings out of 474222 - 343688 string characters out of 5748733 - 2200975 words of memory out of 5000000 - 41353 multiletter control sequences out of 15000+600000 - 692737 words of font info for 213 fonts, out of 8000000 for 9000 + 20493 strings out of 474222 + 351901 string characters out of 5748733 + 2292975 words of memory out of 5000000 + 41569 multiletter control sequences out of 15000+600000 + 697305 words of font info for 241 fonts, out of 8000000 for 9000 1141 hyphenation exceptions out of 8191 - 108i,10n,107p,10941b,2229s stack positions out of 10000i,1000n,20000p,200000b,200000s + 108i,11n,107p,10941b,2229s stack positions out of 10000i,1000n,20000p,200000b,200000s -Output written on main.pdf (20 pages, 300891 bytes). +Output written on main.pdf (39 pages, 374479 bytes). PDF statistics: - 651 PDF objects out of 1000 (max. 8388607) - 609 compressed objects within 7 object streams - 336 named destinations out of 1000 (max. 500000) - 45833 words of extra memory for PDF output out of 51595 (max. 10000000) + 1350 PDF objects out of 1440 (max. 8388607) + 1283 compressed objects within 13 object streams + 668 named destinations out of 1000 (max. 500000) + 46297 words of extra memory for PDF output out of 51595 (max. 10000000) diff --git a/LateX/main.pdf b/LateX/main.pdf index 7a56249..a982267 100644 Binary files a/LateX/main.pdf and b/LateX/main.pdf differ diff --git a/LateX/main.synctex.gz b/LateX/main.synctex.gz index c8b9a8a..b875718 100644 Binary files a/LateX/main.synctex.gz and b/LateX/main.synctex.gz differ diff --git a/LateX/main.tex b/LateX/main.tex index 339973f..e73da4f 100644 --- a/LateX/main.tex +++ b/LateX/main.tex @@ -246,6 +246,9 @@ \input{step_01.tex} \input{step_02.tex} \input{step_03.tex} +\input{step_04.tex} +\input{step_05.tex} +\input{step_06.tex} % Weitere Kapitel folgen hier: % \input{step_02.tex} diff --git a/LateX/main.toc b/LateX/main.toc index 3ddd723..5150865 100644 --- a/LateX/main.toc +++ b/LateX/main.toc @@ -1,35 +1,97 @@ \babel@toc {ngerman}{}\relax -\contentsline {section}{\numberline {1}Server-Absicherung (Ubuntu 24.04 auf Contabo VPS)}{3}{section.1}% -\contentsline {subsection}{\numberline {1.1}Schritt 1: SSH-Verbindung testen}{3}{subsection.1.1}% -\contentsline {subsection}{\numberline {1.2}Schritt 2: System-Updates}{4}{subsection.1.2}% -\contentsline {subsection}{\numberline {1.3}Schritt 3: SSH-Key-Authentifizierung}{4}{subsection.1.3}% -\contentsline {subsection}{\numberline {1.4}Schritt 4: SSH-Client-Konfiguration (Alias)}{5}{subsection.1.4}% -\contentsline {subsection}{\numberline {1.5}Schritt 5: SSH-Timeout auf 20 Minuten}{6}{subsection.1.5}% -\contentsline {subsection}{\numberline {1.6}Schritt 6: Fail2Ban (Bruteforce-Schutz)}{6}{subsection.1.6}% -\contentsline {subsection}{\numberline {1.7}Zusammenfassung}{7}{subsection.1.7}% -\contentsline {section}{\numberline {2}Firewall mit UFW einrichten}{7}{section.2}% -\contentsline {subsection}{\numberline {2.1}Was ist eine Firewall und warum brauchen wir sie?}{8}{subsection.2.1}% -\contentsline {subsection}{\numberline {2.2}Die 65.535 Ports: Ein kurzer Überblick}{8}{subsection.2.2}% -\contentsline {subsection}{\numberline {2.3}Die drei Ports, die wir öffnen}{8}{subsection.2.3}% -\contentsline {subsection}{\numberline {2.4}Warum HTTPS für PWAs Pflicht ist}{8}{subsection.2.4}% -\contentsline {subsection}{\numberline {2.5}Durchführung}{9}{subsection.2.5}% -\contentsline {subsubsection}{\numberline {2.5.1}Standardrichtlinien setzen}{9}{subsubsection.2.5.1}% -\contentsline {subsubsection}{\numberline {2.5.2}Benötigte Ports öffnen}{10}{subsubsection.2.5.2}% -\contentsline {subsubsection}{\numberline {2.5.3}Firewall aktivieren}{10}{subsubsection.2.5.3}% -\contentsline {subsubsection}{\numberline {2.5.4}Konfiguration überprüfen}{11}{subsubsection.2.5.4}% -\contentsline {subsection}{\numberline {2.6}Zusammenfassung}{11}{subsection.2.6}% -\contentsline {section}{\numberline {3}Docker-Images bauen und App deployen}{12}{section.3}% -\contentsline {subsection}{\numberline {3.1}Was ist Docker und warum nutzen wir es?}{12}{subsection.3.1}% -\contentsline {subsection}{\numberline {3.2}Die drei Dockerfiles im Detail}{12}{subsection.3.2}% -\contentsline {subsubsection}{\numberline {3.2.1}Backend-Dockerfile: \texttt {apps/api/Dockerfile}}{12}{subsubsection.3.2.1}% -\contentsline {subsubsection}{\numberline {3.2.2}Frontend-Dockerfile: \texttt {apps/web/Dockerfile}}{13}{subsubsection.3.2.2}% -\contentsline {subsubsection}{\numberline {3.2.3}Nginx-Konfiguration: \texttt {apps/web/nginx.conf}}{14}{subsubsection.3.2.3}% -\contentsline {subsection}{\numberline {3.3}Das Backend: Program.cs im Detail}{15}{subsection.3.3}% -\contentsline {subsection}{\numberline {3.4}Der API-Client: client.ts im Detail}{16}{subsection.3.4}% -\contentsline {subsection}{\numberline {3.5}Das Frontend: App.tsx im Detail}{16}{subsection.3.5}% -\contentsline {subsection}{\numberline {3.6}Images bauen}{17}{subsection.3.6}% -\contentsline {subsection}{\numberline {3.7}Images exportieren und auf den Server kopieren}{18}{subsection.3.7}% -\contentsline {subsection}{\numberline {3.8}Container auf dem Server starten}{18}{subsection.3.8}% -\contentsline {subsection}{\numberline {3.9}Aufgetretene Probleme und Lösungen}{19}{subsection.3.9}% -\contentsline {subsection}{\numberline {3.10}Zusammenfassung}{20}{subsection.3.10}% +\contentsline {section}{\numberline {1}Server-Absicherung (Ubuntu 24.04 auf Contabo VPS)}{4}{section.1}% +\contentsline {subsection}{\numberline {1.1}Schritt 1: SSH-Verbindung testen}{4}{subsection.1.1}% +\contentsline {subsection}{\numberline {1.2}Schritt 2: System-Updates}{5}{subsection.1.2}% +\contentsline {subsection}{\numberline {1.3}Schritt 3: SSH-Key-Authentifizierung}{5}{subsection.1.3}% +\contentsline {subsection}{\numberline {1.4}Schritt 4: SSH-Client-Konfiguration (Alias)}{6}{subsection.1.4}% +\contentsline {subsection}{\numberline {1.5}Schritt 5: SSH-Timeout auf 20 Minuten}{7}{subsection.1.5}% +\contentsline {subsection}{\numberline {1.6}Schritt 6: Fail2Ban (Bruteforce-Schutz)}{7}{subsection.1.6}% +\contentsline {subsection}{\numberline {1.7}Zusammenfassung}{8}{subsection.1.7}% +\contentsline {section}{\numberline {2}Firewall mit UFW einrichten}{8}{section.2}% +\contentsline {subsection}{\numberline {2.1}Was ist eine Firewall und warum brauchen wir sie?}{9}{subsection.2.1}% +\contentsline {subsection}{\numberline {2.2}Die 65.535 Ports: Ein kurzer Überblick}{9}{subsection.2.2}% +\contentsline {subsection}{\numberline {2.3}Die drei Ports, die wir öffnen}{9}{subsection.2.3}% +\contentsline {subsection}{\numberline {2.4}Warum HTTPS für PWAs Pflicht ist}{9}{subsection.2.4}% +\contentsline {subsection}{\numberline {2.5}Durchführung}{10}{subsection.2.5}% +\contentsline {subsubsection}{\numberline {2.5.1}Standardrichtlinien setzen}{10}{subsubsection.2.5.1}% +\contentsline {subsubsection}{\numberline {2.5.2}Benötigte Ports öffnen}{11}{subsubsection.2.5.2}% +\contentsline {subsubsection}{\numberline {2.5.3}Firewall aktivieren}{11}{subsubsection.2.5.3}% +\contentsline {subsubsection}{\numberline {2.5.4}Konfiguration überprüfen}{12}{subsubsection.2.5.4}% +\contentsline {subsection}{\numberline {2.6}Zusammenfassung}{12}{subsection.2.6}% +\contentsline {section}{\numberline {3}Docker-Images bauen und App deployen}{13}{section.3}% +\contentsline {subsection}{\numberline {3.1}Was ist Docker und warum nutzen wir es?}{13}{subsection.3.1}% +\contentsline {subsection}{\numberline {3.2}Die drei Dockerfiles im Detail}{13}{subsection.3.2}% +\contentsline {subsubsection}{\numberline {3.2.1}Backend-Dockerfile: \texttt {apps/api/Dockerfile}}{13}{subsubsection.3.2.1}% +\contentsline {subsubsection}{\numberline {3.2.2}Frontend-Dockerfile: \texttt {apps/web/Dockerfile}}{14}{subsubsection.3.2.2}% +\contentsline {subsubsection}{\numberline {3.2.3}Nginx-Konfiguration: \texttt {apps/web/nginx.conf}}{15}{subsubsection.3.2.3}% +\contentsline {subsection}{\numberline {3.3}Das Backend: Program.cs im Detail}{16}{subsection.3.3}% +\contentsline {subsection}{\numberline {3.4}Der API-Client: client.ts im Detail}{17}{subsection.3.4}% +\contentsline {subsection}{\numberline {3.5}Das Frontend: App.tsx im Detail}{17}{subsection.3.5}% +\contentsline {subsection}{\numberline {3.6}Images bauen}{18}{subsection.3.6}% +\contentsline {subsection}{\numberline {3.7}Images exportieren und auf den Server kopieren}{19}{subsection.3.7}% +\contentsline {subsection}{\numberline {3.8}Container auf dem Server starten}{19}{subsection.3.8}% +\contentsline {subsection}{\numberline {3.9}Aufgetretene Probleme und Lösungen}{20}{subsection.3.9}% +\contentsline {subsection}{\numberline {3.10}Zusammenfassung}{21}{subsection.3.10}% +\contentsline {section}{\numberline {4}Domain kaufen und DNS konfigurieren}{21}{section.4}% +\contentsline {subsection}{\numberline {4.1}Warum eine eigene Domain?}{21}{subsection.4.1}% +\contentsline {subsection}{\numberline {4.2}Grundlagen: Wie funktioniert das DNS?}{21}{subsection.4.2}% +\contentsline {subsection}{\numberline {4.3}Was ist DNS-Propagation?}{22}{subsection.4.3}% +\contentsline {subsection}{\numberline {4.4}Domain-Kauf bei Contabo}{22}{subsection.4.4}% +\contentsline {subsubsection}{\numberline {4.4.1}Schritt 1: Einloggen ins Kundencenter}{22}{subsubsection.4.4.1}% +\contentsline {subsubsection}{\numberline {4.4.2}Schritt 2: Domain bestellen}{22}{subsubsection.4.4.2}% +\contentsline {subsubsection}{\numberline {4.4.3}Schritt 3: Domain-Handles konfigurieren}{23}{subsubsection.4.4.3}% +\contentsline {subsubsection}{\numberline {4.4.4}Schritt 4: Nameserver festlegen}{23}{subsubsection.4.4.4}% +\contentsline {subsubsection}{\numberline {4.4.5}Schritt 5: IP-Adresse auswählen}{23}{subsubsection.4.4.5}% +\contentsline {subsubsection}{\numberline {4.4.6}Schritt 6: Bestellung abschließen}{23}{subsubsection.4.4.6}% +\contentsline {subsection}{\numberline {4.5}DNS-Einträge für die Domain einrichten}{23}{subsection.4.5}% +\contentsline {subsubsection}{\numberline {4.5.1}Schritt 1: DNS Zone Management öffnen}{23}{subsubsection.4.5.1}% +\contentsline {subsubsection}{\numberline {4.5.2}Schritt 2: Notwendige A-Records anlegen}{24}{subsubsection.4.5.2}% +\contentsline {subsection}{\numberline {4.6}DNS-Propagation prüfen und beschleunigen}{24}{subsection.4.6}% +\contentsline {subsubsection}{\numberline {4.6.1}Direkt beim Nameserver prüfen}{24}{subsubsection.4.6.1}% +\contentsline {subsubsection}{\numberline {4.6.2}Lokalen DNS-Cache leeren}{25}{subsubsection.4.6.2}% +\contentsline {subsubsection}{\numberline {4.6.3}Server direkt über IP prüfen}{25}{subsubsection.4.6.3}% +\contentsline {subsubsection}{\numberline {4.6.4}Online DNS-Checker verwenden}{25}{subsubsection.4.6.4}% +\contentsline {subsection}{\numberline {4.7}Zusammenfassung}{25}{subsection.4.7}% +\contentsline {section}{\numberline {5}HTTPS mit nginx-proxy und Let's Encrypt}{26}{section.5}% +\contentsline {subsection}{\numberline {5.1}Warum brauchen wir HTTPS?}{26}{subsection.5.1}% +\contentsline {subsection}{\numberline {5.2}Wie funktioniert das SSL-Zertifikat von Let's Encrypt?}{26}{subsection.5.2}% +\contentsline {subsection}{\numberline {5.3}DNS-Propagation: Wie lange dauert es?}{27}{subsection.5.3}% +\contentsline {subsection}{\numberline {5.4}Architektur: Wie hängen die Container zusammen?}{27}{subsection.5.4}% +\contentsline {subsection}{\numberline {5.5}Schritt-für-Schritt: HTTPS einrichten}{28}{subsection.5.5}% +\contentsline {subsubsection}{\numberline {5.5.1}Schritt 1: Bestehende Container stoppen und löschen}{28}{subsubsection.5.5.1}% +\contentsline {subsubsection}{\numberline {5.5.2}Schritt 2: Verzeichnis für docker-compose anlegen}{28}{subsubsection.5.5.2}% +\contentsline {subsubsection}{\numberline {5.5.3}Schritt 3: docker-compose.yml erstellen}{28}{subsubsection.5.5.3}% +\contentsline {paragraph}{\nonumberline nginx-proxy}{30}{paragraph*.3}% +\contentsline {paragraph}{\nonumberline acme-companion}{30}{paragraph*.5}% +\contentsline {paragraph}{\nonumberline frontend (entscheidende Umgebungsvariablen!)}{30}{paragraph*.7}% +\contentsline {paragraph}{\nonumberline Docker Volumes}{31}{paragraph*.9}% +\contentsline {subsubsection}{\numberline {5.5.4}Schritt 4: Container starten}{31}{subsubsection.5.5.4}% +\contentsline {subsubsection}{\numberline {5.5.5}Schritt 5: Status prüfen}{31}{subsubsection.5.5.5}% +\contentsline {subsubsection}{\numberline {5.5.6}Schritt 6: Logs des acme-companion prüfen}{31}{subsubsection.5.5.6}% +\contentsline {subsection}{\numberline {5.6}Häufige Fehler und ihre Behebung}{31}{subsection.5.6}% +\contentsline {subsubsection}{\numberline {5.6.1}Fehler 1: ''can't get nginx-proxy container ID''}{31}{subsubsection.5.6.1}% +\contentsline {subsubsection}{\numberline {5.6.2}Fehler 2: ''contact email has forbidden domain''}{31}{subsubsection.5.6.2}% +\contentsline {subsubsection}{\numberline {5.6.3}Fehler 3: ''DNS problem: NXDOMAIN''}{32}{subsubsection.5.6.3}% +\contentsline {subsection}{\numberline {5.7}Wie füge ich später weitere Subdomains hinzu?}{32}{subsection.5.7}% +\contentsline {subsection}{\numberline {5.8}Wie funktioniert der Reverse Proxy im Detail?}{32}{subsection.5.8}% +\contentsline {subsection}{\numberline {5.9}Zusammenfassung}{33}{subsection.5.9}% +\contentsline {section}{\numberline {6}Gitea Installation und Server-Übersicht}{33}{section.6}% +\contentsline {subsection}{\numberline {6.1}Warum ein eigener Git-Server?}{33}{subsection.6.1}% +\contentsline {subsection}{\numberline {6.2}OneDev: Der gescheiterte Versuch}{33}{subsection.6.2}% +\contentsline {subsubsection}{\numberline {6.2.1}Installationsversuch mit Docker (Version \texttt {1dev/server:latest})}{34}{subsubsection.6.2.1}% +\contentsline {subsection}{\numberline {6.3}Gitea: Die schlanke Alternative}{34}{subsection.6.3}% +\contentsline {subsection}{\numberline {6.4}Gitea mit Docker installieren}{35}{subsection.6.4}% +\contentsline {subsubsection}{\numberline {6.4.1}Schritt 1: OneDev rückstandslos entfernen}{35}{subsubsection.6.4.1}% +\contentsline {subsubsection}{\numberline {6.4.2}Schritt 2: Gitea-Verzeichnis und docker-compose.yml anlegen}{35}{subsubsection.6.4.2}% +\contentsline {subsubsection}{\numberline {6.4.3}Schritt 3: Container starten}{36}{subsubsection.6.4.3}% +\contentsline {subsubsection}{\numberline {6.4.4}Schritt 4: Firewall öffnen}{36}{subsubsection.6.4.4}% +\contentsline {subsubsection}{\numberline {6.4.5}Schritt 5: Gitea im Browser einrichten}{36}{subsubsection.6.4.5}% +\contentsline {subsection}{\numberline {6.5}Vollständige Server-Übersicht}{37}{subsection.6.5}% +\contentsline {subsubsection}{\numberline {6.5.1}Laufende Docker-Container}{37}{subsubsection.6.5.1}% +\contentsline {subsubsection}{\numberline {6.5.2}Docker-Volumes (persistente Datenspeicher)}{37}{subsubsection.6.5.2}% +\contentsline {subsubsection}{\numberline {6.5.3}Firewall (nur diese Ports sind offen!)}{37}{subsubsection.6.5.3}% +\contentsline {subsubsection}{\numberline {6.5.4}Installierte Systempakete}{38}{subsubsection.6.5.4}% +\contentsline {subsubsection}{\numberline {6.5.5}Verzeichnisstruktur unter /opt}{38}{subsubsection.6.5.5}% +\contentsline {subsection}{\numberline {6.6}Wie Gitea in die Infrastruktur passt}{38}{subsection.6.6}% +\contentsline {subsection}{\numberline {6.7}Zusammenfassung}{39}{subsection.6.7}% \providecommand \tocbasic@end@toc@file {}\tocbasic@end@toc@file diff --git a/LateX/step_04.tex b/LateX/step_04.tex new file mode 100644 index 0000000..364d88e --- /dev/null +++ b/LateX/step_04.tex @@ -0,0 +1,211 @@ +% ============================================ +% STEP 04: DOMAIN KAUFEN & DNS KONFIGURIEREN +% ============================================ + +\section{Domain kaufen und DNS konfigurieren} +\label{sec:step04} + +In diesem Schritt kaufen wir eine eigene Domain und verknüpfen sie mit unserem Server, damit die Fitness-App unter einem eigenen Namen (nicht nur der IP-Adresse) weltweit erreichbar ist. Wir machen das direkt bei unserem Server-Anbieter Contabo – das spart Verwaltungsaufwand, weil alles unter einem Dach bleibt. + +\subsection{Warum eine eigene Domain?} + +Bisher ist unsere App unter \texttt{http://185.209.229.167} erreichbar. Das hat mehrere Nachteile: + +\begin{itemize} + \item \textbf{Schwer zu merken:} Niemand kann sich IP-Adressen merken. + \item \textbf{Kein HTTPS:} Für ein SSL-Zertifikat braucht man eine Domain. Ohne HTTPS keine PWA-Installation! + \item \textbf{Unprofessionell:} Eine eigene Domain wirkt seriös und vertrauenswürdig. + \item \textbf{Flexibel:} Wenn du später den Server wechselst, änderst du einfach den DNS-Eintrag. Die Domain bleibt gleich. +\end{itemize} + +\subsection{Grundlagen: Wie funktioniert das DNS?} + +DNS steht für \textbf{Domain Name System}. Es ist das "Telefonbuch des Internets" und übersetzt menschenlesbare Domain-Namen in maschinenlesbare IP-Adressen. + +\textbf{Die wichtigsten Record-Typen:} + +\begin{table}[h] +\centering +\caption{DNS-Record-Typen und ihre Funktion} +\begin{tabular}{@{}clp{6cm}@{}} +\toprule +\textbf{Typ} & \textbf{Name} & \textbf{Funktion} \\ +\midrule +A & Address Record & Verbindet eine Domain mit einer IPv4-Adresse. "robre.de $\rightarrow$ 185.209.229.167" \\ +AAAA & IPv6 Address Record & Wie A-Record, aber für IPv6-Adressen \\ +CNAME & Canonical Name & Verweist eine Domain auf eine andere Domain (Alias) \\ +MX & Mail Exchange & Legt fest, welcher Server E-Mails für die Domain empfängt \\ +NS & Name Server & Definiert, welche Nameserver für die Domain zuständig sind \\ +TXT & Text Record & Enthält beliebige Textinformationen (z. B. für SPF, DKIM) \\ +\bottomrule +\end{tabular} +\end{table} + +\textbf{Wie eine DNS-Auflösung abläuft:} +\begin{enumerate} + \item Du gibst \texttt{robre.de} in den Browser ein. + \item Dein Rechner fragt seinen DNS-Resolver (meist bei deinem Internet-Provider): "Welche IP hat \texttt{robre.de}?" + \item Der Resolver fragt die Root-Nameserver, dann die .de-Nameserver, dann Contabos Nameserver. + \item Contabo antwortet: \texttt{robre.de = 185.209.229.167} + \item Der Browser stellt eine HTTP-Verbindung zu dieser IP her. + \item Deine App erscheint! +\end{enumerate} + +\subsection{Was ist DNS-Propagation?} + +Wenn du DNS-Einträge änderst, dauert es eine Weile, bis alle DNS-Server weltweit die neuen Informationen haben. Das nennt man \textbf{Propagation} (Verbreitung). + +\begin{itemize} + \item \textbf{Dauer:} Meist 15 Minuten bis 2 Stunden, in seltenen Fällen bis zu 48 Stunden. + \item \textbf{Grund:} Jeder DNS-Resolver hat einen Cache (Zwischenspeicher) mit alten Einträgen. Erst wenn der Cache abläuft (TTL = Time To Live), wird der aktuelle Wert abgefragt. + \item \textbf{TTL-Wert:} Unsere Einträge haben TTL 86400 = 24 Stunden. Deshalb kann es länger dauern, bis alte Caches verfallen sind. +\end{itemize} + +\textbf{Tipp:} Mit dem Befehl \texttt{nslookup robre.de ns1.contabo.net} fragst du \textbf{direkt} bei Contabos Nameserver an – ohne Cache. So siehst du sofort, ob die Konfiguration stimmt, auch wenn dein lokaler DNS die Domain noch nicht kennt. + +\subsection{Domain-Kauf bei Contabo} + +\subsubsection{Schritt 1: Einloggen ins Kundencenter} +Unter \texttt{https://contabo.com} mit deinen Zugangsdaten anmelden. + +\subsubsection{Schritt 2: Domain bestellen} +\begin{enumerate} + \item In der linken Seitenleiste auf \textbf{"Domains"} klicken. + \item Auf den blauen Button \textbf{"Domain bestellen"} klicken. + \item Wunschname eingeben (z. B. "robre") und Endung auswählen (.de, .com, .net, etc.). + \item Auf "Weiter" klicken. +\end{enumerate} + +\subsubsection{Schritt 3: Domain-Handles konfigurieren} +Auf der nächsten Seite werden die sogenannten \textbf{Domain-Handles} (Kontaktdaten) abgefragt: + +\begin{itemize} + \item \textbf{Owner / Besitzer:} Der rechtmäßige Eigentümer der Domain. Das sollte immer eine Privatperson oder Firma sein – NIEMALS der Provider! + \item \textbf{Admin:} Der administrative Ansprechpartner. Meist dieselbe Person wie der Owner. + \item \textbf{Tech:} Der technische Ansprechpartner. Hier kann der Provider stehen (Contabo GmbH). + \item \textbf{Zone:} Zonenverwaltung. Ebenfalls Contabo GmbH. +\end{itemize} + +\textbf{Standardwerte übernehmen:} Für Tech und Zone einfach die vorausgefüllte Contabo GmbH lassen. Das vereinfacht die technische Verwaltung. + +\subsubsection{Schritt 4: Nameserver festlegen} +Auf der nächsten Seite wählst du die Nameserver: + +\begin{itemize} + \item \textbf{Contabo Standard-Nameserver} auswählen (ns1.contabo.net, ns2.contabo.net, ns3.contabo.net). + \item Das bedeutet: Contabo verwaltet die DNS-Einträge für dich. Du kannst sie jederzeit im Kundencenter ändern. +\end{itemize} + +\subsubsection{Schritt 5: IP-Adresse auswählen} +Hier wählst du aus, auf welchen deiner Server die Domain zeigen soll. In unserem Fall: + +\begin{itemize} + \item Server \textbf{"test"} mit IP \texttt{185.209.229.167} + \item Server \textbf{"prod"} mit IP \texttt{185.209.230.235} +\end{itemize} + +\textbf{Empfehlung:} Nur die erste IP (\texttt{185.209.229.167}) auswählen, da dort unsere App läuft. Man kann später weitere Einträge hinzufügen. + +\subsubsection{Schritt 6: Bestellung abschließen} +Die Zusammenfassung prüfen und auf \textbf{"Bestellen \& Bezahlen"} klicken. + +\subsection{DNS-Einträge für die Domain einrichten} + +Nach dem Kauf muss die Domain noch mit unserer Server-IP verknüpft werden. Das machen wir im \textbf{DNS Zone Management}. + +\subsubsection{Schritt 1: DNS Zone Management öffnen} +Im Contabo Control Panel: \textbf{Netzwerkdienste $\rightarrow$ DNS-Verwaltung} oder direkter: \textbf{Netzwerkdienste $\rightarrow$ "DNS-Zone für [deine Domain] bearbeiten"}. + +\subsubsection{Schritt 2: Notwendige A-Records anlegen} +Wir brauchen drei A-Records: + +\begin{enumerate} + \item \textbf{Hauptdomain ohne Subdomain:} + \begin{itemize} + \item Name: \texttt{robre.de} + \item Typ: A + \item Data: \texttt{185.209.229.167} + \item TTL: \texttt{86400} + \end{itemize} + + \item \textbf{www-Subdomain:} + \begin{itemize} + \item Name: \texttt{www.robre.de} + \item Typ: A + \item Data: \texttt{185.209.229.167} + \item TTL: \texttt{86400} + \end{itemize} + + \item \textbf{Wildcard für alle anderen Subdomains (optional, aber nützlich):} + \begin{itemize} + \item Name: \texttt{*.robre.de} + \item Typ: A + \item Data: \texttt{185.209.229.167} + \item TTL: \texttt{86400} + \end{itemize} +\end{enumerate} + +\textbf{Warum alle drei?} +\begin{itemize} + \item \texttt{robre.de} – die Hauptdomain, die die meisten Nutzer eingeben. + \item \texttt{www.robre.de} – viele Nutzer geben aus Gewohnheit "www." ein. + \item \texttt{*.robre.de} – fängt alle zukünftigen Subdomains ab (z. B. \texttt{app.robre.de}, \texttt{api.robre.de}), ohne dass wir jedes Mal einen neuen Eintrag anlegen müssen. +\end{itemize} + +\subsection{DNS-Propagation prüfen und beschleunigen} + +\subsubsection{Direkt beim Nameserver prüfen} +Dieser Befehl fragt \textbf{direkt} Contabos Nameserver an – ohne Cache. Wenn hier die richtige IP erscheint, ist die Konfiguration korrekt und wir müssen nur auf die weltweite Verbreitung warten. + +\begin{lstlisting}[language=Bash, caption={DNS direkt bei Contabo abfragen}] +nslookup robre.de ns1.contabo.net +\end{lstlisting} + +\textbf{Ausgabe bei korrekter Konfiguration:} +\begin{lstlisting}[language=Bash, caption={Erwartete Ausgabe}] +Server: ns1.contabo.net +Address: 2a02:c207:ff00:1200::1#53 + +Name: robre.de +Address: 185.209.229.167 +\end{lstlisting} + +\subsubsection{Lokalen DNS-Cache leeren} +Manchmal hat dein Rechner noch alte DNS-Einträge im Cache. So löschst du ihn: + +\begin{lstlisting}[language=Bash, caption={DNS-Cache leeren unter Linux mit systemd-resolved}] +sudo resolvectl flush-caches +\end{lstlisting} + +\subsubsection{Server direkt über IP prüfen} +Um sicherzugehen, dass der Server selbst erreichbar ist (unabhängig von DNS), testen wir mit curl: + +\begin{lstlisting}[language=Bash, caption={Server direkt über IP testen}] +curl -I http://185.209.229.167 +\end{lstlisting} + +\textbf{Erwartete Ausgabe:} +\begin{lstlisting}[language=Bash, caption={Server antwortet korrekt}] +HTTP/1.1 200 OK +Server: nginx/1.30.0 +Content-Type: text/html +... +\end{lstlisting} + +\texttt{HTTP/1.1 200 OK} bedeutet: Der Server läuft, die App ist erreichbar. Das Problem liegt ausschließlich an der DNS-Verbreitung. + +\subsubsection{Online DNS-Checker verwenden} +Websites wie \texttt{https://dnschecker.org} oder \texttt{https://whatsmydns.net} zeigen an, von welchen Standorten weltweit die Domain bereits aufgelöst wird. Praktisches Werkzeug, um den Fortschritt der Propagation zu verfolgen! + +\subsection{Zusammenfassung} +Nach diesem Schritt haben wir: + +\begin{itemize} + \item Eine eigene Domain \texttt{robre.de} für 11,88 \texteuro\ / Jahr + \item DNS-Einträge, die auf unsere Server-IP \texttt{185.209.229.167} zeigen + \item Geprüft, dass Contabo die Domain korrekt registriert hat + \item Geprüft, dass der Server direkt über die IP erreichbar ist + \item DNS-Propagation abwarten, bis die Domain weltweit funktioniert +\end{itemize} + +Als nächstes folgt die Einrichtung von HTTPS mit einem kostenlosen SSL-Zertifikat – das ist die Voraussetzung für die PWA-Installation! \ No newline at end of file diff --git a/LateX/step_05.tex b/LateX/step_05.tex new file mode 100644 index 0000000..35400c3 --- /dev/null +++ b/LateX/step_05.tex @@ -0,0 +1,323 @@ + +\section{HTTPS mit nginx-proxy und Let's Encrypt} +\label{sec:step05} + +In diesem Schritt richten wir \textbf{HTTPS} für unsere Domain ein. Dafür nutzen wir zwei Docker-Container: \texttt{nginx-proxy} als Reverse Proxy und \texttt{acme-companion} für automatische SSL-Zertifikate von Let's Encrypt. Nach diesem Schritt ist unsere App unter \texttt{https://robre.de} erreichbar und erfüllt alle Voraussetzungen für die PWA-Installation. + +\subsection{Warum brauchen wir HTTPS?} + +HTTP (Hypertext Transfer Protocol) sendet alle Daten im \textbf{Klartext}. Ein Angreifer im gleichen Netzwerk kann mitlesen, manipulieren oder die Verbindung kapern. HTTPS (HTTP Secure) verschlüsselt die gesamte Kommunikation zwischen Browser und Server mittels TLS (Transport Layer Security). + +\textbf{Für Progressive Web Apps ist HTTPS zwingend vorgeschrieben:} +\begin{itemize} + \item Der \textbf{Service Worker} – das Herzstück einer PWA – funktioniert nur mit HTTPS + \item Browser verweigern die PWA-Installation bei unverschlüsselten Verbindungen + \item Moderne Browser-APIs (Geolocation, Kamera, Push-Benachrichtigungen) erfordern HTTPS +\end{itemize} + +\subsection{Wie funktioniert das SSL-Zertifikat von Let's Encrypt?} + +\textbf{Let's Encrypt} ist eine kostenlose Zertifizierungsstelle (Certificate Authority). Der Ablauf der Zertifikatserstellung läuft automatisch nach dem \textbf{ACME-Protokoll} (Automatic Certificate Management Environment): + +\begin{enumerate} + \item Der \texttt{acme-companion} fordert ein Zertifikat für \texttt{robre.de} an + \item Let's Encrypt stellt eine \textbf{Challenge} – eine Aufgabe, die beweist, dass du die Domain kontrollierst + \item Der \texttt{acme-companion} legt eine temporäre Datei auf deinem Webserver ab + \item Let's Encrypt prüft, ob diese Datei unter \texttt{http://robre.de/.well-known/acme-challenge/...} erreichbar ist + \item Wenn ja: Zertifikat wird ausgestellt und automatisch in den nginx eingebunden + \item Das Zertifikat ist 90 Tage gültig und wird automatisch erneuert +\end{enumerate} + +\textbf{Wichtige Voraussetzung:} Die Domain muss weltweit über DNS erreichbar sein (\textbf{DNS-Propagation}). Ohne funktionierende DNS-Auflösung schlägt die Challenge fehl – Let's Encrypt kann die Domain nicht finden und verweigert die Zertifikatsausstellung. + +\subsection{DNS-Propagation: Wie lange dauert es?} + +Wenn du eine neue Domain registrierst oder DNS-Einträge änderst, dauert es eine Weile, bis alle DNS-Server weltweit die neuen Informationen kennen. Diesen Prozess nennt man \textbf{DNS-Propagation}. + +\begin{itemize} + \item \textbf{Normale Dauer:} 15 Minuten bis 2 Stunden + \item \textbf{Maximale Dauer:} Bis zu 48 Stunden (in seltenen Fällen) + \item \textbf{Beeinflussender Faktor:} Der \textbf{TTL-Wert} (Time To Live) der DNS-Einträge. Unser Wert von 86400 Sekunden (24 Stunden) erlaubt anderen DNS-Servern, die Information bis zu 24 Stunden zwischenzuspeichern. +\end{itemize} + +\textbf{So prüfst du den Status der Propagation:} + +\begin{lstlisting}[language=Bash, caption={DNS-Auflösung lokal prüfen}] +# Über deinen Standard-DNS-Resolver +nslookup robre.de + +# Direkt bei Contabos Nameserver (ohne Cache) +nslookup robre.de ns1.contabo.net + +# Über Googles öffentlichen DNS (8.8.8.8) +nslookup robre.de 8.8.8.8 +\end{lstlisting} + +Erscheint als Antwort \texttt{185.209.229.167}, ist die Propagation für diesen Server abgeschlossen. Erscheint \texttt{NXDOMAIN} (Non-Existent Domain), kennt der DNS-Server die Domain noch nicht. + +\textbf{Online-Tool zur weltweiten Prüfung:} \texttt{https://dnschecker.org} zeigt auf einer Weltkarte, an welchen Standorten die Domain bereits aufgelöst wird. + +\subsection{Architektur: Wie hängen die Container zusammen?} + +Nach diesem Schritt sieht unsere Docker-Infrastruktur so aus: + +\begin{verbatim} +Internet + | + | HTTPS (Port 443) + v +nginx-proxy (Reverse Proxy) + | + +-- robre.de --> fitness-web (Port 80) + | | + | | /api/* --> fitness-api (Port 5000) + | + +-- SSL-Zertifikate von acme-companion verwaltet +\end{verbatim} + +\textbf{Erklärung der Komponenten:} +\begin{itemize} + \item \texttt{nginx-proxy}: Empfängt alle HTTP/HTTPS-Anfragen und leitet sie an den richtigen Container weiter. Entscheidet anhand des \texttt{Host}-Headers (enthält die Domain), welcher Container die Anfrage bekommt. + \item \texttt{acme-companion}: Überwacht laufende Container auf die Umgebungsvariable \texttt{LETSENCRYPT\_HOST}. Wenn eine neue Domain auftaucht, fordert er automatisch ein SSL-Zertifikat an und konfiguriert nginx. + \item \texttt{fitness-web}: Unser React-Frontend mit Nginx. Braucht selbst kein SSL – der Proxy übernimmt die Verschlüsselung. + \item \texttt{fitness-api}: Unser .NET-Backend. Nur über das interne Docker-Netzwerk erreichbar, nicht direkt von außen. +\end{itemize} + +\subsection{Schritt-für-Schritt: HTTPS einrichten} + +\subsubsection{Schritt 1: Bestehende Container stoppen und löschen} + +Da wir von manuellen \texttt{docker run}-Befehlen auf \texttt{docker compose} umsteigen, müssen die alten Container entfernt werden. + +\begin{lstlisting}[language=Bash, caption={Alte Container stoppen und löschen}] +ssh testserver +docker stop fitness-web fitness-api +docker rm fitness-web fitness-api +\end{lstlisting} + +\subsubsection{Schritt 2: Verzeichnis für docker-compose anlegen} + +\begin{lstlisting}[language=Bash, caption={Projektverzeichnis auf dem Server}] +mkdir -p /opt/fitness +cd /opt/fitness +\end{lstlisting} + +\subsubsection{Schritt 3: docker-compose.yml erstellen} + +\texttt{docker compose} ist ein Tool, mit dem wir mehrere Container als \textbf{eine Einheit} definieren und verwalten können. Statt vier einzelner \texttt{docker run}-Befehle definieren wir alle Container in einer YAML-Datei. + +Erstelle die Datei mit \texttt{nano /opt/fitness/docker-compose.yml}: + +\begin{lstlisting}[language=YAML, caption={Vollständige docker-compose.yml}] +services: + # ============================================ + # REVERSE PROXY (nimmt HTTP/HTTPS-Anfragen entgegen) + # ============================================ + nginx-proxy: + image: nginxproxy/nginx-proxy + container_name: nginx-proxy + restart: unless-stopped + ports: + - ''80:80'' + - ''443:443'' + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - certs:/etc/nginx/certs + - vhost:/etc/nginx/vhost.d + - html:/usr/share/nginx/html + networks: + - proxy-net + + # ============================================ + # SSL-ZERTIFIKATE (automatisch via Let's Encrypt) + # ============================================ + acme-companion: + image: nginxproxy/acme-companion + container_name: acme-companion + restart: unless-stopped + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - certs:/etc/nginx/certs + - vhost:/etc/nginx/vhost.d + - html:/usr/share/nginx/html + - acme:/etc/acme.sh + environment: + - DEFAULT_EMAIL=robert@robre.de + - NGINX_PROXY_CONTAINER=nginx-proxy + depends_on: + - nginx-proxy + networks: + - proxy-net + + # ============================================ + # BACKEND (.NET 8 API) + # ============================================ + backend: + image: fitness-api:latest + container_name: fitness-api + restart: unless-stopped + volumes: + - fitness-data:/app/data + networks: + - proxy-net + + # ============================================ + # FRONTEND (React + Nginx) + # ============================================ + frontend: + image: fitness-web:latest + container_name: fitness-web + restart: unless-stopped + environment: + - VIRTUAL_HOST=robre.de,www.robre.de + - LETSENCRYPT_HOST=robre.de,www.robre.de + - VIRTUAL_PORT=80 + depends_on: + - backend + networks: + - proxy-net + +# ============================================ +# VOLUMES (persistente Datenspeicher) +# ============================================ +volumes: + certs: + vhost: + html: + acme: + fitness-data: + +# ============================================ +# NETZWERKE +# ============================================ +networks: + proxy-net: + driver: bridge +\end{lstlisting} + +\textbf{Zeile für Zeile erklärt:} + +\paragraph{nginx-proxy} +\begin{itemize} + \item \texttt{image: nginxproxy/nginx-proxy} – Offizielles Image des nginx-proxy-Projekts. + \item \texttt{ports: ''80:80'' / ''443:443''} – Nur dieser Container lauscht auf den Standard-Webports. Alle HTTP/HTTPS-Anfragen kommen hier an. + \item \texttt{/var/run/docker.sock:/tmp/docker.sock:ro} – Bindet den Docker-Socket ein (read-only). Darüber erkennt nginx-proxy, welche Container gerade laufen und welche Domains sie bedienen. + \item \texttt{certs:/etc/nginx/certs} – Hier speichert der acme-companion die SSL-Zertifikate. +\end{itemize} + +\paragraph{acme-companion} +\begin{itemize} + \item \texttt{DEFAULT\_EMAIL} – Für Let's-Encrypt-Benachrichtigungen (z. B. wenn ein Zertifikat abläuft). \textbf{Muss eine echte, erreichbare E-Mail-Adresse sein!} + \item \texttt{NGINX\_PROXY\_CONTAINER=nginx-proxy} – Sagt dem acme-companion explizit, wie der Proxy-Container heißt. Notwendig, wenn der Container-Name vom Standard abweicht. + \item \texttt{depends\_on: nginx-proxy} – Stellt sicher, dass der Proxy zuerst startet. +\end{itemize} + +\paragraph{frontend (entscheidende Umgebungsvariablen!)} +\begin{itemize} + \item \texttt{VIRTUAL\_HOST=robre.de,www.robre.de} – Sagt nginx-proxy: ''Ich bin für diese Domains zuständig''. Alle Anfragen an \texttt{robre.de} oder \texttt{www.robre.de} werden an diesen Container weitergeleitet. + \item \texttt{LETSENCRYPT\_HOST=robre.de,www.robre.de} – Sagt acme-companion: ''Hol SSL-Zertifikate für diese Domains''. + \item \texttt{VIRTUAL\_PORT=80} – Der interne Port, auf dem der Container lauscht (unser Nginx im Frontend-Container). +\end{itemize} + +\paragraph{Docker Volumes} +\begin{itemize} + \item \texttt{certs, vhost, html, acme} – Speichern SSL-Zertifikate, Konfiguration und Challenge-Dateien. Diese Volumes werden von nginx-proxy und acme-companion geteilt. + \item \texttt{fitness-data} – Persistente Speicherung der SQLite-Datenbank (siehe Schritt 03). +\end{itemize} + +\subsubsection{Schritt 4: Container starten} + +\begin{lstlisting}[language=Bash, caption={Alle Container im Hintergrund starten}] +cd /opt/fitness +docker compose up -d +\end{lstlisting} + +\texttt{-d} steht für \textbf{detached} – die Container laufen im Hintergrund und blockieren nicht das Terminal. + +\subsubsection{Schritt 5: Status prüfen} + +\begin{lstlisting}[language=Bash, caption={Laufende Container anzeigen}] +docker ps +\end{lstlisting} + +Es sollten vier Container erscheinen: \texttt{nginx-proxy}, \texttt{acme-companion}, \texttt{fitness-api}, \texttt{fitness-web}. + +\subsubsection{Schritt 6: Logs des acme-companion prüfen} + +\begin{lstlisting}[language=Bash, caption={SSL-Zertifikatserstellung verfolgen}] +docker logs -f acme-companion +\end{lstlisting} + +Bei erfolgreicher Zertifikatserstellung erscheinen diese Meldungen: +\begin{lstlisting}[language=Bash, caption={Erfolgreiche Ausgabe}] +[Thu May 7 09:56:11 UTC 2026] Registered +[Thu May 7 09:56:14 UTC 2026] Account update success +Creating/renewal robre.de certificates... (robre.de www.robre.de) +\end{lstlisting} + +\subsection{Häufige Fehler und ihre Behebung} + +\subsubsection{Fehler 1: ''can't get nginx-proxy container ID''} + +\textbf{Ursache:} Der acme-companion findet den Proxy-Container nicht, weil dieser einen individuellen Namen hat (\texttt{nginx-proxy} statt dem Standard). + +\textbf{Lösung:} Die Umgebungsvariable \texttt{NGINX\_PROXY\_CONTAINER=nginx-proxy} im acme-companion setzen (wie oben bereits eingebaut). + +\subsubsection{Fehler 2: ''contact email has forbidden domain''} + +\textbf{Ursache:} Die \texttt{DEFAULT\_EMAIL} enthält eine ungültige Domain wie \texttt{@example.com} – Let's Encrypt lehnt reservierte Domains ab. + +\textbf{Lösung:} Eine echte, erreichbare E-Mail-Adresse verwenden (z. B. \texttt{robert@robre.de}). + +\subsubsection{Fehler 3: ''DNS problem: NXDOMAIN''} + +\textbf{Ursache:} Die DNS-Propagation ist noch nicht abgeschlossen. Let's Encrypt kann die Domain nicht auflösen und verweigert die Zertifikatsausstellung. + +\textbf{Lösung:} Warten, bis die Domain weltweit erreichbar ist (bis zu 24 Stunden). Dann den acme-companion neustarten: + +\begin{lstlisting}[language=Bash, caption={Zertifikatserstellung erneut anstoßen}] +docker restart acme-companion +\end{lstlisting} + +\subsection{Wie füge ich später weitere Subdomains hinzu?} + +Das System ist extrem flexibel. Angenommen, du willst später eine Todo-App unter \texttt{todo.robre.de} hosten: + +\begin{enumerate} + \item \textbf{DNS-Eintrag beim Hoster:} Einen neuen A-Record für \texttt{todo.robre.de} anlegen, der auf dieselbe Server-IP \texttt{185.209.229.167} zeigt. Oder: Der Wildcard-Eintrag \texttt{*.robre.de} fängt automatisch alle nicht explizit definierten Subdomains ab! + \item \textbf{Docker-Container:} Einen neuen Container mit den Umgebungsvariablen \texttt{VIRTUAL\_HOST=todo.robre.de} und \texttt{LETSENCRYPT\_HOST=todo.robre.de} starten. + \item \textbf{Fertig!} nginx-proxy erkennt den neuen Container automatisch und leitet Anfragen weiter. acme-companion holt automatisch ein SSL-Zertifikat. +\end{enumerate} + +\textbf{Du musst auf dem Server nichts weiter konfigurieren – alles läuft automatisch!} + +\subsection{Wie funktioniert der Reverse Proxy im Detail?} + +Wenn eine Anfrage an \texttt{https://robre.de/api/workouts} eingeht: + +\begin{enumerate} + \item Die Anfrage kommt an Port 443 des Servers an (HTTPS). + \item nginx-proxy nimmt die Anfrage entgegen und entschlüsselt sie mit dem SSL-Zertifikat. + \item nginx-proxy schaut in den \texttt{Host}-Header: \texttt{robre.de}. + \item In seiner Konfiguration findet er: \texttt{robre.de} → Container \texttt{fitness-web}, Port 80. + \item Er leitet die Anfrage an \texttt{fitness-web:80} weiter (internes Docker-Netzwerk). + \item Der Nginx im Frontend-Container empfängt die Anfrage an \texttt{/api/workouts}. + \item Seine Konfiguration sagt: Alles mit \texttt{/api/} → weiterleiten an \texttt{fitness-api:5000}. + \item Das Backend verarbeitet die Anfrage und schickt die Antwort zurück durch die gesamte Kette. +\end{enumerate} + +\textbf{Die gesamte Kommunikation innerhalb des Docker-Netzwerks (Schritte 5-8) läuft unverschlüsselt – das ist okay, weil sie den Server nie verlässt.} + +\subsection{Zusammenfassung} + +Nach diesem Schritt haben wir: + +\begin{itemize} + \item Einen automatischen Reverse Proxy (nginx-proxy), der Anfragen an die richtigen Container verteilt + \item Kostenlose SSL-Zertifikate von Let's Encrypt, die sich automatisch erneuern + \item Eine Infrastruktur, die beliebig viele weitere Domains und Subdomains aufnehmen kann – ohne manuelle Konfiguration + \item Die App ist unter \texttt{https://robre.de} verschlüsselt erreichbar + \item Alle Voraussetzungen für die PWA-Installation sind erfüllt +\end{itemize} + +\textbf{Wartezeit beachten:} Nach der Einrichtung kann es bis zu 24 Stunden dauern, bis die DNS-Propagation abgeschlossen ist und Let's Encrypt die Zertifikate ausstellen kann. Der acme-companion versucht es automatisch jede Stunde erneut. \ No newline at end of file diff --git a/LateX/step_06.tex b/LateX/step_06.tex new file mode 100644 index 0000000..cfa559e --- /dev/null +++ b/LateX/step_06.tex @@ -0,0 +1,325 @@ +% ============================================ +% STEP 06: GITEA INSTALLATION & SERVER-ÜBERSICHT +% ============================================ + +\section{Gitea Installation und Server-Übersicht} +\label{sec:step06} + +In diesem Schritt installieren wir \textbf{Gitea} – einen selbst gehosteten Git-Server mit Web-Oberfläche – als Ersatz für OneDev, das sich leider als fehlerhaft erwies. Am Ende dieses Kapitels hast du einen vollständigen Überblick über deinen Server: welche Container laufen, welche Ports offen sind, wo die Daten liegen und wie alles zusammenhängt. + +\subsection{Warum ein eigener Git-Server?} + +Bisher haben wir den Code manuell gebaut, als Docker-Image exportiert und per \texttt{scp} auf den Server kopiert – ein umständlicher Prozess, der bei jedem Update wiederholt werden muss. Ein eigener Git-Server mit CI/CD-Pipeline automatisiert diesen Ablauf: + +\begin{itemize} + \item \textbf{Push = Deploy:} Code auf den Server pushen, Pipeline baut automatisch Docker-Images und startet Container neu + \item \textbf{Versionierung:} Alle Änderungen sind nachvollziehbar, kein „das ging gestern noch"-Problem + \item \textbf{Teamarbeit:} Mehrere Entwickler können gleichzeitig am Projekt arbeiten + \item \textbf{Backup:} Das Repository liegt auf deinem Server, nicht bei GitHub/GitLab +\end{itemize} + +\subsection{OneDev: Der gescheiterte Versuch} + +Ursprünglich wollten wir \textbf{OneDev} installieren – eine All-in-One-Lösung aus Git-Server, CI/CD-Pipeline, Issue-Tracker und Paket-Registry. OneDev bietet deutlich mehr Funktionen als Gitea, erwies sich jedoch als problematisch: + +\subsubsection{Installationsversuch mit Docker (Version \texttt{1dev/server:latest})} + +\begin{lstlisting}[language=YAML, caption={docker-compose.yml für OneDev}] +services: + onedev: + image: 1dev/server:latest + container_name: onedev + restart: unless-stopped + ports: + - "6610:6610" + - "6611:6611" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - onedev_data:/opt/onedev + +volumes: + onedev_data: +\end{lstlisting} + +\textbf{Aufgetretene Probleme:} + +\begin{enumerate} + \item \textbf{Container stoppt sofort:} Nach dem Start erschien in den Logs nur „INFO - Stopping application". Der Container beendete sich ohne Fehlermeldung. + + \item \textbf{Workaround mit fester Version:} Statt \texttt{latest} nutzten wir \texttt{1dev/server:11.6.13} – gleiches Problem. + + \item \textbf{Datenbank-Fehler:} Die entscheidende Fehlermeldung in \texttt{/opt/onedev/logs/server.log}: + \begin{lstlisting}[language=Bash, caption={Kritischer Fehler beim OneDev-Start}] +java.lang.IllegalStateException: EntityManagerFactory is closed + at org.hibernate.internal.SessionFactoryImpl.validateNotClosed(...) + \end{lstlisting} + + \textbf{Ursache:} OneDevs interne H2-Datenbank wurde beim ersten Start korrupt. Der Befehl \texttt{upgrade /opt/onedev} im Start-Script versuchte, eine nicht existierende Datenbank zu aktualisieren statt sie neu anzulegen. Selbst komplettes Löschen des Volumes und Neustart behoben das Problem nicht – die Logs wurden nach dem ersten Crash nicht mehr aktualisiert, der Container hing fest. + + \item \textbf{Versuch mit direkter Java-Installation:} Nachdem Docker scheiterte, luden wir die JAR-Datei herunter (57 Bytes – defekter Download) und stellten fest, dass Java nicht installiert war. Zu diesem Zeitpunkt war klar: Der Aufwand für OneDev steht in keinem Verhältnis zum Nutzen. +\end{enumerate} + +\textbf{Fazit:} OneDev ist ein mächtiges Tool, aber die Docker-Images sind instabil. Für einen produktiven Einsatz wäre eine native Installation mit externer PostgreSQL-Datenbank empfehlenswert – für unsere Zwecke überdimensioniert. + +\subsection{Gitea: Die schlanke Alternative} + +\textbf{Gitea} ist ein in Go geschriebener Git-Server, der sich durch Einfachheit und geringe Ressourcenanforderungen auszeichnet. Im Vergleich zu OneDev: + +\begin{table}[h] +\centering +\caption{Vergleich OneDev vs. Gitea} +\begin{tabular}{@{}p{3cm}ll@{}} +\toprule +\textbf{Merkmal} & \textbf{OneDev} & \textbf{Gitea} \\ +\midrule +Größe Image & $\sim$500 MB & $\sim$100 MB \\ +Startzeit & 2–5 Minuten & $\sim$5 Sekunden \\ +CI/CD & h Eingebaut & x Extern (z.B. Woodpecker CI) \\ +Datenbank & H2 (intern, fehleranfällig) & SQLite3, PostgreSQL, MySQL \\ +Komplexität & Hoch & Gering \\ +Installation & Fehlgeschlagen & h In 10 Sekunden \\ +\bottomrule +\end{tabular} +\end{table} + +\subsection{Gitea mit Docker installieren} + +\subsubsection{Schritt 1: OneDev rückstandslos entfernen} + +\begin{lstlisting}[language=Bash, caption={OneDev komplett löschen}] +cd /opt/onedev +docker compose down 2>/dev/null # Container stoppen +cd / +rm -rf /opt/onedev # Verzeichnis löschen +docker system prune -af # Ungenutzte Images/Volumes entfernen +\end{lstlisting} + +\texttt{docker system prune -af} löscht: +\begin{itemize} + \item Alle gestoppten Container + \item Alle ungenutzten Netzwerke + \item Alle ungenutzten Images + \item Alle ungenutzten Build-Caches +\end{itemize} + +Insgesamt wurden 806 MB Speicher freigegeben! + +\subsubsection{Schritt 2: Gitea-Verzeichnis und docker-compose.yml anlegen} + +\begin{lstlisting}[language=Bash, caption={Gitea-Verzeichnis vorbereiten}] +mkdir -p /opt/gitea +nano /opt/gitea/docker-compose.yml +\end{lstlisting} + +\begin{lstlisting}[language=YAML, caption={docker-compose.yml für Gitea}] +services: + gitea: + image: gitea/gitea:latest + container_name: gitea + restart: unless-stopped + ports: + - "3000:3000" # Web-UI + - "2222:22" # SSH für Git-Operationen + volumes: + - gitea_data:/data + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + +volumes: + gitea_data: +\end{lstlisting} + +\textbf{Erklärung der Konfiguration:} +\begin{itemize} + \item \texttt{ports: "3000:3000"} – Die Web-Oberfläche ist auf Port 3000 erreichbar + \item \texttt{ports: "2222:22"} – Git-Operationen per SSH laufen auf Port 2222 (weil Port 22 bereits vom Host-SSH belegt ist) + \item \texttt{gitea\_data:/data} – Alle Gitea-Daten (Repositories, Konfiguration, Datenbank) liegen in diesem Volume + \item \texttt{/etc/timezone:/etc/timezone:ro} – Übergibt die Zeitzone des Hosts an den Container (\texttt{ro} = read-only) + \item \texttt{/etc/localtime:/etc/localtime:ro} – Übergibt die lokale Zeit +\end{itemize} + +\subsubsection{Schritt 3: Container starten} + +\begin{lstlisting}[language=Bash, caption={Gitea starten}] +cd /opt/gitea +docker compose up -d +\end{lstlisting} + +Ausgabe: +\begin{lstlisting}[language=Bash, caption={Erfolgreicher Start}] +[+] up 9/9 + h Image gitea/gitea:latest Pulled + h Network gitea_default Created + h Volume gitea_gitea_data Created + h Container gitea Started +\end{lstlisting} + +\subsubsection{Schritt 4: Firewall öffnen} + +\begin{lstlisting}[language=Bash, caption={Port 3000 freigeben}] +ufw allow 3000/tcp +\end{lstlisting} + +\subsubsection{Schritt 5: Gitea im Browser einrichten} + +\textbf{URL:} \texttt{http://185.209.229.167:3000} + +Beim ersten Aufruf erscheint die Installationsseite. Folgende Einstellungen sind vorausgefüllt und können übernommen werden: + +\begin{itemize} + \item \textbf{Datenbanktyp:} SQLite3 (einfachste Option, perfekt für kleine Teams) + \item \textbf{Pfad:} \texttt{/data/gitea/gitea.db} + \item \textbf{Server-Domain:} \texttt{185.209.229.167} + \item \textbf{Gitea-Basis-URL:} \texttt{http://185.209.229.167:3000/} + \item \textbf{SSH-Server-Port:} 22 + \item \textbf{Gitea-HTTP-Listen-Port:} 3000 +\end{itemize} + +\textbf{Wichtig:} Unter „Administratoreninstellungen" (ganz unten aufklappen) musst du einen Admin-Account anlegen: + +\begin{itemize} + \item \textbf{Benutzername:} robert + \item \textbf{Passwort:} [dein sicheres Passwort] + \item \textbf{E-Mail:} robert@robre.de +\end{itemize} + +Dann auf \textbf{„Gitea installieren"} klicken. Nach wenigen Sekunden ist Gitea einsatzbereit. + +\subsection{Vollständige Server-Übersicht} + +Nach diesem Schritt ergibt sich folgendes Gesamtbild deines Servers: + +\subsubsection{Laufende Docker-Container} + +\begin{table}[h] +\centering +\caption{Alle laufenden Container auf dem Server} +\begin{tabular}{@{}llll@{}} +\toprule +\textbf{Container} & \textbf{Image} & \textbf{Ports} & \textbf{Aufgabe} \\ +\midrule +\texttt{gitea} & \texttt{gitea/gitea:latest} & 3000, 2222→22 & Git-Server mit Web-UI \\ +\texttt{nginx-proxy} & \texttt{nginxproxy/nginx-proxy} & 80, 443 & Reverse Proxy \\ +\texttt{acme-companion} & \texttt{nginxproxy/acme-companion} & – & SSL-Zertifikate (Let's Encrypt) \\ +\texttt{fitness-web} & \texttt{fitness-web:latest} & 80 (intern) & React-Frontend \\ +\texttt{fitness-api} & \texttt{fitness-api:latest} & 5000 (intern) & .NET 8 Backend \\ +\bottomrule +\end{tabular} +\end{table} + +\subsubsection{Docker-Volumes (persistente Datenspeicher)} + +\begin{table}[h] +\centering +\caption{Volumes und ihre Inhalte} +\begin{tabular}{@{}ll@{}} +\toprule +\textbf{Volume} & \textbf{Inhalt} \\ +\midrule +\texttt{gitea\_gitea\_data} & Gitea: Repositories, Datenbank, Konfiguration \\ +\texttt{fitness\_fitness-data} & Fitness-App: SQLite-Datenbank (\texttt{/app/data}) \\ +\texttt{fitness\_certs} & SSL-Zertifikate von Let's Encrypt \\ +\texttt{fitness\_html} & Challenge-Dateien für Let's Encrypt \\ +\texttt{fitness\_vhost} & Nginx-Konfiguration pro Virtual Host \\ +\texttt{fitness\_acme} & ACME-Kontodaten \\ +\bottomrule +\end{tabular} +\end{table} + +\subsubsection{Firewall (nur diese Ports sind offen!)} + +\begin{table}[h] +\centering +\caption{Geöffnete Ports} +\begin{tabular}{@{}cll@{}} +\toprule +\textbf{Port} & \textbf{Dienst} & \textbf{Begründung} \\ +\midrule +22 & SSH & Server-Verwaltung \\ +80 & HTTP & Fitness-App, leitet auf HTTPS um \\ +443 & HTTPS & Fitness-App (verschlüsselt), PWA-Pflicht! \\ +3000 & Gitea Web & Git-Server-Oberfläche \\ +\bottomrule +\end{tabular} +\end{table} + +\subsubsection{Installierte Systempakete} + +\begin{itemize} + \item \texttt{docker-ce}, \texttt{docker-ce-cli}, \texttt{docker-compose-plugin} – Docker-Plattform + \item \texttt{fail2ban} – Bruteforce-Schutz für SSH + \item \texttt{git} – Git (von Gitea genutzt) +\end{itemize} + +Der Server ist bewusst schlank gehalten – keine überflüssigen Dienste, keine unnötigen Pakete. + +\subsubsection{Verzeichnisstruktur unter /opt} + +\begin{lstlisting}[language=Bash, caption={Projektverzeichnisse auf dem Server}] +/opt/ + containerd/ # Docker-Laufzeitumgebung + fitness/ # docker-compose.yml fuer Fitness-App + docker-compose.yml + gitea/ # docker-compose.yml fuer Gitea + docker-compose.yml +\end{lstlisting} + +\subsection{Wie Gitea in die Infrastruktur passt} + +\textbf{Aktueller Datenfluss:} + +\textbf{Aktueller Datenfluss:} + +\begin{verbatim} +Du (lokal) Server (testserver) +--------- ------------------ +git push ----------------> Gitea (Port 3000/2222) + | + | (spaeter: CI/CD-Pipeline) + v + Docker-Images bauen + | + v + Container neustarten + | + v + nginx-proxy (Port 80/443) + | + +-------+-------+ + | | + v v + fitness-web fitness-api + (Port 80) (Port 5000) +\end{verbatim} + +\textbf{Was noch fehlt:} Die CI/CD-Pipeline in Gitea (z.B. mit Gitea Actions oder Woodpecker CI), die automatisch bei jedem Push Docker-Images baut und die Container aktualisiert. Das folgt in einem späteren Schritt. + +\subsection{Zusammenfassung} + +Nach diesem Schritt haben wir: + +\begin{itemize} + \item OneDev aufgrund von Docker-Inkompatibilitäten verworfen + \item Gitea erfolgreich mit Docker installiert (in unter 1 Minute!) + \item Einen vollständigen Überblick über alle Container, Volumes, Ports und Verzeichnisse + \item Die Grundlage für eine spätere CI/CD-Pipeline geschaffen +\end{itemize} + +\textbf{Nützliche Befehle für die tägliche Verwaltung:} + +\begin{lstlisting}[language=Bash, caption={Server-Cockpit – wichtige Befehle}] +# Alle laufenden Container +docker ps + +# Alle Volumes +docker volume ls + +# Firewall-Status +ufw status verbose + +# Installierte Pakete +apt list --installed | grep -E "docker|fail2ban" + +# Verzeichnisse unter /opt +ls -la /opt/ +\end{lstlisting} \ No newline at end of file diff --git a/apps/api/fitness.db-shm b/apps/api/fitness.db-shm deleted file mode 100644 index 119628b..0000000 Binary files a/apps/api/fitness.db-shm and /dev/null differ diff --git a/apps/api/fitness.db-wal b/apps/api/fitness.db-wal deleted file mode 100644 index 4f2e796..0000000 Binary files a/apps/api/fitness.db-wal and /dev/null differ diff --git a/apps/api/obj/Debug/net8.0/Api.AssemblyInfo.cs b/apps/api/obj/Debug/net8.0/Api.AssemblyInfo.cs index bb320be..ae686ff 100644 --- a/apps/api/obj/Debug/net8.0/Api.AssemblyInfo.cs +++ b/apps/api/obj/Debug/net8.0/Api.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("Api")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+2f2cbed5bd2f55d8f0fc2abb891b6a20e42ef8ea")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+0e9377739ecf945e0da1e75a85e0a06a95cd0d00")] [assembly: System.Reflection.AssemblyProductAttribute("Api")] [assembly: System.Reflection.AssemblyTitleAttribute("Api")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/apps/api/obj/Debug/net8.0/Api.AssemblyInfoInputs.cache b/apps/api/obj/Debug/net8.0/Api.AssemblyInfoInputs.cache index 49612b0..02a86d0 100644 --- a/apps/api/obj/Debug/net8.0/Api.AssemblyInfoInputs.cache +++ b/apps/api/obj/Debug/net8.0/Api.AssemblyInfoInputs.cache @@ -1 +1 @@ -7fae9bde5435323ac2efd9b5650e0c40dbec5642bd7d43db47980db6bb51f424 +ffe41f120d57867c590b01993978902e9fec8bbb7e05b266dbeabfa061be576e