Compare commits

...

33 Commits

Author SHA1 Message Date
Matthew Wild d1cdca0c2c docs: Update certificate troubleshooting docs with more info 2021-11-25 15:00:41 +00:00
Matthew Wild e5d493483e prosody: Bump prosody-modules for bugfix in 4abb33a15897 2021-11-19 17:02:09 +00:00
Matthew Wild fbc5a46c43 prosody: Bump prosody-modules for bugfix in fd90925dc239 2021-11-18 09:09:05 +00:00
Matthew Wild 8c506217d5
Merge pull request #84 from snikket-im/docs/add-user-roles-page
docs: Add page about user roles
2021-11-17 15:49:35 +00:00
Matthew Wild 861c570b37
Merge pull request #85 from snikket-im/feature/measure-active-users
Feature: measure active users
2021-11-17 15:49:23 +00:00
Matthew Wild ad694d6436 prosody: Enable mod_measure_active_users
This allows an operator (via Prometheus, or eventually the web portal) to keep
tabs on how many people are using the server, e.g. to assist with capacity
planning. This will become more important once we allow user-to-user account
invitations.
2021-11-17 13:51:05 +00:00
Matthew Wild 569fce239c prosody: Switch to and enable mod_lastlog2
This records a timestamp of various account events - account registration
time, last connection and last disconnection.

In the future I would like to keep a time-limited record of account activity
so we can also present it to the user for security purposes (e.g. detecting
account compromise and access by third-parties). That will need additional
design work to figure out how to do it in a privacy-preserving way.
2021-11-17 13:47:42 +00:00
Matthew Wild 6ab178385f
Merge pull request #83 from snikket-im/auto-enable-group-push
prosody: Enable push notifications for offline group members by default
2021-11-16 19:21:20 +00:00
Matthew Wild cd462a28a7 docs: Add page about user roles 2021-11-16 17:11:36 +00:00
Matthew Wild 17444cc3bd prosody: Enable push notifications for offline group members by default
This avoids the app needing to gain logic to opt-in to push notifications.
Such logic may be fragile, and introduce additional traffic and round-trips
that would hurt performance.

Note that this will trigger pushes even to users who only use Android or
non-mobile devices. That should cause no issues, and the impact would be
minor. Also considering that non-iOS devices usually remain online most of the
time anyway.

Not accounted for in this commit is the MUC notification filtering side of
things. By default the MUC will push all messages, and
mod_cloud_notify(_filters) will allow all of them through to the device unless
the user explicitly configures otherwise within the app.

If the server can detect whether a MUC is public or private, it can make the
default behaviour more sensible (maybe when adding bookmarks or something?).
In any case, public channels are not a primary use-case for Snikket and can
easily be configured manually in the app for now.
2021-11-16 16:08:16 +00:00
Matthew Wild a24eddab8b prosody: Add symlink for mod_muc_offline_delivery 2021-11-15 14:15:56 +00:00
Matthew Wild 77ecd4d9b9
Merge pull request #77 from snikket-im/fix/restricted-users
Fix restricted users
2021-11-12 21:46:00 +00:00
Matthew Wild fb518da3c8
Merge branch 'master' into fix/restricted-users 2021-11-12 21:45:38 +00:00
Matthew Wild b2b1ea3660
Merge pull request #76 from snikket-im/feature/admin-shell-prompt
prosody: Show Snikket domain in admin shell prompt
2021-11-12 16:02:51 +00:00
Matthew Wild a2714fc178 prosody: Bump to build 1540 for role improvements
This change will disconnect user sessions when their role changes, ensuring
appropriate policies are always enforced.
2021-11-12 15:58:34 +00:00
Matthew Wild ce14c8153b prosody: Load mod_snikket_restricted_users on main host 2021-11-12 15:56:52 +00:00
Matthew Wild 08080f03b9 prosody: Show Snikket domain in admin shell prompt 2021-11-12 13:43:50 +00:00
Matthew Wild 2d623e7bf5
Merge pull request #75 from snikket-im/fix/tweak-gc-defaults
prosody: Tune GC to be more aggressive by default
2021-11-11 14:57:53 +00:00
Matthew Wild e19b0a32af prosody: Tune GC to be more aggressive by default
It appears that, in some environments at least, large file uploads can still
cause a significant increase in RAM. This reduces that effect.

