Schlagwort-Archive: Ubuntu

Postfix auf mehreren Ports „horchen“ lassen

Viele Netzwerke verbieten den Zugriff auf Port 25, um zu verhindern, dass Spam von ihrem Netzwerk aus gesendet wird (wenn auch nicht über ihren eigenen Mailserver). Muss man trotzdem öfter Mails aus einem solchen Netzwerk verschicken, bietet es sich an, Postfix auf dem Mailserver einen zweiten Port zuzuweisen.

Das ginge zwar auch in der master.cf, eventuell müssten dann aber noch einige andere Sachen geändert werden. Einfacher geht es, indem man iptables anweist, vom zweiten Port aus an 25 umzuleiten:

1
iptables -t nat -A PREROUTING -p tcp --dport 587 -j REDIRECT --to-ports 25

Mit

1
iptables-save

wird die Änderung auch nach dem Serverneustart direkt wieder übernommen.

Root-Partition online vergrößern

Die Root-Partition vergrößern – das klingt schon mal scary. Aber dann auch noch online – das heißt ohne Live-CD, während des Betriebs? Warum um alles in der Welt sollte man sowas machen wollen? Ganz einfach, man stelle sich einen Server vor, bei dem die Root-Partition vergrößert werden soll und zu dem man keinen physischen Zugang hat. Voilà, das Szenario.

HINWEIS: Diese Methode funktioniert nur, wenn der zusätzliche Speicherplatz direkt an die zu vergrößernde Partition anschließt!

HINWEIS: Die hier vorgestellte Methode wurde von mir auf einem CentOS-Server live und erfolgreich angewendet, trotzdem gibt’s wie immer keine Garantie – und man sollte ein Backup in der Hinterhand haben.

Während viele Websites sagen, dass es nicht möglich wäre, die Partition ohne Live-CD oder Rettungssystem zu vergrößern, habe ich auf dem Blog von RaftaMan eine Anleitung gefunden, die genau das ermöglicht. Um einen Neustart des Systems kommt man zwar nicht herum (der Kernel muss die neue Partitionsgröße einlesen bevor man das Filesystem daran anpassen kann), aber es geht alles ohne von CD zu booten.

Also, los geht’s:

1
fdisk -l

zeigt uns die Devices und darauf enthaltenen Partitionen an. Um eine Partition zu bearbeiten müssen wir zunächst in fdisk das Device aufrufen:

1
fdisk /dev/sda

würde jetzt für die erste Festplatte stehen. Auf der Befehlszeile drücken wir nun „p“ und „Enter“, worauf uns noch einmal (zur Sicherheit) die Partitionen angezeigt werden:

1
2
3
4
5
6
7
Command (m for help): p
Disk /dev/sda: 5218 MB, 5218304000 bytes
255 heads, 63 sectors/track, 634 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
 
    Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1         634     5092573+  83  Linux

Den Anfangssektor unbedingt merken oder aufschreiben, wird er falsch gesetzt kann das alle Daten unbrauchbar machen! Diese Partition müssen wir jetzt löschen (oh ja, richtig gehört), aber keine Angst es gehen dabei keine Daten verloren solange der Anfangssektor gleich und die Partition nachher größer als vorher ist. Also geben wir jetzt ein „d“ und „Enter“ ein, worauf wir nach der Nummer der Partition gefragt werden. Da die Zählung bei 1 beginnt also in unserem Fall eine 1. Und noch mal „Enter“.

Als nächstes erstellt man eine neue Partition mit „n“ und „Enter“. Dabei nutzt man den gleichen Partitionstyp und den gleichen Startsektor wie bei der Ausgangspartition. Der Endsektor kann innerhalb der angezeigten Grenzen beliebig gewählt werden, sollte aber größer sein als der Ursprüngliche, damit die Partition keine Daten verliert.

1
2
3
4
5
6
7
8
9
Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-934, default 1):
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-934, default 934): 850

Falls die Ausgangspartition das „boot“-Flag gesetzt hatte, müssen wir das auch hier wieder setzen:

1
2
Command (m for help): a
Partition number (1-4): 1

Schlussendlich schreiben wir die Änderungen mit „w“ und „Enter“ in die Partitionstabelle. Die Bestätigung sollte fast sofort erscheinen und uns darauf hinweisen, dass ein Neustart erforderlich ist.

1
2
3
4
5
6
7
8
9
Command (m for help): w
The partition table has been altered!
 
Calling ioctl() to re-read partition table.
 
WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table.
The new table will be used at the next reboot.
Syncing disks.

Nach dem Neustart, den wir direkt durchführen, kann das Filesystem problemlos live an die neue Partitionsgröße angepasst werden:

1
2
3
4
5
resize2fs /dev/sda1
resize2fs 1.39 (29-May-2006)
Filesystem at /dev/sda1 is mounted on /; on-line resizing required
Performing an on-line resize of /dev/sda1 to 1522150 (4k) blocks.
The filesystem on /dev/sda1 is now 1522150 blocks long.

