30 Commits

Author SHA1 Message Date
7ca468a1ac Update CHANGELOG with new version number 2021-05-19 16:10:11 +01:00
26e1e6559a docs: Add upgrade guide 2021-05-19 16:02:39 +01:00
1bc336d933 Bump prosody-modules to 8e58a1b78336 2021-05-17 21:22:54 +01:00
a948cc141f Install latest prosody from deb, factor out variables 2021-05-17 21:22:01 +01:00
105c04a2c7 Add unreleased items to changelog 2021-05-17 18:27:24 +01:00
3cab4faaf9 prosody: Allow specifying additional config include path via environment 2021-03-17 15:22:30 +00:00
bd5329c84d prosody: Allow specification of external TURN via environment 2021-03-17 15:16:27 +00:00
088d9cb840 Add bootstrapped admin accounts to the default group/circle (thanks jonas!) 2021-03-16 14:00:10 +00:00
2bee41057b prosody: bump prosody-modules rev to latest (no particular reason) 2021-03-16 07:18:03 +00:00
173ca8b0c9 Add lua-unbound for more robust DNS resolution 2021-03-15 19:55:33 +00:00
7f26c50ba8 prosody: Add mod_http_host_status_check 2021-03-10 14:37:19 +00:00
32a7bc8954 mod_invites_bootstrap: Fix parameters to store:set() 2021-03-10 12:37:41 +00:00
e9e5762936 mod_invites_bootstrap: Reject old index values 2021-03-10 12:13:11 +00:00
90b13aed6e prosody: Fix another typo, sigh 2021-03-10 12:12:15 +00:00
b2431438b2 mod_invites_bootstrap: API and behaviour improvements 2021-03-10 11:49:18 +00:00
dcc02d374b prosody: Fix typo in module name 2021-03-10 10:32:06 +00:00
13228b1fc3 Some whitespace fixes 2021-03-09 16:33:22 +00:00
36ffd5d4a0 mod_invites_bootstrap: Module/API to create initial admin invite at startup 2021-03-09 16:33:12 +00:00
c4a8a88028 docker: Remove obsolete letsencrypt things (moved to cert-manager) 2021-03-09 15:28:09 +00:00
43c244d55d Merge pull request #34 from resoli/patch-2
Updated reverse_proxy.md Apace section.
2021-03-06 08:20:34 +00:00
19dc32e3e8 Update reverse_proxy.md 2021-03-06 09:12:31 +01:00
7b37c629dd Merge pull request #33 from resoli/patch-1
Add Apache configuration snippet
2021-03-01 21:21:53 +00:00
087b02ca5a Add Apache configuration snippet 2021-03-01 21:28:20 +01:00
724335019e prosody, coturn: Add environment variable to disable TURN server 2021-02-24 14:36:06 +00:00
3c3a74f1cc prosody: Bump prosody-modules to 6d595857164a 2021-02-23 21:00:18 +00:00
c6aa7a9732 prosody: Bump prosody-modules to 38bd4d557413 2021-02-23 16:45:36 +00:00
2ad719122d Add docker healthcheck for docker ps output
Mostly to improve the docker ui, ie it will say "unhealthy" if it takes
too long to start e.g. waiting for certs, or if Prosody crashes without
getting restarted.

Probes the http port on the assumption that this means Prosody is up and
running.

Signed-off-by: Matthew Wild <mwild1@gmail.com>
2021-02-23 15:27:12 +00:00
a9ee76b2f1 Bump prosody-modules to ea820de69265 2021-02-23 15:26:00 +00:00
e881c983a6 prosody: Bump to latest prosody-modules 2021-02-22 13:18:42 +00:00
0224f93843 prosody: Allow custom HTTP bind interface 2021-02-17 13:28:30 +00:00
11 changed files with 241 additions and 26 deletions

View File

@ -1,5 +1,14 @@
# Snikket Server changelog
## beta.20210519
- Allow custom HTTP bind interface
- Add docker health checks
- Fix warnings about obsolete letsencrypt user
- Add bootstrap API to create initiatal invite in an automated way
- Switch to libunbound for DNS resolution (more robust)
- Add environment variables to disable/replace the built-in TURN service
## beta.20210205
- Fix destruction of circle group chats when a circle

View File

