From b31a934a804aed3f35442ceafe2080b0955e7317 Mon Sep 17 00:00:00 2001 From: dcc Date: Wed, 15 May 2024 00:57:23 -0700 Subject: total rebase --- installation/apache-cache-purge.sh.example | 36 ++ installation/caddyfile-pleroma.example | 17 + installation/freebsd/rc.d/pleroma | 27 + installation/init.d/pleroma | 46 ++ installation/netbsd/rc.d/pleroma | 57 ++ installation/nginx-cache-purge.sh.example | 40 ++ installation/openbsd/httpd.conf | 36 ++ installation/openbsd/rc.d/pleromad | 34 ++ installation/openbsd/relayd.conf | 44 ++ installation/pleroma-apache.conf | 84 +++ installation/pleroma-mediaproxy.nginx | 97 +++ installation/pleroma-mongooseim.cfg | 936 +++++++++++++++++++++++++++++ installation/pleroma.nginx | 109 ++++ installation/pleroma.service | 36 ++ installation/pleroma.supervisord | 21 + installation/pleroma.vcl | 127 ++++ 16 files changed, 1747 insertions(+) create mode 100755 installation/apache-cache-purge.sh.example create mode 100644 installation/caddyfile-pleroma.example create mode 100755 installation/freebsd/rc.d/pleroma create mode 100755 installation/init.d/pleroma create mode 100755 installation/netbsd/rc.d/pleroma create mode 100755 installation/nginx-cache-purge.sh.example create mode 100644 installation/openbsd/httpd.conf create mode 100755 installation/openbsd/rc.d/pleromad create mode 100644 installation/openbsd/relayd.conf create mode 100644 installation/pleroma-apache.conf create mode 100644 installation/pleroma-mediaproxy.nginx create mode 100755 installation/pleroma-mongooseim.cfg create mode 100644 installation/pleroma.nginx create mode 100644 installation/pleroma.service create mode 100644 installation/pleroma.supervisord create mode 100644 installation/pleroma.vcl (limited to 'installation') diff --git a/installation/apache-cache-purge.sh.example b/installation/apache-cache-purge.sh.example new file mode 100755 index 0000000..7b42628 --- /dev/null +++ b/installation/apache-cache-purge.sh.example @@ -0,0 +1,36 @@ +#!/bin/sh + +# A simple shell script to delete a media from Apache's mod_disk_cache. +# You will likely need to setup a sudo rule like the following: +# +# Cmnd_Alias HTCACHECLEAN = /usr/local/sbin/htcacheclean +# pleroma ALL=HTCACHECLEAN, NOPASSWD: HTCACHECLEAN +# +# Please also ensure you have enabled: +# +# config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Script, url_format: :htcacheclean +# +# which will correctly format the URLs passed to this script for the htcacheclean utility. +# + +SCRIPTNAME=${0##*/} + +# mod_disk_cache directory +CACHE_DIRECTORY="/tmp/pleroma-media-cache" + +## Removes an item via the htcacheclean utility +## $1 - the filename, can be a pattern . +## $2 - the cache directory. +purge_item() { + sudo htcacheclean -v -p "${2}" "${1}" +} # purge_item + +purge() { + for url in $@ + do + echo "$SCRIPTNAME delete \`$url\` from cache ($CACHE_DIRECTORY)" + purge_item "$url" $CACHE_DIRECTORY + done +} + +purge $@ diff --git a/installation/caddyfile-pleroma.example b/installation/caddyfile-pleroma.example new file mode 100644 index 0000000..cc7dda0 --- /dev/null +++ b/installation/caddyfile-pleroma.example @@ -0,0 +1,17 @@ +# default Caddyfile config for Pleroma +# +# Simple installation instructions: +# 1. Replace 'example.tld' with your instance's domain wherever it appears. +# 2. Copy this section into your Caddyfile and restart Caddy. + +example.tld { + log { + output file /var/log/caddy/pleroma.log + } + + encode gzip + + # this is explicitly IPv4 since Pleroma.Web.Endpoint binds on IPv4 only + # and `localhost.` resolves to [::0] on some systems: see issue #930 + reverse_proxy 127.0.0.1:4000 +} diff --git a/installation/freebsd/rc.d/pleroma b/installation/freebsd/rc.d/pleroma new file mode 100755 index 0000000..f62aef1 --- /dev/null +++ b/installation/freebsd/rc.d/pleroma @@ -0,0 +1,27 @@ +#!/bin/sh +# $FreeBSD$ +# PROVIDE: pleroma +# REQUIRE: DAEMON postgresql +# KEYWORD: shutdown + +# sudo -u pleroma MIX_ENV=prod elixir --erl \"-detached\" -S mix phx.server + +. /etc/rc.subr + +name=pleroma +rcvar=pleroma_enable + +desc="Pleroma Social Media Platform" + +load_rc_config ${name} + +: ${pleroma_user:=pleroma} +: ${pleroma_home:=$(getent passwd ${pleroma_user} | awk -F: '{print $6}')} +: ${pleroma_chdir:="${pleroma_home}/pleroma"} +: ${pleroma_env:="HOME=${pleroma_home} MIX_ENV=prod"} + +command=/usr/local/bin/elixir +command_args="--erl \"-detached\" -S /usr/local/bin/mix phx.server" +procname="*beam.smp" + +run_rc_command "$1" diff --git a/installation/init.d/pleroma b/installation/init.d/pleroma new file mode 100755 index 0000000..cb6635a --- /dev/null +++ b/installation/init.d/pleroma @@ -0,0 +1,46 @@ +#!/sbin/openrc-run +supervisor=supervise-daemon +command_user=pleroma:pleroma +command_background=1 +# Ask process to terminate within 30 seconds, otherwise kill it +retry="SIGTERM/30/SIGKILL/5" +pidfile="/var/run/pleroma.pid" +directory=/opt/pleroma +healthcheck_delay=60 +healthcheck_timer=30 +no_new_privs="yes" + +: ${pleroma_port:-4000} + +# Needs OpenRC >= 0.42 +#respawn_max=0 +#respawn_delay=5 + +# put pleroma_console=YES in /etc/conf.d/pleroma if you want to be able to +# connect to pleroma via an elixir console +if yesno "${pleroma_console}"; then + command=elixir + command_args="--name pleroma@127.0.0.1 --erl '-kernel inet_dist_listen_min 9001 inet_dist_listen_max 9001 inet_dist_use_interface {127,0,0,1}' -S mix phx.server" + + start_post() { + einfo "You can get a console by using this command as pleroma's user:" + einfo "iex --name console@127.0.0.1 --remsh pleroma@127.0.0.1" + } +else + command=/usr/bin/mix + command_args="phx.server" +fi + +export MIX_ENV=prod + +depend() { + need nginx postgresql +} + +healthcheck() { + # put pleroma_health=YES in /etc/conf.d/pleroma if you want healthchecking + # and make sure you have curl installed + yesno "$pleroma_health" || return 0 + + curl -q "localhost:${pleroma_port}/api/pleroma/healthcheck" +} diff --git a/installation/netbsd/rc.d/pleroma b/installation/netbsd/rc.d/pleroma new file mode 100755 index 0000000..1114668 --- /dev/null +++ b/installation/netbsd/rc.d/pleroma @@ -0,0 +1,57 @@ +#!/bin/sh +# PROVIDE: pleroma +# REQUIRE: DAEMON pgsql + +if [ -f /etc/rc.subr ]; then + . /etc/rc.subr +fi + +name="pleroma" +rcvar=${name} +command="/usr/pkg/bin/elixir" +command_args="--detached -S /usr/pkg/bin/mix phx.server" +start_precmd="ulimit -n unlimited" +pidfile="/dev/null" + +pleroma_chdir="${pleroma_home}/pleroma" +pleroma_env="HOME=${pleroma_home} MIX_ENV=prod" + +check_pidfile() +{ + pid=$(pgrep -U "${pleroma_user}" /bin/beam.smp$) + echo -n "${pid}" +} + +if [ -f /etc/rc.subr -a -d /etc/rc.d -a -f /etc/rc.d/DAEMON ]; then + # newer NetBSD + load_rc_config ${name} + run_rc_command "$1" +else + # ancient NetBSD, Solaris and illumos, Linux, etc... + cmd=${1:-start} + + case ${cmd} in + start) + echo "Starting ${name}." + ${start_cmd} + ;; + + stop) + echo "Stopping ${name}." + check_pidfile + ! [ -n ${pid} ] && kill ${pid} + ;; + + restart) + ( $0 stop ) + sleep 5 + $0 start + ;; + + *) + echo 1>&2 "Usage: $0 [start|stop|restart]" + exit 1 + ;; + esac + exit 0 +fi diff --git a/installation/nginx-cache-purge.sh.example b/installation/nginx-cache-purge.sh.example new file mode 100755 index 0000000..5f6cbb1 --- /dev/null +++ b/installation/nginx-cache-purge.sh.example @@ -0,0 +1,40 @@ +#!/bin/sh + +# A simple shell script to delete a media from the Nginx cache. + +SCRIPTNAME=${0##*/} + +# NGINX cache directory +CACHE_DIRECTORY="/tmp/pleroma-media-cache" + +## Return the files where the items are cached. +## $1 - the filename, can be a pattern . +## $2 - the cache directory. +## $3 - (optional) the number of parallel processes to run for grep. +get_cache_files() { + local max_parallel=${3-16} + find $2 -maxdepth 2 -type d | xargs -P $max_parallel -n 1 grep -E -Rl "^KEY:.*$1" | sort -u +} + +## Removes an item from the given cache zone. +## $1 - the filename, can be a pattern . +## $2 - the cache directory. +purge_item() { + for f in $(get_cache_files $1 $2); do + echo "found file: $f" + [ -f $f ] || continue + echo "Deleting $f from $2." + rm $f + done +} # purge_item + +purge() { + for url in "$@" + do + echo "$SCRIPTNAME delete \`$url\` from cache ($CACHE_DIRECTORY)" + purge_item $url $CACHE_DIRECTORY + done + +} + +purge $@ diff --git a/installation/openbsd/httpd.conf b/installation/openbsd/httpd.conf new file mode 100644 index 0000000..82f4803 --- /dev/null +++ b/installation/openbsd/httpd.conf @@ -0,0 +1,36 @@ +# +# Default httpd.conf file for Pleroma on OpenBSD +# Simple installation instructions +# 1. Place file in /etc +# 2. Replace with your public IP address +# 3. If using IPv6, uncomment IPv6 lines and replace with your public IPv6 address +# 4. Check file using 'doas httpd -n' +# 5. Enable and start httpd: +# # doas rcctl enable httpd +# # doas rcctl start httpd +# + +ext_inet="" +#ext_inet6="" + +server "default" { + listen on $ext_inet port 80 # Comment to disable listening on IPv4 +# listen on $ext_inet6 port 80 # Comment to disable listening on IPv6 + listen on 127.0.0.1 port 80 # Do NOT comment this line + + log syslog + directory no index + + location "/.well-known/acme-challenge/*" { + root "/acme" + request strip 2 + } + + location "/robots.txt" { root "/htdocs/local/" } + location "/*" { block return 302 "https://$HTTP_HOST$REQUEST_URI" } +} + +types { + include "/usr/share/misc/mime.types" +} + diff --git a/installation/openbsd/rc.d/pleromad b/installation/openbsd/rc.d/pleromad new file mode 100755 index 0000000..19ac4bb --- /dev/null +++ b/installation/openbsd/rc.d/pleromad @@ -0,0 +1,34 @@ +#!/bin/ksh +# +# Default init file for Pleroma on OpenBSD +# +# Simple installation instructions: +# 1. Install Pleroma per wiki instructions +# 2. Place this pleromad file in /etc/rc.d +# 3. Enable and start Pleroma +# # doas rcctl enable pleromad +# # doas rcctl start pleromad +# + +daemon="/usr/local/bin/elixir" +daemon_flags="--detached -S /usr/local/bin/mix phx.server" +daemon_user="_pleroma" + +. /etc/rc.d/rc.subr + +rc_reload=NO +pexp="phx.server" + +rc_check() { + pgrep -q -U _pleroma -f "phx.server" +} + +rc_start() { + ${rcexec} "cd pleroma; ${daemon} ${daemon_flags}" +} + +rc_stop() { + pkill -q -U _pleroma -f "phx.server" +} + +rc_cmd $1 diff --git a/installation/openbsd/relayd.conf b/installation/openbsd/relayd.conf new file mode 100644 index 0000000..31c2c11 --- /dev/null +++ b/installation/openbsd/relayd.conf @@ -0,0 +1,44 @@ +# +# Default relayd.conf file for Pleroma on OpenBSD +# Simple installation instructions: +# 1. Place in /etc +# 2. Replace with your public IPv4 address +# 3. If using IPv6i, uncomment IPv6 lines and replace with your public IPv6 address +# 4. Check file using 'doas relayd -n' +# 5. Reload/start relayd +# # doas rcctl enable relayd +# # doas rcctl start relayd +# + +ext_inet="" +#ext_inet6="" + +table { 127.0.0.1 } +table { 127.0.0.1 } + +http protocol plerup { # Protocol for upstream pleroma server + #tcp { nodelay, sack, socket buffer 65536, backlog 128 } # Uncomment and adjust as you see fit + tls ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA0-POLY1305" + tls ecdhe secp384r1 + + # Forward some paths to the local server (as pleroma won't respond to them as you might want) + pass request quick path "/robots.txt" forward to + + # Append a bunch of headers + match request header append "X-Forwarded-For" value "$REMOTE_ADDR" # This two header and the next one are not strictl required by pleroma but adding them won't hurt + match request header append "X-Forwarded-By" value "$SERVER_ADDR:$SERVER_PORT" + + match request header append "Connection" value "upgrade" + +} + +relay wwwtls { + listen on $ext_inet port https tls # Comment to disable listening on IPv4 +# listen on $ext_inet6 port https tls # Comment to disable listening on IPv6 + + protocol plerup + + forward to port 4000 check http "/" code 200 + forward to port 80 check http "/robots.txt" code 200 +} + diff --git a/installation/pleroma-apache.conf b/installation/pleroma-apache.conf new file mode 100644 index 0000000..139abe9 --- /dev/null +++ b/installation/pleroma-apache.conf @@ -0,0 +1,84 @@ +# Sample Apache config for Pleroma +# +# Simple installation instructions: +# 1. Install your TLS certificate. We recommend using Let's Encrypt via Certbot +# 2. Replace 'example.tld' with your instance's domain. +# 3. This assumes a Debian-style Apache config. Copy this file to +# /etc/apache2/sites-available/ and then activate the site by running +# 'a2ensite pleroma-apache.conf', then restart Apache. +# +# Optional: enable disk-based caching for the media proxy +# For details, see https://git.pleroma.social/pleroma/pleroma/wikis/How%20to%20activate%20mediaproxy +# +# 1. Create a directory as shown below for the CacheRoot and make sure +# the Apache user can write to it. +# 2. Configure Apache's htcacheclean to clean the directory periodically. +# Your OS may provide a service you can enable to do this automatically. + +Define servername example.tld + + + LoadModule proxy_module libexec/apache24/mod_proxy.so + + + LoadModule proxy_http_module libexec/apache24/mod_proxy_http.so + + + LoadModule proxy_wstunnel_module libexec/apache24/mod_proxy_wstunnel.so + + + LoadModule rewrite_module libexec/apache24/mod_rewrite.so + + + LoadModule ssl_module libexec/apache24/mod_ssl.so + + + LoadModule cache_module libexec/apache24/mod_cache.so + + + LoadModule cache_disk_module libexec/apache24/mod_cache_disk.so + + +ServerName ${servername} +ServerTokens Prod + +# If you want Pleroma-specific logs +#ErrorLog /var/log/httpd-pleroma-error.log +#CustomLog /var/log/httpd-pleroma-access.log combined + + + RewriteEngine on + RewriteCond %{SERVER_NAME} =${servername} + RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] + + + + SSLEngine on + SSLCertificateFile /etc/letsencrypt/live/${servername}/fullchain.pem + SSLCertificateKeyFile /etc/letsencrypt/live/${servername}/privkey.pem + # Make sure you have the certbot-apache module installed + Include /etc/letsencrypt/options-ssl-apache.conf + + # Uncomment the following to enable MediaProxy caching on disk + #CacheRoot /tmp/pleroma-media-cache/ + #CacheDirLevels 1 + #CacheDirLength 2 + #CacheEnable disk /proxy + #CacheLock on + #CacheHeader on + #CacheDetailHeader on + ## 16MB max filesize for caching, configure as desired + #CacheMaxFileSize 16000000 + #CacheDefaultExpire 86400 + + RewriteEngine On + RewriteCond %{HTTP:Connection} Upgrade [NC] + RewriteCond %{HTTP:Upgrade} websocket [NC] + RewriteRule /(.*) ws://127.0.0.1:4000/$1 [P,L] + + #ProxyRequests must be off or you open your server to abuse as an open proxy + ProxyRequests off + ProxyPass / http://127.0.0.1:4000/ + ProxyPassReverse / http://127.0.0.1:4000/ + ProxyPreserveHost On + diff --git a/installation/pleroma-mediaproxy.nginx b/installation/pleroma-mediaproxy.nginx new file mode 100644 index 0000000..6f2edf2 --- /dev/null +++ b/installation/pleroma-mediaproxy.nginx @@ -0,0 +1,97 @@ +# This file is for those who want to serve uploaded media and media proxy over +# another domain. This is STRONGLY RECOMMENDED. +# This is meant to be used ALONG WITH `pleroma.nginx`. + +# If this is a new instance, replace the `location ~ ^/(media|proxy)` section in +# `pleroma.nginx` with the following to completely disable access to media from the main domain: +# location ~ ^/(media|proxy) { +# return 404; +# } +# +# If you are configuring an existing instance to use another domain +# for media, you will want to keep redirecting all existing local media to the new domain +# so already-uploaded media will not break. +# Replace the `location ~ ^/(media|proxy)` section in `pleroma.nginx` with the following: +# +# location /media { +# return 301 https://some.other.domain$request_uri; +# } +# +# location /proxy { +# return 404; +# } + +server { + server_name some.other.domain; + + listen 80; + listen [::]:80; + + # Uncomment this if you need to use the 'webroot' method with certbot. Make sure + # that the directory exists and that it is accessible by the webserver. If you followed + # the guide, you already ran 'mkdir -p /var/lib/letsencrypt' to create the folder. + # You may need to load this file with the ssl server block commented out, run certbot + # to get the certificate, and then uncomment it. + # + # location ~ /\.well-known/acme-challenge { + # root /var/lib/letsencrypt/; + # } + location / { + return 301 https://$server_name$request_uri; + } +} + +server { + server_name some.other.domain; + + listen 443 ssl http2; + listen [::]:443 ssl http2; + ssl_session_timeout 1d; + ssl_session_cache shared:MozSSL:10m; # about 40000 sessions + ssl_session_tickets off; + + ssl_trusted_certificate /etc/letsencrypt/live/some.other.domain/chain.pem; + ssl_certificate /etc/letsencrypt/live/some.other.domain/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/some.other.domain/privkey.pem; + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + ssl_prefer_server_ciphers off; + # In case of an old server with an OpenSSL version of 1.0.2 or below, + # leave only prime256v1 or comment out the following line. + ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1; + ssl_stapling on; + ssl_stapling_verify on; + + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_buffers 16 8k; + gzip_http_version 1.1; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/activity+json application/atom+xml; + + # the nginx default is 1m, not enough for large media uploads + client_max_body_size 16m; + ignore_invalid_headers off; + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + location / { return 404; } + + location ~ ^/(media|proxy) { + proxy_cache pleroma_media_cache; + slice 1m; + proxy_cache_key $host$uri$is_args$args$slice_range; + proxy_set_header Range $slice_range; + proxy_cache_valid 200 206 301 304 1h; + proxy_cache_lock on; + proxy_ignore_client_abort on; + proxy_buffering on; + chunked_transfer_encoding on; + proxy_pass http://phoenix; + } +} diff --git a/installation/pleroma-mongooseim.cfg b/installation/pleroma-mongooseim.cfg new file mode 100755 index 0000000..6b568fd --- /dev/null +++ b/installation/pleroma-mongooseim.cfg @@ -0,0 +1,936 @@ +%%% +%%% ejabberd configuration file +%%% +%%%' + +%%% The parameters used in this configuration file are explained in more detail +%%% in the ejabberd Installation and Operation Guide. +%%% Please consult the Guide in case of doubts, it is included with +%%% your copy of ejabberd, and is also available online at +%%% http://www.process-one.net/en/ejabberd/docs/ + +%%% This configuration file contains Erlang terms. +%%% In case you want to understand the syntax, here are the concepts: +%%% +%%% - The character to comment a line is % +%%% +%%% - Each term ends in a dot, for example: +%%% override_global. +%%% +%%% - A tuple has a fixed definition, its elements are +%%% enclosed in {}, and separated with commas: +%%% {loglevel, 4}. +%%% +%%% - A list can have as many elements as you want, +%%% and is enclosed in [], for example: +%%% [http_poll, web_admin, tls] +%%% +%%% Pay attention that list elements are delimited with commas, +%%% but no comma is allowed after the last list element. This will +%%% give a syntax error unlike in more lenient languages (e.g. Python). +%%% +%%% - A keyword of ejabberd is a word in lowercase. +%%% Strings are enclosed in "" and can contain spaces, dots, ... +%%% {language, "en"}. +%%% {ldap_rootdn, "dc=example,dc=com"}. +%%% +%%% - This term includes a tuple, a keyword, a list, and two strings: +%%% {hosts, ["jabber.example.net", "im.example.com"]}. +%%% +%%% - This config is preprocessed during release generation by a tool which +%%% interprets double curly braces as substitution markers, so avoid this +%%% syntax in this file (though it's valid Erlang). +%%% +%%% So this is OK (though arguably looks quite ugly): +%%% { {s2s_addr, "example-host.net"}, {127,0,0,1} }. +%%% +%%% And I can't give an example of what's not OK exactly because +%%% of this rule. +%%% + + +%%%. ======================= +%%%' OVERRIDE STORED OPTIONS + +%% +%% Override the old values stored in the database. +%% + +%% +%% Override global options (shared by all ejabberd nodes in a cluster). +%% +%%override_global. + +%% +%% Override local options (specific for this particular ejabberd node). +%% +%%override_local. + +%% +%% Remove the Access Control Lists before new ones are added. +%% +%%override_acls. + + +%%%. ========= +%%%' DEBUGGING + +%% +%% loglevel: Verbosity of log files generated by ejabberd. +%% 0: No ejabberd log at all (not recommended) +%% 1: Critical +%% 2: Error +%% 3: Warning +%% 4: Info +%% 5: Debug +%% +{loglevel, 3}. + +%%%. ================ +%%%' SERVED HOSTNAMES + +%% +%% hosts: Domains served by ejabberd. +%% You can define one or several, for example: +%% {hosts, ["example.net", "example.com", "example.org"]}. +%% +{hosts, ["pleroma.soykaf.com"] }. + +%% +%% route_subdomains: Delegate subdomains to other XMPP servers. +%% For example, if this ejabberd serves example.org and you want +%% to allow communication with an XMPP server called im.example.org. +%% +%%{route_subdomains, s2s}. + + +%%%. =============== +%%%' LISTENING PORTS + +%% +%% listen: The ports ejabberd will listen on, which service each is handled +%% by and what options to start it with. +%% +{listen, + [ + %% BOSH and WS endpoints over HTTP + { 5280, ejabberd_cowboy, [ + {num_acceptors, 10}, + {transport_options, [{max_connections, 1024}]}, + {modules, [ + + {"_", "/http-bind", mod_bosh}, + {"_", "/ws-xmpp", mod_websockets, [{ejabberd_service, [ + {access, all}, + {shaper_rule, fast}, + {ip, {127, 0, 0, 1}}, + {password, "secret"}]} + %% Uncomment to enable connection dropping or/and server-side pings + %{timeout, 600000}, {ping_rate, 2000} + ]} + %% Uncomment to serve static files + %{"_", "/static/[...]", cowboy_static, + % {dir, "/var/www", [{mimetypes, cow_mimetypes, all}]} + %}, + + %% Example usage of mod_revproxy + + %% {"_", "/[...]", mod_revproxy, [{timeout, 5000}, + %% % time limit for upstream to respond + %% {body_length, 8000000}, + %% % maximum body size (may be infinity) + %% {custom_headers, [{<<"header">>,<<"value">>}]} + %% % list of extra headers that are send to upstream + %% ]} + + %% Example usage of mod_cowboy + + %% {"_", "/[...]", mod_cowboy, [{http, mod_revproxy, + %% [{timeout, 5000}, + %% % time limit for upstream to respond + %% {body_length, 8000000}, + %% % maximum body size (may be infinity) + %% {custom_headers, [{<<"header">>,<<"value">>}]} + %% % list of extra headers that are send to upstream + %% ]}, + %% {ws, xmpp, mod_websockets} + %% ]} + ]} + ]}, + + %% BOSH and WS endpoints over HTTPS + { 5285, ejabberd_cowboy, [ + {num_acceptors, 10}, + {transport_options, [{max_connections, 1024}]}, + {ssl, [{certfile, "priv/ssl/fullchain.pem"}, {keyfile, "priv/ssl/privkey.pem"}, {password, ""}]}, + {modules, [ + {"_", "/http-bind", mod_bosh}, + {"_", "/ws-xmpp", mod_websockets, [ + %% Uncomment to enable connection dropping or/and server-side pings + %{timeout, 600000}, {ping_rate, 60000} + ]} + %% Uncomment to serve static files + %{"_", "/static/[...]", cowboy_static, + % {dir, "/var/www", [{mimetypes, cow_mimetypes, all}]} + %}, + ]} + ]}, + + %% MongooseIM HTTP API it's important to start it on localhost + %% or some private interface only (not accessible from the outside) + %% At least start it on different port which will be hidden behind firewall + + { {8088, "127.0.0.1"} , ejabberd_cowboy, [ + {num_acceptors, 10}, + {transport_options, [{max_connections, 1024}]}, + {modules, [ + {"localhost", "/api", mongoose_api_admin, []} + ]} + ]}, + + { 8089 , ejabberd_cowboy, [ + {num_acceptors, 10}, + {transport_options, [{max_connections, 1024}]}, + {protocol_options, [{compress, true}]}, + {ssl, [{certfile, "priv/ssl/fullchain.pem"}, {keyfile, "priv/ssl/privkey.pem"}, {password, ""}]}, + {modules, [ + {"_", "/api/sse", lasse_handler, [mongoose_client_api_sse]}, + {"_", "/api/messages/[:with]", mongoose_client_api_messages, []}, + {"_", "/api/contacts/[:jid]", mongoose_client_api_contacts, []}, + {"_", "/api/rooms/[:id]", mongoose_client_api_rooms, []}, + {"_", "/api/rooms/[:id]/config", mongoose_client_api_rooms_config, []}, + {"_", "/api/rooms/:id/users/[:user]", mongoose_client_api_rooms_users, []}, + {"_", "/api/rooms/[:id]/messages", mongoose_client_api_rooms_messages, []} + ]} + ]}, + + %% Following HTTP API is deprecated, the new one above should be used instead + + { {5288, "127.0.0.1"} , ejabberd_cowboy, [ + {num_acceptors, 10}, + {transport_options, [{max_connections, 1024}]}, + {modules, [ + {"localhost", "/api", mongoose_api, [{handlers, [mongoose_api_metrics, + mongoose_api_users]}]} + ]} + ]}, + + %% If you want dual stack, you have to clone this entire config stanza + %% and change the bind to "::" + { {5222, "0.0.0.0"}, ejabberd_c2s, [ + + %% + %% If TLS is compiled in and you installed a SSL + %% certificate, specify the full path to the + %% file and uncomment this line: + %% + {certfile, "priv/ssl/both.pem"}, starttls, + + %%{zlib, 10000}, + %% https://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS + %% {ciphers, "DEFAULT:!EXPORT:!LOW:!SSLv2"}, + {access, c2s}, + {shaper, c2s_shaper}, + {max_stanza_size, 65536}, + {protocol_options, ["no_sslv3"]} + + ]}, + + + + %% + %% To enable the old SSL connection method on port 5223: + %% + %%{5223, ejabberd_c2s, [ + %% {access, c2s}, + %% {shaper, c2s_shaper}, + %% {certfile, "/path/to/ssl.pem"}, tls, + %% {max_stanza_size, 65536} + %% ]}, + + %% If you want dual stack, you have to clone this entire config stanza + %% and change the bind to "::" + { {5269, "0.0.0.0"}, ejabberd_s2s_in, [ + {shaper, s2s_shaper}, + {max_stanza_size, 131072}, + {protocol_options, ["no_sslv3"]} + + ]} + + %% + %% ejabberd_service: Interact with external components (transports, ...) + %% + ,{8888, ejabberd_service, [ + {access, all}, + {shaper_rule, fast}, + {ip, {127, 0, 0, 1}}, + {password, "secret"} + ]} + + %% + %% ejabberd_stun: Handles STUN Binding requests + %% + %%{ {3478, udp}, ejabberd_stun, []} + + ]}. + +%% +%% s2s_use_starttls: Enable STARTTLS + Dialback for S2S connections. +%% Allowed values are: false optional required required_trusted +%% You must specify a certificate file. +%% +{s2s_use_starttls, optional}. +%% +%% s2s_certfile: Specify a certificate file. +%% +{s2s_certfile, "priv/ssl/both.pem"}. + +%% https://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS +%% {s2s_ciphers, "DEFAULT:!EXPORT:!LOW:!SSLv2"}. + +%% +%% domain_certfile: Specify a different certificate for each served hostname. +%% +%%{domain_certfile, "example.org", "/path/to/example_org.pem"}. +%%{domain_certfile, "example.com", "/path/to/example_com.pem"}. + +%% +%% S2S whitelist or blacklist +%% +%% Default s2s policy for undefined hosts. +%% +{s2s_default_policy, deny }. + +%% +%% Allow or deny communication with specific servers. +%% +%%{ {s2s_host, "goodhost.org"}, allow}. +%%{ {s2s_host, "badhost.org"}, deny}. + +{outgoing_s2s_port, 5269 }. + +%% +%% IP addresses predefined for specific hosts to skip DNS lookups. +%% Ports defined here take precedence over outgoing_s2s_port. +%% Examples: +%% +%% { {s2s_addr, "example-host.net"}, {127,0,0,1} }. +%% { {s2s_addr, "example-host.net"}, { {127,0,0,1}, 5269 } }. +%% { {s2s_addr, "example-host.net"}, { {127,0,0,1}, 5269 } }. + +%% +%% Outgoing S2S options +%% +%% Preferred address families (which to try first) and connect timeout +%% in milliseconds. +%% +%%{outgoing_s2s_options, [ipv4, ipv6], 10000}. +%% +%%%. ============== +%%%' SESSION BACKEND + +%%{sm_backend, {mnesia, []}}. + +%% Requires {redis, global, default, ..., ...} outgoing pool +%%{sm_backend, {redis, []}}. + +{sm_backend, {mnesia, []} }. + + +%%%. ============== +%%%' AUTHENTICATION + +%% Advertised SASL mechanisms +{sasl_mechanisms, [cyrsasl_plain]}. + +%% +%% auth_method: Method used to authenticate the users. +%% The default method is the internal. +%% If you want to use a different method, +%% comment this line and enable the correct ones. +%% +%% {auth_method, internal }. +{auth_method, http }. +{auth_opts, [ + {http, global, auth, [{workers, 50}], [{server, "https://pleroma.soykaf.com"}]}, + {password_format, plain} % default + %% {password_format, scram} + + %% {scram_iterations, 4096} % default + + %% + %% For auth_http: + %% {basic_auth, "user:password"} + %% {path_prefix, "/"} % default + %% auth_http requires {http, Host | global, auth, ..., ...} outgoing pool. + %% + %% For auth_external + %%{extauth_program, "/path/to/authentication/script"}. + %% + %% For auth_jwt + %% {jwt_secret_source, "/path/to/file"}, + %% {jwt_algorithm, "RS256"}, + %% {jwt_username_key, user} + %% For cyrsasl_external + %% {authenticate_with_cn, false} + {cyrsasl_external, standard} + ]}. + +%% +%% Authentication using external script +%% Make sure the script is executable by ejabberd. +%% +%%{auth_method, external}. + +%% +%% Authentication using RDBMS +%% Remember to setup a database in the next section. +%% +%%{auth_method, rdbms}. + +%% +%% Authentication using LDAP +%% +%%{auth_method, ldap}. +%% + +%% List of LDAP servers: +%%{ldap_servers, ["localhost"]}. +%% +%% Encryption of connection to LDAP servers: +%%{ldap_encrypt, none}. +%%{ldap_encrypt, tls}. +%% +%% Port to connect to on LDAP servers: +%%{ldap_port, 389}. +%%{ldap_port, 636}. +%% +%% LDAP manager: +%%{ldap_rootdn, "dc=example,dc=com"}. +%% +%% Password of LDAP manager: +%%{ldap_password, "******"}. +%% +%% Search base of LDAP directory: +%%{ldap_base, "dc=example,dc=com"}. +%% +%% LDAP attribute that holds user ID: +%%{ldap_uids, [{"mail", "%u@mail.example.org"}]}. +%% +%% LDAP filter: +%%{ldap_filter, "(objectClass=shadowAccount)"}. + +%% +%% Anonymous login support: +%% auth_method: anonymous +%% anonymous_protocol: sasl_anon | login_anon | both +%% allow_multiple_connections: true | false +%% +%%{host_config, "public.example.org", [{auth_method, anonymous}, +%% {allow_multiple_connections, false}, +%% {anonymous_protocol, sasl_anon}]}. +%% +%% To use both anonymous and internal authentication: +%% +%%{host_config, "public.example.org", [{auth_method, [internal, anonymous]}]}. + + +%%%. ============== +%%%' OUTGOING CONNECTIONS (e.g. DB) + +%% Here you may configure all outgoing connections used by MongooseIM, +%% e.g. to RDBMS (such as MySQL), Riak or external HTTP components. +%% Default MongooseIM configuration uses only Mnesia (non-Mnesia extensions are disabled), +%% so no options here are uncommented out of the box. +%% This section includes configuration examples; for comprehensive guide +%% please consult MongooseIM documentation, page "Outgoing connections": +%% - doc/advanced-configuration/outgoing-connections.md +%% - https://mongooseim.readthedocs.io/en/latest/advanced-configuration/outgoing-connections/ + + +{outgoing_pools, [ +% {riak, global, default, [{workers, 5}], [{address, "127.0.0.1"}, {port, 8087}]}, +% {elastic, global, default, [], [{host, "elastic.host.com"}, {port, 9042}]}, + {http, global, auth, [{workers, 50}], [{server, "https://pleroma.soykaf.com"}]} +% {cassandra, global, default, [{workers, 100}], [{servers, [{"server1", 9042}]}, {keyspace, "big_mongooseim"}]}, +% {rdbms, global, default, [{workers, 10}], [{server, {mysql, "server", 3306, "database", "username", "password"}}]} +]}. + +%% More examples that may be added to outgoing_pools list: +%% +%% == MySQL == +%% {rdbms, global, default, [{workers, 10}], +%% [{server, {mysql, "server", 3306, "database", "username", "password"}}, +%% {keepalive_interval, 10}]}, +%% keepalive_interval is optional + +%% == PostgreSQL == +%% {rdbms, global, default, [{workers, 10}], +%% [{server, {pgsql, "server", "port", "database", "username", "password"}}]}, + +%% == ODBC (MSSQL) == +%% {rdbms, global, default, [{workers, 10}], +%% [{server, "DSN=mongooseim;UID=mongooseim;PWD=mongooseim"}]}, + +%% == Elastic Search == +%% {elastic, global, default, [], [{host, "elastic.host.com"}, {port, 9042}]}, + +%% == Riak == +%% {riak, global, default, [{workers, 20}], [{address, "127.0.0.1"}, {port, 8087}]}, + +%% == HTTP == +%% {http, global, conn1, [{workers, 50}], [{server, "http://server:8080"}]}, + +%% == Cassandra == +%% {cassandra, global, default, [{workers, 100}], +%% [ +%% {servers, [ +%% {"cassandra_server1.example.com", 9042}, +%% {"cassandra_server2.example.com", 9042}, +%% {"cassandra_server3.example.com", 9042}, +%% {"cassandra_server4.example.com", 9042} +%% ]}, +%% {keyspace, "big_mongooseim"} +%% ]} + +%% == Extra options == +%% +%% If you use PostgreSQL, have a large database, and need a +%% faster but inexact replacement for "select count(*) from users" +%% +%%{pgsql_users_number_estimate, true}. +%% +%% rdbms_server_type specifies what database is used over the RDBMS layer +%% Can take values mssql, pgsql, mysql +%% In some cases (for example for MAM with pgsql) it is required to set proper value. +%% +%% {rdbms_server_type, pgsql}. + +%%%. =============== +%%%' TRAFFIC SHAPERS + +%% +%% The "normal" shaper limits traffic speed to 1000 B/s +%% +{shaper, normal, {maxrate, 1000}}. + +%% +%% The "fast" shaper limits traffic speed to 50000 B/s +%% +{shaper, fast, {maxrate, 50000}}. + +%% +%% This option specifies the maximum number of elements in the queue +%% of the FSM. Refer to the documentation for details. +%% +{max_fsm_queue, 1000}. + +%%%. ==================== +%%%' ACCESS CONTROL LISTS + +%% +%% The 'admin' ACL grants administrative privileges to XMPP accounts. +%% You can put here as many accounts as you want. +%% +%{acl, admin, {user, "alice", "localhost"}}. +%{acl, admin, {user, "a", "localhost"}}. + +%% +%% Blocked users +%% +%%{acl, blocked, {user, "baduser", "example.org"}}. +%%{acl, blocked, {user, "test"}}. + +%% +%% Local users: don't modify this line. +%% +{acl, local, {user_regexp, ""}}. + +%% +%% More examples of ACLs +%% +%%{acl, jabberorg, {server, "jabber.org"}}. +%%{acl, aleksey, {user, "aleksey", "jabber.ru"}}. +%%{acl, test, {user_regexp, "^test"}}. +%%{acl, test, {user_glob, "test*"}}. + +%% +%% Define specific ACLs in a virtual host. +%% +%%{host_config, "localhost", +%% [ +%% {acl, admin, {user, "bob-local", "localhost"}} +%% ] +%%}. + +%%%. ============ +%%%' ACCESS RULES + +%% Maximum number of simultaneous sessions allowed for a single user: +{access, max_user_sessions, [{10, all}]}. + +%% Maximum number of offline messages that users can have: +{access, max_user_offline_messages, [{5000, admin}, {100, all}]}. + +%% This rule allows access only for local users: +{access, local, [{allow, local}]}. + +%% Only non-blocked users can use c2s connections: +{access, c2s, [{deny, blocked}, + {allow, all}]}. + +%% For C2S connections, all users except admins use the "normal" shaper +{access, c2s_shaper, [{none, admin}, + {normal, all}]}. + +%% All S2S connections use the "fast" shaper +{access, s2s_shaper, [{fast, all}]}. + +%% Admins of this server are also admins of the MUC service: +{access, muc_admin, [{allow, admin}]}. + +%% Only accounts of the local ejabberd server can create rooms: +{access, muc_create, [{allow, local}]}. + +%% All users are allowed to use the MUC service: +{access, muc, [{allow, all}]}. + +%% In-band registration allows registration of any possible username. +%% To disable in-band registration, replace 'allow' with 'deny'. +{access, register, [{allow, all}]}. + +%% By default the frequency of account registrations from the same IP +%% is limited to 1 account every 10 minutes. To disable, specify: infinity +{registration_timeout, infinity}. + +%% Default settings for MAM. +%% To set non-standard value, replace 'default' with 'allow' or 'deny'. +%% Only user can access his/her archive by default. +%% An online user can read room's archive by default. +%% Only an owner can change settings and purge messages by default. +%% Empty list (i.e. `[]`) means `[{deny, all}]`. +{access, mam_set_prefs, [{default, all}]}. +{access, mam_get_prefs, [{default, all}]}. +{access, mam_lookup_messages, [{default, all}]}. +{access, mam_purge_single_message, [{default, all}]}. +{access, mam_purge_multiple_messages, [{default, all}]}. + +%% 1 command of the specified type per second. +{shaper, mam_shaper, {maxrate, 1}}. +%% This shaper is primeraly for Mnesia overload protection during stress testing. +%% The limit is 1000 operations of each type per second. +{shaper, mam_global_shaper, {maxrate, 1000}}. + +{access, mam_set_prefs_shaper, [{mam_shaper, all}]}. +{access, mam_get_prefs_shaper, [{mam_shaper, all}]}. +{access, mam_lookup_messages_shaper, [{mam_shaper, all}]}. +{access, mam_purge_single_message_shaper, [{mam_shaper, all}]}. +{access, mam_purge_multiple_messages_shaper, [{mam_shaper, all}]}. + +{access, mam_set_prefs_global_shaper, [{mam_global_shaper, all}]}. +{access, mam_get_prefs_global_shaper, [{mam_global_shaper, all}]}. +{access, mam_lookup_messages_global_shaper, [{mam_global_shaper, all}]}. +{access, mam_purge_single_message_global_shaper, [{mam_global_shaper, all}]}. +{access, mam_purge_multiple_messages_global_shaper, [{mam_global_shaper, all}]}. + +%% +%% Define specific Access Rules in a virtual host. +%% +%%{host_config, "localhost", +%% [ +%% {access, c2s, [{allow, admin}, {deny, all}]}, +%% {access, register, [{deny, all}]} +%% ] +%%}. + +%%%. ================ +%%%' DEFAULT LANGUAGE + +%% +%% language: Default language used for server messages. +%% +{language, "en"}. + +%% +%% Set a different default language in a virtual host. +%% +%%{host_config, "localhost", +%% [{language, "ru"}] +%%}. + +%%%. ================ +%%%' MISCELLANEOUS + +{all_metrics_are_global, false }. + +%%%. ======== +%%%' SERVICES + +%% Unlike modules, services are started per node and provide either features which are not +%% related to any particular host, or backend stuff which is used by modules. +%% This is handled by `mongoose_service` module. + +{services, + [ + {service_admin_extra, [{submods, [node, accounts, sessions, vcard, + roster, last, private, stanza, stats]}]} + ] +}. + +%%%. ======= +%%%' MODULES + +%% +%% Modules enabled in all mongooseim virtual hosts. +%% For list of possible modules options, check documentation. +%% +{modules, + [ + + %% The format for a single route is as follows: + %% {Host, Path, Method, Upstream} + %% + %% "_" can be used as wildcard for Host, Path and Method + %% Upstream can be either host (just http(s)://host:port) or uri + %% The difference is that host upstreams append whole path while + %% uri upstreams append only remainder that follows the matched Path + %% (this behaviour is similar to nginx's proxy_pass rules) + %% + %% Bindings can be used to match certain parts of host or path. + %% They will be later overlaid with parts of the upstream uri. + %% + %% {mod_revproxy, + %% [{routes, [{"www.erlang-solutions.com", "/admin", "_", + %% "https://www.erlang-solutions.com/"}, + %% {":var.com", "/:var", "_", "http://localhost:8080/"}, + %% {":domain.com", "/", "_", "http://localhost:8080/:domain"}] + %% }]}, + +% {mod_http_upload, [ + %% Set max file size in bytes. Defaults to 10 MB. + %% Disabled if value is `undefined`. +% {max_file_size, 1024}, + %% Use S3 storage backend +% {backend, s3}, + %% Set options for S3 backend +% {s3, [ +% {bucket_url, "http://s3-eu-west-1.amazonaws.com/konbucket2"}, +% {region, "eu-west-1"}, +% {access_key_id, "AKIAIAOAONIULXQGMOUA"}, +% {secret_access_key, "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"} +% ]} +% ]}, + + {mod_adhoc, []}, + + {mod_disco, [{users_can_see_hidden_services, false}]}, + {mod_commands, []}, + {mod_muc_commands, []}, + {mod_muc_light_commands, []}, + {mod_last, []}, + {mod_stream_management, [ + % default 100 + % size of a buffer of unacked messages + % {buffer_max, 100} + + % default 1 - server sends the ack request after each stanza + % {ack_freq, 1} + + % default: 600 seconds + % {resume_timeout, 600} + ]}, + %% {mod_muc_light, [{host, "muclight.@HOST@"}]}, + %% {mod_muc, [{host, "muc.@HOST@"}, + %% {access, muc}, + %% {access_create, muc_create} + %% ]}, + %% {mod_muc_log, [ + %% {outdir, "/tmp/muclogs"}, + %% {access_log, muc} + %% ]}, + {mod_offline, [{access_max_user_messages, max_user_offline_messages}]}, + {mod_privacy, []}, + {mod_blocking, []}, + {mod_private, []}, +% {mod_private, [{backend, mnesia}]}, +% {mod_private, [{backend, rdbms}]}, +% {mod_register, [ +% %% +% %% Set the minimum informational entropy for passwords. +% %% +% %%{password_strength, 32}, +% +% %% +% %% After successful registration, the user receives +% %% a message with this subject and body. +% %% +% {welcome_message, {""}}, +% +% %% +% %% When a user registers, send a notification to +% %% these XMPP accounts. +% %% +% +% +% %% +% %% Only clients in the server machine can register accounts +% %% +% {ip_access, [{allow, "127.0.0.0/8"}, +% {deny, "0.0.0.0/0"}]}, +% +% %% +% %% Local c2s or remote s2s users cannot register accounts +% %% +% %%{access_from, deny}, +% +% {access, register} +% ]}, + {mod_roster, []}, + {mod_sic, []}, + {mod_vcard, [%{matches, 1}, +%{search, true}, +%{ldap_search_operator, 'or'}, %% either 'or' or 'and' +%{ldap_binary_search_fields, [<<"PHOTO">>]}, +%% list of binary search fields (as in vcard after mapping) +{host, "vjud.@HOST@"} +]}, + {mod_bosh, []}, + {mod_carboncopy, []} + + %% + %% Message Archive Management (MAM, XEP-0313) for registered users and + %% Multi-User chats (MUCs). + %% + +% {mod_mam_meta, [ + %% Use RDBMS backend (default) +% {backend, rdbms}, + + %% Do not store user preferences (default) +% {user_prefs_store, false}, + %% Store user preferences in RDBMS +% {user_prefs_store, rdbms}, + %% Store user preferences in Mnesia (recommended). + %% The preferences store will be called each time, as a message is routed. + %% That is why Mnesia is better suited for this job. +% {user_prefs_store, mnesia}, + + %% Enables a pool of asynchronous writers. (default) + %% Messages will be grouped together based on archive id. +% {async_writer, true}, + + %% Cache information about users (default) +% {cache_users, true}, + + %% Enable archivization for private messages (default) +% {pm, [ + %% Top-level options can be overridden here if needed, for example: +% {async_writer, false} +% ]}, + + %% + %% Message Archive Management (MAM) for multi-user chats (MUC). + %% Enable XEP-0313 for "muc.@HOST@". + %% +% {muc, [ +% {host, "muc.@HOST@"} + %% As with pm, top-level options can be overridden for MUC archive +% ]}, +% + %% Do not use a element (by default stanzaid is used) +% no_stanzaid_element, +% ]}, + + + %% + %% MAM configuration examples + %% + + %% Only MUC, no user-defined preferences, good performance. +% {mod_mam_meta, [ +% {backend, rdbms}, +% {pm, false}, +% {muc, [ +% {host, "muc.@HOST@"} +% ]} +% ]}, + + %% Only archives for c2c messages, good performance. +% {mod_mam_meta, [ +% {backend, rdbms}, +% {pm, [ +% {user_prefs_store, mnesia} +% ]} +% ]}, + + %% Basic configuration for c2c messages, bad performance, easy to debug. +% {mod_mam_meta, [ +% {backend, rdbms}, +% {async_writer, false}, +% {cache_users, false} +% ]}, + + %% Cassandra archive for c2c and MUC conversations. + %% No custom settings supported (always archive). +% {mod_mam_meta, [ +% {backend, cassandra}, +% {user_prefs_store, cassandra}, +% {muc, [{host, "muc.@HOST@"}]} +% ]} + +% {mod_event_pusher, [ +% {backends, [ +% %% +% %% Configuration for Amazon SNS notifications. +% %% +% {sns, [ +% %% AWS credentials, region and host configuration +% {access_key_id, "AKIAJAZYHOIPY6A2PESA"}, +% {secret_access_key, "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"}, +% {region, "eu-west-1"}, +% {account_id, "251423380551"}, +% {region, "eu-west-1"}, +% {sns_host, "sns.eu-west-1.amazonaws.com"}, +% +% %% Messages from this MUC host will be sent to the SNS topic +% {muc_host, "muc.@HOST@"}, +% +% %% Plugin module for defining custom message attributes and user identification +% {plugin_module, mod_event_pusher_sns_defaults}, +% +% %% Topic name configurations. Removing a topic will disable this specific SNS notification +% {presence_updates_topic, "user_presence_updated-dev-1"}, %% For presence updates +% {pm_messages_topic, "user_message_sent-dev-1"}, %% For private chat messages +% {muc_messages_topic, "user_messagegroup_sent-dev-1"} %% For group chat messages +% +% %% Pool options +% {pool_size, 100}, %% Worker pool size for publishing notifications +% {publish_retry_count, 2}, %% Retry count in case of publish error +% {publish_retry_time_ms, 50} %% Base exponential backoff time (in ms) for publish errors +% ]} +% ]} + +]}. + + +%% +%% Enable modules with custom options in a specific virtual host +%% +%%{host_config, "localhost", +%% [{ {add, modules}, +%% [ +%% {mod_some_module, []} +%% ] +%% } +%% ]}. + +%%%. +%%%' + +%%% $Id$ + +%%% Local Variables: +%%% mode: erlang +%%% End: +%%% vim: set filetype=erlang tabstop=8 foldmarker=%%%',%%%. foldmethod=marker: +%%%. diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx new file mode 100644 index 0000000..273cfb3 --- /dev/null +++ b/installation/pleroma.nginx @@ -0,0 +1,109 @@ +# default nginx site config for Pleroma +# +# Simple installation instructions: +# 1. Install your TLS certificate, possibly using Let's Encrypt. +# 2. Replace 'example.tld' with your instance's domain wherever it appears. +# 3. Copy this file to /etc/nginx/sites-available/ and then add a symlink to it +# in /etc/nginx/sites-enabled/ and run 'nginx -s reload' or restart nginx. + +proxy_cache_path /tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g + inactive=720m use_temp_path=off; + +# this is explicitly IPv4 since Pleroma.Web.Endpoint binds on IPv4 only +# and `localhost.` resolves to [::0] on some systems: see issue #930 +upstream phoenix { + server 127.0.0.1:4000 max_fails=5 fail_timeout=60s; +} + +server { + server_name example.tld; + + listen 80; + listen [::]:80; + + # Uncomment this if you need to use the 'webroot' method with certbot. Make sure + # that the directory exists and that it is accessible by the webserver. If you followed + # the guide, you already ran 'mkdir -p /var/lib/letsencrypt' to create the folder. + # You may need to load this file with the ssl server block commented out, run certbot + # to get the certificate, and then uncomment it. + # + # location ~ /\.well-known/acme-challenge { + # root /var/lib/letsencrypt/; + # } + location / { + return 301 https://$server_name$request_uri; + } +} + +# Enable SSL session caching for improved performance +ssl_session_cache shared:ssl_session_cache:10m; + +server { + server_name example.tld; + + listen 443 ssl http2; + listen [::]:443 ssl http2; + ssl_session_timeout 1d; + ssl_session_cache shared:MozSSL:10m; # about 40000 sessions + ssl_session_tickets off; + + ssl_trusted_certificate /etc/letsencrypt/live/example.tld/chain.pem; + ssl_certificate /etc/letsencrypt/live/example.tld/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/example.tld/privkey.pem; + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + ssl_prefer_server_ciphers off; + # In case of an old server with an OpenSSL version of 1.0.2 or below, + # leave only prime256v1 or comment out the following line. + ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1; + ssl_stapling on; + ssl_stapling_verify on; + + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_buffers 16 8k; + gzip_http_version 1.1; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/activity+json application/atom+xml; + + # the nginx default is 1m, not enough for large media uploads + client_max_body_size 16m; + ignore_invalid_headers off; + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + location / { + proxy_pass http://phoenix; + } + + # Uncomment this if you want notice compatibility routes for frontends like Soapbox. + # location ~ ^/@[^/]+/([^/]+)$ { + # proxy_pass http://phoenix/notice/$1; + # } + # + # location ~ ^/@[^/]+/posts/([^/]+)$ { + # proxy_pass http://phoenix/notice/$1; + # } + # + # location ~ ^/[^/]+/status/([^/]+)$ { + # proxy_pass http://phoenix/notice/$1; + # } + + location ~ ^/(media|proxy) { + proxy_cache pleroma_media_cache; + slice 1m; + proxy_cache_key $host$uri$is_args$args$slice_range; + proxy_set_header Range $slice_range; + proxy_cache_valid 200 206 301 304 1h; + proxy_cache_lock on; + proxy_ignore_client_abort on; + proxy_buffering on; + chunked_transfer_encoding on; + proxy_pass http://phoenix; + } +} diff --git a/installation/pleroma.service b/installation/pleroma.service new file mode 100644 index 0000000..8338228 --- /dev/null +++ b/installation/pleroma.service @@ -0,0 +1,36 @@ +[Unit] +Description=Pleroma social network +After=network.target postgresql.service + +[Service] +ExecReload=/bin/kill $MAINPID +KillMode=process +Restart=on-failure + +; Name of the user that runs the Pleroma service. +User=pleroma +; Declares that Pleroma runs in production mode. +Environment="MIX_ENV=prod" + +; Make sure that all paths fit your installation. +; Path to the home directory of the user running the Pleroma service. +Environment="HOME=/var/lib/pleroma" +; Path to the folder containing the Pleroma installation. +WorkingDirectory=/opt/pleroma +; Path to the Mix binary. +ExecStart=/usr/bin/mix phx.server + +; Some security directives. +; Use private /tmp and /var/tmp folders inside a new file system namespace, which are discarded after the process stops. +PrivateTmp=true +; The /home, /root, and /run/user folders can not be accessed by this service anymore. If your Pleroma user has its home folder in one of the restricted places, or use one of these folders as its working directory, you have to set this to false. +ProtectHome=true +; Mount /usr, /boot, and /etc as read-only for processes invoked by this service. +ProtectSystem=full +; Sets up a new /dev mount for the process and only adds API pseudo devices like /dev/null, /dev/zero or /dev/random but not physical devices. Disabled by default because it may not work on devices like the Raspberry Pi. +PrivateDevices=false +; Drops the sysadmin capability from the daemon. +CapabilityBoundingSet=~CAP_SYS_ADMIN + +[Install] +WantedBy=multi-user.target diff --git a/installation/pleroma.supervisord b/installation/pleroma.supervisord new file mode 100644 index 0000000..19efffd --- /dev/null +++ b/installation/pleroma.supervisord @@ -0,0 +1,21 @@ +; Assumes pleroma is installed in /home/pleroma/pleroma and running as the pleroma user +; Also assumes mix is in /usr/bin, this might differ on BSDs or niche Linux distros +; Logs into /home/pleroma/logs +[program:pleroma] +command=/usr/bin/mix phx.server +directory=/home/pleroma/pleroma +autostart=true +autorestart=true +user=pleroma +environment = + MIX_ENV=prod, + HOME=/home/pleroma, + USER=pleroma, + PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/pleroma/bin:%(ENV_PATH)s", + PWD=/home/pleroma/pleroma +stdout_logfile=/home/pleroma/logs/stdout.log +stdout_logfile_maxbytes=50MB +stdout_logfile_backups=10 +stderr_logfile=/home/pleroma/logs/stderr.log +stderr_logfile_maxbytes=50MB +stderr_logfile_backups=10 \ No newline at end of file diff --git a/installation/pleroma.vcl b/installation/pleroma.vcl new file mode 100644 index 0000000..4eb2f3c --- /dev/null +++ b/installation/pleroma.vcl @@ -0,0 +1,127 @@ +# Recommended varnishncsa logging format: '%h %l %u %t "%m %{X-Forwarded-Proto}i://%{Host}i%U%q %H" %s %b "%{Referer}i" "%{User-agent}i"' +# Please use Varnish 7.0+ for proper Range Requests / Chunked encoding support +vcl 4.1; +import std; + +backend default { + .host = "127.0.0.1"; + .port = "4000"; +} + +# ACL for IPs that are allowed to PURGE data from the cache +acl purge { + "127.0.0.1"; +} + +sub vcl_recv { + # Redirect HTTP to HTTPS + if (std.port(server.ip) != 443) { + set req.http.X-Forwarded-Proto = "http"; + set req.http.x-redir = "https://" + req.http.host + req.url; + return (synth(750, "")); + } else { + set req.http.X-Forwarded-Proto = "https"; + } + + # Pipe if WebSockets request is coming through + if (req.http.upgrade ~ "(?i)websocket") { + return (pipe); + } + + # Allow purging of the cache + if (req.method == "PURGE") { + if (!client.ip ~ purge) { + return (synth(405,"Not allowed.")); + } + return (purge); + } +} + +sub vcl_backend_response { + # gzip text content + if (beresp.http.content-type ~ "(text|text/css|application/x-javascript|application/javascript)") { + set beresp.do_gzip = true; + } + + # Retry broken backend responses. + if (beresp.status == 503) { + set bereq.http.X-Varnish-Backend-503 = "1"; + return (retry); + } + + # Bypass cache for large files + # 50000000 ~ 50MB + if (std.integer(beresp.http.content-length, 0) > 50000000) { + set beresp.uncacheable = true; + return (deliver); + } + + # Don't cache objects that require authentication + if (beresp.http.Authorization && !beresp.http.Cache-Control ~ "public") { + set beresp.uncacheable = true; + return (deliver); + } + + # Allow serving cached content for 6h in case backend goes down + set beresp.grace = 6h; + + # Do not cache 5xx responses + if (beresp.status == 500 || beresp.status == 502 || beresp.status == 503 || beresp.status == 504) { + set beresp.uncacheable = true; + return (abandon); + } + + # Do not cache redirects and errors + if ((beresp.status >= 300) && (beresp.status < 500)) { + set beresp.uncacheable = true; + set beresp.ttl = 30s; + return (deliver); + } +} + +# The synthetic response for 301 redirects +sub vcl_synth { + if (resp.status == 750) { + set resp.status = 301; + set resp.http.Location = req.http.x-redir; + return (deliver); + } +} + +# Ensure WebSockets through the pipe do not close prematurely +sub vcl_pipe { + if (req.http.upgrade) { + set bereq.http.upgrade = req.http.upgrade; + set bereq.http.connection = req.http.connection; + } +} + +sub vcl_backend_fetch { + # Be more lenient for slow servers on the fediverse + if (bereq.url ~ "^/proxy/") { + set bereq.first_byte_timeout = 300s; + } + + if (bereq.retries == 0) { + # Clean up the X-Varnish-Backend-503 flag that is used internally + # to mark broken backend responses that should be retried. + unset bereq.http.X-Varnish-Backend-503; + } else { + if (bereq.http.X-Varnish-Backend-503) { + if (bereq.method != "POST" && + std.healthy(bereq.backend) && + bereq.retries <= 4) { + # Flush broken backend response flag & try again. + unset bereq.http.X-Varnish-Backend-503; + } else { + return (abandon); + } + } + } +} + +sub vcl_backend_error { + # Retry broken backend responses. + set bereq.http.X-Varnish-Backend-503 = "1"; + return (retry); +} -- cgit v1.2.3