Und fertig. Der neue Speicherplatz steht vollständig zur Verfügung.

phpmyadmin sicher(er) zur Verfügung stellen

Möchte man phpmyadmin mehreren Domains zur Verfügung stellen, so bietet sich dafür das Debian-Paket „phpmyadmin“ an:

1
apt-get install phpmyadmin

Danach kann man unter /etc/phpmyadmin/apache.conf eine config finden, die man per

1
ln -s /etc/phpmyadmin/apache.conf /etc/apache2/conf.d/phpmyadmin.conf

in das Apache-Verzeichnis einbindet.

Jetzt muss an hier aber noch ein wenig gefeilt werden, denn so stellt man phpmyadmin grundsätzlich auch über HTTP – also unverschlüsselt – zur Verfügung. Administriert jetzt jemand über ein öffentliches Netzwerk seine Datenbank (immer an den DAU denken, auch wenn es sich erst mal vollkommen an den Haaren herbeigezogen anhört), hat man ruck-zuck ein Problem.

Deshalb leite ich grundsätzlich alle HTTP-Anfragen an phpmyadmin einfach nach HTTPS weiter. Dazu öffnet man die /etc/phpmyadmin/apache.conf und fügt ganz oben folgenden Text ein:

1
2
3
4
5
6
7
8
9
<IfModule mod_rewrite.c>
        <IfModule mod_ssl.c>
                <Location ~ "/phpmyadmin(/|$)">
                        RewriteEngine on
                        RewriteCond %{HTTPS} off
                        RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI}
                </Location>
        </IfModule>
</IfModule>

Jetzt wird jeder Besucher von http://domain.de/phpmyadmin zu https://domain.de/phpmyadmin umgeleitet, was phpmyadmin ein ganzes Stück sicherer macht. Trotzdem ist zu überlegen, ob man die Software nicht lieber zusätzlich mit einem .htaccess-Schutz versieht. Wie das geht, erfährt man unter anderem bei SELFHTML.

Nodejs-Server via Apache-Reverse-Proxy und Monit

Um einen Nodejs-Server aufzusetzen braucht es nicht viel. Eigentlich nur die Binaries und eine JS-Datei mit dem eigentlichen Server. Doch wenn man den Server dauerhaft und bequem zugreifbar betreiben möchte, sind ein paar mehr Schritte notwendig.

Zunächst wird Nodejs und der Paketmanager npm installiert:

1
apt-get install nodejs npm

Danach richten wir den Proxy ein, sonst wäre ein Aufruf nur über einen Nicht-Standard-Port (80 ist ja schon vom Apachen belegt) möglich. In der Regel verwendet Nodejs hier Port 3000, aber das ist je nach Script unterschiedlich. Wir aktiviren also zunächst den Passthrough-Modus:

1
2
a2enmod proxy
a2enmod proxy_http

Für die eigentliche Einrichtung kann jetzt ein eigener VHost (z.B. eine Subdomain) angelegt werden, oder – wie in meinem Beispiel – ein Unterverzeichnis hergenommen werden.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<VirtualHost ip:80>
	ServerName   myhost.com:80
	ServerAlias  www.myhost.com
	UseCanonicalName Off
	DocumentRoot /var/www/vhosts/myhost/httpdocs
	ErrorLog  /var/www/vhosts/myhost/statistics/logs/error_log
 
	...
 
	<Directory /var/www/vhosts/myhost/httpdocs>
		Options -Includes +ExecCGI
	</Directory>
 
	<Proxy *>
  		Order deny,allow
  		Allow from all
	</Proxy>
 
	<Location /mynodejspath>
  		ProxyPass http://localhost:3000
  		ProxyPassReverse http://localhost:3000
	</Location>
</VirtualHost>

Würde man nun nodejs manuell starten, könnte man schon per http://myhost.com/mynodejspath darauf zugreifen. Da Nodejs aber noch ein wenig fehleranfällig ist und dann gern mal sang- und klanglos abtritt, benutze ich monit zur Überwachung und ggf. zum Neustart des Servers (der Nodejs-App).

1
apt-get install monit

Als Startscript verwende ich ein Standard-init.d-Script, sodass ich auch beim Systemstart problemlos den Nodejs-Server mitstarten lassen kann. Dabei ist zu beachten, dass ich auf Benutzer „root“ prüfe und den Nodejs-Server ggf. über einen extra User starte. Andere Nutzer starten die Nodejs-App mit diesem Script als sie selbst.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/bin/bash
DIR=/var/www/vhosts/myhost/httpdocs/mynodejspath
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
NODE_PATH=/usr/lib/node_modules
NODE=/usr/bin/node
 
test -x $NODE || exit 0
 