It is expected that a future release will switch to Lua 5.4, which has shown
to have far better GC behaviour.
2021-11-11 14:40:09 +00:00
Matthew Wild b57057f809
Merge pull request #74 from snikket-im/fix/no-roles-no-isolation
mod_snikket_restricted_users: Don't isolate users with no roles
2021-11-10 17:51:14 +00:00
Matthew Wild 457096a13d mod_snikket_restricted_users: Don't isolate users with no roles
The code was originally written to fail safe in the event of failure, hence
the 'if roles and ...'. However a user with no roles (which is normal for a
normal user, especially on upgrade) can return nil.

Failure is signified by 'false', so now we explicitly catch this and return
early without bypassing isolation. Users with no roles (nil) or with roles
but not prosody:restricted bypass isolation.
2021-11-10 17:27:09 +00:00
Matthew Wild f85250461c CHANGELOG: Add unreleased changes 2021-11-10 14:41:44 +00:00
Matthew Wild 631c3acc99
Merge pull request #72 from snikket-im/restricted-users
Restrictions for restricted users
2021-11-09 16:21:39 +00:00
Matthew Wild 8d16897cff
Merge pull request #73 from snikket-im/fix-uploads-allow-for-gcm-tag
prosody: Add 16 bytes to upload limit to allow for appended GCM tag
2021-11-09 16:17:50 +00:00
Matthew Wild ca242ce8a4 prosody: Add 16 bytes to upload limit to allow for appended GCM tag (XEP-0454) 2021-11-09 14:25:56 +00:00
Matthew Wild a5084a289e mod_snikket_restricted_users: Add some explanatory comments 2021-11-09 12:28:50 +00:00
Matthew Wild 40daaa883b prosody: Disable user invitations for restricted users
Note that this currently has no effect, because user and contact invitations
are disabled globally for non-admins.
2021-11-09 12:01:59 +00:00
Matthew Wild 263d5cf286 prosody: Bump to trunk build 1535 + prosody-modules 8bd36bba2292 2021-11-09 11:51:16 +00:00
Matthew Wild d47a6ddbc0 mod_snikket_restricted_users: Use event.actor, which is preferred and always present 2021-11-09 11:23:49 +00:00
Matthew Wild 2f997d50b5 prosody: Enable mod_snikket_restricted_users on MUC host to enforce channel creation 2021-11-09 11:23:19 +00:00
Matthew Wild 0294b0e7e0 prosody: Prevent restricted users from creating public channels (#37) 2021-11-08 16:13:07 +00:00
Matthew Wild 5dddfeb876 prosody: Prevent federation for users with prosody:restricted role (#37) 2021-11-08 12:51:14 +00:00
Matthew Wild 00ad72bcf1 prosody: add symlink for mod_cloud_notify_extensions 2021-11-02 12:52:51 +00:00
7 changed files with 190 additions and 7 deletions

View File

@ -1,5 +1,21 @@
# Snikket Server changelog
## UNRELEASED
- Increase shared file size limit from 16MB to 100MB
- Allow configurable storage quota for shared files
- Initial support for "limited" user accounts
- Support for group chat notifications on iOS
- Configurable port range for TURN service
- Ability to see basic server metrics in the web admin interface
- Support for advanced monitoring/alerting via Prometheus
### Upgrading
If you are using a reverse proxy in front of Snikket, ensure it can
handle the new upload limit (for example, in nginx the `client_max_body_size`
option).
## beta.20210519
- Allow custom HTTP bind interface

View File

@ -29,6 +29,13 @@ data_path = "/snikket/prosody"
pidfile = "/var/run/prosody/prosody.pid"
admin_shell_prompt = ("prosody [%s]> "):format(DOMAIN)
-- Aggressive GC to reduce resource consumption. These values are not
-- incredibly scientific, but should be good for a small private server.
-- They should be reviewed on the upgrade to Lua 5.4.
gc = { threshold = 100, speed = 750 }
modules_enabled = {
-- Generally required
@ -75,8 +82,11 @@ modules_enabled = {
"update_notify";
"turncredentials";
"admin_shell";
"isolate_host";
"snikket_client_id";
"snikket_ios_preserve_push";
"snikket_restricted_users";
"lastlog2";
-- Spam/abuse management
"spam_reporting"; -- Allow users to report spam/abuse
@ -117,6 +127,7 @@ modules_enabled = {
-- Monitoring & maintenance
"measure_process";
"measure_active_users";
}
registration_watchers = {} -- Disable by default
@ -140,6 +151,9 @@ registration_invite_only = true
-- over what happens when a user invites someone.
allow_contact_invites = false
-- Disallow restricted users to create invitations to the server
deny_user_invites_by_roles = { "prosody:restricted" }
invites_page = ENV_SNIKKET_INVITE_URL or ("https://"..DOMAIN.."/invite/{invite.token}/");
invites_page_external = true
@ -203,6 +217,9 @@ if ENV_SNIKKET_TWEAK_TURNSERVER ~= "0" or ENV_SNIKKET_TWEAK_TURNSERVER_DOMAIN th
turncredentials_secret = ENV_SNIKKET_TWEAK_TURNSERVER_SECRET or assert(io.open("/snikket/prosody/turn-auth-secret-v2")):read("*l");
end
-- Allow restricted users access to push notification servers
isolate_except_domains = { "push.snikket.net", "push-ios.snikket.net" }
VirtualHost (DOMAIN)
authentication = "internal_hashed"
@ -234,11 +251,20 @@ Component ("groups."..DOMAIN) "muc"
"vcard_muc";
"muc_defaults";
"muc_offline_delivery";
"snikket_restricted_users";
"muc_auto_reserve_nicks";
}
restrict_room_creation = "local"
muc_local_only = { "general@groups."..DOMAIN }
muc_room_default_persistent = true
-- Default configuration for rooms (typically overwritten by the client)
muc_room_default_allow_member_invites = true
muc_room_default_persistent = true
muc_room_default_public = false
-- Enable push notifications for offline group members by default
-- (this also requires mod_muc_auto_reserve_nicks in practice)
muc_offline_delivery_default = true
default_mucs = {
{
@ -263,8 +289,13 @@ Component ("share."..DOMAIN) "http_file_share"
http_host = "share."..DOMAIN
http_external_url = "https://share."..DOMAIN.."/"
end
http_file_share_size_limit = 1024 * 1024 * 100 -- 100MB
-- 128 bits (i.e. 16 bytes) is the maximum length of a GCM auth tag, which
-- is appended to encrypted uploads according to XEP-0454. This ensures we
-- allow files up to the size limit even if they are encrypted.
http_file_share_size_limit = (1024 * 1024 * 100) + 16 -- 100MB + 16 bytes
http_file_share_expire_after = 60 * 60 * 24 * RETENTION_DAYS -- N days
if UPLOAD_STORAGE_GB then
http_file_share_global_quota = 1024 * 1024 * 1024 * UPLOAD_STORAGE_GB
end

View File

@ -7,9 +7,9 @@
vars:
prosody:
package: "prosody-trunk"
build: "1521"
build: "1544"
prosody_modules:
revision: "8b3e91249cff"
revision: "4abb33a15897"
tasks:
- import_tasks: tasks/prosody.yml
- import_tasks: tasks/supervisor.yml

View File

@ -79,6 +79,7 @@
loop:
- mod_smacks
- mod_cloud_notify
- mod_cloud_notify_extensions
- mod_cloud_notify_encrypted
- mod_cloud_notify_priority_tag
- mod_cloud_notify_filters
@ -86,7 +87,7 @@
- mod_compact_resource
- mod_conversejs
- mod_migrate_http_upload
- mod_lastlog
- mod_lastlog2
- mod_limit_auth
- mod_password_policy
- mod_roster_allinall
@ -116,11 +117,15 @@
- mod_groups_muc_bookmarks
- mod_muc_defaults
- mod_muc_local_only
- mod_muc_offline_delivery
- mod_http_host_status_check
- mod_measure_process
- mod_prometheus
- mod_spam_reporting
- mod_watch_spam_reports
- mod_isolate_host
- mod_muc_auto_reserve_nicks
- mod_measure_active_users
- name: Enable wanted modules (snikket-modules)
file:
@ -134,6 +139,7 @@
- mod_invites_bootstrap
- mod_snikket_client_id
- mod_snikket_ios_preserve_push
- mod_snikket_restricted_users
- name: "Install lua-ossl for encrypted push notifications"
apt:

View File

@ -0,0 +1,53 @@
---
title: User roles
---
# User roles
Snikket allows you to select a role for users, each role granting different
permissions.
Each user may have one of three roles:
## Administrator
This is the default role of the first user (if you're reading this, that's
probably you!).
Administrators have full control over the server, settings, users and circles.
These features can be accessed primarily through the admin panel in the
Snikket web interface.
## Normal
This is the default role for most users. It gives access to all
non-administrative server functionality.
## Limited
Limited users have various restrictions. The purpose of this role is to
allow granting someone an account on the server, only for the purposes of
communicating with other people on that server. This can be useful to provide
a guest or child account, for example.
In particular, limited users are not allowed to:
- Communicate with users on other servers
- Join group chats on other servers
- Create public channels (including on the current server)
- Invite new users to the server (regardless of whether this is enabled for
normal users).
### Caveats
The current support for limited users has some known issues. It is designed to
prevent casual misuse of the server, but it is not intended to be a foolproof
security measure. For example, limited users are still able to *receive*
messages and contact requests from other servers, even though they cannot send
them to other servers. It is expected that we will restrict incoming traffic
for limited users in a future release, after further testing.
Also note that limited accounts may have issues using non-Snikket mobile apps
that use push notifications, depending on the design of the app. This is
because the restrictions may prevent the app communicating with its'
developer's push notification services over XMPP.

View File

@ -110,16 +110,38 @@ for more information on correctly configuring reverse proxies.
### Certificate debugging commands
If everything looks okay and you're not sure what the problem could be,
you can get the error message from the debug log:
#### Checking for errors
If you think you have everything set up correctly and you're not sure what the
problem could be, check the error log:
```
docker-compose exec snikket_certs cat /var/log/letsencrypt/errors.log
```
If you get a "No such file or directory" error when running the above command,
inspect the debug log instead:
```
docker-compose exec snikket_certs cat /var/log/letsencrypt/letsencrypt.log | grep detail
```
#### Trying again
Once you have fixed any problems, you can force a new attempt with the
following command:
```
docker-compose exec snikket_certs /etc/cron.daily/certbot
```
If that command says that no certificates are due for renewal, but you need to
trigger a renewal anyway, run:
```
docker-compose exec snikket_certs su letsencrypt -- -c "certbot renew --config-dir /snikket/letsencrypt --cert-path /etc/ssl/certbot --force-renew"
```
Note that Let's Encrypt has strict [rate limits](https://letsencrypt.org/docs/rate-limits/) -
do not run these commands more often than necessary, or you may find yourself
unable to get new certificates for a while.

View File

@ -0,0 +1,55 @@
local jid_bare = require "util.jid".bare;
local um_get_roles = require "core.usermanager".get_roles;
local function load_main_host(module)
-- Check whether a user should be isolated from remote JIDs
-- If not, set a session flag that allows them to bypass mod_isolate_host
local function check_user_isolated(event)
local session = event.session;
if not session.no_host_isolation then
local bare_jid = jid_bare(session.full_jid);
local roles = um_get_roles(bare_jid, module.host);
if roles == false then return; end
if not roles or not roles["prosody:restricted"] then
-- Bypass isolation for all unrestricted users
session.no_host_isolation = true;
end
end
end
-- Add low-priority hook to run after the check_user_isolated default
-- behaviour in mod_isolate_host
module:hook("resource-bind", check_user_isolated, -0.5);
end
local function load_groups_host(module)
local primary_host = module.host:gsub("^%a+%.", "");
local function is_restricted(user_jid)
local roles = um_get_roles(user_jid, primary_host);
return not roles or roles["prosody:restricted"];
end
module:hook("muc-config-submitted/muc#roomconfig_publicroom", function (event)
if not is_restricted(event.actor) then return; end
-- Don't allow modification of this value by restricted users
return true;
end, 5);
module:hook("muc-config-form", function (event)
if not is_restricted(event.actor) then return; end -- Don't restrict admins
-- Hide the option from the config form for restricted users
local form = event.form;
for i = #form, 1, -1 do
if form[i].name == "muc#roomconfig_publicroom" then
table.remove(form, i);
end
end
end);
end
if module:get_host_type() == "component" and module:get_option_string("component_module") == "muc" then
load_groups_host(module);
else
load_main_host(module);
end