FreeBSD Jail: Etherpad Lite per Node.JS mit Apache Reverse Proxy

screenshot_etherpad

Etherpad is a highly customizable Open Source online editor providing collaborative editing in really real-time.

Quelle: http://www.etherpad.org

Gewünscht ist die Installation eines Etherpad Lite, mittels node.js und Apache Reverse Proxy (für IPv6 und SSL Support) in einer FreeBSD Jail, dabei soll der Apache Server auf dem FreeBSD HOST laufen, die Etherpad IPv4 Anbindung läuft dabei über ein Loopback Device mit PF NAT zur Public Adresse, die unmittelbare IPv6 Adresse dient nur der Jail-Administration per SSH:

Hinweis: nodejs bzw Java Script V8 unterstützt kein SPARC64, somit muss auf eine FreeBSD AMD64 Maschine zurück gegriffen werden!

Punkt 1: @HOST: zweites Loopback Device starten lassen

$
vi /etc/rc.local
$
$
#!/bin/sh
/bin/echo "---> ezjail <---"

/sbin/ifconfig lo1 create

/bin/echo ""
#EOF
$

Falls die ezjails vor dem erstellen des lo1 gebootet werden sollten, lassen sich per /etc/rc.local auch einzeln die Jails starten

$
/usr/local/bin/ezjail-admin onestart etherpad.domain.tld
$

Punkt 2: @HOST: Jail erstellen

$
ezjail-admin create etherpad.domain.tld 're0|2a01:aaaa:bbbb:cccc::dddd,lo0|127.0.1.1,lo1|127.1.1.1'
$

Wenn das fdescfs.ko Kernel-Modul fehlen sollte, kann es nachgeladen werden

$
vi /boot/loader.conf
$
$
fdescfs_load="YES"
$

Punkt 3: @HOST: raw_sockets für die JAIL erlauben

$
vi /usr/local/etc/ezjail/etherpad_domain_tld
$
$
export jail_etherpad_domain_tld_parameters="allow.raw_sockets=1 allow.sysvipc=1"
$

Punkt 4: @HOST: JAIL auf 10 GB beschränken und kurzzeitig starten lassen

$
zfs set quota=10g tank/root/ezjail/etherpad.domain.tld

/usr/local/bin/ezjail-admin onestart etherpad.domain.tld
cat /var/log/jail_etherpad_domain_tld_console.log
/usr/local/bin/ezjail-admin onestop etherpad.domain.tld
$

Punkt 5: @HOST: JAIL hosts, rc.conf und sshd_config Anpassung

$
vi /usr/jails/etherpad.domain.tld/etc/hosts
$
$
### ### ### PLITC ### ### ###
#
127.0.1.1   localhost   localhost.my.domain
#
2a01:aaaa:bbbb:cccc::dddd   etherpad.domain.tld   etherpad
#
### ### ### PLITC ### ### ###
# EOF
$
$
vi /usr/jails/etherpad.domain.tld/etc/rc.conf
$
$
### ### ### PLITC - JAIL ### ### ###
#
hostname="etherpad.domain.tld"

sshd_enable="YES"

syslogd_enable="YES"
syslogd_flags="-ss"

sendmail_enable="NO"

### SSMTP
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"

### ---> Service <--- ###
##
#

#
##
### ---> Service <--- ###

#
### ### ### PLITC - JAIL ### ### ###
# EOF
$
$
vi /usr/jails/etherpad.domain.tld/etc/ssh/sshd_config
$
$
### ### ### PLITC ### ### ###
ListenAddress 2a01:aaaa:bbbb:cccc::dddd
### ### ### PLITC ### ### ###
$

Punkt 6: @HOST: PF Firewall Beispielregeln für IPv4 NAT und IPv6 passthrough

$
vi /etc/pf.conf
$
$
### Interfaces ###
# --------->
ext1_if = "re0"
# --------->

### unlimited traffic for vpn and loopback ###
# --------->
set skip on lo0
# --------->

# lo0 - fuer Internet Zugriff
nat pass on $ext1_if proto {tcp udp icmp} from 127.0.1.1 to any -> ($ext1_if)

# direkter IPv6 Zugriff
pass out on $ext1_if inet6 proto {tcp udp} from 2a01:aaaa:bbbb:cccc::dddd to any
pass in on $ext1_if inet6 proto {tcp udp} from any to 2a01:aaaa:bbbb:cccc::dddd
$

Möchte man direkt den etherpad Port 9001 per NAT routen, kann man folgende Regeln verwenden:

$
# vps1 - etherpad.domain.tld - direktes nat routing an lo0
rdr on $ext1_if proto tcp from any to ($ext1_if) port 9001 -> 127.0.1.1 port 9001
rdr on $ext1_if proto udp from any to ($ext1_if) port 9001 -> 127.0.1.1 port 9001
$

Punkt 7: @HOST: PF Regeln testen und aktivieren