function start_app {
  if [ $(whoami) = "root" ]
  then
    NODE_ENV=production nohup sudo -u nodejsusername "$NODE" "$DIR/app.js" 1>>"$DIR/logs/node.log" 2>&1 &
    echo $! > "$DIR/pids/node.pid"
  else
    NODE_ENV=production nohup "$NODE" "$DIR/app.js" 1>>"$DIR/logs/node.log" 2>&1 &
    echo $! > "$DIR/pids/node.pid"
  fi
}
 
function stop_app {
  kill `cat $DIR/pids/node.pid`
}
 
case $1 in
   start)
      start_app ;;
    stop)
      stop_app ;;
    restart)
      stop_app
      start_app
      ;;
    *)
      echo "usage: myapp {start|stop|restart}" ;;
esac
exit 0

Die Verzeichnisse „pids“ und „logs“ müssen unter dem App-Pfad noch angelegt werden. Danach kommt das Monit-Script nach /etc/monit/noderc:

1
2
3
4
5
6
7
8
9
10
#!monit
set logfile /var/log/monit.log
 
check process nodejs with pidfile "/var/www/vhosts/myhost/httpdocs/mynodejspath/pids/node.pid"
    start program = "/etc/init.d/myapp start"
    stop program  = "/etc/init.d/myapp stop"
    if failed port 3000 protocol HTTP
        request /
        with timeout 10 seconds
        then restart

… und ein Starter-init.d Script nach /etc/init.d/monit:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash
 
case $1 in
   start)
      monit -d 60 -c /etc/monit/noderc
      ;;
    stop)
      killall monit
      ;;
    restart)
      stop_app
      start_app
      ;;
    *)
      echo "usage: monit {start|stop|restart}" ;;
esac
exit 0

Ein Symlink nach rc2.d komplettiert die Automatisierung:

1
2
cd /etc/rc2.d/
ln -s ../init.d/monit S99monit

 

Somit haben wir viele Probleme gelöst:

  • Nodejs startet mit dem Server
  • Es wird überwacht und falls notwendig neu gestartet
  • Der Jeweilige Besitzer (und root) können es manuell neu starten
  • Es läuft mit eingeschränkten Userrechten
  • Es ist über Port 80 zugreifbar
  • und wir haben wieder etwas gelernt 😉

Gitlab aufsetzen unter Debian/Ubuntu mit Apache

github.com ist ein großartiges Tool für Open Source Projekte auf der ganzen Welt. Es stellt einfachen Zugriff auf das git-Versionierungssystem zur Verfügung, ohne dass man sich um die Befehle für das Erstellen und Warten eines solchen Repos Gedanken machen müsste.

Das ist toll, allerdings hat github einen Nachteil: für private Repositories – also solche, bei denen der Code nicht der ganzen Welt zur Verfügung steht – werden (relativ hohe) Gebühren fällig. Somit ist dieses Tool für kommerzielle Zwecke nur bedingt geeignet, falls man nicht die „Plans“ (github: Plans & Pricing) in Anspruch nehmen möchte.

Lange Zeit gab es keine Softwarelösung, die man sich auf dem eigenen Server installieren konnte, und die ähnlichen Komfort wie github zu bieten hatte. Doch seit einiger Zeit etabliert sich eine solche Lösung: Gitlab. Das Tool steht github kaum noch in etwas nach und kann kostenfrei auf (fast) jedem Rootserver betrieben werden:

  • Ubuntu Linux
  • Debian/GNU Linux
  • Fedora
  • CentOs
  • RedHat.

Zur Installation reichen je nach Komplexität der Installation einige wenige Schritte aus, mehr Komfort gibt es – wie immer – mit mehr Schritten. Doch zunächst das Basis-Setup:

Wer ein paar Basis-Programme nicht installiert hat, muss dies zuerst nachholen:

1
sudo apt-get install wget git git-core build-essential libyaml-dev

Als Nächstes laden wir das Installscript von gitlab herunter und installieren es, was uns viel Arbeit erspart. Es ist dabei von Vorteil, noch kein RubyOnRails installiert zu haben (falls Ruby schon installiert ist, muss es zwingend Ruby 1.9.2 oder besser sein). Ansonsten muss das Script angepasst werden, die Befehle sind relativ selbsterklärend. Hier nun die Variante mit Script (Download-Adresse aktualisiert 19.10.2012):

1
2
3
wget https://raw.github.com/gitlabhq/gitlab-recipes/master/install/debian_ubuntu.sh
chmod +x debian_ubuntu.sh
./debian_ubuntu.sh

Alternativ sind Schritte 1-4 dieser Anleitung auszuführen.

Nun setzen wir die Komponenten für den Ruby-Server auf:

1
2
3
4
5
6
7
sudo gem install charlock_holmes
sudo pip install pygments
sudo gem install bundler
cd /home/gitlab
sudo -H -u gitlab git clone git://github.com/gitlabhq/gitlabhq.git gitlab
cd gitlab
sudo -u gitlab cp config/gitlab.yml.example config/gitlab.yml
1
2
3
sudo -u gitlab cp config/database.yml.sqlite config/database.yml
ODER
sudo -u gitlab cp config/database.yml.example config/database.yml

