Optimierte .htaccess für TYPO3

Über passende Regeln in der .htaccess-Datei wird die Website noch schöner, schneller und besser. Vor fast 5 Jahren hatten wir bereits im Beitrag Optimierte .htaccess fuer TYPO3 auf Apache2 von Stephan eine alternative .htaccess-Datei veröffentlicht. Die damals von TYPO3 mitgelieferte Version behandelte nur wenige Grundeinstellungen und war für den Produktivbetrieb eher suboptimal. Über die Jahre hat sich vieles getan und holte die Default-htaccess von TYPO3 auf. Ein Punkt von damals gilt aber auch noch heute

  • eine .htaccess wird mit jedem File-Hit geparst, besser wäre es natürlich die Einstellung direkt in der Apache Konfiguration der VirtualHosts vorzunehmen. Das scheitert aber vermutlich meist an entsprechenden Rechten.
  • Dadurch dass es geparst werden muss, sollte man die Datei klein halten, d.h. alle Kommentare entfernen.

Weiterlesen»

Einfügen / aktualisieren von SSL-Zertifikaten unter ispCP

SSL-Zertifikate unter ispCP einzurichten oder zu Verlängern ist etwas aufwändiger als im Apache aus der Dose.

Grundlagen

Das Vorgehen sieht im Detail wie folgt aus:
Auf dem fraglichen Server prüft man zuerst, ob die notwendigen Voraussetzungen erfüllt sind. Am einfachsten fällt dies, indem man sich über

crontab -l

die aktuellen Cronjobs anzeigen lässt. Hier muss folgende Zeile vorhanden sein:

 M  H  D   Mo   DoW    test -x /var/www/ispcp-bin/upd-ssl.pl && /var/www/ispcp-bin/upd-ssl.pl > /etc/apache2/sites-enabled/ispcp-ssl.conf 2>/dev/null

Hier erkennt man auch schon, welches Script relevant ist, in diesem Fall

/var/www/ispcp-bin/upd-ssl.pl

Sieht man sich dieses Script genauer an, wird man im Konfigurationsbereich u. a. die folgenden beiden Zeilen vorfinden:

my $sslenabledconfig='{Pfad zur}ssl.list';
my $sslcertfificatepath = "{Pfad}/ssl";

Zertifikate erstellen (die .pem-Dateien)

In den .pem-Dateien werden Schlüssel und Zertifikat gemeinsam gehalten. Sie sollten am Ende immer folgendermaßen aussehen:

-----BEGIN RSA PRIVATE KEY-----
MIIEp/IB//bC/QE/0f00rZqqrzbJZ0BtXCMzY3yVrQ4rHVLJVHBsX0IEbjq4RYnB
[...]
5j6je638LnVrVryj1iz3JmCN+ChyCpileIh4oe7FeP/m7CfY3bOmX/==
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIFoTCCBImg/XIB/gIR/P+iVOuoGOHV6V5tX1YXFr4XVQYJboZIhvcN/QEFBQ/X
[...]
Y8eGOYE=
-----ENV CERTIFICATE-----

Wie man unschwer erkennen kann bestehen diese Dateien also aus einer Konkatenation von Schlüssel und Zertifikat als flache Textdatei. Nachdem man sichergestellt hat, dass die Datei mit einer Leerzeile endet, war es das an diesem Punkt auch schon. Die Datei wird unter dem Namen „sub.domainmitssl.org.pem“ im Verzeichnis, das in „$sslcertfificatepath“ definiert ist, abgespeichert.
Dieser Vorgang ist selbstverständlich für alle einzufügenden oder zu aktualisierenden Zertifikate entsprechend zu wiederholen.

Intermediate-Zertifikate

Für die meisten Zertifikate ist ein Intermediate-Zertifikat erforderlich um die Vertrauenskette zu einem Rootzertifikat lückenlos sicherstellen zu können. Diese werden analog zu den Zertifikatsdateien selbst als „sub.domainmitssl.org.pem.CA“ benannt und ebenfalls im Verzeichnis „$sslcertfificatepath“ abgelegt.

Zertifikate hinzufügen

