Compare commits

...

3 Commits

Author SHA1 Message Date
Avently 16edc24c16 android, desktop: testing grouping of chat items 2024-10-14 19:50:41 +07:00
Evgeny Poberezkin 1cb3c25478 docs: correction 2024-10-13 22:01:14 +01:00
sh 13912a4af9 docs/smp-server: update to latest changes (#4960)
* docs/smp-server: update to latest changes

* update

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2024-10-13 09:43:47 +01:00
4 changed files with 504 additions and 97 deletions
@@ -0,0 +1,60 @@
package chat.simplex.common.views.chat
import androidx.compose.runtime.snapshots.SnapshotStateList
import chat.simplex.common.model.*
data class SectionItems (
val mergeCategory: CIMergeCategory?,
val items: SnapshotStateList<ChatItem>,
val revealed: Boolean,
val showAvatar: MutableSet<Long>,
)
fun List<ChatItem>.putIntoGroups(revealedItems: Set<Long>): List<SectionItems> {
println("LALAL LENGTH ${size}")
val start = System.currentTimeMillis()
val groups = ArrayList<SectionItems>()
var recent: SectionItems = if (isNotEmpty()) {
val first = this[0]
SectionItems(
mergeCategory = first.mergeCategory,
items = SnapshotStateList<ChatItem>().also { it.add(first) },
revealed = first.mergeCategory == null || revealedItems.contains(first.id),
showAvatar = mutableSetOf<Long>().also { if (first.chatDir is CIDirection.GroupRcv) it.add(first.id) })
} else {
return emptyList()
}
groups.add(recent)
var prev = this[0]
var index = 0
while (index < size) {
if (index == 0) {
index++
continue
}
val item = this[index]
val category = item.mergeCategory
if (recent.mergeCategory == category) {
recent.items.add(item)
if (item.chatDir is CIDirection.GroupRcv && prev.chatDir is CIDirection.GroupRcv && item.chatDir.groupMember == (prev.chatDir as CIDirection.GroupRcv).groupMember) {
recent.showAvatar.add(item.id)
}
} else {
recent = SectionItems(
mergeCategory = item.mergeCategory,
items = SnapshotStateList<ChatItem>().also { it.add(item) },
revealed = item.mergeCategory == null || revealedItems.contains(item.id),
showAvatar = mutableSetOf<Long>().also {
if (item.chatDir is CIDirection.GroupRcv && (prev.chatDir !is CIDirection.GroupRcv || (prev.chatDir as CIDirection.GroupRcv).groupMember != item.chatDir.groupMember)) {
it.add(item.id)
}
}
)
groups.add(recent)
}
prev = item
index++
}
println("LALAL RES ${System.currentTimeMillis() - start}, groups: ${groups.size}")
return groups
}
@@ -11,6 +11,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.snapshots.AutoboxingStateValueProperty
import androidx.compose.ui.*
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawWithCache
@@ -988,6 +989,8 @@ fun BoxWithConstraintsScope.ChatItemsList(
Spacer(Modifier.size(8.dp))
val reversedChatItems by remember { derivedStateOf { chatModel.chatItems.asReversed() } }
val revealedItems = rememberSaveable { mutableStateOf(setOf<Long>()) }
val groups by remember { derivedStateOf { (reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems + reversedChatItems).putIntoGroups(revealedItems.value) } }
val maxHeightRounded = with(LocalDensity.current) { maxHeight.roundToPx() }
val scrollToItem: (Long) -> Unit = { itemId: Long ->
val index = reversedChatItems.indexOfFirst { it.id == itemId }
@@ -1011,8 +1014,8 @@ fun BoxWithConstraintsScope.ChatItemsList(
VideoPlayerHolder.releaseAll()
}
)
LazyColumnWithScrollBar(Modifier.align(Alignment.BottomCenter), state = listState, reverseLayout = true) {
itemsIndexed(reversedChatItems, key = { _, item -> item.id to item.meta.createdAt.toEpochMilliseconds() }) { i, cItem ->
@Composable
fun ChatViewListItem(i: Int, showAvatar: Boolean, cItem: ChatItem) {
CompositionLocalProvider(
// Makes horizontal and vertical scrolling to coexist nicely.
// With default touchSlop when you scroll LazyColumn, you can unintentionally open reply view
@@ -1104,7 +1107,7 @@ fun BoxWithConstraintsScope.ChatItemsList(
} else {
null to 1
}
if (prevItem == null || showMemberImage(member, prevItem) || prevMember != null) {
if (showMemberImage(member, prevItem) || showAvatar) {
Column(
Modifier
.padding(top = 8.dp)
@@ -1225,37 +1228,6 @@ fun BoxWithConstraintsScope.ChatItemsList(
}
}
}
val (currIndex, nextItem) = chatModel.getNextChatItem(cItem)
val ciCategory = cItem.mergeCategory
if (ciCategory != null && ciCategory == nextItem?.mergeCategory) {
// memberConnected events and deleted items are aggregated at the last chat item in a row, see ChatItemView
} else {
val (prevHidden, prevItem) = chatModel.getPrevShownChatItem(currIndex, ciCategory)
val itemSeparation = getItemSeparation(cItem, nextItem)
val previousItemSeparation = if (prevItem != null) getItemSeparation(prevItem, cItem) else null
if (itemSeparation.date != null) {
DateSeparator(itemSeparation.date)
}
val range = chatViewItemsRange(currIndex, prevHidden)
if (revealed.value && range != null) {
reversedChatItems.subList(range.first, range.last + 1).forEachIndexed { index, ci ->
val prev = if (index + range.first == prevHidden) prevItem else reversedChatItems[index + range.first + 1]
ChatItemView(ci, null, prev, itemSeparation, previousItemSeparation)
}
} else {
ChatItemView(cItem, range, prevItem, itemSeparation, previousItemSeparation)
}
if (i == reversedChatItems.lastIndex) {
DateSeparator(cItem.meta.itemTs)
}
}
if (cItem.isRcvNew && chatInfo.id == ChatModel.chatId.value) {
LaunchedEffect(cItem.id) {
scope.launch {
@@ -1264,6 +1236,29 @@ fun BoxWithConstraintsScope.ChatItemsList(
}
}
}
val itemSeparation = getItemSeparation(cItem, null)
ChatItemView(cItem, null, null, itemSeparation, null)
}
}
LazyColumnWithScrollBar(Modifier.align(Alignment.BottomCenter), state = listState, reverseLayout = true) {
for (group in groups) {
if (group.revealed) {
itemsIndexed(group.items, key = { _, item -> (item.id to item.meta.createdAt.toEpochMilliseconds()).toString() }) { i, cItem ->
// index here is just temporary, should be removed at all or put in the section items
ChatViewListItem(reversedChatItems.indexOf(cItem), showAvatar = group.showAvatar.contains(cItem.id), cItem)
}
} else {
val item = group.items.last()
item(key = { (item.id to item.meta.createdAt.toEpochMilliseconds()).toString() }) {
// here you make one collapsed item from multiple items (should be already in section items)
ChatViewListItem(reversedChatItems.indexOf(item), showAvatar = group.showAvatar.contains(item.id), item)
}
}
}
if (reversedChatItems.isNotEmpty()) {
item {
DateSeparator(reversedChatItems.last().meta.itemTs)
}
}
}
+414 -62
View File
@@ -1,13 +1,16 @@
---
title: Hosting your own SMP Server
revision: 03.06.2024
revision: 12.10.2024
---
| Updated 28.05.2024 | Languages: EN, [FR](/docs/lang/fr/SERVER.md), [CZ](/docs/lang/cs/SERVER.md), [PL](/docs/lang/pl/SERVER.md) |
# Hosting your own SMP Server
| Updated 12.10.2024 | Languages: EN, [FR](/docs/lang/fr/SERVER.md), [CZ](/docs/lang/cs/SERVER.md), [PL](/docs/lang/pl/SERVER.md) |
### Table of Contents
- [Hosting your own SMP server](#hosting-your-own-smp-server)
- [Quick start](#quick-start)
- [Detailed guide](#detailed-guide)
- [Overview](#overview)
- [Installation](#installation)
- [Configuration](#configuration)
@@ -29,17 +32,218 @@ revision: 03.06.2024
- [Updating your SMP server](#updating-your-smp-server)
- [Configuring the app to use the server](#configuring-the-app-to-use-the-server)
# Hosting your own SMP Server
## Quick start
## Overview
To create SMP server, you'll need:
- VPS or any other server.
- Your server domain, with A and AAAA records specifying server IPv4 and IPv6 addresses (`smp1.example.com`)
- A basic Linux knowledge.
*Please note*: while you can run an SMP server without a domain name, in the near future client applications will start using server domain name in the invitation links (instead of `simplex.chat` domain they use now). In case a server does not have domain name and server pages (see below), the clients will be generaing the links with `simplex:` scheme that cannot be opened in the browsers.
1. Install server with [Installation script](https://github.com/simplex-chat/simplexmq#using-installation-script).
2. Adjust firewall:
```sh
ufw allow 80/tcp &&\
ufw allow 443/tcp &&\
ufw allow 5223/tcp
```
3. Init server:
Replace `smp1.example.com` with your actual server domain.
```sh
su smp -c 'smp-server init --yes \
--store-log \
--no-password \
--control-port \
--socks-proxy \
--source-code \
--fqdn=smp1.example.com
```
4. Install tor:
```sh
CODENAME="$(lsb_release -c | awk '{print $2}')"
echo "deb [signed-by=/usr/share/keyrings/tor-archive-keyring.gpg] https://deb.torproject.org/torproject.org ${CODENAME} main
deb-src [signed-by=/usr/share/keyrings/tor-archive-keyring.gpg] https://deb.torproject.org/torproject.org ${CODENAME} main" > /etc/apt/sources.list.d/tor.list &&\
curl --proto '=https' --tlsv1.2 -sSf https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gpg --dearmor | tee /usr/share/keyrings/tor-archive-keyring.gpg >/dev/null &&\
apt update && apt install -y tor deb.torproject.org-keyring
```
5. Configure tor:
```sh
tor-instance-create tor2 &&\
mkdir /var/lib/tor/simplex-smp/ &&\
chown debian-tor:debian-tor /var/lib/tor/simplex-smp/ &&\
chmod 700 /var/lib/tor/simplex-smp/
```
```sh
vim /etc/tor/torrc
```
Paste the following:
```sh
# Enable log (otherwise, tor doesn't seem to deploy onion address)
Log notice file /var/log/tor/notices.log
# Enable single hop routing (2 options below are dependencies of the third) - It will reduce the latency at the cost of lower anonimity of the server - as SMP-server onion address is used in the clients together with public address, this is ok. If you deploy SMP-server with onion-only address, keep standard configuration.
SOCKSPort 0
HiddenServiceNonAnonymousMode 1
HiddenServiceSingleHopMode 1
# smp-server hidden service host directory and port mappings
HiddenServiceDir /var/lib/tor/simplex-smp/
HiddenServicePort 5223 localhost:5223
HiddenServicePort 443 localhost:443
```
```sh
vim /etc/tor/instances/tor2/torrc
```
Paste the following:
```sh
# Log tor to systemd daemon
Log notice syslog
# Listen to local 9050 port for socks proxy
SocksPort 9050
```
6. Start tor:
```sh
systemctl enable tor &&\
systemctl start tor &&\
systemctl restart tor &&\
systemctl enable --now tor@tor2
```
7. Install Caddy:
```sh
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl &&\
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg &&\
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list &&\
sudo apt update && sudo apt install caddy
```
8. Configure Caddy:
```sh
vim /etc/caddy/Caddyfile
```
Replace `smp1.example.com` with your actual server domain. Paste the following:
```
http://smp1.example.com {
redir https://smp1.example.com{uri} permanent
}
smp1.example.com:8443 {
tls {
key_type rsa4096
}
}
```
```sh
vim /usr/local/bin/simplex-servers-certs
```
Replace `smp1.example.com` with your actual server domain. Paste the following:
```sh
#!/usr/bin/env sh
set -eu
user='smp'
group="$user"
domain='smp1.example.com'
folder_in="/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/${domain}"
folder_out='/etc/opt/simplex'
key_name='web.key'
cert_name='web.crt'
# Copy certifiacte from Caddy directory to smp-server directory
cp "${folder_in}/${domain}.crt" "${folder_out}/${cert_name}"
# Assign correct permissions
chown "$user":"$group" "${folder_out}/${cert_name}"
# Copy certifiacte key from Caddy directory to smp-server directory
cp "${folder_in}/${domain}.key" "${folder_out}/${key_name}"
# Assign correct permissions
chown "$user":"$group" "${folder_out}/${key_name}"
```
```sh
chmod +x /usr/local/bin/simplex-servers-certs
```
```sh
sudo crontab -e
```
Paste the following:
```sh
# Every week on 00:20 sunday
20 0 * * 0 /usr/local/bin/simplex-servers-certs
```
9. Enable and start Caddy service:
Wait until "good to go" has been printed.
```sh
systemctl enable --now caddy &&\
sleep 10 &&\
/usr/local/bin/simplex-servers-certs &&\
echo 'good to go'
```
10. Enable and start smp-server:
```sh
systemctl enable --now smp-server.service
```
11. Print your address:
```sh
smp="$(journalctl --output cat -q _SYSTEMD_INVOCATION_ID="$(systemctl show -p InvocationID --value smp-server)" | grep -m1 'Server address:' | awk '{print $NF}' | sed 's/:443.*//')"
tor="$(cat /var/lib/tor/simplex-smp/hostname)"
echo "$smp,$tor"
```
## Detailed guide
### Overview
SMP server is the relay server used to pass messages in SimpleX network. SimpleX Chat apps have preset servers (for mobile apps these are smp11, smp12 and smp14.simplex.im), but you can easily change app configuration to use other servers.
SimpleX clients only determine which server is used to receive the messages, separately for each contact (or group connection with a group member), and these servers are only temporary, as the delivery address can change.
To create SMP server, you'll need:
1. VPS or any other server.
2. Your own domain, pointed at the server (`smp.example.com`)
3. A basic Linux knowledge.
_Please note_: when you change the servers in the app configuration, it only affects which servers will be used for the new contacts, the existing contacts will not automatically move to the new servers, but you can move them manually using ["Change receiving address"](../blog/20221108-simplex-chat-v4.2-security-audit-new-website.md#change-your-delivery-address-beta) button in contact/member information pages it will be automated in the future.
## Installation
### Installation
1. First, install `smp-server`:
@@ -82,8 +286,10 @@ Manual installation requires some preliminary actions:
```sh
# For Ubuntu
sudo ufw allow 5223/tcp
sudo ufw allow 443/tcp
sudo ufw allow 80/tcp
# For Fedora
sudo firewall-cmd --permanent --add-port=5223/tcp && \
sudo firewall-cmd --permanent --add-port=5223/tcp --add-port=443/tcp --add-port=80/tcp && \
sudo firewall-cmd --reload
```
@@ -102,6 +308,7 @@ Manual installation requires some preliminary actions:
LimitNOFILE=65535
KillSignal=SIGINT
TimeoutStopSec=infinity
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
@@ -109,7 +316,7 @@ Manual installation requires some preliminary actions:
And execute `sudo systemctl daemon-reload`.
## Configuration
### Configuration
To see which options are available, execute `smp-server` without flags:
@@ -129,7 +336,7 @@ You can get further help by executing `sudo su smp -c "smp-server <command> -h"`
After that, we need to configure `smp-server`:
### Interactively
#### Interactively
Execute the following command:
@@ -159,7 +366,7 @@ These statistics include daily counts of created, secured and deleted queues, se
Enter your domain or ip address that your smp-server is running on - it will be included in server certificates and also printed as part of server address.
### Via command line options
#### Via command line options
Execute the following command:
@@ -223,7 +430,7 @@ Server address: smp://d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=:V8ONoJ6ICwnrZ
The server address above should be used in your client configuration, and if you added server password it should only be shared with the other people who you want to allow using your server to receive the messages (all your contacts will be able to send messages - it does not require a password). If you passed IP address or hostnames during the initialisation, they will be printed as part of server address, otherwise replace `<hostnames>` with the actual server hostnames.
## Further configuration
### Further configuration
All generated configuration, along with a description for each parameter, is available inside configuration file in `/etc/opt/simplex/smp-server.ini` for further customization. Depending on the smp-server version, the configuration file looks something like this:
@@ -245,26 +452,26 @@ source_code: https://github.com/simplex-chat/simplexmq
# condition_amendments: link
# Server location and operator.
server_country: <YOUR_SERVER_LOCATION>
operator: <YOUR_NAME>
operator_country: <YOUR_LOCATION>
website: <WEBSITE_IF_AVAILABLE>
# server_country: ISO-3166 2-letter code
# operator: entity (organization or person name)
# operator_country: ISO-3166 2-letter code
# website:
# Administrative contacts.
#admin_simplex: SimpleX address
admin_email: <EMAIL>
# admin_simplex: SimpleX address
# admin_email:
# admin_pgp:
# admin_pgp_fingerprint:
# Contacts for complaints and feedback.
# complaints_simplex: SimpleX address
complaints_email: <COMPLAINTS_EMAIL>
# complaints_email:
# complaints_pgp:
# complaints_pgp_fingerprint:
# Hosting provider.
hosting: <HOSTING_PROVIDER_NAME>
hosting_country: <HOSTING_PROVIDER_LOCATION>
# hosting: entity (organization or person name)
# hosting_country: ISO-3166 2-letter code
[STORE_LOG]
# The server uses STM memory for persistence,
@@ -278,6 +485,7 @@ enable: on
# they are preserved in the .bak file until the next restart.
restore_messages: on
expire_messages_days: 21
expire_ntfs_hours: 24
# Log daily server statistics to CSV file
log_stats: on
@@ -294,11 +502,17 @@ new_queues: on
# with the users who you want to allow creating messaging queues on your server.
# create_password: password to create new queues (any printable ASCII characters without whitespace, '@', ':' and '/')
# control_port_admin_password:
# control_port_user_password:
[TRANSPORT]
# host is only used to print server address on start
host: <your server domain/ip>
port: 5223
# Host is only used to print server address on start.
# You can specify multiple server ports.
host: <domain/ip>
port: 5223,443
log_tls_errors: off
# Use `websockets: 443` to run websockets server in addition to plain TLS.
websockets: off
# control_port: 5224
@@ -310,7 +524,7 @@ websockets: off
# required_host_mode: off
# The domain suffixes of the relays you operate (space-separated) to count as separate proxy statistics.
# own_server_domains: <your domain suffixes>
# own_server_domains:
# SOCKS proxy port for forwarding messages to destination servers.
# You may need a separate instance of SOCKS proxy for incoming single-hop requests.
@@ -326,7 +540,7 @@ websockets: off
[INACTIVE_CLIENTS]
# TTL and interval to check inactive clients
disconnect: off
# ttl: 43200
# ttl: 21600
# check_interval: 3600
[WEB]
@@ -336,18 +550,18 @@ static_path: /var/opt/simplex/www
# Run an embedded server on this port
# Onion sites can use any port and register it in the hidden service config.
# Running on a port 80 may require setting process capabilities.
# http: 8000
#http: 8000
# You can run an embedded TLS web server too if you provide port and cert and key files.
# Not required for running relay on onion address.
# https: 443
# cert: /etc/opt/simplex/web.cert
# key: /etc/opt/simplex/web.key
https: 443
cert: /etc/opt/simplex/web.crt
key: /etc/opt/simplex/web.key
```
## Server security
### Server security
### Initialization
#### Initialization
Although it's convenient to initialize smp-server configuration directly on the server, operators **ARE ADVISED** to initialize smp-server fully offline to protect your SMP server CA private key.
@@ -367,7 +581,7 @@ Follow the steps to quickly initialize the server offline:
rsync -hzasP $HOME/simplex/smp/config/ <server_user>@<server_address>:/etc/opt/simplex/
```
### Private keys
#### Private keys
Connection to the smp server occurs via a TLS connection. During the TLS handshake, the client verifies smp-server CA and server certificates by comparing its fingerprint with the one included in server address. If server TLS credential is compromised, this key can be used to sign a new one, keeping the same server identity and established connections. In order to protect your smp-server from bad actors, operators **ARE ADVISED** to move CA private key to a safe place. That could be:
@@ -392,7 +606,7 @@ Follow the steps to secure your CA keys:
rm /etc/opt/simplex/ca.key
```
### Online certificate rotation
#### Online certificate rotation
Operators of smp servers **ARE ADVISED** to rotate online certificate regularly (e.g., every 3 months). In order to do this, follow the steps:
@@ -468,9 +682,9 @@ Operators of smp servers **ARE ADVISED** to rotate online certificate regularly
10. Done!
## Tor: installation and configuration
### Tor: installation and configuration
### Installation for onion address
#### Installation for onion address
SMP-server can also be deployed to be available via [Tor](https://www.torproject.org) network. Run the following commands as `root` user.
@@ -526,6 +740,7 @@ SMP-server can also be deployed to be available via [Tor](https://www.torproject
# smp-server hidden service host directory and port mappings
HiddenServiceDir /var/lib/tor/simplex-smp/
HiddenServicePort 5223 localhost:5223
HiddenServicePort 443 localhost:443
```
- Create directories:
@@ -550,7 +765,7 @@ SMP-server can also be deployed to be available via [Tor](https://www.torproject
cat /var/lib/tor/simplex-smp/hostname
```
### SOCKS port for SMP PROXY
#### SOCKS port for SMP PROXY
SMP-server versions starting from `v5.8.0-beta.0` can be configured to PROXY smp servers available exclusively through [Tor](https://www.torproject.org) network to be accessible to the clients that do not use Tor. Run the following commands as `root` user.
@@ -597,9 +812,11 @@ SMP-server versions starting from `v5.8.0-beta.0` can be configured to PROXY smp
...
```
## Server information page
### Server information page
SMP-server versions starting from `v5.8.0` can be configured to serve Web page with server information that can include admin info, server info, provider info, etc. Run the following commands as `root` user.
SMP server **SHOULD** be configured to serve Web page with server information that can include admin info, server info, provider info, etc. It will also serve connection links, generated using the mobile/desktop apps. Run the following commands as `root` user.
_Please note:_ this configuration is supported since `v6.1.0-beta.2`.
1. Add the following to your smp-server configuration (please modify fields in [INFORMATION] section to include relevant information):
@@ -608,8 +825,19 @@ SMP-server versions starting from `v5.8.0` can be configured to serve Web page w
```
```ini
[TRANSPORT]
# host is only used to print server address on start
host: <domain/ip>
port: 443,5223
websockets: off
log_tls_errors: off
control_port: 5224
[WEB]
https: 443
static_path: /var/opt/simplex/www
cert: /etc/opt/simplex/web.crt
key: /etc/opt/simplex/web.key
[INFORMATION]
# AGPLv3 license requires that you make any source code modifications
@@ -678,16 +906,23 @@ SMP-server versions starting from `v5.8.0` can be configured to serve Web page w
[Full Caddy instllation instructions](https://caddyserver.com/docs/install)
3. Replace Caddy configuration with the following (don't forget to replace `<YOUR_DOMAIN>`):
3. Replace Caddy configuration with the following:
Please replace `YOUR_DOMAIN` with your actual domain (smp.example.com).
```sh
vim /etc/caddy/Caddyfile
```
```caddy
<YOUR_DOMAIN> {
root * /var/opt/simplex/www
file_server
```
http://YOUR_DOMAIN {
redir https://YOUR_DOMAIN{uri} permanent
}
YOUR_DOMAIN:8443 {
tls {
key_type rsa4096
}
}
```
@@ -697,17 +932,75 @@ SMP-server versions starting from `v5.8.0` can be configured to serve Web page w
systemctl enable --now caddy
```
5. Upgrade your smp-server to latest version - [Updating your smp server](#updating-your-smp-server)
5. Create script to copy certificates to your smp directory:
6. Access the webpage you've deployed from your browser. You should see the smp-server information that you've provided in your ini file.
Please replace `YOUR_DOMAIN` with your actual domain (smp.example.com).
## Documentation
```sh
vim /usr/local/bin/simplex-servers-certs
```
```sh
#!/usr/bin/env sh
set -eu
user='smp'
group="$user"
domain='HOST'
folder_in="/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/${domain}"
folder_out='/etc/opt/simplex'
key_name='web.key'
cert_name='web.crt'
# Copy certifiacte from Caddy directory to smp-server directory
cp "${folder_in}/${domain}.crt" "${folder_out}/${cert_name}"
# Assign correct permissions
chown "$user":"$group" "${folder_out}/${cert_name}"
# Copy certifiacte key from Caddy directory to smp-server directory
cp "${folder_in}/${domain}.key" "${folder_out}/${key_name}"
# Assign correct permissions
chown "$user":"$group" "${folder_out}/${key_name}"
```
6. Make the script executable and execute it:
```sh
chmod +x /usr/local/bin/simplex-servers-certs && /usr/local/bin/simplex-servers-certs
```
7. Check if certificates were copied:
```sh
ls -haltr /etc/opt/simplex/web*
```
8. Create cronjob to copy certificates to smp directory in timely manner:
```sh
sudo crontab -e
```
```sh
# Every week on 00:20 sunday
20 0 * * 0 /usr/local/bin/simplex-servers-certs
```
9. Then:
- If you're running at least `v6.1.0-beta.2`, [restart the server](#systemd-commands).
- If you're running below `v6.1.0-beta.2`, [upgrade the server](#updating-your-smp-server).
10. Access the webpage you've deployed from your browser (`https://smp.example.org`). You should see the smp-server information that you've provided in your ini file.
### Documentation
All necessary files for `smp-server` are located in `/etc/opt/simplex/` folder.
Stored messages, connections, statistics and server log are located in `/var/opt/simplex/` folder.
### SMP server address
#### SMP server address
SMP server address has the following format:
@@ -727,7 +1020,7 @@ smp://<fingerprint>[:<password>]@<public_hostname>[,<onion_hostname>]
Your configured hostname(s) of `smp-server`. You can check your configured hosts in `/etc/opt/simplex/smp-server.ini`, under `[TRANSPORT]` section in `host:` field.
### Systemd commands
#### Systemd commands
To start `smp-server` on host boot, run:
@@ -786,16 +1079,18 @@ Nov 23 19:23:21 5588ab759e80 smp-server[30878]: not expiring inactive clients
Nov 23 19:23:21 5588ab759e80 smp-server[30878]: creating new queues requires password
```
### Monitoring
#### Monitoring
You can enable `smp-server` statistics for `Grafana` dashboard by setting value `on` in `/etc/opt/simplex/smp-server.ini`, under `[STORE_LOG]` section in `log_stats:` field.
Logs will be stored as `csv` file in `/var/opt/simplex/smp-server-stats.daily.log`. Fields for the `csv` file are:
```sh
fromTime,qCreated,qSecured,qDeleted,msgSent,msgRecv,dayMsgQueues,weekMsgQueues,monthMsgQueues,msgSentNtf,msgRecvNtf,dayCountNtf,weekCountNtf,monthCountNtf,qCount,msgCount,msgExpired,qDeletedNew,qDeletedSecured,pRelays_pRequests,pRelays_pSuccesses,pRelays_pErrorsConnect,pRelays_pErrorsCompat,pRelays_pErrorsOther,pRelaysOwn_pRequests,pRelaysOwn_pSuccesses,pRelaysOwn_pErrorsConnect,pRelaysOwn_pErrorsCompat,pRelaysOwn_pErrorsOther,pMsgFwds_pRequests,pMsgFwds_pSuccesses,pMsgFwds_pErrorsConnect,pMsgFwds_pErrorsCompat,pMsgFwds_pErrorsOther,pMsgFwdsOwn_pRequests,pMsgFwdsOwn_pSuccesses,pMsgFwdsOwn_pErrorsConnect,pMsgFwdsOwn_pErrorsCompat,pMsgFwdsOwn_pErrorsOther,pMsgFwdsRecv,qSub,qSubAuth,qSubDuplicate,qSubProhibited,msgSentAuth,msgSentQuota,msgSentLarge
fromTime,qCreated,qSecured,qDeleted,msgSent,msgRecv,dayMsgQueues,weekMsgQueues,monthMsgQueues,msgSentNtf,msgRecvNtf,dayCountNtf,weekCountNtf,monthCountNtf,qCount,msgCount,msgExpired,qDeletedNew,qDeletedSecured,pRelays_pRequests,pRelays_pSuccesses,pRelays_pErrorsConnect,pRelays_pErrorsCompat,pRelays_pErrorsOther,pRelaysOwn_pRequests,pRelaysOwn_pSuccesses,pRelaysOwn_pErrorsConnect,pRelaysOwn_pErrorsCompat,pRelaysOwn_pErrorsOther,pMsgFwds_pRequests,pMsgFwds_pSuccesses,pMsgFwds_pErrorsConnect,pMsgFwds_pErrorsCompat,pMsgFwds_pErrorsOther,pMsgFwdsOwn_pRequests,pMsgFwdsOwn_pSuccesses,pMsgFwdsOwn_pErrorsConnect,pMsgFwdsOwn_pErrorsCompat,pMsgFwdsOwn_pErrorsOther,pMsgFwdsRecv,qSub,qSubAuth,qSubDuplicate,qSubProhibited,msgSentAuth,msgSentQuota,msgSentLarge,msgNtfs,msgNtfNoSub,msgNtfLost,qSubNoMsg,msgRecvGet,msgGet,msgGetNoMsg,msgGetAuth,msgGetDuplicate,msgGetProhibited,psSubDaily,psSubWeekly,psSubMonthly,qCount2,ntfCreated,ntfDeleted,ntfSub,ntfSubAuth,ntfSubDuplicate,ntfCount,qDeletedAllB,qSubAllB,qSubEnd,qSubEndB,ntfDeletedB,ntfSubB,msgNtfsB,msgNtfExpired
```
#### Fields description
| Field number | Field name | Field Description |
| ------------- | ---------------------------- | -------------------------- |
| 1 | `fromTime` | Date of statistics |
@@ -856,6 +1151,34 @@ fromTime,qCreated,qSecured,qDeleted,msgSent,msgRecv,dayMsgQueues,weekMsgQueues,m
| 45 | `msgSentAuth` | Authentication errors |
| 46 | `msgSentQuota` | Quota errors |
| 47 | `msgSentLarge` | Large message errors |
| 48 | `msgNtfs` | XXXXXXXXXXXXXXXXXXXX |
| 49 | `msgNtfNoSub` | XXXXXXXXXXXXXXXXXXXX |
| 50 | `msgNtfLost` | XXXXXXXXXXXXXXXXXXXX |
| 51 | `qSubNoMsg` | Removed, always 0 |
| 52 | `msgRecvGet` | XXXXXXXXXXXXXXXXX |
| 53 | `msgGet` | XXXXXXXXXXXXXXXXX |
| 54 | `msgGetNoMsg` | XXXXXXXXXXXXXXXXX |
| 55 | `msgGetAuth` | XXXXXXXXXXXXXXXXX |
| 56 | `msgGetDuplicate` | XXXXXXXXXXXXXXXXX |
| 57 | `msgGetProhibited` | XXXXXXXXXXXXXXXXX |
| 58 | `psSub_dayCount` | Removed, always 0 |
| 59 | `psSub_weekCount` | Removed, always 0 |
| 60 | `psSub_monthCount` | Removed, always 0 |
| 61 | `qCount` | XXXXXXXXXXXXXXXXX |
| 62 | `ntfCreated` | XXXXXXXXXXXXXXXXX |
| 63 | `ntfDeleted` | XXXXXXXXXXXXXXXXX |
| 64 | `ntfSub` | XXXXXXXXXXXXXXXXX |
| 65 | `ntfSubAuth` | XXXXXXXXXXXXXXXXX |
| 66 | `ntfSubDuplicate` | XXXXXXXXXXXXXXXXX |
| 67 | `ntfCount` | XXXXXXXXXXXXXXXXX |
| 68 | `qDeletedAllB` | XXXXXXXXXXXXXXXXX |
| 69 | `qSubAllB` | XXXXXXXXXXXXXXXXX |
| 70 | `qSubEnd` | XXXXXXXXXXXXXXXXX |
| 71 | `qSubEndB` | XXXXXXXXXXXXXXXXX |
| 72 | `ntfDeletedB` | XXXXXXXXXXXXXXXXX |
| 73 | `ntfSubB` | XXXXXXXXXXXXXXXXX |
| 74 | `msgNtfsB` | XXXXXXXXXXXXXXXXX |
| 75 | `msgNtfExpired` | XXXXXXXXXXXXXXXXX |
To import `csv` to `Grafana` one should:
@@ -863,83 +1186,112 @@ To import `csv` to `Grafana` one should:
2. Allow local mode by appending following:
```sh
[plugin.marcusolsson-csv-datasource]
allow_local_mode = true
```
```sh
[plugin.marcusolsson-csv-datasource]
allow_local_mode = true
```
... to `/etc/grafana/grafana.ini`
... to `/etc/grafana/grafana.ini`
3. Add a CSV data source:
- In the side menu, click the Configuration tab (cog icon)
- Click Add data source in the top-right corner of the Data Sources tab
- Enter "CSV" in the search box to find the CSV data source
- Click the search result that says "CSV"
- In URL, enter a file that points to CSV content
- In the side menu, click the Configuration tab (cog icon)
- Click Add data source in the top-right corner of the Data Sources tab
- Enter "CSV" in the search box to find the CSV data source
- Click the search result that says "CSV"
- In URL, enter a file that points to CSV content
4. You're done! You should be able to create your own dashboard with statistics.
For further documentation, see: [CSV Data Source for Grafana - Documentation](https://grafana.github.io/grafana-csv-datasource/)
## Updating your SMP server
### Updating your SMP server
To update your smp-server to latest version, choose your installation method and follow the steps:
- Manual deployment
1. Stop the server:
```sh
sudo systemctl stop smp-server
```
2. Update the binary:
```sh
curl -L https://github.com/simplex-chat/simplexmq/releases/latest/download/smp-server-ubuntu-20_04-x86-64 -o /usr/local/bin/smp-server && chmod +x /usr/local/bin/smp-server
```
3. Start the server:
```sh
sudo systemctl start smp-server
```
- [Offical installation script](https://github.com/simplex-chat/simplexmq#using-installation-script)
1. Execute the followin command:
```sh
sudo simplex-servers-update
```
To install specific version, run:
```sh
export VER=<version_from_github_releases> &&\
sudo -E simplex-servers-update
```
2. Done!
- [Docker container](https://github.com/simplex-chat/simplexmq#using-docker)
1. Stop and remove the container:
```sh
docker rm $(docker stop $(docker ps -a -q --filter ancestor=simplexchat/smp-server --format="\{\{.ID\}\}"))
```
2. Pull latest image:
```sh
docker pull simplexchat/smp-server:latest
```
3. Start new container:
```sh
docker run -d \
-p 5223:5223 \
-p 443:443 \
-v $HOME/simplex/smp/config:/etc/opt/simplex:z \
-v $HOME/simplex/smp/logs:/var/opt/simplex:z \
simplexchat/smp-server:latest
```
- [Linode Marketplace](https://www.linode.com/marketplace/apps/simplex-chat/simplex-chat/)
1. Pull latest images:
```sh
docker-compose --project-directory /etc/docker/compose/simplex pull
```
2. Restart the containers:
```sh
docker-compose --project-directory /etc/docker/compose/simplex up -d --remove-orphans
```
3. Remove obsolete images:
```sh
docker image prune
```
## Configuring the app to use the server
### Configuring the app to use the server
To configure the app to use your messaging server copy it's full address, including password, and add it to the app. You have an option to use your server together with preset servers or without them - you can remove or disable them.
+1 -1
View File
@@ -226,7 +226,7 @@ While introduced members establish connection inside group, inviting member forw
### Member roles
Currently members can have one of three roles - `owner`, `admin`, `member` and `observer`. The user that created the group is self-assigned owner role, the new members are assigned role by the member who adds them - only `owner` and `admin` members can add new members; only `owner` members can add members with `owner` role. `Observer` members only receive messages and aren't allowed to send messages.
Currently members can have one of four roles - `owner`, `admin`, `member` and `observer`. The user that created the group is self-assigned owner role, the new members are assigned role by the member who adds them - only `owner` and `admin` members can add new members; only `owner` members can add members with `owner` role. `Observer` members only receive messages and aren't allowed to send messages.
### Messages to manage groups and add members