$
pfctl -nf /etc/pf.conf
pfctl -f /etc/pf.conf
$

Punkt 8: @HOST: ZFS Snapshot erstellen

$
/sbin/zfs snapshot tank/root/ezjail/etherpad.domain.tld@GMT-`date -u +%Y.%m.%d-%H.%M.%S`_ETHERPAD
$

Punkt 9: @HOST: JAIL booten

$
/usr/local/bin/ezjail-admin onestart etherpad.domain.tld
$

— — — — — — — — —

Punkt 9.1: @@JAIL: (optional) Fish Shell

$
cd /usr/ports/shells/fish
make install clean

chsh -s /usr/local/bin/fish root
$

FreeBSD Beastie EtherPad Installation

Punkt 10: @@JAIL: node, npm und git installieren

$
cd /usr/ports/www/node/ && make install clean
cd /usr/ports/www/npm/ && make install clean
cd /usr/ports/devel/git/ && make install clean
$

Punkt 11: @@JAIL: Etherpad-Lite installieren

$
cd /

git clone https://github.com/ether/etherpad-lite.git

cp /etherpad-lite/settings.json.template /etherpad-lite/settings.json
$

Punkt 12: @@JAIL: Etherpad-Lite Config anpassen

$
vi /etherpad-lite/settings.json
$
$
  //IP and port which etherpad should bind at
  "ip": "127.0.1.1",
  "port" : 9001,
$

Punkt 13: @@JAIL: Etherpad-Lite starten

$
/etherpad-lite/bin/run.sh --root
$

— — — — — — — — —

Punkt 14: @HOST: Apache 2.4 installieren

$
cd /usr/ports/www/apache24/ && make install clean
$

Punkt 15: @HOST: Apache 2.4 als SSL Reverse Proxy für Etherpad

$
vi /usr/local/etc/apache24/httpd.conf
$
$
# wichtige Module
### ### ### PLITC ### ### ###
LoadModule proxy_module libexec/apache24/mod_proxy.so
LoadModule proxy_http_module libexec/apache24/mod_proxy_http.so
LoadModule proxy_connect_module libexec/apache24/mod_proxy_connect.so
LoadModule proxy_fcgi_module libexec/apache24/mod_proxy_fcgi.so
LoadModule proxy_scgi_module libexec/apache24/mod_proxy_scgi.so
#
LoadModule rewrite_module libexec/apache24/mod_rewrite.so
#
LoadModule deflate_module libexec/apache24/mod_deflate.so
#
LoadModule vhost_alias_module libexec/apache24/mod_vhost_alias.so
LoadModule negotiation_module libexec/apache24/mod_negotiation.so
#
LoadModule ssl_module libexec/apache24/mod_ssl.so
LoadModule socache_shmcb_module libexec/apache24/mod_socache_shmcb.so
#
LoadModule session_module libexec/apache24/mod_session.so
LoadModule session_cookie_module libexec/apache24/mod_session_cookie.so
LoadModule session_crypto_module libexec/apache24/mod_session_crypto.so
### ### ### PLITC ### ### ###

<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin

SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
 
SSLPassPhraseDialog     builtin
SSLSessionCache         "shmcb:/var/run/ssl_scache(512000)"
SSLSessionCacheTimeout  300
</IfModule>

# VHOST
<VirtualHost *:443>
        ServerName pad.domain.tld
        ServerAdmin service@domain.tld
        ServerSignature Off
        CustomLog /var/log/etherpad_access.log combined
        ErrorLog /var/log/etherpad_error.log

        # SSL
        SSLEngine on
        SSLCertificateFile /usr/local/etc/apache24/certs/pad.domain.tld.crt
        SSLCertificateKeyFile /usr/local/etc/apache24/certs/pad.domain.tld.key

### 06.01.2014
Header always set Strict-Transport-Security "max-age=31556926 includeSubDomains"

