Auf mehreren Systemen habe ich aktuell die Aktualisierung ausführen lassen. Ausgangspunkt war jeweils die Version 20.0.14, die nicht mehr unterstützt wird. Zum Glück ist bei Nextcloud das Update kein großes Problem, wobei der Teufel im Detail steckt.

1. Update auf 21.0.9

Beim Update teilt Nextcloud mit, dass zwei Erweiterungen deaktiviert werden müssten:

  • Deck
  • Talk (speed)

Die Erwähnung von Talk irritierte mich, es ist aber nach dem Update ganz normal vorhanden.

In der Einstellungsübersicht wurde dann auf fehlende Indices hingewiesen. Das lässt sich prinzipiell lösen mittels:

 sudo -u www-data php occ db:add-missing-indices

Doch gab es hier eine Warnung über ein Fehlen von einem  APC Modul. Daher musste ich erst die Zeile

apc.enable_cli=1

in der Datei  /etc/php/7.4/cli/php.ini ergänzen.

Danach ließen sich die Indizes ergänzen.

Bei einem der Systeme gab es dann Fehlermeldungen im Zusammenhang mit Unterverzeichnissen von .well-known. Eigentlich war meine Konfiguration stimmig, ich habe aber dann trotzdem den Alias-Eintrag nochmals für Port 80 und 443 gesetzt:

 Alias /.well-known /var/www/vhosts/beispiel-domain.de/httpdocs/.well-known

Nach einem Neustart des Apache war der Fehler beseitigt.

Und nun noch der nette Hinweis:

Für Deine Installation ist keine Standard-Telefonregion festgelegt....

Das muss man händisch in der Datei config/config.php machen. Dort ergänzt man die Zeile:

'default_phone_region' => 'DE',

Bei einem der Systeme tauchte die Meldung auf:

Dem Modul php-imagick fehlt die SVG-Unterstützung...

Das lässt sich lösen, indem man ein Paket nachinstalliert:

sudo apt install libmagickcore-6.q16-6-extra:amd64

 

2. Update auf 22.2.5

Unter Einstellungen -> Übersicht geht es dann an die nächste Runde des Updates. Danach wurden wieder fehlende Indices moniert, also erneut

 sudo -u www-data php occ db:add-missing-indices

Nun noch in der Apache Konfiguration ergänzen

 Header add Strict-Transport-Security "max-age=15768000"

und dann blieb noch die Fehlermeldung

Eine Hintergrundaufgabe, die nach vom Benutzer importierten SSL-Zertifikaten sucht, läuft noch. Bitte später erneut versuchen.

Das ließ sich nach etwas Recherche beseitigen mittels:

sudo -u www-data php -f ./cron.php

Nun sind alle Prüfungen bestanden.

Wenn das immer so einfach wäre 😉

Veröffentlicht unter linux.