„$sslenabledconfig“ zeigt auf die Liste von SSL-Zertifikaten, die berücksichtigt werden sollen. Der Inhalt dieser Datei folgt stets dem Schema

sub.domainmitssl.org sub.domainmitssl.org.pem

Im Detail bedeutet das, für die Domain „sub.domainmitssl.org“ ist die „Zertifikatdatei“ „sub.domainmitssl.org.pem“ zu benutzen.
Hier fügt man nun die Domain(s) mit den zugehörigen .pem-Dateien ein.

Hat man alle Domains in die Liste eingetragen und sichergestellt, dass die notwendigen Zertifikatdateien existieren, kann man entweder warten, bis der Cron, den wir am Anfang betrachtet haben, wieder läuft oder man startet das Script

/var/www/ispcp-bin/upd-ssl.pl

einfach manuell. Das Script erzeugt dann automatisch alle notwendigen Konfigurationen.

#!/usr/bin/perl 
#
use strict;

#####CONFIG
#
my $ispcpconfig='/etc/apache2/sites-enabled/ispcp.conf';
my $sslenabledconfig='/etc/ispcp/apache/ssl.list';
my $sslcertfificatepath = "/etc/apache2/ssl";

##


# ssl sites list
open (SSL,"<$sslenabledconfig");
my @tmpssl=grep /\w+/, <SSL>;
my %sslsites;
foreach(@tmpssl)
    {
    @_=split(/\s+/,$_);
    $sslsites{$_[0]}=$_[1];
    }

open(APACHE,"<$ispcpconfig");

my %virtualhosts;
while(<APACHE>)
    {
    my @tmpvirthost;
    chomp($_);
    if ($_ =~ /^\s*<VirtualHost/i)
        {
        push @tmpvirthost,$_;
        while(<APACHE>)
            {
            chomp($_);
            push @tmpvirthost,$_;
            last if ($_ =~ /^\s*<\/VirtualHost/i);
            }

        my @servname=map { $_ =~ /^\s+Servername\s+([\w.-]+)/i; $1 } grep(/ServerName/i, @tmpvirthost);
        my $serv=$servname[0];

#        print Dumper(@tmpvirthost);
    $virtualhosts{$serv}=\@tmpvirthost;
        }
            
        
        
    }

foreach my $onessl (keys %sslsites)
    {
    if (!defined($virtualhosts{$onessl}))
        {
        print "$onessl config is missing\n";
        next;
        }


    @{$virtualhosts{$onessl}}[0] =~ s/(<VirtualHost\s.+):80(.+)/$1:443$2/i;
    splice @{$virtualhosts{$onessl}},2,0,"SSLEngine ON";
    splice @{$virtualhosts{$onessl}},3,0,"SSLCertificateFile $sslcertfificatepath/$sslsites{$onessl}";
    if ( -f "$sslcertfificatepath/$sslsites{$onessl}.CA" )
        {
        splice @{$virtualhosts{$onessl}},3,0,"SSLCACertificateFile  $sslcertfificatepath/$sslsites{$onessl}.CA";
        }

    # print out the config, but only if the certificate file exists
    if ( -f "$sslcertfificatepath/$sslsites{$onessl}" )
        {
        print join("\n",@{$virtualhosts{$onessl}})."\n";
        }
    }

Fertig

Zum Abschluss startet man den Apache einmal neu, sodass die neuen Einstellungen greifen.

Notiz: Zu aktivierende Apache Module auf ispcp Servern

a2enmod headers
a2enmod include
a2enmod deflate
a2enmod expires
a2enmod rewrite
a2enmod setenvif
a2enmod actions
a2enmod alias

Bei fcgid (was Standard ist) ganz wichtig:
a2dismod php5

Optimierte .htaccess fuer TYPO3 auf Apache2

Dieser Artikel ist sehr alt. TYPO3 wurde weiterentwickelt, wodurch die Inhalte des Artikels möglicherweise nicht mehr zur aktuellen TYPO3-Version passen. Der Beitrag Optimierte .htaccess für TYPO3 ist neuer und befassts ich mit dem gleichen Thema.