### 03.12.2013 - Apache against BEAST
SSLProtocol all -SSLv2
SSLHonorCipherOrder On
SSLCipherSuite EECDH+AES:EDH+AES:-SHA1:EECDH+RC4:EDH+RC4:RC4-SHA:EECDH+AES256:EDH+AES256:AES256-SHA:!3DES:!aNULL:!eNULL:!EXP:!LOW:!MD5
# SSLCompression Off

            RewriteEngine On
            RewriteRule /p/*$ https://pad.domain.tld/ [NC,L]
            RewriteCond %{REQUEST_URI} !^/locales/
            RewriteCond %{REQUEST_URI} !^/locales.json
            RewriteCond %{REQUEST_URI} !^/admin/
            RewriteCond %{REQUEST_URI} !^/p/
            RewriteCond %{REQUEST_URI} !^/static/
            RewriteCond %{REQUEST_URI} !^/pluginfw/
            RewriteCond %{REQUEST_URI} !^/javascripts/
            RewriteCond %{REQUEST_URI} !^/socket.io/
            RewriteCond %{REQUEST_URI} !^/ep/
            RewriteCond %{REQUEST_URI} !^/minified/
            RewriteCond %{REQUEST_URI} !^/api/
            RewriteCond %{REQUEST_URI} !^/ro/
            RewriteCond %{REQUEST_URI} !^/error/
            RewriteCond %{REQUEST_URI} !^/jserror
            RewriteCond %{REQUEST_URI} !^/tests/
            RewriteCond %{REQUEST_URI} !/favicon.ico
            RewriteCond %{REQUEST_URI} !/robots.txt
            RewriteRule ^/+(.+)$ https://pad.domain.tld/p/$1 [L]

            ProxyVia On
            ProxyRequests Off
            ProxyPass / http://127.0.1.1:9001/
            ProxyPassReverse / http://127.0.1.1:9001/
            ProxyPreserveHost on
            <Proxy *>
               Options FollowSymLinks MultiViews
               AllowOverride All
               Order allow,deny
               allow from all
            </Proxy>
</VirtualHost>
$

Punkt 16: @HOST: Apache Config testen und starten

$
vi /etc/rc.conf
$
$
apache24_enable="YES"
$
$
apachectl configtest

service apache24 start
$

— — — >
DNS Einträge:

etherpad.domain.tld = IPv6 Adresse der JAIL
pad.domain.tld = IPv4 Adresse des Apache Reverse Proxy (JAIL-HOST)
pad.domain.tld = IPv6 Adresse des Apache Reverse Proxy (JAIL-HOST)

Hinweis: Für einen robusten SSL Betrieb sollten noch weitere Einstellungen angepasst werden!

Natürlich könnte man jetzt noch die Etherpad Daten in eine (stunnel abgesicherte) MySQL Datenbank gießen

etherpad-lite starte ich persönlich immer in einer tmux session

Die stunnel / MySQL Anbindung kann man sich am Ende des Pads anschauen:

PAD Vorlage: FreeBSD Jail – EtherPad per Node.JS mit Apache Reverse Proxy

Ergänzung: @HOST: stunnel / MySQL bind address

Der MySQL-Server erlaubt nur 2 Methoden zur Bindung von Adressen an Interfaces (my.cnf auf dem JAIL-HOST):
bind-address = 0.0.0.0 (was ALLE Schnittstellen betrifft, wie re0, lo0 und lo1)
bind-address = 127.0.0.1 (was ausschließlich localhost entspricht)
Eine Bindung an explizit 2 Interfaces ist NICHT möglich!

Dementsprechend verhält sich dann auch der MySQL-Client so:
Bei einer Angabe von: mysql -h localhost -P 3307 wird trotzdem der Port 3306 verwendet.

Um diese Einschränkung zu umgehen, kann der lokal laufende MySQL-Server an die reguläre localhost/127.0.0.1 Adresse gebunden werden, die Bindung vom stunnel erfolgt an lo1 (127.1.1.1) Interface auf Port 3306, nun kann durch das lo1 Interface, in der Jail, ein Transport über stunnel erfolgen.

die /etc/hosts der JAIL sieht dabei wie folgt aus:

$
### ### ### PLITC ### ### ###
#
127.0.1.1                localhost           localhost.my.domain
127.1.1.1                localhostr          localhostr.my.domain
#
2a01:aaaa:bbbb:cccc::dddd   etherpad.domain.tld   etherpad
#
### ### ### PLITC ### ### ###
# EOF
$

Falls beim Systembooten (des JAIL-HOSTs) der stunnel nicht erfolgreich gestartet werden konnte, weil die Bindungs-Adresse erst nach dem starten der Jail ins Interface eingetragen wird:

$
2013-12-18T00:15:06.210097+01:00 server2 root: /etc/rc: WARNING: failed to start stunnel
$

der kann einfach den Start des stunnels, über die /etc/rc.local erneut anregen:

$
# erst JAIL
/usr/local/bin/ezjail-admin onestart etherpad.domain.tld
# dann stunnel
/usr/local/etc/rc.d/stunnel onestart
$

< --- --- --- Punkt 17: @@JAIL: (optional) Installation von Abiword für erweiterten IMPORT/EXPORT

$
cd /usr/ports/editors/abiword/ && make install clean
$
$
vi /etherpad-lite/settings.json
$
$
"abiword" : "/usr/local/bin/abiword",
$

Hinweis: baut komplett Abiword und dessen Abhängigkeiten mit X11 Support, falls “gtk-update-icon-cache-2.24.22: Needs cairo with X11 support enabled” kommt, führt make erneut aus, die weiteren Abhängigkeiten wie DBus etc. werden dann einfach nachgebaut

Punkt 18: @@JAIL: zukünftige Etherpad-Lite Updates erfolgen sehr einfach per GitHub

$
cd /etherpad-lite

# update: node package manager
npm update

# update: etherpad-lite
git pull
$

Schreibe einen Kommentar