Hier nun eine verbesserte Version des Bootstrap Carousels. Diese Version zeigt alle Bilder an, die in den Seiten-Eigenschaften definiert sind. Zusätzlich werden die Metainformation des jeweiligen Bildes dargestellt. Ich habe mich dabei an der Vorlage unter Blog Teamgeist-Medien orientiert.

 lib.field_headerimage = COA

 lib.field_headerimage {
  wrap (
     <div id="skiplink">
       <a class="skip" title="Direkt zur Navigation springen" href="#navigation">Zur Navigation springen</a><br>
       <a class="skip" title="Direkt zum Content springen" href="#content">Zum Content springen</a>
     </div>
     <div id="blogo">
        <a href="/"><img src="fileadmin/user_upload/Logo_trans.png" /></a>
     </div>
     <div id="hslider" class="carousel slide carousel-fade" data-ride="carousel"  data-interval="5000">|</div>
  )
  #Hier hole ich die Bilder aus den Seiteneigenschaften(Ressourcen/Media) um die Navigation zu erstellen.
  10 = FILES
  10 {
    stdWrap.wrap = <ol class="carousel-indicators">|</ol>
    references {
      data = levelmedia:-1, slide
      treatIdAsReference = 1
    }
    renderObj = TEXT
    renderObj {
      wrap = <li data-target="#hslider" data-slide-to="|" class="active"></li>|*|<li data-target="#hslider" data-slide-to="|"></li>
      value = {register:FILE_NUM_CURRENT}
      insertData = 1
    } #Ende renderObj
  } #Ende 10

  #Hier nochmal das gleiche Spiel nur mit Ausgabe der Bilder
  20 = FILES
  20 {
    stdWrap.wrap = <div class="carousel-inner">|</div>
    references {
      data = levelmedia:-1, slide
      treatIdAsReference = 1
    }
    renderObj = COA
    renderObj {
      wrap = <div class="item active">|</div>|*|<div class="item">|</div>
      3 = IMAGE
      3 {
        stdWrap.wrap = |
        stdWrap.required = 1
        file.import.data = file:current:originalUid
        # Setze den Link der im Bild eingestellt ist um das Bild
        stdWrap.typolink.parameter.data = file:current:link
        altText.data = file:current:alternative
        titleText.data = file:current:alternative
      } #Ende 3
      # Hier Titel und Beschreibung für das Bild, wird auch vom Link umgeben.
      6 = COA
      6 {
        # alles nur, wenn Titel gesetzt ist
        if.isTrue.data = file:current:title
        wrap = <div class="carousel-caption">|</div>
        stdWrap.required = 1
        stdWrap.typolink.parameter.data = file:current:link
        4 = TEXT
        4.wrap = <h3>|</h3>
        4.data = file:current:title
         
        8 = TEXT
        8.wrap = <p>|</p>
        8.data = file:current:description 

      } #Ende 6
    } #Ende renderObj
  } #Ende 20
} #Ende headerimage

Letztendlich wird hier ein Carousel genau nach Beschreibung aufgebaut. Im Wrap ein paar vorbereitende Zeilen (inclusive überlagertem Logo) und dann der Kopf des Carousels mit der Geschwindigkeitsangabe und der Klasse zum Starten.

Danach wird dann unter 10 der Carousel-Indicator aufgebaut, dabei geht Typoscript durch alle Bilder. Wenn man den Indicator nicht haben möchte, dann kann man den ganzen 10er Block einfach weglassen.

Anschließend werden unter 20 die Bilder eingebunden und ggf. mit den Metadaten versehen.

Veröffentlicht unter typo3.

Für ein aktuelle Projekt brauchte ich einen Bilder-Slider im Header. Meine sonstigen Slider sind eher als Content-Elemente gedacht. Daher habe ich mich mit dem Bootstrap Carousel beschäftigt.

Der Slider soll mit dem Bildern aus der Seiteneigenschaft Resourcen arbeiten. Zur Vereinfachung gehe ich einfach davon aus, dass er die ersten drei Bilder benutzt. Bei Gelegenheit muss ich mir dann auch einmal Gedanken über eine Schleifenstruktur durch die vorhandenen Bilder machen.

Mit einer festen Zahl ist die Lösung recht einfach:

 lib.field_headerimage = COA
   lib.field_headerimage.10 = TEXT
   lib.field_headerimage.10.value (
     <div id="skiplink">
     <a class="skip" title="Direkt zur Navigation springen" href="#navigation">Zur Navigation springen</a><br>
     <a class="skip" title="Direkt zum Content springen" href="#content">Zum Content springen</a>
     </div>

    <div id="blogo">
     <a href="/"><img src="fileadmin/user_upload/Logo_trans.png" /></a>
    </div>
    <div id="hslider" class="carousel slide carousel-fade">
    <div class="carousel-inner">
   )

   lib.field_headerimage.20 = IMG_RESOURCE
   lib.field_headerimage.20 {
    file.import.data = levelmedia:2, slide
    file.treatIdAsReference = 1
    file.import.listNum = 0
    stdWrap.wrap = <div class='item active'><a href='/'><img src='|' style='width: 100%;' /></a></div>
   }

   lib.field_headerimage.30 = IMG_RESOURCE
   lib.field_headerimage.30 {
     file.import.data = levelmedia:2, slide
     file.treatIdAsReference = 1
     file.import.listNum = 1
     stdWrap.wrap = <div class='item'><a href='/'><img src='|' style='width: 100%;' /></a></div>
   }

   lib.field_headerimage.40 < lib.field_headerimage.30 
   lib.field_headerimage.40.file.import.listNum = 2
 
   lib.field_headerimage.90 = TEXT
   lib.field_headerimage.90 {
   value = {$styles.content.hspeed}
   wrap (
     </div></div>
     <script type='text/javascript'>$(document).ready(function(){
     $("#hslider").carousel({interval: |});
    });</script>
  )
}