Nachdem die Datenbank-Konfiguration kopiert wurde, müssen bei MySQL die Verbindungsparameter angepasst werden. SQLite läuft sofort „out of the box“.

Im folgenden Schritt initialisieren und konfigurieren wir Gitlab für den Ruby-Server, anschließend testen wir die Umgebung:

1
2
3
sudo -u gitlab -H bundle install --without development test --deployment
sudo -u gitlab bundle exec rake gitlab:app:setup RAILS_ENV=production
sudo -u gitlab bundle exec rake gitlab:app:status RAILS_ENV=production
1
2
3
4
5
6
7
8
9
10
11
12
Starting diagnostic
config/database.yml............exists
config/gitlab.yml............exists
/home/git/repositories/............exists
/home/git/repositories/ is writable?............YES
remote: Counting objects: 603, done.
remote: Compressing objects: 100% (466/466), done.
remote: Total 603 (delta 174), reused 0 (delta 0)
Receiving objects: 100% (603/603), 53.29 KiB, done.
Resolving deltas: 100% (174/174), done.
Can clone gitolite-admin?............YES
UMASK for .gitolite.rc is 0007? ............YES

Der Output des Testbefehls sollte keine „failed“- oder „no“- Einträge haben. Falls alle Zeichen auf „grün“ stehen können wir den Server starten.

1
2
sudo -u gitlab bundle exec rails s -e production -d
./resque.sh

Der Server läuft nun und ist über Port 3000 bereits zugreifbar (nicht wundern, der erste Seitenaufruf dauert ziemlich lange). Wem das reicht, der ist bereits fertig.

Ich selbst mag meine Web-Anwendungen alle über HTTP(S) abrufen, so auch gitlab. Dazu nutze ich nicht die vom Tutorial vorgeschlagene Variante nginx + Unicorn sondern Passenger für Apache (weil Apache bei mir für alle Webanwendungen genutzt wird und Unicorn viel zu umständlich für kleine bis mittlere Installationen ist):

1
2
gem install passenger
passenger-install-apache2-module

Bei der Installation einfach den Anweisungen folgen, es sind ja nicht viele. Danach kann ein VirtualHost für gitlab angelegt werden, wichtig dabei: DocumentRoot muss auf das „public“-Verzeichnis von gitlab zeigen! Schon kann man z.B. über http(s)://gitlab.yourdomain.com auf gitlab zugreifen und loslegen.

Wichtig: Passenger ersetzt quasi den Deploy-Prozess von gits bundle exec, d.h. der Server auf dem Port 3000 muss dann nicht mehr laufen. Wenn man die Wartezeit für den ersten Besucher von gitlab nach dem Serverstart verkürzen will kann man den Apache wie folgt konfigurieren:

1
2
3
4
5
6
7
8
9
PassengerPreStart https://git.yourdomain.com/
 
<VirtualHost ip:443 >
        ServerName git.yourdomain.com
        UseCanonicalName Off
        DocumentRoot /home/gitlab/gitlab/public
 
        PassengerMinInstances 1
        ...

Als optionalen Schritt kann man nun noch ein Shell-Script für init.d schreiben, damit man resque nach einem Neustart nicht immer von Hand aufrufen muss:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#! /bin/bash
### BEGIN INIT INFO
# Provides:          gitlab
# Required-Start:    $local_fs $remote_fs $network $syslog redis-server
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: resque service for gitlab
# Description:       resque service for gitlab
### END INIT INFO
 
NAME=resque
DESC="resque service"
RESQUE_PID=/home/gitlab/gitlab/tmp/pids/resque_worker.pid
 
case "$1" in
  start)
        CD_TO_APP_DIR="cd /home/gitlab/gitlab"
        START_RESQUE_PROCESS="./resque.sh"
 
        echo -n "Starting $DESC: "
        if [ `whoami` = root ]; then
          sudo -u gitlab sh -l -c "$CD_TO_APP_DIR > /dev/null 2>&1 && $START_RESQUE_PROCESS"
        else
          $CD_TO_APP_DIR > /dev/null 2>&1 && $START_RESQUE_PROCESS
        fi
        echo "$NAME."
        ;;
  stop)
        echo -n "Stopping $DESC: "
        kill -QUIT `cat $RESQUE_PID`
        echo "$NAME."
        ;;
  restart)
        echo -n "Restarting $DESC: "
        kill -USR2 `cat $RESQUE_PID`
        echo "$NAME."
        ;;
  reload)
        echo -n "Reloading $DESC configuration: "
        kill -HUP `cat $RESQUE_PID`
        echo "$NAME."
        ;;
  *)
        echo "Usage: $NAME {start|stop|restart|reload}" >&2
        exit 1
        ;;