Die .htaccess Datei welche standardmäßig in einer TYPO3 Installation (meist als _htaccess) mitgeliefert wird ist fuer Dokumentationszwecke besser geeignet als zum produktiven Einsatz.

  1. .htaccess
    • eine .htaccess wird mit jedem File-Hit geparst, besser wäre es natürlich die Einstellung direkt in der Apache Konfiguration der VirtualHosts vorzunehmen. Das scheitert aber vermutlich meist an entsprechenden Rechten.
    • Dadurch dass es geparst werden muss, sollte man die Datei klein halten. D.h. alle Kommentare entfernen.
  2. Die Direktiven sind „einfach so“ vorhanden. Besser ist es natürlich nur Direktiven zu verwenden, die der Apache auch durch die entsprechenden Modules eingebunden hat. D.h. <IfModule …></IfModule> sind zwingend verwenden um hässliche 500 Serverfehler zu vermeiden.
  3. Etag, Expiration und Compression Direktiven sind in der TYPO3 Vorlage nicht enthalten, bieten sich aber natürlich an. Der geneigte Websitebetreiber sollte dann natürlich die Module aktivieren (a2enmod headers; a2enmod deflate; a2enmod expires)

.htaccess

Hier die optimierte .htaccess (hier für RealURL-Verwendung, die _htaccess Dokumentation verliert natürlich nicht ihre Gueltigkeit bezüglich RewriteBase…)

<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]
        RewriteCond %{REQUEST_URI} ^.+(/(uploads|fileadmin|(typo3(conf|temp)?))/.*)
        RewriteRule ^.*$ %1 [L,R=301]
        RewriteRule ^fileadmin/(.*/)?_recycler_/ - [F]
        RewriteRule ^fileadmin/(templates|ts)/.*(\.txt|\.ts)$ - [F]
        RewriteRule ^typo3conf/ext/[^/]+/Resources/Private/ - [F]
        RewriteRule ^typo3_src\-(.*)$ /
        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 [L]
</IfModule>
<IfModule mod_headers.c>
 FileETag Size
</IfModule>
<IfModule mod_expires.c>
        ExpiresActive on
        ExpiresDefault "access plus 24 hours"
        ExpiresByType image/x-icon "access plus 1 months"
        ExpiresByType image/jpg "access plus 1 months"
        ExpiresByType image/gif "access plus 1 months"
        ExpiresByType image/jpeg "access plus 1 months"
        ExpiresByType image/png "access plus 1 months"
        ExpiresByType text/css "access plus 1 months"
        ExpiresByType text/javascript "access plus 1 months"
        ExpiresByType application/javascript "access plus 1 months"
        ExpiresByType application/x-shockwave-flash "access plus 1 months"
</IfModule>
<IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE text/plain
        AddOutputFilterByType DEFLATE text/html
        AddOutputFilterByType DEFLATE text/xml
        AddOutputFilterByType DEFLATE text/css
        AddOutputFilterByType DEFLATE text/javascript
        AddOutputFilterByType DEFLATE application/xml
        AddOutputFilterByType DEFLATE application/xhtml+xml
        AddOutputFilterByType DEFLATE application/rss+xml
        AddOutputFilterByType DEFLATE application/javascript
        AddOutputFilterByType DEFLATE application/x-javascript
        AddOutputFilterByType DEFLATE application/x-shockwave-flash
        BrowserMatch ^Mozilla/4 gzip-only-text/html
        BrowserMatch ^Mozilla/4\.0[678] no-gzip
        BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
        SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
        <IfModule mod_headers.c>
                Header append Vary User-Agent env=!dont-vary
        </IfModule>
</IfModule>

Update 11.07.2013:

Es gab hier einen Fallstrick, der in dem Fall, dass mod_headers nicht installiert ist, im Block bzgl. mod_deflate einen Error 500 verursacht. Dies wurde mithilfe des verschachtelten „IfModule“-Blocks innerhalb des mod_deflate.c gefixed, sodass auch nur bei Vorhandensein des notwendigen Moduls die Header gesendet werden.