Im ersten Textbereich werden ein paar Standars-Zeilen generiert und dann der Kopf des Carousels definiert. Über das Javascript im letzten Block wird das Carousel aktiviert. Grundsätzlich kann man das Carousel über Javascript oder folgenden Datenblock aktivieren:

<div id="hslider" class="carousel slide carousel-fade" data-ride="carousel" data-interval="5000">

Ich habe die Version per Javascript benutzt, einfach weil sich das aus meiner Vorlage so ergab und mir nicht klar war, ob das auch mit dem Fade funktioniert. Bei Gelegenheit werde ich aber auf die andere Variante ohne Javascript umstellen.

Normalerweise scrollen die Bilder, mit dem Fade-Effekt kommt es zu einer weicheren Überblendung.

 

Veröffentlicht unter typo3.

Für meine Typo3-Erweiterung nettgrids habe ich ein Accordion-Element (Bootstrap Collapse) erstellt. Für ein Projekte wollte ich jetzt erreichen, dass über einen Link jeweils der passende Tab geöffnet wird.

Nach etwas Experimentieren mit Anregung von https://stackoverflow.com/questions/22254248/bootstrap-3-expand-accordion-from-url#answer-33444574 bin ich zu folgendem Javascript gekommen:

<script type="text/javascript"> $("a").click(function () {     
  function show_tab(){
   if(location.hash != null && location.hash != "")
   {         $('.collapse').removeClass('in');
             $(location.hash + '.collapse').collapse('show');     
   }
    }
    window.setTimeout(show_tab, 100);
  }); 
</script>

Das Script kann man einfach in ein HTML-Element vor dem Accordion packen.

Im vorliegenden Listing wird die Javascript-Funktion gestartet, wenn auf einen Link auf der Seite geklickt wird. Man könnte es auch an andere Ereignisse koppeln.

In der Funktion show_tab wird überprüft, ob ein Anker-Links vorhanden ist. Wenn ja, dann wird der aktuelle Tab geschlossen und der Zieltab geöffnet. Um die Funktion herum liegt eine Funktion zur Verzögerung. Ohne Verzögerung wäre der neun Link mit dem Anker-Ziel noch aktuell und der Aufruf käme zu früh. Die Verzögerung ist hier auf 0,1 Sekunden eingestellt.

Veröffentlicht unter typo3.

Meine Schülerfirma Netthelp betreut eine Reihe von Kunden, die ihre Domains bei Domainfactory liegen haben. Wenn bei Netthelp ein Serverwechsel ansteht, dann taucht immer wieder das Problem auf, dass wir die Zugangsdaten der Kunden brauchen. Der letzte Zugriff auf die Domainverwaltung ist dann zum Teil schon mehrere Jahre her und die Zugangsdaten sind nirgends mehr im Zugriff. Dieses Problem trat bei den aktuellen Umstellungen massiv auf, da DF die Regeln für gültige Passwörter geändert hat und ungültige Passwörter dann deaktiviert hatte.

Unser erster Ansatz dieses Problem zu Lösen war eine Cluster-IP bei Strato. Diese IP ist relativ teuer 9,99€ im Monat und für uns nahezu nutzlos, da sie an einen Server-Vertrag gebunden ist. Wenn wir diesen Server wechseln, dann ändert sich auch die Cluster-IP.