esac
 
exit 0

Diese Datei speichern wir unter /etc/init.d/resque und machen es mit

1
sudo chmod +x /etc/init.d/resque

ausführbar. Danach noch einen symbolischen Link nach /etc/rc2.d/ anlegen

1
2
cd /etc/rc2.d
ln -s /etc/init.d/resque S99resque

Fertig.

Achtung: Das von Gitlab angelegte Admin-Passwort ist immer gleich, d.h. es ist zu empfehlen, sich einen eigenen Account mit Administrationsrechten anzulegen und den Admin-Account dann zu blocken, oder das Passwort des Admin-Accounts zu ändern.

Einzelne Datenbank/Tabelle aus MySQL-Dump wiederherstellen

Auf meinem Rootserver läuft jeden Tag ein Backup mit fwbackups, welches meine Dateien und Datenbanken mittels externem Script sichert und, ebenfalls mit Hilfe eines externen Scripts, auf einen FTP-Backupspace lädt. Das ist – einmal eingerichtet – sehr komfortabel. Möchte ich nun aber an die Daten heran und nur eine Datenbank oder Tabelle zurückspielen so müsste ich eigentlich einen zweiten MySQL-Server starten, das Backup einspielen und dann nur das gewünschte exportieren. Das wäre extrem umständlich, daher habe ich nach einem einfacheren Weg gesucht und ihn auch gefunden:

Nur eine Datenbank zurücksichern:

sed -n '/^-- Current Database: `dbname`/,/^-- Current Database: `/p' dumpfile > dbname.sql 2>error

Nur eine Tabelle zurücksichern:

sed -n -e '/CREATE TABLE.*mytable/,/CREATE TABLE/p' mysql.dump > mytable.dump

Hat man mehrere Tabellen, die ähnlich heißen sollte man Backquotes für die Namen verwenden.

 
Danke an uloBasEI von stackoverflow.com und Prabhat Kumar von adminlinux.blogspot.com für diese Tipps.

//Update: Danke an Kai Hessing, der mich per Mail aufmerksam gemacht hat, dass es mit obriger SQL-Anweisung ein Problem gibt, wenn die Tabelle vor der Rücksicherung schon existiert. Also dann entweder die Tabelle erst löschen oder folgendes Kommando benutzen:

sed -n -e '/DROP TABLE.*MYTABLE/,/UNLOCK TABLES/p' $BACKUPDIR/$FILE > $BACKUPDIR/$FILE.mytable

Praktische Methode zum „Kopieren mit Ausschluss“ unter Linux

Das Linux-Command cp enthält leider keine „–exclude“-Funktion. Daher kann man, wenn man rekursiv kopieren will, keine Verzeichnisse oder Dateien angeben, die ausgeschlossen werden sollen. In einem Forum habe ich diesen Tipp gelesen (und dann ausprobiert), der wirklich clever ist.

Das Programm tar enthält eine exclude-Funktion. Also nutzen wir doch einfach dieses:

1
tar -cvf - --exclude dir1 --exclude dir2 --exclude file1.ext --exclude file2.ext /path/to/source | (cd /path/to/destination; tar -xvf -)

Danke für diesen Tipp an vsemaska von linuxforums.org.

Webhosting mit ACLs

Die bekannten Unix-Rechte 644 oder 755 mögen für das Hosting eines einzelnen Projekts oder mehrerer Projekte, auf die man Shell-Zugriff hat, ausreichen. Wenn man aber Usern anbietet, ihre Site zu hosten gelangt man damit schnell an einen Punkt, wo diese Rechte einfach nicht mehr ausreichen.

Wenn zum Beispiel das CMS Joomla eine Komponente oder ein Modul über das Webinterface installiert bekommt so haben die Dateien, die installiert werden, als „Owner“ den User, unter dem der Webserver läuft (meist www-data). Andererseits hat ein manuell über FTP eingespieltes Template als „Owner“ den Hosting-Nutzer. Auf den meisten Systemen kommt dazu eine default-umask von 022, die allen neu erstellten Dateien ausschließlich Schreibrechte für den Ersteller/Besitzer der Datei zugesteht. Das könnte man zwar theoretisch ändern, würde damit aber die Sicherheit bei mehreren Nutzern kompromittieren (z.B. indem man die Nutzer und www-data einer Gruppe zuordnet, die Schreibrechte hat).

Alles in allem eine sehr unbefriedigende Lösung. Aber es gibt Abhilfe: ACLs (Access Control Lists) erlauben die feingranulare Einstellung der Rechte auf Nutzerebene wie auch in Gruppen. Mit ihnen lassen sich Konstrukte schaffen wie „www-data und Hostingnutzer haben rwx-Rechte“ – und das auch für neu erstellte Dateien. Doch der Reihe nach.

