top of page
AutorenbildOliver Schwerttner

Debian Server 11 - Teil 5 - Webserver, Java JDK und Tomcat (SpringBoot)

Aktualisiert: 19. Apr. 2023




In diesem Teil geht es darum, den Debian Server mit weiteren Produkten zu einem einfachen JSON/Rest Backend Server zu erweitern. Die Datenbank wurde bereits installiert. Nun folgen die Installation von Apache Webserver und Tomcat in Form von SpringBoot auf Basis des Java Developement Kits (JDK)


Dieser JSON/Rest Backend Server wird in diesem Teil als "einfacher", kleiner Backend Server konfiguriert. Daher verzichte ich hier auf eine komplexere Konfiguration / Installation mit Docker, Kubernetes, Cluster Konfiguration, Helm Charts, usw.


Des Weiteren soll dieser Server "nur" als öffentlicher JSON/Rest Backend Server dienen. Die eigentliche Software Entwicklung findet auf einem anderen Server statt. Daher werden hier auch keine CD/CI Entwicklungstools installiert, wie bspw. GitHub, Git als Repository, Maven, Ant, Python, Nexus, usw.


Apache 2 Webserver


Es gibt mittlerweile jede Menge schnelle und schlanke Webserver. Ich bleibe allerdings beim "Klassiker", dem Webserver 2 von Apache. Die Installation erfolgt einfach als root per APT:

# apt update
# apt install apache2
# systemctl restart apache2 (Webserver neu starten)
# systemctl status apache2 (Webserver überprüfen)
# ufw allow 80 (Firewall für den Webserver freischalten)
# ufw allow 443 (Firewall für https:// freischalten)
# ufw enable
# ufw status

Die Default Webseite vom Apache 2 Webserver löschen bzw. durch eine eigene (leere) Webseite ersetzen:

# cd /var/www/html/index.html
<html>
<head></head>
<body></body>
</html>

Über Webmin kann man dann den Server bequem konfigurieren