Der einzige Ansatz der uns (Dank an Lukas Thiel) jetzt noch einfällt ist eine Domain-Weiterleitung auf eine Netthelp-Subdomain. Dabei muss man ein kleines bisschen tricksen, weil der Grund-Eintrag für linux-diskless.de keine cname sein darf, sondern ein A-Record erwartet wird. Der Trick besteht darin den Eintrag auf Domainfactory zu belassen und dann dort eine Header-Weiterleitung auf www.linux-diskless.de einzurichten. Der Eintrag für „www“ und sogar der für „*“ darf dann ein cname sein.

Für den MX-Eintrag wird ebenfalls linux-diskless.netthelp.de genutzt und keine Subdomain der jeweiligen Domain. Ein MX-Record muss in erster Instanz auf einen A-Record und darf nicht auf einen cname-Record verweisen.

Der einzige Schönheitsfehler besteht in der zwingenden Weiterleitung auf www.

Als Beispiel soll hier die Domain linux-diskless.de dienen:

  1. Ich lege einen A-Record linux-diskless.netthelp.de an, der auf die gewünschte Server-IP zeigt
  2. Nun gehe Ich zur Domain-Verwaltung von linux-diskless.de und lege unter Domain-Einstellungen eine Weiterleitung auf www.linux-diskless.de an (http:// oder wenn konfiguriert besser https://.
  3. Dann folgen die Verweise auf die Netthelp-Subdomain:

Für zukünftige Serverwechsel müssen wir jetzt nur noch den Eintrag für die Netthelp-Subdomain ändern Ein Zugriff auf den DF-Account des Kunden ist nicht mehr notwendig.

Weitere Informationen unter:

Bei vielen Typo3-Seiten gibt es Einträge der Art

config.baseURL= http://<domain>/

im root-Template. Will man dem Benutzer die Wahl lassen zwischen http und https ist das ein Problem, weil dann bei einer sicheren Verbindung Inhalte unsicher nachgeladen werden. Firefox blockt diese Inhalte. Da das  dann oft CSS-Dateien oder ähnliches sind wird die Seite ziemlich verunstaltet.

Eine Lösung besteht darin das benutzte Protokoll zu erfragen. Dazu gibt man im Template unter Konstanten folgenden Code ein:

protocol = http
[globalString = IENV:TYPO3_SSL=1]
  protocol = https
[global]

Nun kann man im Setup darauf Bezug nehmen:

# Das Protokoll wird unter Constants ermittelt
config.baseURL= {$protocol}://<domain>/

Nun klappt das auch mit der sicheren Verbindung.

Veröffentlicht unter typo3.

Mit letsencrypt soll es für alle Webseiten einfach und erschwinglich werden eine Verschlüsselung zu ermöglichen.

Eine schöne Beschreibung findet sich unter https://lukasthiel.de/wiki/SSL-Zertifikate_mit_Let%27s_Encrypt

Installation

Die Installation erfolgt mittels:

cd /root
git clone https://github.com/letsencrypt/letsencrypt

Das Script lädt notwendige Pakete und Aktualisierungen beim ersten Aufruf nach, hier z.B. über den Aufruf der Hilfefunktion:

/root/letsencrypt/letsencrypt-auto -h

Dabei werden einige Pakete über die Paketverwaltung der Distribution ergänzt und zusätzlich einiger Python-Code nach /root/.local/share/letsencrypt/ gebracht.

Bootstrapping dependencies for openSUSE-based OSes...

The following 8 NEW packages are going to be installed:
  dialog libdialog11 libffi48-devel python-devel python-pip python-setuptools 
  python-virtualenv python-xml 

The following package is suggested, but will not be installed:
  terminfo 

8 neue Pakete zu installieren.
Gesamtgröße des Downloads: 5,8 MiB. Nach der Operation werden zusätzlich 26,8 
MiB belegt.
Fortfahren? [j/n/? zeigt alle Optionen] (j): j
Creating virtual environment...
Installing Python packages...
...

Am Ende wird der Hilfe-Text ausgegeben.

Das Tool legt an einer Reihe von Stellen Dateien ab:

  • /etc/letsencrypt/  hier liegen die Zertifikate und die zugehörigen Einstellungen
  • /root/.local/share/letsencrypt/ in diesem Verzeichnis liegen die benötigten Python Scripte
  • /var/log/letsencrypt hier liegt die Logdatei und die zugehörigen Archive
  • /var/lib/letsencrypt für Backups
  • /root/letsencrypt vom Benutzer festgelegtes Verzeichnis für das Programmpaket, denkbar z.B. auch /opt/letsencrypt

Zertifikats-Erzeugung im Dialog

Der Aufruf von

/root/letsencrypt/letsencrypt-auto --rsa-key-size 4096 certonly

erzeugt dann im Prinzip das Zertifikat. Bei mit (OpenSUSE) wollte das nicht funktionieren, weil das Tool das Verzeichnis /etc/apache2/sites-enabled vermisste. Nachdem ich das Verzeichnis angelegt hatte (das Verzeichnis selber kann leer bleiben) ließ sich das Zertifikat erzeugen.

Es startet ein fensterbasiertes Tool an der Konsole. Im ersten Schritt gibt man an, wie sich der Webserver gegenüber dem Zertifikats-Aussteller authentifizieren soll. Die einfachste Version besteht darin das Script eine Datei im Webroot der Seite plazieren zu lassen. Dazu muss das Script die Pfade kennen:

letsencrypt-1

letsencrypt-2

letsencrypt-3

letsencrypt-4

Wenn die Datei über den Webserver erreichbar war, dann kommt die Erfolgsmeldung:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/elearn-server.de/fullchain.pem. Your cert will
   expire on 2016-09-14. To obtain a new or tweaked version of this
   certificate in the future, simply run letsencrypt-auto again. To
   non-interactively renew *all* of your certificates, run
   "letsencrypt-auto renew"
 - If you lose your account credentials, you can recover through
   e-mails sent to <admin>@<domain>.
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Zertifikats-Erzeugung mit Parametern

Man kann sich den Ablauf auch etwas einfacher machen, vor allem, wenn man mehrere Domains betreut, indem man statt der Dialog orientierten Variante eine Parameter orientierte Variante benutzt (alles in einer Zeile):

/root/letsencrypt/letsencrypt-auto --rsa-key-size 4096 certonly --webroot -w /srv/www/vhosts/elearn-server.de/httpdocs/ -d elearn-server.de -d www.elearn-server.de

Für umfangreiche Nutzung kann es noch geschickter sein sich für jede Domain eine Konfigurationsdatei, z.B. letsencrypt.ini, anzulegen

# Wir nutzen 4096 bit RSA key statt 2048
rsa-key-size = 4096

# allgemeine Angaben
email = <admin>@<domain>
authenticator = webroot

# Domains fuer die wir Zertifikate beantragen, die erste in
# der liste legt den Hauptnamen fest. Alle Domains müssen beim
# Aufruf erreichbar sein
domains = elearn-server.de, www.elearn-server.de

# Dies ist das Verzeichnis zur Domain, wo letsencrypt seinen Hash in
# /.well-known/acme-challenge schreiben will. Der Pfad muss auf / enden
webroot-path = /srv/www/vhosts/elearn-server.de/httpdocs/

Aufgerufen wird letsencrypt-auto dann mittels (alles in einer Zeile):

/root/letsencrypt/letsencrypt-auto certonly --config /srv/www/vhosts/elearn-server.de/letsencrypt.ini

Aufpassen muss man aber unbedingt mit Subdomains. Letsencrypt lässt nämlich nur etwa 5 Aufrufe pro Domain und Woche zu. In dem Beispiel sind dann schon zwei Aufrufe verbraucht. Mehr als 5 Subdomains im gleichen Zertifikat sind wohl nicht möglich.

Im Laufe der Erzeugung legt letsencrypt in der Wurzel des angegebenen Servers ein Verzeichnis .well-known an. Das Zertifikat selber wird unter /etc/letsencrypt/live/<domain>/ abgelegt und besteht aus den vier Dateien

  • cert.pem
  • chain.pem
  • fullchain.pem
  • privkey.pem

dies sind Links auf die Dateien

  • /etc/letsencrypt/archive/<domain>/cert1.pem
  • /etc/letsencrypt/archive/<domain>/chain1.pem
  • /etc/letsencrypt/archive/<domain>/fullchain1.pem
  • /etc/letsencrypt/archive/<domain>/privkey1.pem

Diese Verlinkung soll vermutlich die Aktualisierung der Zertifikate vereinfachen.

Apache konfigurieren

Jetzt muss nur noch der Apache-Webserver von den neuen Möglichkeiten wissen. Die notwendigen Einstellungen für den Host sind in der Datei /etc/letsencrypt/options-ssl-apache.conf zu finden:

# Baseline setting to Include for SSL sites

SSLEngine on

# Intermediate configuration, tweak to your needs
SSLProtocol             all -SSLv2 -SSLv3
SSLCipherSuite          ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
SSLHonorCipherOrder     on
SSLCompression          off

SSLOptions +StrictRequire

# Add vhost name to log entries:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined
LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common

#CustomLog /var/log/apache2/access.log vhost_combined
#LogLevel warn
#ErrorLog /var/log/apache2/error.log

# Always ensure Cookies have "Secure" set (JAH 2012/1)
#Header edit Set-Cookie (?i)^(.*)(;\s*secure)??((\s*;)?(.*)) "$1; Secure$3$4"

Testen kann man das Zertifikat dann unter https://www.ssllabs.com/ssltest/

Weitere Informationen

Möchte man sein Zertifikat um weitere Subdomains erweitern, so ist das kein Problem. Hat man z.b. nur für <domain> und www.<domain> ein Zertifikat erstellt und möchte jetzt auch blog.<domain> mit aufnehmen, so erweitert man einfach die Liste der Domains entsprechend und löst die Erstellung des Zertifikats erneut aus. Es erscheint jetzt ein Dialog, der nachfragt, ob man das Zertifikat erweitern möchte. Hier klickt man auf Expand und wenn die Subdomain erreichbar ist, dann wir das Zertifikat neu erzeugt.
Laut https://community.letsencrypt.org/t/rate-limits-for-lets-encrypt/6769 gilt hierfür nicht das Limit von 5 pro Woche.

Unter /etc/letsencrypt/csr/ findet man die Key-signing-requests, ein Hinweis darauf, dass das Schlüsselpaar auf dem eigenen Server erzeugt wurde und der private Schlüssel auch letsencrypt nicht bekannt ist.

Bei owncloud gibt es einen Abschnitt in der .htacess, der die Überprüfung durch letsencrypt verhindert:

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteRule ^\.well-known/host-meta /public.php?service=host-meta [QSA,L]
RewriteRule ^\.well-known/host-meta\.json /public.php?service=host-meta-json [QSA,L]
RewriteRule ^\.well-known/carddav /remote.php/carddav/ [R=301,L]
RewriteRule ^\.well-known/caldav /remote.php/caldav/ [R=301,L] 
RewriteRule ^apps/calendar/caldav\.php remote.php/caldav/ [QSA,L]
RewriteRule ^apps/contacts/carddav\.php remote.php/carddav/ [QSA,L]
RewriteRule ^remote/(.*) remote.php [QSA,L]
RewriteRule ^(build|tests|config|lib|3rdparty|templates)/.* - [R=404,L]
RewriteRule ^(\.|autotest|occ|issue|indie|db_|console).* - [R=404,L] 
</IfModule>

Das Einfügen der Zeile

RewriteRule ^\.well-known/acme-challenge - [L]

löst das Problem. Mal sehen,  ob es Seiteneffekte gibt.

 

Löschen von Schlüsseln

Mit

/root/letsencrypt/certbot-auto certificates

kann man abfragen, wie die Zertifikate auf dem Server genau heißen und die zugehörigen Dateien dann mittels

/root/letsencrypt/certbot-auto delete --cert-name <gefundener Name>

vom eigenen Server entfernen.

Mit folgendem Kommando kann man abfragen, welche Domains im Zertifikat eingetragen sind:

openssl x509 -in /etc/letsencrypt/live/<domain-bezeichnung>/cert.pem -text -noout | grep DNS

Mit den Schritten ist das Zertifikat selber aber nicht gelöscht, das wäre dann erst nach einigen Tagen automatisch der Fall. Noch nicht getestet habe ich die Schritte:

certbot revoke --cert-path /PATH/TO/cert.pem --key-path /PATH/TO/key.pem

das müsste natürlich vor dem Löschen der lokalen Dateien erfolgen.

 

Links

 

Nachtrag vom 6.10.2021

Will man eine Domain aus einem Zertifikat für mehrere Domains entfernen, so soll das mit folgendem Parameter klappen:

$ certbot renew --allow-subset-of-names

 

Ich bin jetzt zweimal auf ein Problem im Zusammenhang mit Typo3 und dem Nivo-Slider gestoßen. In beiden Fällen hat ein Browser die Bilder im Slider bei jedem Durchlauf neu geladen und damit eine gewisse Netzlast erzeugt, natürlich abhängig von der Internetanbindung des zugehörigen Rechners.

In einem ersten Durchlauf habe ich die zugehörige IP mit iptables blockiert und konnte anhand der IP den Verursacher erreichen. Im zweiten Fall ist das aber ein Ntuzer mit dynamischer IP, die sich täglich ändert. Das kann auf Dauer mühsam werden da am Ball zu bleiben, zumal der Verursacher keine weiteren Informationen bekommt.

Daher habe ich jetzt versucht per .htaccess der IP-Adresse eine andere Seite mit Probleminformationen zukommen zu lassen. Dazu habe ich die .htaccess von dem zugehörigen Typo3-System um folgende Zeilen erweitert:

RewriteCond %{REMOTE_ADDR} ^192\.168\.1\.1$  
RewriteCond %{REQUEST_URI} !^\/sorry\.html
RewriteRule $ /sorry.html [R=302,L]

Die IP-Adresse habe ich hier natürlich verändert.

Jeder Aufruf von dem Rechner aus wird also auf die Seite sorry.html umgeleitet, die Hinweise auf das Problem liefert.

Quellen:
http://www.the-art-of-web.com/system/rewrite/
http://www.modrewrite.de/mod-rewrite/beispiele/ip-bereiche-blocken/

Ich bin gerade dabei mich mit dem Framework Bootstrap zu beschäftigen. Dabei tauchte mal wieder das Problem der gleich langen Spalten auf, das anscheinend in den zugehörigen Anleitungen nirgends beschrieben wird. Ein dreispaltiges Lyout beschreibt man dort z.B. mittels:

<div class="container">
  <div class="row">
    <div class="col-md-3">Spalte1</div>
    <div class="col-md-6">Spalte2</div>
    <div class="col-md-3">Spalte3</div>
  </div>
</div>

Leider sind dabei die Spalten ungleich hoch, abhängig von der Menge an Text, wenn sie einen Hintergrund besitzen. Eine einfache Lösung besteht darin zwei zusätzlich CSS-Klassen einzuführen:

.equal{
    margin-bottom: -99999px;
    padding-bottom: 99999px;
    background-color:#efefef;
}

.equalheight {
    overflow: hidden; 
}

Die drei Spalten werden durch den negativen unteren Rand sehr weit ausgedehnt, gleichzeitig wird dies durch das gleichgroße Padding wieder aufgehoben. Alle Spalten haben also quasi einen unteren Farbigen Rand von 9999 Pixeln. Das äußere Element schneidet den überflüssigen Teil durch das overflow: hidden dann ab, wodurch alle Spalten die gleiche Länge bekommen.

<div class="container equalheight">
  <div class="row">
    <div class="col-md-3 equal">Spalte1</div>
    <div class="col-md-6 equal">Spalte2</div>
    <div class="col-md-3 equal">Spalte3</div>
  </div>
</div>

Weitere Lösungen zu dem gleichen Problem finden sich auf folgenden Seiten:

Es ist nicht ganz einfach Informationen zu finden, wie man bei Typo3 zu korrekten Fehlerseiten kommt, die auch einen 404er Fehlercode zurückliefern, vor allem wenn man mit simulatestatic arbeitet. Untersuchen kann man den gelieferten Fehlercode übrigens recht einfach mit der Firefox-Extension Firebug. In der Rubrik Netzwerk wird dort bei einem Seitenaufruf auch der Statuscode mit angezeigt.

Es gibt bei Typo3-Seiten eigentlich zwei unterschiedliche Situationen:

  1. Typo3 wird direkt (/index.php?id=000) oder indirekt (/000.html) mit einer illegalen id aufgerufen
  2. Die Domain wird mit einer URL aufgerufen, die nicht zur Typo3-Installation passt, z.B. mit einem Unterverzeichnis (/mediawiki/..)

Der erste Fall ist relativ einfach zu regeln, man erstellt in Typo3 eine Fehlerseite (hier fehler404.html) und erweitert die Konfigurationsdatei typo3conf/localconf.php folgendermaßen:

[FE][pageNotFound_handling] = /fehler404.html
[FE][pageNotFound_handling_statheader] = HTTP/1.0 404 Not Found

Damit wird für den Fall einer illegalen id die Fehlerseite aufgerufen und ein 404er Fehlercode zurückgeliefert.

Bleibt noch der zweite Fall. Typo3 würde in der Regel die Startseite liefern, egal was aufgerufen wurde. War in der aufgerufenen URL ein Unterverzeichnis angegeben, so wird das in dem Sinne berücksichtigt, dass Typo3 das Stylesheet nicht mehr findet. Die ausgelieferte Seite sieht also ganz komisch aus.

Um das zu ändern muss man an die Datei .htaccess ran, die man für simulatestatic ja aktivieren musste. Hier die .htacess, so wie sie von Typo3 geliefert wurde, ich habe alle Kommentarzeilen entfernt. Verändert habe ich lediglich die vorletzte Zeile:

<FilesMatch "\.(js|css)$">
  <IfModule mod_expires.c>
    ExpiresActive on
    ExpiresDefault "access plus 7 days"
  </IfModule>
  FileETag MTime Size
</FilesMatch>

<IfModule mod_rewrite.c>

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)\.(\d+)\.(php|js|css|png|jpg|gif|gzip)$ $1.$3 [L]