Für die Nutzung von ACLs unter Ubuntu/Debian braucht es einen einigermaßen modernen Kernel (>2.5.46, ob man diesen Kernel von 2002 noch „einigermaßen modern“ nennen kann lasse ich jetzt mal dahingestellt ;)) und die Partitionen müssen mit ext2 oder höher formatiert sein. In der /etc/fstab muss bei den Mountoptions aller Partitionen, mit denen ACLs genutzt werden sollen, der Parameter acl hinzugefügt werden, z.B.:

1
2
3
4
5
6
7
# /etc/fstab: static file system information.
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
proc            /proc           proc    defaults        0       0
UUID=c1234f7f-fb32-4199-342a-4a12342f9a9d       /               ext3    defaults,usrquota,acl   0       1
UUID=f12349d1-d7e1-4ce5-4f3w-ddf971234b7       /boot           ext2    defaults        0       2
UUID=a1234b2b-b6bb-4572-33df-9351234335a0       none            swap    sw              0       0

Für die Bootpartition und die Swap-Partition brauchen wir natürlich keine ACLs, daher erfolgt der Eintrag nur auf der ersten Festplatte. Nach einer Änderung an der fstab muss das System neu gestartet werden um die Mountoptions zu übernehmen. Alternativ kann man natürlich auch den entsprechenden Mountpoint aushängen und manuell mit dem zusätzlichen Parameter neu mounten.

Als nächstes gehen wir in das Verzeichnis, welches die neuen ACLs erhalten soll und vergeben sie entsprechend unseren Wünschen:

1
2
3
cd /var/www/vhosts/username/
setfacl -R -m u::rwX,u:www-data:rwX,u:username:rwX .
setfacl -R -d -m u::rwX,u:www-data:rwX,u:username:rwX .

Die Zeile 2 des Codeschnipsels sorgt dafür, dass die User www-data und username Lese-, Schreib- und Ausführungsrechte für bereits bestehende Dateien/Ordner im Verzeichnis und allen Unterverzeichnissen erhalten. Das groß geschriebene „X“ sorgt dabei für eine automatische Berechnung der Maske, ohne die es zu Einschränkungen im Zugriff kommen kann. Zeile 3 macht das Gleiche wie Zeile 2, nur für neu erstellte Objekte (Parameter d = default). Mit Hilfe dieses Konstrukts hat man eine Umgebung geschaffen, in der der Nutzer sich mit FTP und PHP-Fileuploads austoben kann und doch die Sicherheit des Systems gewahrt bleibt. Zugleich haben andere Nutzer nach wie vor keinen Zugriff auf die Dateien und Ordner von Benutzer username.

Für den „Hausgebrauch“ reichen diese Befehle schon aus, um ein komfortables Arbeiten zu ermöglichen. Wer aber noch mehr erfahren möchte, dem sei die Seite über ACLs im Ubuntu-Wiki empfohlen. Dort wird u.a. ausführlich erklärt, wie man mit Gruppenrechten hantiert, wie man erstellte ACLs wieder los wird und wie man ein Backup seiner Listen anlegen kann.

Postfix + Courier unter Debian/Ubuntu oder: einen Mailserver aufsetzen

Vor einigen Tagen habe ich mein Ubuntu-System wegen der vielen Neuerungen und Security-Updates auf die Version 10.04 (Lucid Lynx) gebracht. Vorher natürlich ein Vollbackup erstellt (stolze 16 GB, wusste garnicht dass so viel drauf ist *g*), aber glücklicherweise nicht benötigt. Das Upgrade ging einfach und schnell, ein paar Fragen zu Config-Dateien waren schnell beantwortet und nach einem Neustart mit frischem Kernel 2.6.32-22 lief auf den ersten Blick alles super. Auf den zweiten Blick dann ein (kleiner) Schock: Plesk ging nicht mehr. Es war garnicht mehr installiert. Auf der Website von Parallels findet sich nur der Hinweis, dass maximal Ubuntu 8.04 unterstützt wird (nicht mal 9.10 – schwach). Na ja im Grunde genommen waren mir Systeme wie Plesk schon immer suspekt, man hat manchmal mehr Ärger damit als Nutzen davon und so bin ich nicht zurück zu 8.04 gegangen sondern habe im Internet gesucht wie ich am besten einen Mailserver aufsetze – denn der funktionierte nichtmehr.

Eigentlich wollte ich ja das Courier-Gesamtpaket courier-mta + courier-pop und courier-imap einsetzen. Nach langem Herumprobieren inklusive zu Rate ziehen der Mailingliste von Courier (courier-users) musste ich aber leider zum Schluss kommen, dass die zur Zeit im Lucid Lynx vorhandene Version der courier-mta wohl einen Bug aufweist, der die MTA nicht mit dem Authentifizierungsdaemon kommunizieren lässt. So bekam ich immer beim Eingehen einer Mail den Fehler

courieresmtpd: authdaemon: s_connect() failed: Permission denied