SSL/TLS (https://)


Grundsätzlich sollte man seine Webseiten mit https:// absichern.


SSL/TLS Zertifikate gibt es von "LetsEncrypt" mittlerweile kostenlos! Die Erstellung und Installation erfolgt ganz einfach mit 2 Befehlen.


Davor sollte man allerdings in allen Webseiten-Konfigurationen von Apache, die auf Port 80 konfiguriert wurden, unbedingt darauf achten, dass der ServerName eingetragen wurde und die Firewall abgeschaltet wurde!


Datei: /etc/apache2/sites-available/000-default.conf

<VirtualHost *:80>
	ServerName my.testserver.com

SSL/TLS installieren

# apt install certbot python3-certbot-apache
# certbot --apache

Das Zertifikat ist zwar nur 90 Tage gültig, der CertBot erneuert das Zertifikat allerdings automatisch selbst! Man muss sich also um nichts kümmern!


Die Neugenerierung kann man auch mit folgendem Befehl simulieren:

# certbot renew --dry-run

MIt dem nachfolgenden Befehl kann man seine Mailadresse nachträglich ändern:

# certbot update_account --email mynewmail

Danach schaltet man die Firewall wieder ein und gibt den Port für https:// (443) frei, falls nicht schon erledigt.

# ufw enable
# ufw allow 443
# ufw status

OpenJDK


OpenJDK ist der "fork" vom offiziellen Oracle Java JDK. Die Installation erfolgt mit folgendem Befehl:

# apt install openjdk-17-jdk

Oracle Java Developement Kit (JDK)


Alternativ zu OpenJDK kann man natürlich auch das originale Java JDK vom Hersteller Oracle installieren.


Ab Version 17 darf das Oracle Java JDK auf öffentlichen Repositories liegen und kostenlos ausgeliefert werden. Mit den nachfolgenden Befehlen wird das APT-Repository auf dem Debian Server erweitert und das Oracle Java JDK 17 installiert.

# cd ~ (Tilde nicht vergessen!)
# apt install software-properties-common
# add-apt-repository ppa:linuxuprising/java
# ./files/scripts/migrate-keys/migrate-apt-keys.sh
# apt update
# su - (Minus nicht vergessen!)
# echo "deb http://ppa.launchpad.net/linuxuprising/java/ubuntu focal main" | tee /etc/apt/sources.list.d/linuxuprising-java.list
# apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 73C3DB2A
# apt update
# apt install oracle-java17-installer --install-recommends


Auswahl des Default Java JDK


Mit folgenden Befehlen kann man das Standard Java auswählen:

# update-alternatives --config java
# update-alternatives --config javac

JAVA_HOME Umgebungsvariable


Definition der JAVA_HOME Umgebungsvariable. Öffnen Sie dazu die Datei "/etc/environment" und fügen sie folgenden Eintrag hinzu


JAVA_HOME="/usr/lib/jvm/java-17-oracle" (bzw. das JDK, das man vorher als Default ausgewählt hat)


... anschließend booten wir den Debian Server. Danach kann man mit folgendem Befehl den Eintrag überprüfen:

# env

SpringBoot als Server (systemd)


SpringBoot produziert eine ausführbare jar-Datei. Darin enthalten ist dann u. a. auch der Apache Tomcat Servlet Server. Die jar-Datei kann man natürlich auch manuell als User starten, nur läuft die Software dann nicht im Hintergrund und startet nicht automatisch bei jedem Serverstart. Wir wollen aber einen eigenständigen Serverdienst und diesen erstellen wir uns nun.

  1. jar-Datei ausführbar machen (rwx-rx-rx)

  2. prüfen, ob die eigene jar-Datei euch wirklich läuft

  3. prüfen, ob die Ports offen sind.

# chmod +rx /var/lib/spring-boot/rest-service.jar
# /usr/bin/java -jar /var/lib/spring-boot/rest-service.jar
# ss -ltn


Als nächstes erstellen wir einen Service-User.

# adduser --system --no-create-home --group springboot

Seit Version 8 verwenden alle Debianserver das sog. SystemD zum Starten und Stoppen von Serverdiensten. Hierzu erstellen wir nun eine kleine Konfigurationsdatei.

  1. Verzeichnis "/var/lib/spring-boot/" für die eigene SpringBoot jar-Datei erstellen

  2. die eigene jar-datei, bspw. "rest-service.jar" dort hinein kopieren

  3. Im Service-Verzeichnis die Datei "/etc/systemd/system/rest.service" erstellen

  4. in dieser Datei den folgenden Text hinzufügen:

[Unit]
Description=Own SpringBoot Service
After=syslog.target network.target

[Service]
SuccessExitStatus=143
User=springboot
Group=springboot
WorkingDirectory=/var/lib/spring-boot
Type=simple
Restart=always
RestartSec=30s
ExecStart=/usr/bin/java -jar /var/lib/spring-boot/rest-service.jar 

[Install]
WantedBy=multi-user.target

6. um den SpringBoot Dienst beim Serverstart automatisch zu starten, gibt man folgenden Befehl ein:

# systemctl enable rest.service

Mit folgenden Befehlen kann man den Dienst manuell kontrollieren

# systemctl start rest.service
# systemctl stop rest.service
# systemctl restart rest.service

Verbindung zw. Apache 2 und SpringBoot (Tomcat)


Nun verbinden wir den Apache 2 Webserver mit dem embedded Tomcat Servlet Server von SpringBoot. Dies erfolgt in 3 Schritten.

  1. Aktivierung der Proxy Module für den Apache 2 Webserver

  2. Konfiguration des Apache 2 Webservers

  3. Konfiguration des Tomcat Servers innerhalb von Springboot.


Aktivierung der Proxy Module für den Apache 2 Webserver


Virtuelle Links für die 3 Module "proxy.conf", "proxy.load" und "proxy_ajp.load" im Verzeichnis mods-enabled erstellen.



Konfiguration des Apache 2 Webservers


Als root die folgende Datei öffnen und wie folgt konfigurieren:


=> /etc/apache2/sites-available/000-default-le-ssl.conf

<IfModule mod_ssl.c>
<VirtualHost *:443>
	ServerName my.testserver.com

	ServerAdmin admin@mytestserver.com
	DocumentRoot /var/www/html

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined
    
    # secret without ""!
	
	ProxyPass /rest/ ajp://localhost:8009/ retry=0 ttl=600 secret=myajpsecret
	ProxyPassReverse /rest/ ajp://localhost/

	ProxyPass /rest/* ajp://localhost:8009/* retry=0 ttl=600 secret=myajpsecret
	ProxyPassReverse /rest/* ajp://localhost/*

	SSLCertificateFile /etc/letsencrypt/live/rest.datingtest.social/fullchain.pem
	SSLCertificateKeyFile /etc/letsencrypt/live/rest.datingtest.social/privkey.pem
	Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

Konfiguration des Tomcat Servers innerhalb von Springboot.


import org.apache.catalina.connector.Connector;
import org.apache.coyote.ajp.AjpNioProtocol;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/*
 * @Author Oliver Schwerttner, www.inter-net.de
 */
@Configuration()
public class TomcatConfiguration {
    private static final Logger LOG = LogManager.getLogger(TomcatConfiguration.class);
    private static final String PROTOCOL = "AJP/1.3";

    @Value("${tomcat.ajp.port:8009}")
    private int ajpPort;

    @Value("${tomcat.ajp.redirectport:8443}")
    private int ajpRedirectPort;

    @Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> connectorCustomizer() {
        try {
            return (tomcat) -> tomcat.addAdditionalTomcatConnectors(createConnector());

        } catch (Exception e) {
            LOG.equals(e);
            return null;
        }
    }

    private Connector createConnector() {
        try {
            Connector ajpConnector = new Connector(PROTOCOL);

            /*
             * the secret has to be defined here and additional equal in the Apache 2 config file
             * for the <VirtualHost *:80> by the ProxyPass!
             *
             * Example:
             * --------
             * secret in the Apache 2 Server config without ""!
        *     
             * ProxyPass /rest/ ajp://localhost:8009/ retry=0 ttl=600 secret=myajpsecret  
             * ProxyPassReverse /rest/ ajp://localhost/
             * ProxyPass /rest/* ajp://localhost:8009/* retry=0 ttl=600 secret=myajpsecret
             * ProxyPassReverse /rest/* ajp://localhost/*
             */
            AjpNioProtocol protocol = (AjpNioProtocol) ajpConnector.getProtocolHandler();
            protocol.setSecret("myajpsecret");
            protocol.setSecretRequired(false); // will be ignored!

            ajpConnector.setSecure(false);
            ajpConnector.setAllowTrace(false);
            ajpConnector.setScheme("http");
            ajpConnector.setPort(ajpPort);
            ajpConnector.setRedirectPort(ajpRedirectPort);
            return ajpConnector;

        } catch (Exception e) {
            LOG.equals(e);
            return null;
        }
    }
}

Abschluß


1. SpringBoot Dienst neu starten und offene Ports überprüfen

# systemctl restart rest.service
# ss -ltn


2. Apache Webserver neu starten und Rest-Service im Webbrowser aufrufen

# systemctl restart apache2

=> https://my.testserver.com/rest/[eigener Rest Link]



Nun haben wir einen funktierenden Json/Rest-Backend Server. Die Verbindung vom Tomcat zur MySQL Datenbank erfolgt innerhalb von SpringBoot über die Java Persistence Api (JPA).


73 Ansichten0 Kommentare

Aktuelle Beiträge

Alle ansehen

Comments


left.jpg
bottom of page