RewriteRule ^(typo3/|t3lib/|fileadmin/|typo3conf/|typo3temp/|uploads/|favicon\.ico) - [L]

RewriteRule ^typo3$ typo3/index_re.php [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l

RewriteRule .* index.php?id=000 [L]

</IfModule>

In vielen Versionen der Datei werden nur Dateien mit der Endung .html ersetzt (RewriteRule ^[^/]*\.html$ index.php), hier wird jetzt immer die index.php aufgerufen, wenn die ursprüngliche Datei nicht gefunden wurde. Die index.php wird aber mit einer illegalen id aufgerufen, so dass ein Fehler nach Punkt 1 erzeugt wird. Typo3 wertet die übergebene id als String aus und nicht numerisch, eine id 000 wird es als sicherlich nicht geben, da beim Erzeugen einer Seite die id numerisch festgelegt wird. Die Idee dazu stammt von http://typo3.toaster-schwerin.de/typo3_dev/2008_04/msg00492.html.

Sofern die ursprünglich aufgerufenen id gültig war, spielt diese fehlerhafte id keine Rolle. Eine Erklärung dafür habe ich nicht, eventuell hat das etwas mit der Auswertungsreihenfolge von GET/POST Daten zu tun. Von daher ist nicht sichergestellt, dass dieser Trick auch in zukünftigen Typo3-Versionen funktioniert.

Ein Problem gibt es aber, wenn ein Slash (/) im Dateinamen auftaucht, dann gibt es zwar einen korrekten 404er Returncode, aber eine nackte Fehlerseite, da wieder das CSS nicht gefunden wird.

Mit

RewriteRule ^[^/]*\.html$ index.php [L]

stattdessen werden nur Adresse ohne Slash (/) ersetzt, bei anderen Adressen wird die Fehlerseite des Apache gezeigt, mit korrektem Fehlercode. Nun gibt es zwei unterschiedliche Fehlerseiten, einerseits die in Typo3, andererseits die vom Webserver. In beiden Fällen wird aber ein korrekter Fehlercode geliefert.