Nachdem ich diesen Fehler also nicht lösen konnte (sogar die selbst kompilierte Variante bockte mit dem gleichen Fehler rum) habe ich mich schweren Herzens (ich hasse ungelöste Probleme^^) entschieden, Postfix als MTA einzusetzen und Courier für den IMAP- und POP-Zugriff.

 

Zuallererst müssen natürlich die erforderlichen Programme installiert werden (als root):

1
apt-get install postfix courier-authdaemon courier-authlib courier-authlib-userdb courier-base courier-imap courier-imap-ssl courier-pop courier-pop-ssl sasl2-bin libsasl2-2 libsasl2-modules

Bei der Installation von Postfix wählt man als Betriebsmodus Internet-Site aus.

adduser vmail einen neuen Benutzer an. Dabei wird auch ein Nutzerverzeichnis /home/vmail angelegt, in dem später alle Mails gespeichert werden. Die User- und Gruppenid merken wir uns für später. Jetzt wechseln wir zu dem angelegten Nutzer vmail, z.B. mit su vmail --preserve-environment (preserve-environment verhindert, dass die default-shell des Nutzers vmail zum Einsatz kommt, die ist normalerweise nämlich nicht was wir wollen). Als User vmail erstellen wir jetzt die Unterverzeichnisse für die einzelnen Domains und Nutzer, also z.B. für 2 Nutzer auf the-enlightened.de:

1
2
3
4
5
cd /home/vmail
mkdir -p the-enlightened.de/amras
maildirmake the-enlightened.de/amras/Maildir
mkdir -p the-enlightened.de/aerith
maildirmake the-enlightened.de/aerith/Maildir

Als Nächses kommt die Postfix-Config dran. Dafür muss man wieder als root angemeldet sein (neues Terminal oder exit als user vmail). Die Config befindet sich in /etc/postfix/main.cf. Hier muss überprüft werden, dass myhostname auf den Rechnernamen gesetzt ist, ansonsten muss das nachgeholt werden. Das Feld mydestination muss meist nicht geändert werden, hier sollten localhost und ebenfalls der Rechnername eingetragen sein. Schlussendlich sollte inet_interfaces auf all stehen, aber das sollte ebenfalls bereits so sein. Wir springen ans Ende des file und fügen folgende Zeilen ein (die Domains sowie die uid und die gid [die wir uns ja gemerkt haben] sind natürlich entsprechend anzupassen):

1
2
3
4
5
6
7
8
9
10
11
12
13
#virtual domains & smtp auth
virtual_mailbox_domains = the-enlightened.de domain2.tld domain3.tld
virtual_mailbox_base = /home/vmail
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_minimum_uid = 100
virtual_uid_maps = static:1006
virtual_gid_maps = static:1001
virtual_alias_maps = hash:/etc/postfix/virtual          
smtpd_sasl_path = smtpd
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous 
smtpd_sasl_tls_security_options = $smtpd_sasl_security_options

Dann abspeichern und die in der config gerade angebenen files erzeugen:

1
2
touch /etc/postfix/vmailbox
touch /etc/postfix/virtual

Jetzt wird /etc/postfix/vmailbox editiert. Für jede Adresse wird die virtuelle Mailbox, in dem die Mails später landen sollen, angegeben, bei mir also z.B.

1
2
amras@the-enlightened.de        the-enlightened.de/amras/Maildir/
aerith@the-enlightened.de       the-enlightened.de/aerith/Maildir/

Wichtig ist hier der abschließende Slash, dadurch wird Postfix veranlasst, die Maildir-Struktur statt seiner eigenen zu benutzen. Die Angabe erfolgt also als Mailadresse + Leerzeichen/Tab + Pfad zum Maildir unter /home/vmail. Jetzt speichern und folgende Befehle ausführen:

1
2
3
postmap /etc/postfix/virtual
postmap /etc/postfix/vmailbox 
/etc/init.d/postfix reload

Ankommende Mails werden jetzt schonmal richtig einsortiert. Kommen wir also zum 2. Teil des Tutorials, dem Zugriff auf die Mails via Courier.

 

Hier kommen zuerst die Nutzerpasswörter an die Reihe. Dafür muss man weiter als root angemeldet sein. Wir ändern den Eintrag authmodulelist in /etc/courier/authdaemonrc auf
authmodulelist="authuserdb"

und legen mittels der folgenden Befehle die Nutzerpasswörter an:

1
2
3
4
5
6
7
8
9
userdbpw -md5 | userdb -f /etc/courier/userdb/the-enlightened.de amras@the-enlightened.de set systempw
(Passwort 2x eingeben)
userdb -f /etc/courier/userdb/the-enlightened.de amras@the-enlightened.de set home=/home/vmail/the-enlightened.de/amras/ gid=1001 uid=1006
 
