Add steps for domain purchase and DNS configuration, set up HTTPS with nginx-proxy and Let's Encrypt, and install Gitea as a self-hosted Git server. Remove temporary database files and update assembly info for API project.

This commit is contained in:
2026-05-08 14:53:33 +02:00
parent 0e9377739e
commit b8cfa1689f
15 changed files with 1285 additions and 141 deletions
+95 -33
View File
@@ -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