commit 16e9418632e03a6d9351499949e5d9037f8a1674 Author: shaula Date: Tue Oct 18 20:20:59 2016 +0000 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..07f43b8 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +data/* \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0f3056e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,68 @@ +FROM resin/rpi-raspbian + +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y \ + libevent-dev \ + lua5.1 \ + lua-dbi-sqlite3 \ + lua-dbi-mysql \ + lua-dbi-postgresql \ + lua-event \ + lua-expat \ + lua-filesystem \ + lua-socket \ + lua-sec \ + wget \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +ENV PROSODY_VERSION 0.9.10 +ENV PROSODY_DOWNLOAD_URL https://prosody.im/downloads/source/prosody-${PROSODY_VERSION}.tar.gz +ENV PROSODY_DOWNLOAD_SHA1 572b3dc6f29cb304cc7d4c5a2ef570cf0638fe63 + +RUN buildDeps='gcc libc6-dev make liblua5.1-dev libidn11-dev libssl-dev' \ + && set -x \ + && apt-get update && apt-get install -y $buildDeps --no-install-recommends \ + && rm -rf /var/lib/apt/lists/* \ + && wget -O prosody.tar.gz "$PROSODY_DOWNLOAD_URL" \ + && echo "$PROSODY_DOWNLOAD_SHA1 *prosody.tar.gz" | sha1sum -c - \ + && mkdir -p /usr/src/prosody \ + && tar -xzf prosody.tar.gz -C /usr/src/prosody --strip-components=1 \ + && rm prosody.tar.gz \ + && cd /usr/src/prosody && ./configure --ostype=debian \ + && make -C /usr/src/prosody \ + && make -C /usr/src/prosody install \ + && rm -r /usr/src/prosody \ + && apt-get purge -y --auto-remove $buildDeps + +EXPOSE 5000 5222 5269 5347 5280 5281 + +RUN groupadd -r prosody \ + && useradd -r -g prosody prosody \ + && chown prosody:prosody /usr/local/var/lib/prosody + +# https://github.com/prosody/prosody-docker/issues/25 +ENV __FLUSH_LOG yes + +VOLUME ["/usr/local/var/lib/prosody"] + +COPY prosody.cfg.lua /usr/local/etc/prosody/prosody.cfg.lua +COPY docker-entrypoint.sh /entrypoint.sh +COPY conf.d/*.cfg.lua /usr/local/etc/prosody/conf.d/ + +COPY docker-prosody-module-* /usr/local/bin/ +RUN docker-prosody-module-install \ + blocking `# blocking command (XEP-0191)` \ + carbons `# message carbons (XEP-0280)` \ + csi `# client state indication (XEP-0352)` \ + e2e_policy `# require end-2-end encryption` \ + filter_chatstates `# disable "X is typing" type messages` \ + http_upload `# file sharing (XEP-0363)` \ + mam `# message archive management (XEP-0313)` \ + smacks `# stream management (XEP-0198)` \ + throttle_presence `# presence throttling in CSI` + +USER prosody + +ENTRYPOINT ["/entrypoint.sh"] +CMD ["prosody"] diff --git a/conf.d/01-modules.cfg.lua b/conf.d/01-modules.cfg.lua new file mode 100644 index 0000000..2618b8c --- /dev/null +++ b/conf.d/01-modules.cfg.lua @@ -0,0 +1,51 @@ +plugin_paths = { "/usr/local/lib/prosody/custom-modules/" }; + +modules_enabled = { + -- Generally required + "roster"; -- Allow users to have a roster. Recommended ;) + "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in. + "tls"; -- Add support for secure TLS on c2s/s2s connections + "dialback"; -- s2s dialback support + "disco"; -- Service discovery + + -- Not essential, but recommended + "private"; -- Private XML storage (for room bookmarks, etc.) + "vcard"; -- Allow users to set vCards + + -- These are commented by default as they have a performance impact + "privacy"; -- Support privacy lists + --"compression"; -- Stream compression (Debian: requires lua-zlib module to work) + + -- Nice to have + "version"; -- Replies to server version requests + "uptime"; -- Report how long server has been running + "time"; -- Let others know the time here on this server + "ping"; -- Replies to XMPP pings with pongs + "pep"; -- Enables users to publish their mood, activity, playing music and more + "register"; -- Allow users to register on this server using a client and change passwords + + -- Admin interfaces + "admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands + --"admin_telnet"; -- Opens telnet console interface on localhost port 5582 + + -- HTTP modules + --"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP" + --"http_files"; -- Serve static files from a directory over HTTP + + -- Other specific functionality + "posix"; -- POSIX functionality, sends server to background, enables syslog, etc. + --"groups"; -- Shared roster support + --"announce"; -- Send announcement to all online users + --"welcome"; -- Welcome users who register accounts + --"watchregistrations"; -- Alert admins of registrations + --"motd"; -- Send a message to users when they log in + --"legacyauth"; -- Legacy authentication. Only used by some old clients and bots. +}; + +-- These modules are auto-loaded, but should you want +-- to disable them then uncomment them here: +modules_disabled = { + -- "offline"; -- Store offline messages + -- "c2s"; -- Handle client connections + -- "s2s"; -- Handle server-to-server connections +}; diff --git a/conf.d/02-storage.cfg.lua b/conf.d/02-storage.cfg.lua new file mode 100644 index 0000000..69cf370 --- /dev/null +++ b/conf.d/02-storage.cfg.lua @@ -0,0 +1,13 @@ +default_storage = "sql" +sql = { + driver = "SQLite3"; + database = "prosody.sqlite"; +} + +storage = { + -- this makes mod_mam use the sql storage backend + archive2 = "sql"; +} + +-- https://modules.prosody.im/mod_mam.html +archive_expires_after = "1y" diff --git a/conf.d/03-e2e-policy.cfg.lua b/conf.d/03-e2e-policy.cfg.lua new file mode 100644 index 0000000..ba094e5 --- /dev/null +++ b/conf.d/03-e2e-policy.cfg.lua @@ -0,0 +1,7 @@ +e2e_policy_chat = "required" +e2e_policy_muc = "required" +e2e_policy_whitelist = {} +e2e_policy_message_optional_chat = "For security reasons, OMEMO, OTR or PGP encryption is STRONGLY recommended for conversations on this server." +e2e_policy_message_required_chat = "For security reasons, OMEMO, OTR or PGP encryption is required for conversations on this server." +e2e_policy_message_optional_muc = "For security reasons, OMEMO, OTR or PGP encryption is STRONGLY recommended for MUC on this server." +e2e_policy_message_required_muc = "For security reasons, OMEMO, OTR or PGP encryption is required for MUC on this server." \ No newline at end of file diff --git a/conf.d/04-vhost.cfg.lua b/conf.d/04-vhost.cfg.lua new file mode 100644 index 0000000..d9efcac --- /dev/null +++ b/conf.d/04-vhost.cfg.lua @@ -0,0 +1,18 @@ +local domain = os.getenv("DOMAIN") + +ssl = { + key = "/usr/local/etc/prosody/certs/prosody.key"; + certificate = "/usr/local/etc/prosody/certs/prosody.crt"; +} + +VirtualHost (domain) + +-- Set up a SOCKS5 bytestream proxy for server-proxied file transfers +Component ("proxy." .. domain) "proxy65" + proxy65_address = domain + proxy65_acl = { domain } + + +-- Set up a http file upload because proxy65 is not working in muc +-- Component (domain) "http_upload" +-- is set-up via modules_enabled diff --git a/data/.gitkeep b/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100755 index 0000000..4e327d1 --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -e + +if [[ "$1" != "prosody" ]]; then + exec prosodyctl $* + exit 0; +fi + +if [ "$LOCAL" -a "$PASSWORD" -a "$DOMAIN" ] ; then + prosodyctl register $LOCAL $DOMAIN $PASSWORD +fi + +exec "$@" \ No newline at end of file diff --git a/docker-prosody-module-install b/docker-prosody-module-install new file mode 100755 index 0000000..6464399 --- /dev/null +++ b/docker-prosody-module-install @@ -0,0 +1,60 @@ +#!/bin/sh +set -e + +source="/usr/src/prosody-modules" +target="/usr/local/lib/prosody/custom-modules" +config="/usr/local/etc/prosody/conf.d/01-modules.cfg.lua" + +srcExists= +if [ -d ${source} ]; then + srcExists=1 +fi +docker-prosody-module-source pullTo ${source} + +if [ -z "$srcExists" ]; then + touch ${source}/.docker-delete-me +fi + +cd ${source} + +usage() { + echo "usage: $0 ext-name [ext-name ...]" + echo " ie: $0 carbons e2e_policy proxy65" + echo + echo 'Possible values for ext-name:' + find . -mindepth 1 -maxdepth 1 -type d | sort | sed s/\.\\/mod_//g | xargs +} + +exts= +for ext; do + if [ -z "mod_$ext" ]; then + continue + fi + if [ ! -d "mod_$ext" ]; then + echo >&2 "error: $PWD/mod_$ext does not exist" + echo >&2 + usage >&2 + exit 1 + fi + exts="$exts $ext" +done + +if [ -z "$exts" ]; then + usage >&2 + exit 1 +fi + +for ext in $exts; do + echo "Installing mod_${ext}" + + echo " - copying to ${target}" + cp -r "${source}/mod_${ext}" "${target}/" + + echo " - enabling within ${config}" + new_config=$(cat "${config}" | module="${ext}" perl -0pe 's/(modules_enabled[ ]*=[ ]*{[^}]*)};/$1\n\t"$ENV{module}";\n};/') + echo "${new_config}" > "${config}" +done + +if [ -e ${source}/.docker-delete-me ]; then + docker-prosody-module-source deleteFrom ${source} +fi diff --git a/docker-prosody-module-source b/docker-prosody-module-source new file mode 100755 index 0000000..9fe22ed --- /dev/null +++ b/docker-prosody-module-source @@ -0,0 +1,39 @@ +#!/bin/sh +set -e + +dir=$2 + +usage() { + echo "usage: $0 COMMAND DIR" + echo + echo "Manage prosody-modules source lifecycle." + echo + echo "Commands:" + echo " pullTo extract prosody-module sources into directory ${dir} if not already done." + echo " deleteFrom delete extracted prosody-module sources located into ${dir} if not already done." + echo +} + +case "$1" in + pullTo) + mkdir -p "${dir}" + + if [ ! -f "${dir}/.docker-pulled" ]; then + wget https://hg.prosody.im/prosody-modules/archive/tip.tar.gz + tar -xzf tip.tar.gz -C "${dir}" --strip-components=1 + rm tip.tar.gz + touch "${dir}/.docker-pulled" + fi + + ;; + + deleteFrom) + rm -rf "${dir}" + + ;; + + *) + usage + exit 1 + ;; +esac diff --git a/prosody.cfg.lua b/prosody.cfg.lua new file mode 100644 index 0000000..dcb8ba0 --- /dev/null +++ b/prosody.cfg.lua @@ -0,0 +1,21 @@ +-- see example config at https://hg.prosody.im/0.9/file/0.9.10/prosody.cfg.lua.dist +-- easily extendable by putting into different config files within conf.d folder + +admins = {}; + +use_libevent = true; -- improves performance + +allow_registration = true; + +c2s_require_encryption = true; +s2s_secure_auth = true; + +authentication = "internal_hashed"; + +daemonize = false; + +log = { + {levels = {min = "info"}, to = "console"}; +}; + +Include "conf.d/*.cfg.lua"; diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..5461517 --- /dev/null +++ b/readme.md @@ -0,0 +1,111 @@ +# Prosody XMPP server for Raspberry Pi + +This docker image provides you with a configured [Prosody](https://prosody.im/) XMPP server. The image is intended to run on a Raspberry Pi (as it is based on _resin/rpi-raspbian_). +The server was tested using the Android App [Conversations](https://conversations.im/) and the Desktop client [Gajim](https://gajim.org). + +While Conversations got everything set-up out-of-the-box, Gajim was used with the following extensions: +* HttpUpload +* Off-The-Record Encryption +* OMEMO (requires _python-axolotl_ to be installed) +* Url Image preview + +## Features + +* Secure by default + * SSL certificate required + * End-to-end encryption required (using [OMEMO](https://conversations.im/omemo/) or [OTR](https://en.wikipedia.org/wiki/Off-the-Record_Messaging)) +* Data storage + * SQLite message store + * Configured file upload and image sharing +* Allows registration + +## Requirements + +* You need a SSL certificate. I recommend [LetsEncrypt](https://letsencrypt.org/) for that. +* Your Raspberry Pi should have docker set-up and running. You could use the Raspberry image for [Hypriot OS](http://blog.hypriot.com/downloads/) to get started quickly. + +## Image Details + +### Ports + +The following ports are exposed: + +* 5000: proxy65 port used for file sharing +* 5222: c2s port (client to server) +* 5269: s2s port (server to server) +* 5347: XMPP component port +* 5280: BOSH / websocket port +* 5281: Secure BOSH / websocket port + +### Directories + +* Data: ```/usr/local/var/lib/prosody/``` + * used for SQLite file + * used for HTTP uploads + * this is exposed as docker volume +* Bundled modules: ```/usr/local/lib/prosody/modules/``` +* Additionally installed prosody modules: ```/usr/local/lib/prosody/custom-modules/``` +* Config: ```/usr/local/etc/prosody/``` + * containing the main config file called ```prosody.cfg.lua``` + * containing additional config files within ```conf.d/``` +* SSL certificates: ```/usr/local/etc/prosody/certs/``` + * expects private key to be named ```prosody.key``` and certificate (fullchain) to be ```prosody.crt``` + +### Run + +I recommend using a ```docker-compose.yml``` file: + +```yaml +version: '2' + +services: + server: + build: . + ports: + - "5000:5000" + - "5222:5222" + - "5269:5269" + - "5281:5281" + environment: + DOMAIN: your.domain.com + volumes: + - ./privkey.pem:/usr/local/etc/prosody/certs/prosody.key + - ./fullchain.pem:/usr/local/etc/prosody/certs/prosody.crt + - ./data:/usr/local/var/lib/prosody + restart: unless-stopped +``` + + +Boot it via: ```docker-compose up -d``` + +Inspect logs: ```docker-compose logs -f``` + +### Extend + +There is a helper script that eases installing additional prosody modules: ```docker-prosody-module-install``` + +It downloads the current [prosody-modules](https://hg.prosody.im/prosody-modules/) repository. The specified modules are copied and its name is added to the ```modules_enabled``` variable within ```conf.d/01-modules.cfg.lua```. + +If you need additional configuration just overwrite the respective _cfg.lua_ file or add new ones. + +### Debugging + +Change to verbose logging by replacing the following config lines within ```prosody.cfg.lua```: + +```lua +log = { + {levels = {min = "info"}, to = "console"}; +}; +``` +with: + +```lua +log = { + {levels = {min = "debug"}, to = "console"}; +}; +``` + +## Missing + +* [Multi-User-Chats](https://prosody.im/doc/modules/mod_muc) (MUC) is not yet configured +* ?? \ No newline at end of file