userdbpw -md5 | userdb -f /etc/courier/userdb/the-enlightened.de aerith@the-enlightened.de set systempw
(Passwort 2x eingeben)
userdb -f /etc/courier/userdb/the-enlightened.de aerith@the-enlightened.de set home=/home/vmail/the-enlightened.de/aerith/ gid=1001 uid=1006
 
makeuserdb

Nach einem Neustart von courier-authdaemon (kA ob das nötig ist, schädlich ist es aber keinesfalls)
/etc/init.d/courier-authdaemon restart
können sich die eingetragenen Nutzer per POP oder IMAP (ggf. mit SSL) anmelden.

Um Mails versenden zu können (nicht von localhost sondern mit Anmeldung) erfordert es ein paar weitere Schritte. So muss die Datei /etc/postfix/master.cf editiert werden (als root). Hier wird beim ersten Eintrag (smtp) für den Parameter chroot ein „n“ festgelegt. Mit der chrooted-Umgebung habe ich es nach unzähligen Versuchen nämlich nicht zum Laufen bekommen.

1
2
3
4
5
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
smtp      inet  n       -       n       -       -       smtpd

Als finaler Schritt editieren wir nun die /etc/postfix/sasl/smtpd.conf wie folgt:

1
2
3
4
pwcheck_method: authdaemond
mech_list: PLAIN LOGIN
authdaemond_path: /var/run/courier/authdaemon/socket
#autotransition: true

autotransition:true wird meiner Erfahrung nach nur bei der Benutzung von saslauthd benötigt, authdaemond kommt ohne aus. Bei wem es nicht funktioniert möge trotzdem den Parameter mal testweise anstellen (Mailserver scheinen die verschiedensten Macken zu haben, die sie nicht-deterministisch auf diveren Konfigurationen behindern).

Nach einem Neustart von Postfix und ggf. dem Start von courier-authdaemon via /etc/init.d/courier-authdaemon start sollte der Mailserver nun voll funktionstüchtig sein.

VPN-Tunnel mit pptpd

Wenn man in öffentlichen, nicht verschlüsselten Netzwerken unterwegs ist ist es immer eine gute Idee, den gesamten Internetverkehr zu verschlüsseln. Und wenn man schonmal einen Rootserver hat…

Also habe ich mich entschieden pptpd aufzusetzen, weil es nicht nur von Windows nativ unterstützt wird sondern auch von fast allen modernen Mobilgeräten und auch von Linux. Die Konfiguration ist eigentlich sehr simpel, der „Trick-Teil“ kommt am Ende. Für den muss ich mich bei „Lord Gurke“ aus dem Serversupportforum bedanken.

Also, los gehts:

apt-get install pptpd

Das war schon alles, was man installieren muss. Nun folgt die Config. Zunächst kommt /etc/pptpd.conf dran. Hier werden u.a. die IP-Adressen für das neue Netzwerk bestimmt.

1
2
3
4
option /etc/ppp/pptpd-options
logwtmp
localip 192.168.1.1
remoteip 192.168.1.200-253

Das heißt im Klartext, dass mein Rootserver die IP 192.168.1.1 erhält und alle Clients automatisch Adressen von 200 bis 253 zugewiesen bekommen. Sehr komfortabel 🙂

Als nächstes wird /etc/ppp/pptpd-options editiert:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
name pptpd
refuse-pap
refuse-chap
refuse-mschap
require-mschap-v2
require-mppe-128
ms-dns 192.168.1.1
proxyarp
nodefaultroute
mtu 1490
mru 1490
noipx
lock
nobsdcomp

Neben einigen für das System wichtigen Einstellungen wird hier eingestellt, dass der Rootserver seine Adresse als DNS-Server an die Clients pusht und dass nur das (noch) als sicher geltende MS-CHAPv2 als Authentifizierungsverfahren zum Einsatz kommt.

Die Benutzerdaten liegen bei pptpd leider unverschlüsselt im Keyfile, insofern sollte man vorsichtshalber einen zufälligen Schlüssel nehmen, den man sonst nirgends verwendet. Das Keyfile ist /etc/ppp/chap-secrets und wie folgt aufgebaut:

Username<TAB>*<TAB>Passwort<TAB>*
Das letzte Sternchen kann man dabei auch durch eine IP-Adresse oder einen IP-Adressbereich ersetzen, dann kann man nur aus diesem Netz bzw. von dieser IP auf den Server zugreifen.

Soa, jetzt zum „Trick-Teil“ 😉
PPTPD leitet in der bis jetzt geschaffenen Umgebung keine Internetanfragen weiter. Dazu muss über iproute erst noch eine Route eingerichtet werden:

1
2
3
iptables -A FORWARD -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -P OUTPUT ACCEPT

Das packt man am besten direkt in ein rc-Script damit es beim Serverneustart geladen wird.
Als letztes dann noch die /etc/sysctl.conf bearbeitet werden und die Zeile

net.ipv4.ip_forward = 1

von ihrer Kommentar-Raute befreit werden. Und fertig.

css.php