@ -1,5 +1,10 @@
#!/bin/sh
if [ "$SNIKKET_TWEAK_TURNSERVER" = "0" ]; then
echo "TURN server disabled by environment, not launching.";
exit 0;
fi
CERTFILE="/snikket/letsencrypt/live/$SNIKKET_DOMAIN/fullchain.pem";
KEYFILE="/snikket/letsencrypt/live/$SNIKKET_DOMAIN/privkey.pem";
@ -11,7 +16,6 @@ done
TURN_EXTERNAL_IP="$(snikket-turn-addresses "$SNIKKET_DOMAIN")"
exec /usr/bin/turnserver -c /etc/turnserver.conf --prod \
--static-auth-secret="$(cat /snikket/prosody/turn-auth-secret-v2)" \
--cert="$CERTFILE" --pkey "$KEYFILE" -r "$SNIKKET_DOMAIN" \

View File

@ -61,6 +61,7 @@ modules_enabled = {
-- HTTP modules
"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
"websocket"; -- XMPP over WebSockets
"http_host_status_check"; -- Health checks over HTTP
-- Other specific functionality
"limits"; -- Enable bandwidth limiting for XMPP connections
@ -95,6 +96,7 @@ modules_enabled = {
"invites_register_api";
"invites_tracking";
"invites_default_group";
"invites_bootstrap";
"firewall";
@ -115,7 +117,7 @@ registration_notification = "New user registered: $username"
reload_global_modules = { "http" }
http_ports = { ENV_SNIKKET_TWEAK_INTERNAL_HTTP_PORT or 5280 }
http_interfaces = { "127.0.0.1" }
http_interfaces = { ENV_SNIKKET_TWEAK_INTERNAL_HTTP_INTERFACE or "127.0.0.1" }
https_ports = {};
@ -133,6 +135,9 @@ allow_contact_invites = false
invites_page = ENV_SNIKKET_INVITE_URL or ("https://"..DOMAIN.."/invite/{invite.token}/");
invites_page_external = true
invites_bootstrap_index = tonumber(ENV_TWEAK_SNIKKET_BOOTSTRAP_INDEX)
invites_bootstrap_secret = ENV_TWEAK_SNIKKET_BOOTSTRAP_SECRET
c2s_require_encryption = true
s2s_require_encryption = true
s2s_secure_auth = true
@ -175,8 +180,10 @@ http_host = DOMAIN
http_external_url = "https://"..DOMAIN.."/"
http_max_content_size = 1024 * 1024 * 16 -- 16MB
turncredentials_host = DOMAIN
turncredentials_secret = assert(io.open("/snikket/prosody/turn-auth-secret-v2")):read("*l");
if ENV_SNIKKET_TWEAK_TURNSERVER ~= "0" or ENV_SNIKKET_TWEAK_TURNSERVER_DOMAIN then
turncredentials_host = ENV_SNIKKET_TWEAK_TURNSERVER_DOMAIN or DOMAIN
turncredentials_secret = ENV_SNIKKET_TWEAK_TURNSERVER_SECRET or assert(io.open("/snikket/prosody/turn-auth-secret-v2")):read("*l");
end
VirtualHost (DOMAIN)
authentication = "internal_hashed"
@ -234,4 +241,4 @@ Component ("share."..DOMAIN) "http_upload"
http_upload_file_size_limit = 1024 * 1024 * 16 -- 16MB
http_upload_expire_after = 60 * 60 * 24 * RETENTION_DAYS -- N days
Include "/snikket/prosody/*.cfg.lua"
Include (ENV_SNIKKET_TWEAK_EXTRA_CONFIG or "/snikket/prosody/*.cfg.lua")

View File

@ -27,7 +27,8 @@ umask=002
[program:coturn]
command=start-coturn.sh
startsecs=0
autorestart=true
autorestart=unexpected
exitcodes=0
stopwaitsecs=30
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
@ -41,4 +42,3 @@ stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
redirect_stderr=true
umask=002

View File

@ -4,6 +4,12 @@
- hosts: all
become: yes
gather_facts: no
vars:
prosody:
package: "prosody-trunk"
build: "1436"
prosody_modules:
revision: "8e58a1b78336"
tasks:
- import_tasks: tasks/prosody.yml
- import_tasks: tasks/supervisor.yml

View File

@ -11,9 +11,12 @@
- name: "Add Prosody package repo"
apt_repository:
repo: "deb https://packages.prosody.im/debian buster main"
- name: "Detect dpkg architecture name"
shell: dpkg --print-architecture
register: dpkg_arch
- name: "Install Prosody package"
apt:
name: prosody-trunk
deb: "https://packages.prosody.im/debian/pool/main/p/{{ prosody.package }}/{{ prosody.package }}_1nightly{{ prosody.build }}-1~buster_{{ dpkg_arch.stdout }}.deb"
state: present
install_recommends: yes
- name: "Deploy Prosody config"
@ -64,10 +67,10 @@
hg:
repo: https://hg.prosody.im/prosody-modules
dest: /usr/local/lib/prosody-modules
revision: b3e0295e14a3
revision: "{{ prosody_modules.revision }}"
purge: yes
update: yes
- name: Enable wanted modules
- name: Enable wanted modules (prosody-modules)
file:
state: link
src: "/usr/local/lib/prosody-modules/{{item}}"
@ -112,8 +115,9 @@
- mod_groups_muc_bookmarks
- mod_muc_defaults
- mod_muc_local_only
- mod_http_host_status_check
- name: Enable wanted modules
- name: Enable wanted modules (snikket-modules)
file:
state: link
src: "/usr/local/lib/snikket-modules/{{item}}"
@ -122,9 +126,51 @@
- mod_update_check
- mod_update_notify
- mod_invites_default_group
- mod_invites_bootstrap
- name: "Install lua-ossl for encrypted push notifications"
apt:
name: lua-luaossl
state: present
install_recommends: no
- name: "Fetch luaunbound source"
get_url:
url: https://code.zash.se/dl/luaunbound/luaunbound-0.5.tar.gz
sha256sum: a6564ac1cca6bb350576eb2a5cfa03adb0aafd4f99d6cd491bd8028d046c62a7
dest: /tmp/luaunbound-0.5.tar.gz
- name: "Extract luaunbound"
unarchive:
src: /tmp/luaunbound-0.5.tar.gz
remote_src: yes
dest: /tmp
- name: "Install libunbound-dev"
apt:
name:
- libunbound8
- libunbound-dev
- liblua5.2-dev
state: present
- name: "Build luaunbound"
make:
chdir: /tmp/luaunbound-0.5
- name: "Install luaunbound"
make:
chdir: /tmp/luaunbound-0.5
target: install
- name: "Remove luaunbound source"
file:
path: /tmp/luaunbound-0.5
state: absent
- name: "Remove libunbound-dev"
apt:
name:
- libunbound-dev
- liblua5.2-dev
state: absent

View File

@ -14,6 +14,8 @@ ADD docker/entrypoint.sh /bin/entrypoint.sh
RUN chmod 770 /bin/entrypoint.sh
ENTRYPOINT ["/bin/entrypoint.sh"]
HEALTHCHECK CMD lua -l socket -e 'assert(socket.connect(os.getenv"SNIKKET_TWEAK_INTERNAL_HTTP_INTERFACE" or "127.0.0.1",os.getenv"SNIKKET_TWEAK_INTERNAL_HTTP_PORT" or "5280"))'
ADD ansible /opt/ansible
ADD snikket-modules /usr/local/lib/snikket-modules
@ -23,7 +25,7 @@ RUN apt-get update \
software-properties-common ca-certificates \
gpg gpg-agent \
ansible python-passlib python3-passlib \
libcap2-bin \
libcap2-bin build-essential\
&& rm -rf /var/lib/apt/lists/* \
&& c_rehash \
&& ansible-playbook -c local -i localhost, --extra-vars "ansible_python_interpreter=/usr/bin/python2" /opt/ansible/snikket.yml \
@ -32,7 +34,7 @@ RUN apt-get update \
software-properties-common \
gpg gpg-agent \
python-passlib python3-passlib \
mercurial libcap2-bin \
mercurial libcap2-bin build-essential \
&& apt-get autoremove -y \
&& rm -rf /var/cache/*

View File

@ -30,9 +30,6 @@ PGID=${PGID:=$(stat -c %g /snikket)}
if [ "$PUID" != 0 ] && [ "$PGID" != 0 ]; then
usermod -o -u "$PUID" prosody
groupmod -o -g "$PGID" prosody
usermod -o -u "$PUID" letsencrypt
groupmod -o -g "$PGID" letsencrypt
fi
if ! test -d /snikket/prosody; then
@ -41,16 +38,6 @@ fi
chown -R prosody:prosody /var/spool/anacron /var/run/prosody /snikket/prosody /etc/prosody
if ! test -d /snikket/letsencrypt; then
install -o letsencrypt -g letsencrypt -m 750 -d /snikket/letsencrypt;
fi
install -o letsencrypt -g letsencrypt -m 750 -d /var/lib/letsencrypt;
install -o letsencrypt -g letsencrypt -m 750 -d /var/log/letsencrypt;
install -o letsencrypt -g letsencrypt -m 755 -d /var/www/.well-known/acme-challenge;
chown -R letsencrypt:letsencrypt /snikket/letsencrypt
## Generate secret for coturn auth if necessary
if ! test -f /snikket/prosody/turn-auth-secret-v2; then
head -c 32 /dev/urandom | base64 > /snikket/prosody/turn-auth-secret-v2;

View File

@ -109,3 +109,65 @@ protocols:
);
```
### apache
**Note**: The following configuration is for reverse proxying from another machine
(other from the one hosting Snikket containers). A prerequisite is a mechanism to sync
Snikket-managed letsencrypt TLS key and cert to `/opt/chat/letsencrypt`. This is required because
Apache 2.4 is not able to revproxying based on SNI, routing encrypted TLS directly to the Snikket machine.
If the containers are on the same machine
of the reverse proxy, you have to tweak HTTP/S ports as indicated before, and you don't need
to proxy over SSL.
```
<VirtualHost *:443>
ServerName chat.example.com
ServerAlias groups.chat.example.com
ServerAlias share.chat.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/chat
ErrorLog ${APACHE_LOG_DIR}/chat.example.com-ssl_error.log
CustomLog ${APACHE_LOG_DIR}/chat.example.com-ssl_access.log combined
SSLEngine on
#
SSLCertificateFile /opt/chat/letsencrypt/chat.example.com/cert.pem
SSLCertificateKeyFile /opt/chat/letsencrypt/chat.example.com/privkey.pem
SSLCertificateChainFile /opt/chat/letsencrypt/chat.example.com/chain.pem
SSLProxyEngine On
ProxyPreserveHost On
ProxyPass / https://chat.example.com/
ProxyPassReverse / https://chat.example.com/
</VirtualHost>
<VirtualHost *:80>
ServerName chat.example.com
ServerAlias groups.chat.example.com
ServerAlias share.chat.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/chat
ProxyPreserveHost On
ProxyPass / http://chat.example.com/
ProxyPassReverse / http://chat.example.com/
ErrorLog ${APACHE_LOG_DIR}/chat.example.com_error.log
CustomLog ${APACHE_LOG_DIR}/chat.example.com_access.log combined
</VirtualHost>
```

26
docs/setup/upgrading.md Normal file
View File

@ -0,0 +1,26 @@
---
title: "Upgrading your Snikket server"
date: 2021-05-19T14:32:02Z
---
Upgrading to a new Snikket release is typically very easy.
## snikket-selfhosted
If you installed Snikket using the [snikket-selfhosted][] scripts, simply run:
cd /opt/snikket
git pull
./scripts/update.sh
## Snikket quickstart
If you're using a version installed from the [original quickstart][] guide on
the website, use these commands instead:
cd /etc/snikket
docker-compose pull
docker-compose up -d
[snikket-selfhosted]: https://github.com/snikket-im/snikket-selfhosted
[original quickstart]: https://snikket.org/service/quickstart/

View File

@ -0,0 +1,66 @@
--luacheck: ignore 143/module
local http_formdecode = require "net.http".formdecode;
local secret = module:get_option_string("invites_bootstrap_secret");
if not secret then return; end
local invites_bootstrap_store = module:open_store("invites_bootstrap");
-- This should be a non-negative integer higher than any set for the
-- previous bootstrap event (if any)
local current_index = module:get_option_number("invites_bootstrap_index");
local invites = module:depends("invites");
module:depends("http");
local function handle_request(event)
local query_params = http_formdecode(event.request.url.query);
if not query_params.token or query_params.token ~= secret then
return 403;
end
local bootstrap_records = invites_bootstrap_store:get() or {};
if #bootstrap_records > 0 then
local last_bootstrap = bootstrap_records[#bootstrap_records];
if current_index == last_bootstrap.index then
event.response.headers.Location = last_bootstrap.result;
return 303;
elseif current_index < last_bootstrap.index then
return 410;
end
end
-- Create invite
local invite, invite_err = invites.create_account(nil, {
roles = { ["prosody:admin"] = true };
groups = { "default" };
source = "api/token/bootstrap-"..current_index;
});
if not invite then
module:log("error", "Failed to create bootstrap invite! %s", invite_err);
return 500;
end
-- Record this bootstrap event (to prevent replay)
table.insert(bootstrap_records, {
index = current_index;
timestamp = os.time();
result = invite.landing_page or invite.uri;
});
local record_ok, record_err = invites_bootstrap_store:set(nil, bootstrap_records);
if not record_ok then
module:log("error", "Failed to store bootstrap record: %s", record_err);
return 500;
end
event.response.headers.Location = invite.landing_page or invite.uri;
return 303;
end
module:provides("http", {
route = {
GET = handle_request;
};
});