diff --git a/ejabberd/Makefile b/ejabberd/Makefile new file mode 100644 index 0000000..de219eb --- /dev/null +++ b/ejabberd/Makefile @@ -0,0 +1,38 @@ +02firstboot = $(CHROOT)/etc/local.d/02firstboot.start +cert-renew.sh = $(CHROOT)/usr/local/bin/cert-renew.sh +nginx_conf = $(CHROOT)/etc/nginx/nginx.conf.orig +example_com_conf = $(CHROOT)/etc/nginx/conf.d/example.com.conf +ejabberd_example_com_conf = $(CHROOT)/etc/nginx/conf.d/ejabberd.example.com.conf + +$(02firstboot): appliance/02firstboot.start + mkdir -p $(CHROOT)/etc/local.d + cp $< $@ + touch $(CHROOT)/02firstboot + +$(cert-renew.sh): appliance/cert-renew.sh + cp $< $@ + +$(nginx_conf): nginx/nginx.conf + mv $(CHROOT)/etc/nginx/nginx.conf $@ + cp $< $(CHROOT)/etc/nginx/nginx.conf + +$(example_com_conf): nginx/conf.d/example.com.conf + mkdir -p $(CHROOT)/etc/nginx/conf.d + cp $< $@ + +$(ejabberd_example_com_conf): nginx/conf.d/ejabberd.example.com.conf + mkdir -p $(CHROOT)/etc/nginx/conf.d + cp $< $@ + +preinstall: + # workaround for https://bugs.gentoo.org/716968 + mkdir -p $(CHROOT)/etc/ssl/ejabberd + touch $(CHROOT)/etc/ssl/ejabberd/server.pem + +postinstall: $(nginx_conf) $(example_com_conf) $(ejabberd_example_com_conf) $(02firstboot) $(cert-renew.sh) + # workaround for https://bugs.gentoo.org/716968 + rm -rf $(CHROOT)/etc/ssl/ejabberd + # configure postgresql + sed -i 's#^PG_INITDB_OPTS=.*#PG_INITDB_OPTS="--encoding=UTF8 --locale=de_DE.UTF-8"#' $(CHROOT)/etc/conf.d/postgresql-* + rm -rf $(CHROOT)/var/lib/postgresql/* + RUN emerge --config dev-db/postgresql diff --git a/ejabberd/appliance/02firstboot.start b/ejabberd/appliance/02firstboot.start new file mode 100755 index 0000000..5878ba7 --- /dev/null +++ b/ejabberd/appliance/02firstboot.start @@ -0,0 +1,92 @@ +#!/bin/bash + +# variables +LABEL="DATA" +DATABASE_PASS="Di1sgPgSQLPw." +TLD="example.com" +HOST="ejabberd" +ORGNAME="Ejabberd example" + +# start +set -e + +PGVER=$(eselect postgresql show) + +[ -e /01firstboot ] && exit 0 +[ -e /02firstboot ] || exit 0 + +if [ ! -d "/$LABEL/var/lib/postgresql" ]; then + echo 'Start PostgeSQL DB, create ejabberd database...' + systemctl stop postgresql-$PGVER + mkdir -p "/$LABEL/var/lib" + rm -rf "/$LABEL/var/lib/postgresql.orig" + cp -a "/var/lib/postgresql" "/$LABEL/var/lib/postgresql.orig" + mv "/var/lib/postgresql" "/$LABEL/var/lib/postgresql" + ln -s "/$LABEL/var/lib/postgresql" "/var/lib/postgresql" + systemctl start postgresql-$PGVER + psql -U postgres -d postgres -c "CREATE ROLE ejabberd WITH LOGIN;" + psql -U postgres -d postgres -c "ALTER USER ejabberd WITH PASSWORD '$DATABASE_PASS';" + psql -U postgres -d postgres -c "CREATE DATABASE ejabberd WITH OWNER ejabberd;" + psql -U ejabberd -d ejabberd < /usr/share/ejabberd/sql/pg.new.sql +else + echo 'start PostgreSQL DB...' + rm -rf "/$LABEL/var/lib/postgresql.orig" + mv "/var/lib/postgresql" "/$LABEL/var/lib/postgresql.orig" + ln -s "/$LABEL/var/lib/postgresql" "/var/lib/postgresql" + systemctl start postgresql-$PGVER +fi + +if [ ! -f "/$LABEL/etc/jabber/ejabberd.yml" ]; then + echo 'edit ejabberd configuration' + mkdir -p "/$LABEL/etc/jabber" + chown jabber:jabber "/$LABEL/etc/jabber" + chmod 770 "/$LABEL/etc/jabber" + cp "/etc/jabber/ejabberd.yml" "/$LABEL/etc/jabber/ejabberd.yml.orig" + mv "/etc/jabber/ejabberd.yml" "/$LABEL/etc/jabber/ejabberd.yml" + ln -s "/$LABEL/etc/jabber/ejabberd.yml" "/etc/jabber/ejabberd.yml" + sed -i 's# - localhost# - localhost\n - example.com#' "/$LABEL/etc/jabber/ejabberd.yml" + sed -i 's/listen:/### ==============\n### DATABASE SETUP\n\nlisten:/' "/$LABEL/etc/jabber/ejabberd.yml" + sed -i 's/listen:/sql_type: pgsql\nlisten:/' "/$LABEL/etc/jabber/ejabberd.yml" + sed -i 's/listen:/sql_server: "localhost"\nlisten:/' "/$LABEL/etc/jabber/ejabberd.yml" + sed -i 's/listen:/sql_database: "ejabberd"\nlisten:/' "/$LABEL/etc/jabber/ejabberd.yml" + sed -i 's/listen:/sql_username: "ejabberd"\nlisten:/' "/$LABEL/etc/jabber/ejabberd.yml" + sed -i "s/listen:/sql_password: \"$DATABASE_PASS\"\\nlisten:/" "/$LABEL/etc/jabber/ejabberd.yml" + sed -i 's/listen:/default_db: sql\nlisten:/' "/$LABEL/etc/jabber/ejabberd.yml" + sed -i 's/listen:/new_sql_schema: true\n\nlisten:/' "/$LABEL/etc/jabber/ejabberd.yml" +else + mv "/$LABEL/etc/jabber/ejabberd.yml.orig" "/$LABEL/etc/jabber/ejabberd.yml.orig-alt" + mv "/etc/jabber/ejabberd.yml" "/$LABEL/etc/jabber/ejabberd.yml.orig" + ln -s "/$LABEL/etc/jabber/ejabberd.yml" "/etc/jabber/ejabberd.yml" +fi + +if [ ! -f "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD-cert.pem" ]; then + echo 'Create certificates...' + mkdir -p "/$LABEL/CERTS/KEYS/" + mkdir -p "/$LABEL/CERTS/$HOST.$TLD" + echo "FQDN = $HOST.$TLD" > "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD.cnf" + echo "ORGNAME = $ORGNAME" >> "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD.cnf" + echo "ALTNAMES = DNS:$HOST.$TLD , DNS:$TLD , DNS:conference.$TLD , DNS:guest.$TLD , DNS:proxy.$TLD , DNS:pubsub.$TLD , DNS:turn.$TLD , DNS:upload.$TLD" >> "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD.cnf" + echo -e "\n[ req ]\ndefault_bits = 4096\ndefault_md = sha256\nprompt = no\nencrypt_key = no\ndistinguished_name = dn\nreq_extensions = req_ext\ndefault_keyfile = ../KEYS/\$FQDN-key.pem\n" >> "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD.cnf" + echo -e "\n[ dn ]\nC = DE\nO = \$ORGNAME\nCN = \$FQDN\n" >> "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD.cnf" + echo -e "\n[ req_ext ]\nsubjectAltName = \$ALTNAMES" >> "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD.cnf" + openssl req -x509 -new -config "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD.cnf" -out "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD-cert.pem" -keyout "/$LABEL/CERTS/KEYS/$HOST.$TLD-key.pem" + cp "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD-cert.pem" "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD-fullchain.pem" + touch "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD-chain.pem" +fi + +rm -rf /etc/ssl/ejabberd +rm -rf /etc/ssl/nginx +mkdir -p /etc/ssl +ln -sf "/$LABEL/etc/ssl/ejabberd" "/etc/ssl/ejabberd" +ln -sf "/$LABEL/etc/ssl/nginx" "/etc/ssl/nginx" + +systemctl enable postgresql-$PGVER +systemctl enable ejabberd +systemctl enable nginx + +/usr/local/bin/cert-renew.sh + +systemctl start ejabberd +systemctl start nginx + +rm /02firstboot diff --git a/ejabberd/appliance/cert-renew.sh b/ejabberd/appliance/cert-renew.sh new file mode 100755 index 0000000..4553df9 --- /dev/null +++ b/ejabberd/appliance/cert-renew.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +HOST="ejabberd" +TLD="example.com" +FQDN="$HOST.$TLD" +LABEL="DATA" + +CERT_DIR=/$LABEL/CERTS +CERT_EJABBERD=/$LABEL/etc/ssl/ejabberd +CERT_NGINX=/$LABEL/etc/ssl/nginx +GETREPO="" +GETUSER="" +GETPASS="" + +function getCurrentVersion() { +# Get hash from latest revision + git log --format=format:%H -1 +} + +cd $CERT_DIR + +if [ -z "$GETREPO" ]; then + GIT_REVISION=0 + GIT_NEW_REVISION=1 + cd $FQDN +elif [ ! -d "$FQDN" ]; then + GIT_REVISION=0 + git clone "https://$GETUSER:$GETPASS@$GETREPO" + cd $FQDN + GIT_NEW_REVISION=$(getCurrentVersion) +else + cd $FQDN + GIT_REVISION=$(getCurrentVersion) + git commit -m "CRON: auto commit" + git fetch + git merge origin/master -m "Auto Merge" + GIT_NEW_REVISION=$(getCurrentVersion) +fi + +echo "old: $GIT_REVISION" +echo "new: $GIT_NEW_REVISION" + +if [ $GIT_REVISION != $GIT_NEW_REVISION ] +then + echo "Update Ejabberd certificate..." + mkdir -p $CERT_EJABBERD + cp $CERT_DIR/$FQDN/$FQDN-fullchain.pem $CERT_EJABBERD/server.pem + cp $CERT_DIR/KEYS/$FQDN-key.pem $CERT_EJABBERD/server.key + chown root:jabber $CERT_EJABBERD/server.* + chmod 444 $CERT_EJABBERD/server.pem + chmod 440 $CERT_EJABBERD/server.key + echo "Restart Ejabberd..." + systemctl restart ejabberd + + echo "Update Nginx certificate..." + mkdir -p $CERT_NGINX + cp $CERT_DIR/$FQDN/$FQDN-fullchain.pem $CERT_NGINX/nginx.pem + cp $CERT_DIR/KEYS/$FQDN-key.pem $CERT_NGINX/nginx.key + chown nginx:nginx $CERT_NGINX/nginx.* + chmod 444 $CERT_NGINX/nginx.pem + chmod 400 $CERT_NGINX/nginx.key + echo "Restart Nginx..." + systemctl restart nginx +fi diff --git a/ejabberd/ejabberd.cfg b/ejabberd/ejabberd.cfg new file mode 100644 index 0000000..d64c79f --- /dev/null +++ b/ejabberd/ejabberd.cfg @@ -0,0 +1,2 @@ +REPO_NAMES += unitas-xmpp +REPO_URI_unitas-xmpp = https://git.unitas-network.de/Gentoo/unitas-xmpp.git diff --git a/ejabberd/make.conf b/ejabberd/make.conf new file mode 100644 index 0000000..8c4468e --- /dev/null +++ b/ejabberd/make.conf @@ -0,0 +1 @@ +PHP_TARGETS="php7-4" diff --git a/ejabberd/nginx/conf.d/ejabberd.example.com.conf b/ejabberd/nginx/conf.d/ejabberd.example.com.conf new file mode 100644 index 0000000..f5c04e6 --- /dev/null +++ b/ejabberd/nginx/conf.d/ejabberd.example.com.conf @@ -0,0 +1,107 @@ +server { + listen 80 default_server; + listen [::]:80 default_server; + server_name ejabberd.example.com + conference.example.com + guest.example.com + proxy.example.com + pubsub.example.com + turn.example.com + upload.example.com; + + access_log /var/log/nginx/ejabberd.example.com.access_log main; + error_log /var/log/nginx/ejabberd.example.com.error_log info; + + root /var/www/ejabberd.example.com/htdocs; +} + +server { + listen 127.0.0.1:8443 ssl http2 default_server; + listen [::1]:8443 ssl http2 default_server; + server_name ejabberd.example.com + conference.example.com + guest.example.com + proxy.example.com + pubsub.example.com + turn.example.com + upload.example.com; + + ssl_certificate /etc/ssl/nginx/nginx.pem; + ssl_certificate_key /etc/ssl/nginx/nginx.key; + + access_log /var/log/nginx/ejabberd.example.com.ssl_access_log main; + error_log /var/log/nginx/ejabberd.example.com.ssl_error_log info; + + root /var/www/ejabberd.example.com/htdocs; + + index index.html index.php; + + location ~* ^/admin/ { + proxy_pass http://127.0.0.1:5280; + proxy_set_header Host example.com; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_redirect off; + proxy_buffering off; + } + + location ~* ^/bosh/ { + proxy_pass http://127.0.0.1:5280; + proxy_set_header Host example.com; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_redirect off; + proxy_buffering off; + } + + location ~* ^/captcha/ { + proxy_pass http://127.0.0.1:5280; + proxy_set_header Host example.com; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_redirect off; + proxy_buffering off; + } + + location ~* ^/register/ { + proxy_pass http://127.0.0.1:5280; + proxy_set_header Host example.com; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_redirect off; + proxy_buffering off; + } + + location ~* ^/upload/ { + proxy_pass http://127.0.0.1:5280; + proxy_set_header Host upload.example.com; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_redirect off; + proxy_buffering off; + client_max_body_size 200M; + } + + location ~* ^/ws/ { + proxy_pass http://127.0.0.1:5280; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_redirect off; + proxy_buffering off; + proxy_read_timeout 86400; + } + # CORS + location ~ .(ttf|ttc|otf|eot|woff|woff2|font.css|css|js)$ { + add_header Access-Control-Allow-Origin "*"; # Decide here whether you want to allow all or only a particular domain + } +} diff --git a/ejabberd/nginx/conf.d/example.com.conf b/ejabberd/nginx/conf.d/example.com.conf new file mode 100644 index 0000000..81a52e1 --- /dev/null +++ b/ejabberd/nginx/conf.d/example.com.conf @@ -0,0 +1,59 @@ +server { + listen 80; + listen [::]:80; + server_name example.com; + + access_log /var/log/nginx/example.com.access_log main; + error_log /var/log/nginx/example.com.error_log info; + + root /var/www/example.com/htdocs; + + location /.well-known/host-meta { + default_type text/xml; + add_header Access-Control-Allow-Origin *; + } + + location /.well-known/host-meta.json { + default_type application/json; + add_header Access-Control-Allow-Origin *; + } + + location ^~ /.well-known/acme-challenge/ { + allow all; + default_type text/plain; + return 200 "$1.abcd-efgh"; + } + + location / { + return 301 https://www.example.com$request_uri; + } +} + +server { + listen 127.0.0.1:8443 ssl http2; + listen [::1]:8443 ssl http2; + server_name example.com; + + ssl_certificate /etc/ssl/nginx/nginx.pem; + ssl_certificate_key /etc/ssl/nginx/nginx.key; + + access_log /var/log/nginx/example.com.ssl_access_log main; + error_log /var/log/nginx/example.com.ssl_error_log info; + + root /var/www/example.com/htdocs; + + location /.well-known/host-meta { + default_type text/xml; + add_header Access-Control-Allow-Origin *; + } + + location /.well-known/host-meta.json { + default_type application/json; + add_header Access-Control-Allow-Origin *; + } + + location / { + return 301 https://www.example.com$request_uri; + } + +} diff --git a/ejabberd/nginx/nginx.conf b/ejabberd/nginx/nginx.conf new file mode 100644 index 0000000..04dc4c5 --- /dev/null +++ b/ejabberd/nginx/nginx.conf @@ -0,0 +1,85 @@ +user nginx nginx; +worker_processes 1; + +error_log /var/log/nginx/error_log info; + +events { + worker_connections 1024; + use epoll; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main + '$remote_addr - $remote_user [$time_local] ' + '"$request" $status $bytes_sent ' + '"$http_referer" "$http_user_agent" ' + '"$gzip_ratio"'; + + client_header_timeout 10m; + client_body_timeout 10m; + send_timeout 10m; + + connection_pool_size 256; + client_header_buffer_size 1k; + large_client_header_buffers 4 2k; + request_pool_size 4k; + + gzip off; + + output_buffers 1 32k; + postpone_output 1460; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + + keepalive_timeout 75 20; + + ignore_invalid_headers on; + + index index.html; + + include /etc/nginx/conf.d/*.conf; +} + +# "Auseinanderbasteln" von HTTPS und XMPP auf Port 443 +# Der Stream-Server hört an allen Interfaces/IPs auf Port 443 +# und leitet per Proxy an $upstream weiter +# Upstream wird beim ALPN "xmpp-client" auf xmppserver gemappt, +# bei den verschiedenen HTTP-ALPNs auf httpserver, +# bei allen anderen ALPNs auf httpserver. +# httpserver sind die oben definierten server, +# die deswegen nur auf localhost mit Port 8443 hören. +# xmppserver ist der TLS-Port für Clients von ejabberd +stream { + upstream httpserver { + server localhost:8443; # webserver_host:webserver_port + } + + upstream xmppserver { + server localhost:5223; # xmpp_server_host:xmpp_over_tls_port + } + + upstream turnserver { + server localhost:5349; # turnserver_host:turn_over_tls_port + } + + map $ssl_preread_alpn_protocols $upstream { + ~\bh2\b httpserver; + ~\bhttp/1.1\b httpserver; + ~\bh2,http/1.1\b httpserver; + ~\bxmpp-client\b xmppserver; + default turnserver; + } + + server { + listen 443; + listen [::]:443; + + ssl_preread on; + proxy_pass $upstream; + } +} diff --git a/ejabberd/package.accept_keywords b/ejabberd/package.accept_keywords new file mode 100644 index 0000000..0093bcb --- /dev/null +++ b/ejabberd/package.accept_keywords @@ -0,0 +1,28 @@ +# ejabberd +net-im/ejabberd +dev-erlang/p1_oauth2 +dev-erlang/ezlib +dev-erlang/eimp +dev-erlang/iconv +dev-erlang/idna +dev-erlang/jiffy +dev-erlang/jose +dev-erlang/xmpp +dev-erlang/epam +dev-erlang/base64url +dev-erlang/cache_tab +dev-erlang/fast_yaml +dev-erlang/lager +dev-erlang/p1_acme +dev-erlang/p1_utils +dev-erlang/pkix +dev-erlang/mqtree +dev-erlang/fast_xml +dev-erlang/stringprep +dev-erlang/fast_tls +dev-erlang/p1_pgsql +dev-erlang/luerl +dev-erlang/esip +dev-erlang/stun +dev-erlang/yconf +dev-erlang/unicode_util_compat diff --git a/ejabberd/package.use b/ejabberd/package.use new file mode 100644 index 0000000..6b5cec6 --- /dev/null +++ b/ejabberd/package.use @@ -0,0 +1,11 @@ +# Nginx +app-eselect/eselect-php fpm +dev-lang/php cli curl fpm gd pdo postgres webp +media-gfx/imagemagick jpeg -openmp webp +www-servers/nginx nginx_modules_stream_map nginx_modules_stream_ssl_preread + +# XMPP +net-im/ejabberd captcha postgres redis sip stun +dev-lang/erlang kpoll smp +media-gfx/imagemagick png truetype +media-libs/gd png jpeg truetype webp diff --git a/ejabberd/world b/ejabberd/world new file mode 100644 index 0000000..2960277 --- /dev/null +++ b/ejabberd/world @@ -0,0 +1,8 @@ +app-crypt/certbot-nginx +dev-db/postgresql +dev-lang/php +dev-php/pecl-imagick +media-gfx/gd-captcha +media-gfx/imagemagick +net-im/ejabberd +www-servers/nginx