phone

    • chevron_right

      Paul Schaub: Reproducible Builds – Telling of a Debugging Story

      news.movim.eu / PlanetJabber • 19 June, 2022 • 7 minutes

    Reproducibility is an important tool to empower users. Why would a user care about that? Let me elaborate.

    For a piece of software to be reproducible means that everyone with access to the software’s source code is able to build the binary form of it (e.g. the executable that gets distributed). What’s the matter? Isn’t that true for any project with accessible source code? Not at all. Reproducibility means that the resulting binary EXACTLY matches what gets distributed. Each and every bit and byte of the binary is exactly the same, no matter on which machine the software gets built.

    The benefit of this is that on top of being able to verify that the source code doesn’t contain any spyware or unwanted functionality, the user now is also able to verify that the distributable they got e.g. from an app store has no malicious code added into it. If for example the Google Play Store would inject spyware into an application submitted by a developer, the resulting binary that gets distributed via the store would be different from the binary built by the user.

    Why is this important? Well, Google already requires developers to submit their signing keys , so they can modify software releases after the fact. Now, reproducibility becomes a tool to verify that Google did not tamper with the binaries.

    I try to make PGPainless build reproducible as well. A few months ago I added some lines to the build script which were supposed to make the project reproducible by using static file modification dates, as well as a deterministic file order in the JAR archive.

        // Reproducible Builds
        tasks.withType(AbstractArchiveTask) {
            preserveFileTimestamps = false
            reproducibleFileOrder = true
        }

    It took a bit more tinkering back then to get it to work though, as I was using a Properties file written to disk during build time to access the libraries version during runtime, and it turns out that the default Writer for Properties files includes the current time and date in a comment line. This messed up reproducibility, as now that file would be different each time the project got built. I eventually managed to fix that though by writing the file myself using a custom Writer. When I tested my build script back then, both my laptop and my desktop PC were able to build the same exact JAR archive. I thought I was done with reproducibility.

    Today I drafted another release for PGPainless. I noticed that my table of reprodubile build hashes for each release was missing the checksums for some recent releases. I quickly checked out those releases, computed the checksums and updated the table. Then I randomly chose the 1.2.2 release and decided to check if the checksum published to maven central still matches my local checksum. And to my surprise it didn’t! Was this a malicious act from Maven Central?

    Release 1.2.2 was created while I was on my Journey through Europe, so I had used my Laptop to draft the release. So the first thing I did was grab the laptop, checkout the releases source in git and build the binaries. Et voila, I got checksums matching those on Maven Central. So it wasn’t an attack, but for some reason my laptop was producing different binaries than my main machine.

    I transferred the “faulty” binaries over to my main machine to compare them in more detail. First I tried Meld, which is a nice graphical diff tool for text files. It completely froze though, as apparently it is not so great for comparing binary files.

    Next I decompressed both binaries and compared the resulting folders. Meld did not report any differences, the directories matched perfectly. What the heck?

    Next I tried diff 1.jar 2.jar which very helpfully displayed the message “Binary files 1.jar and 2.jar are different”. Thanks for nothing. After some more research, I found out that you could use the flag --text to make diff spit out more details. However, the output was not really helpful either, as the binary files were producing lots of broken output in the command line.

    I did some research and found that there were special diff tools for JAR files. Checking out one project called jardiff looked promising initially, but eventually it reported that the files were identical. Hm…

    Then I opened both files in ghex to inspect their byte code in hexadecimal. By chance I spotted some differences near the end of the files.

    The same spots in the other JAR file look identical, but the A4 got replaced with B4 in the other file. Strange. I managed to find another command which found and displayed all places in the JAR files which had mismatches:

    $ cmp -l 1.jar 2.jar | gawk '{printf "%08X %02X %02X\n", $1, strtonum(0$2), strtonum(0$3)}'
    00057B80 ED FD
    00057BB2 ED FD
    00057BEF A4 B4
    00057C3C ED FD
    00057C83 A4 B4
    00057CDE A4 B4
    00057D3F A4 B4
    00057DA1 A4 B4
    ...

    Weird, in many places ED got changed to DF and A4 got changed into B4 in what looked like some sort of index near the end of the JAR file. At this point I was sure that my answers would unfortunately lay within the ZIP standard. Why ZIP? For what I understand, JAR files are mostly ZIP files. Change the file ending from .jar to .zip and any standard ZIP tool will be able to extract your JAR file. There are probably nuances, but if there are, they don’t matter for the sake of this post.

    The first thing I did was to check which versions of zip were running on both of my machines. To my surprise they matched and since I wasn’t even sure if JAR files would be generated using the standard zip tool, this was a dead end for me. Searching the internet some more eventually lead me to this site describing the file structure for PKZIP files . I originally wasn’t sure if PKZIP was what I was looking for, but I had seen the characters PK when investigating the hex code before, so I gave the site a try.

    Somewhere I read The signature of the local file header. This is always '\x50\x4b\x03\x04'. Aha! I just had to search for the octets 50 4B 03 04 in my file! It should be in approximation to the bytes in question so I just had to read backwards until I found them. Aaaand: 50 4B 01 02 Damn. This wasn’t it. But 01 02 looks so suspiciously non-random, maybe I oversaw something? Let’s continue to read on the website. Aha! The Central directory file header. This is always "\x50\x4b\x01\x02". The section even described its format in a nice table. Now I just had to manually count the octets to determine what exactly differed between the two JAR files.

    It turns out that the octets 00 00 A4 81 I had observed to change in the file were labeled as “external file attributes; host-system dependent”. Again, not very self-explanatory but something I could eventually throw into a search engine.

    Some post on StackOverflow suggested that this had to do with file permissions. Apparently ZIP files (and by extension also JAR files) would use the external attributes field to store read and write permissions of the files inside the archive. Now the question turned into: “How can I set those to static values?”.

    After another hour of researching the internet with permutations of the search terms jar, archive, file permissions, gradle, external attributes, zip I finally stumbled across a bug report in another software project that talked about the same exact issue I had; differing jar files on different machines. In their case, their CI would build the jar file in a docker container and set different file permissions than the locally built file, hence a differing JAR archive.

    In the end I found a bug report on the gradle issue tracker , which exactly described my issue and even presented a solution: dirMode and fileMode could be used to statically set permissions for files and directories in the JAR archive. One of the comments in that issue reads:

    We should update the documentation.

    The bug report was from 3 years ago…

    Yes, this would have spared me from 3h of debugging 😉
    But I probably would also not have gone onto this little dive into the JAR/ZIP format, so in the end I’m not mad.

    Finally, my build script now contains the following lines to ensure reproducibility, no matter the file permissions:

        // Reproducible Builds
        tasks.withType(AbstractArchiveTask) {
            preserveFileTimestamps = false
            reproducibleFileOrder = true
    
            dirMode = 0755
            fileMode = 0644
        }

    Finally my laptop and my desktop machine produce the same binaries again. Hopefully this post can help others to fix their reproducibility issue.

    Happy Hacking!

    • wifi_tethering open_in_new

      This post is public

      blog.jabberhead.tk /2022/06/20/reproducible-builds-telling-of-a-debugging-story/

    • chevron_right

      ProcessOne: Announcing ejabberd DEB and RPM Repositories

      news.movim.eu / PlanetJabber • 16 June, 2022 • 1 minute

    Today, we are happy to announce our official Linux packages repository: a source of .deb and .rpm packages for ejabberd Community Server . This repository provides a new way for the community to install and upgrade ejabberd.

    All details on how to set this up are described on the dedicated website:
    https://repo.process-one.net

    ejabberd installation log

    What packages are available?

    Currently, the latest DEB and RPM packages are available for the open-source ejabberd version (eCS 22.05). New versions will be published as they’re released to https://repo.process-one.net .

    Which platforms are currently supported?

    The DEB and RPM packages currently target popular amd64 and arm64 systems. So if you are using Debian or centOS you should be fine. If your platform is not in this list, you can open an issue on Github describing which platform you would like to be added.

    We aim to expand the support to other widely adopted architectures and platforms in the future.

    What is next?

    In addition to providing packages for ejabberd for upcoming releases, as well as expanding distribution and architecture support, we will make improvements to this official repository. Away from prying eyes, we’ve been studying the possibility to make ejabberd’s installers (.deb, .rpm, .run) directly on Github below each Release and that’s now the case! You can check them here now.

    We’re looking forward to the community feedback on these packages to provide the best possible experience. Feel free to get in touch if needed!

    The post Announcing ejabberd DEB and RPM Repositories first appeared on ProcessOne .
    • wifi_tethering open_in_new

      This post is public

      www.process-one.net /blog/announcing-ejabberd-deb-and-rpm-repositories/

    • chevron_right

      Erlang Solutions: MongooseIM 5.1 Configuration Rework

      news.movim.eu / PlanetJabber • 8 June, 2022 • 10 minutes

    MongooseIM is a modern messaging server that is designed for scalability and high performance. The use of XMPP (Extensible Messaging and Presence Protocol) extensions (XEPs) means it is also highly customisable. Since version 4.0 it has been using the TOML configuration file format, which is much more user-friendly than the previously used Erlang terms. The latest release, MongooseIM 5.1 , makes it more developer-friendly as well by reworking how the configuration is processed and stored, hence making it easier to understand and extend. Other significant changes in this release include improvements of the Inbox feature, support for the latest Erlang/OTP 25 and numerous internal improvements, like getting rid of the dynamically compiled modules. For all changes, see the Release Notes .

    Until version 3.7, MongooseIM was configured with a file called mongooseim.cfg , that contained Erlang terms. It was a legacy format that was the primary obstacle encountered by new users. The configuration terms were interpreted and converted to the internal format. This process was difficult because there was no configuration schema – all conversion logic was scattered around the system. Some of the conversion and validation was done when parsing the configuration terms, and some was done afterwards, sometimes deeply inside the logic handling specific use cases. This meant that many errors were only reported when the corresponding features were used instead of when the system started, leading to unwanted runtime errors. As a result, the whole configuration subsystem needed to be rewritten. The new configuration file is now called mongooseim.toml and it uses the TOML format, which is simple, intuitive and easy to learn.

    Because of the significant code base size and the tight coupling of system logic with configuration processing, it was very difficult to write a new configuration subsystem from scratch in one release cycle. What is more, simultaneous support for both formats was needed during the transition period. This led us to dividing the work into three main steps:

    1. Addition of new config parsing, validating and processing logic, which used the old internal format as the target (version 4.0).
    2. Dropping the old Erlang configuration format (version 4.1).
    3. Reworking the internal format to be consistent with the TOML configuration file (version 5.1).

    Each of the steps was further divided into multiple small changesets, keeping all CI tests passing the entire time. We also periodically load-tested the code to monitor the performance.

    What did we do?

    Here is one of the most complicated sections from the default mongooseim.cfg file taken from the old MongooseIM 3.7.1:

    {8089, ejabberd_cowboy, [
      {num_acceptors, 10},
      {transport_options, [{max_connections, 1024}]},
      {protocol_options, [{compress, true}]},
      {ssl, [{certfile, "priv/ssl/fake_cert.pem"}, {keyfile, "priv/ssl/fake_key.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, []},
        %% Swagger
        {"_", "/api-docs", cowboy_swagger_redirect_handler, {priv_file, cowboy_swagger, "swagger/index.html"}},
        {"_", "/api-docs/swagger.json", cowboy_swagger_json_handler, #{}},
        {"_", "/api-docs/[...]", cowboy_static, {priv_dir, cowboy_swagger, "swagger", [{mimetypes, cow_mimetypes, all}]}}
      ]}
    ]},
    

    This section used to define one of the listeners that accept incoming connections –  this one accepted HTTP connections, because it used the ejabberd_cowboy module. It had multiple handlers defined in the {modules, [...]} tuple. Together they formed the client-facing REST API, which could be used to send messages without the need for XMPP connections. The whole part was difficult to understand, and most of the terms should not be modified, because the provided values were the only ones that worked correctly. To customise it, one would need to know the internal details of the implementation. However, the logic was scattered around multiple Erlang modules, making it difficult to figure out what the resulting internal structures were. For version 5.0, we used TOML, but the configuration was still quite complex because it reflected the complicated internals of the resulting Erlang terms – actually this was one of the very few parts of the file needing further rework. By cleaning up the internal format in 5.1, we have managed to make the default configuration simple and intuitive:

    [[listen.http]]
      port = 8089
      transport.num_acceptors = 10
      transport.max_connections = 1024
      protocol.compress = true
      tls.verify_mode = "none"
      tls.certfile = "priv/ssl/fake_cert.pem"
      tls.keyfile = "priv/ssl/fake_key.pem"
      tls.password = ""
    
      [[listen.http.handlers.mongoose_client_api]]
        host = "_"
        path = "/api"
    

    By just looking at the top line, one can see that the section is about listening for HTTP connections. The [[...]] TOML syntax denotes an element in an array of tables , which means that there could be other HTTP listeners. Below are the listener options. The first one, port , is just an integer. The remaining options are grouped into subsections (TOML tables ). One could use the typical section syntax there, e.g.

    [listen.http.transport]
      num_acceptors = 10
      max_connections = 1024
    

    Alternatively, an inline table could be used:

    transport = {num_acceptors = 10, max_connections = 1024}

    However, for such simple subsections the dotted keys used in the example seem to be the best choice. The TLS options make it obvious that fake certificates are used, and they should be replaced with real ones. The verify_node option is set to none, which means that client certificates are not checked.

    The biggest improvement in this configuration section was made in the API definition itself – now it is clear that [[listen.http.handlers.mongoose_client_api]] defines a handler for the client-facing API. The double brackets remind that there can be multiple handlers, if, for example, you would like to have another API hosted at the same port. The question is: what has happened to all these specific handlers that were present in the old configuration format? The answer is simple: they are all enabled by default, and if you want, you can control which ones are enabled. The options configurable for the user are limited to the ones that actually do work, limiting unnecessary frustration and easing up the learning curve. See the documentation for more details about this section. By the way, the docs have improved a lot as well.

    How did we do it?

    One of the challenges of supporting the old internal format was that the new TOML configuration format should be defined once and from then changed as little as possible, to avoid forcing users to constantly change their configuration with each software version. This was achieved with a customisable config processor that takes configuration specification (called config spec for short) and the parsed TOML tree (the tomerl parser was used here) as arguments. Each node is processed recursively with the corresponding config spec node and the current path (a list of keys from the root to the leaf). The config spec consists of three types of config nodes, specified with Erlang records corresponding to the following TOML types:

    TOML type Parsed node (Erlang type) Config specification record Description
    Table Map #section{items = Items} Configuration section, which is a key-value map. For each key a config spec record is specified.
    Array List #list{items = ConfigSpec} List of values sharing the same config spec.
    StringIntegerFloatBoolean BinaryIntegerFloatBoolean #option{type = string}#option{type = binary}#option{type = integer}#option{type = int_or_infinity}#option{type = float}#option{type = boolean} Value of a primitive type. The type specifies how the parsed nodes are converted to the target types.

    The root node is a section. TOML processing for each config node is done in up to 5 steps (depending on the node type). Each step is configured by the fields of the corresponding node specification record, allowing you to customise how the value is processed.

    Step Node types Record fields Description
    Parse section requiredvalidate_keysitemsdefaults Check required keys, validate keys, recursively process each item, and merge the resulting values with defaults. The result is a key-value list unless a custom processing function was used for the values.
    Parse list items Recursively process each item. The result is a list.
    Parse option type Check the type and convert the value to the specified type.
    Validate all validate Check the value with the specified validator.
    Format items section, list format_items Format contents as a list (default for lists) or a map (default for sections).
    Process all process Apply a custom processing function to the value.
    Wrap all wrap Wrap the node in a top-level config item, a key-value pair, or inject the contents (as a list) to the items of the parent node.

    The flexibility of these options enabled processing of any TOML structure into arbitrary Erlang terms that was needed to support the legacy internal configuration format. The complete config spec contains 1,245 options in total, grouped into 353 sections and 117 lists, many of which are deeply nested. The specification is mostly declarative, but the fact that it is constructed with Erlang code makes it possible to reuse common sections to avoid code duplication, and to delegate specification of the customisable parts of the system, e.g. the extension modules to the modules themselves, using Erlang behaviours. This way, if you fork MongooseIM and add your own extensions, you can extend the configuration by implementing a config_spec function in the extension module.

    In the recent MongooseIM versions (4.0-5.0), the resulting top-level config options were stored in three different Mnesia tables for legacy reasons. This was unnecessarily complicated, and the first step towards version 5.1 was to put each top-level configuration node into a persistent term. Next, the internal format of each option was reworked to resemble the TOML tree as much as possible. Some options, like the extension modules, needed a more significant rework as they used custom ETS tables for storing the processed configuration. The effort resulted in a significant reduction of technical debt, and the code base was also reduced by a few thousand lines increasing readability and maintainability without any loss in overall performance. The table below summarises the whole configuration rework that has been undertaken over the last few releases.

    Version 3.7 4.0 – 5.0 5.1
    Configuration file format Erlang terms TOML: nested tables and arrays with options TOML: nested tables and arrays with options
    Conversion logic Scattered around the code Organised, but complex Organised, simple, minimal
    Internal options Arbitrary Erlang terms stored in Mnesia and ETS, additional custom ETS tables Persistent terms with nested maps and lists. No custom ETS tables. Persistent terms with nested maps and lists. No custom ETS tables.

    Config processing in action

    As an example, let’s see how the first option in the general section, loglevel , is defined and processed:

    general() ->
      #section{items = #{<<"loglevel">> => #option{type = atom,
                                                   validate = loglevel,
                                                   wrap = global_config},
                         (...)
                        }
              }.
    

    The TOML configuration file contains this option at the top:

    [general]
      loglevel = "warning"
      (...)
    

    The type atom means that it will be converted to an Erlang atom warning. It is then validated as loglevel – the validators are defined in the mongoose_config_validator module. The f ormat_items step does not apply to options, and the process step is skipped as well, because there is no custom processing function defined. The option is then wrapped as global_config and will be put in a separate persistent term (it is not a nested option). It can be accessed in the code like this:

    mongoose_config:get_opt(loglevel)

    There are many more features, e.g. nested options can be accessed by their paths, and there are host-type-specific options as well, but this simple example shows the general idea.

    Plans for the future

    Going back to the topic of HTTP API, you can still find multiple REST API definitions in the default configuration file, which can be a bit confusing. This is because of the long evolution of the APIs and the backwards compatibility. However, for the upcoming release we are redesigning the API and command line interface (CLI), adding brand new GraphQL support, and making the APIs more complete and organised. Stay tuned, because we are already working on a new release!

    If you would like to talk to us about how your project can benefit from using MongooseIM, you can contact us at general@erlang-solutions.com and one of our expert team will get right back to you.

    The post MongooseIM 5.1 Configuration Rework appeared first on Erlang Solutions .

    • chevron_right

      Erlang Solutions: Modern Software Engineering Principles for Fintechs by Daniel Pilon at SumUp

      news.movim.eu / PlanetJabber • 7 June, 2022 • 8 minutes

    Daniel Pilon is a Software Engineering Manager at SumUp. Since 2007 he has worked across several industries before arriving in the fintech space. He has experience in many programming languages, such as C#, Java and JavaScript but since discovering Elixir and the power of functional programming a few years ago, he hasn’t looked back.

    Right now he is building SumUp Bank, a complete digital banking solution to empower small merchants and simplify their financial needs.

    We spoke to Daniel about his experiences using Elixir in the financial services domain, here’s what he had to say.

    Why are system resilience and scalability so important in financial services?

    Financial services handle, in different ways, other people’s or companies’ money. It’s vital for the success of a fintech company that those clients can trust that their money will be handled without any unpleasant surprises and that they can use the services any time they need. For fintechs to be able to give this level of trust to their clients, they must start by first trusting their operation.

    Given that fintechs don’t have the same level of resources and size as banks and incumbent Financial Services Institutions (FSIs) that have been established for decades – any problem that arises could be critical and difficult to determine and recover, should it need manual intervention. For these reasons, it’s really crucial to the business that the services that support the operation are up and available for the vast majority of the time.

    What are the commercial risks of system downtime to fintechs?

    There are many reputational and business risks that may arise from downtime or intermittence in availability. For example, if you’re a fintech that provides payment services, it might cause the client to be unable to pay for their shopping cart in a supermarket or online. When this occurs, clients lose confidence and will either stop using your services or even seek legal ways to repair their damage. This leads to reputational damage to your brand and metrics such as your Net Promoter Score (NPS).

    There are several practices that are required in order to keep services up and to anticipate problems, such as building robust observability, having a comprehensive automated test suite, keeping track of MTTD (mean time to detect), MTTR (mean time to recover) and MTBF (mean time between failures) and always iterating over those metrics in order to learn what they say about the opportunities to enhance the company infrastructure.

    Designing for system scalability with Elixir

    When it comes to handling demand and being able to scale, it’s crucial that the company can statistically determine business expectations so that the engineering teams can decide the best approach for development. Without numbers it’s possible that engineers will either be too optimistic about the load the applications supports or will try to optimise early for a load that shouldn’t be expected in the short or mid-term, delaying deliveries and losing time to market. With the right information, engineers are empowered to decide what is important for the current status of the company and what can be done later, as well as having stress and load tests that can show how the system is behaving against the expectations.

    What I like the most about using Elixir/Erlang programming languages is the aspect that it’s often easy to design applications that are resilient and always evolving. Being idiomatic and understanding the way workers, supervisors, and the supervision tree work helps in system design so that eventual crashes are handled properly and without side effects. Also, it is easy to modularise different domains so that, should expectations change and more load is required, it’s simple to increase the processing power or even separate into a different application that can scale more specifically.

    Why did SumUp use the Erlang ecosystem?

    The Erlang ecosystem has been empowering SumUp since day one. We started as a payment solutions provider for small merchants and the core services that enabled us to scale our transaction processing power to the millions were mostly written in Erlang.

    Since SumUp’s mission is to enable small businesses to have access to digital payment solutions and most of our clients are transacting small amounts in their transactions, we needed confidence that we could take those transactions. They are vital to our client’s businesses, so they are vital for SumUp as well.

    Erlang and the BEAM VM gave us the highest level of confidence in this aspect, given that it is battle-tested for decades, it’s built to scale readily, it allows us to make concurrent processing easier and it has fault tolerance as a first-class citizen. But, most importantly, we need platforms where I/O intensive operations are handled well by design, so we can confidently process as many parallel payments as we need. The BEAM VM checks the boxes for all of the aforementioned aspects.

    How they used Elixir to build a fintech backend for SumUp Bank

    Over time SumUp grew exponentially and now we are in a position of increasing our offer of financial products to clients, adding services such as digital banking and credit/lending. The building of a digital bank in Brazil started in 2019 when it was decided that the core language for our backend services would be Elixir.

    With Elixir, we continue to have everything that makes Erlang so powerful, but with a modernised syntax and mature tooling for production usage. At SumUp Bank we currently run Elixir in a microservices architecture, running on AWS with Kubernetes via EKS. Our services are backed by Postgres databases when needed, with data exposure via RESTful APIs. For asynchronous communication, we use AWS SNS/SQS. Our clients all connect to BFFs (Backends for frontends) built using GraphQL. This is all made possible by robust libraries that are available as open-source for Elixir applications, such as Phoenix, Ecto, Absinthe, ExAws and Broadway.

    Over these last two years of running a bank in production, we learnt that Elixir/Erlang was the best choice we could have made. We were able to start small, quickly run in production and scale as we needed. For example, it was not until we reached some scale that we started to prioritise asynchronous communication between services and it was simple and straightforward to move to this type of architecture with the help of a library like Dashbit’s Broadway. The Elixir/Erlang applications being lightweight and fault-tolerant also give us a lot of flexibility to use computational resources wisely, lowering our costs with infrastructure, while still providing outstanding throughput.

    The future of open-source in fintech and the Elixir community

    Open-source has dramatically changed fintech and many other industries for the better. Personally, I can’t imagine us living in such a fast-changing and diverse world of options if not for the popularity and adoption of open-source. The speed at which companies are now able to deliver new technologies without the burden of having to reinvent the wheel or pay a huge amount for proprietary software is one of the foundations for such a transformation.

    In the Elixir community, contribution to open-source is just an organic aspect of how things work. When I started my journey, the community was something that really caught my attention. The energy and the willingness to help each other were way advanced when compared to my days with .NET or Java. Today, those technologies also have strong communities contributing to open-source, but it’s something that most people had to learn while it was happening.

    With Elixir, most of the general purpose libraries are open-source and they are very mature. I can cite that my experience writing code for financial services using Phoenix, Broadway, Ecto and others have been joyful and every time I had to seek help with the appropriate usage or with issues, I have found it. The power and synergy of the Elixir community are impressive as there’s always somewhere one can reach out in order to seek help or contribute.

    Of course, there are some areas where I think we still need to improve. For instance, some of the libraries that make the ecosystem stronger and that can ease the adoption of the language are not always highly maintained. The ExAws library is a great library to interact with AWS services. However, it was on the verge of being abandoned around 2020, when the original maintainer left the project. Now another maintainer stepped in and assumed the responsibility for the project, so it’s receiving contributions and being released.

    Also, financial systems commonly have to handle integrations with third parties which are not always straightforward RESTful APIs, or some other more commonly used technology for integrations. Integrations based on positional files, or SOAP are unfortunately still there. More established ecosystems, such as Java, have plenty of options for implementations in these scenarios, while in Elixir, given that it’s more recent, it’s not always the case. However, from my experience, this is a minor issue weighed against all the positives the language brings and hasn’t been a massive burden when this sort of requirement has arisen.

    It would be great if there were more companies using Elixir willing to give back to the open-source community for Elixir. Either via opening their internal libraries or via incentives for their developers to contribute when certain cases are not covered by existing libraries. Also, sponsoring projects that are open to receiving it would be a great way to allow the maintainers to have more focus on their libraries getting better and better.

    About SumUp

    SumUp is a fintech company founded in 2012. Primarily a leader as a payment services provider, it has grown to be a multiproduct company, now offering other financial services, such as digital banking and lending.

    SumUp tech is all built as cloud-native applications, running mostly in Erlang/Elixir, Ruby and Go.

    A big thank you to Daniel for sharing his thoughts and experiences of Elixir, the Erlang ecosystem and innovation in fintech, you can connect with him via his LinkedIn profile .

    If you would like to speak about collaboration around telling the stories of using Elixir or Erlang in fintech, please reach out to Michael Jaiyeola (Erlang Solutions’ Fintech Marketing Lead) by email or on LinkedIn.

    The post Modern Software Engineering Principles for Fintechs by Daniel Pilon at SumUp appeared first on Erlang Solutions .

    • chevron_right

      Erlang Solutions: WombatOAM & the machine learning library

      news.movim.eu / PlanetJabber • 26 May, 2022 • 19 minutes

    WombatOAM, the powerful operations, monitoring, and maintenance platform has a new machine learning library to assist with metric prediction. Learn about the main features, the algorithms used and how you can benefit from it together with WombatOAM’s new UI from Mohamed Ali Khechine , Tamás Lengyel and Janos Sandor .

    WombatOAM

    Mohamed Ali Khechine : The theme of today’s webinar is the way we have created a machine learning library for metric prediction for the monitoring and maintenance tool WombatOAM which we develop at Erlang Solutions . We built this tool using Elixir . This will be presented by the next host and for now, I just wanted to say a few words about the Wombat tool itself, WombatOAM is a software used to monitor BEAM-based systems. What I wanted to show today are the main capabilities. I will go through them and I will explain bit by bit why are they used by WombatOAM and how we came up with these tools in our software.

    Wombat is a software that you self-host and you can use it for monitoring systems that vary from RabbitMQ to Elixir, Phoenix, and, of course, Erlang itself. So we have many ways to install Wombat in your system, AWS, Kubernetes or simply having it locally. So I will share this documentation after the webinar is finished, but I just wanted to tell you that depending on how your system and the environment are, Wombat will be able to adapt and use all of the capabilities there.

    When you install Wombat and start it, you just have to set up a new password and that’s it. Then you can access the interface.

    You should be able to access the node that you wish to monitor through the internet or through a network that you have set up locally, or anything which allows distributed communication through TCP. So you just need to specify the node name and the cookie, and then Wombat is able to add it. For example, for this webinar, I have set up a RabbitMQ node and I have set up four Erlang nodes.

    When you add a node, what happens is that Wombat will automatically start these GenServers agents on the specified node and these GenServers are responsible for getting the metrics and the capabilities to the Wombat node.

    So for example, we have here a group of agents or GenServers that are mainly focused on bringing the BEAM specific metrics that we can, for example, see here.

    By default, out of the box, Wombat will offer you all of the specific metrics that are important to monitor for the health of your node, but also a few others that are a bit more like the health of the machine. The node where the application is running, and of course, we have a few extra metrics that I will explain later, but we do have, a more in-depth view of the processes that are running. For example, we can have information about memory usage, of all of the processes that are running in this specific application. We also have a similar reduction number of all processes running in a specific application.

    So all of this information is fine-grained to allow the user to get more information out of the node and the same thing is happening for nodes that, for example, have the RabbitMQ application.

    The next part of the system is that Wombat by default collects also all of the logs that are generated in the nodes that you wish to monitor and all of these logs are, of course, stored in your machine, and you can filter them, you can explore them, and you can also if you wish to send them to another log-aggregating tool like Graylog or anything like that, you can also push them there in the same way. I wanted to show, for example, how alarms are shown.

    We can monitor specific processes, for example. Let’s say you have a very important process that you use for routing, and you want to monitor that specific process for its memory usage, and its message queue length. What you should do is you should create a monitor for it, and let’s see how we can trigger it. Let’s try to push some metrics.

    Wombat will detect that a process has an issue with the mailbox, this by default will create an alarm with all of the information that is necessary to debug this issue as soon as it happens. Wombat first needs to check the number of messages that are stuck. If it’s for example, 100 and then it drops down, it would not be triggered because they were quickly resolved. But if it just gets stuck then Wombat will automatically create an alarm and it will be shown within a minute of the peak of the message queue.

    These are the alarms that are generated by default by Wombat. What you can see above is that you can get information about the Pid of the process where the issue occurred and you can get a sample of the messages that are stuck in the message queue so that you can at least know what type of message is making the process get stuck in that phase.

    The processes are all listed and sorted by message queue or reductions. For example, you can get information about the process that has the highest messages in their mailbox.

    Wombat allows you also to have a remote shell towards your monitored node. You can also explore the Mnesia and ETS tables.

    In case you want to send the information that you saw now to other tools, you can have a choice here of which system you already use. For example, I have already set up the Grafana dashboard with the metrics coming in from Wombat. What I did is basically, set up Wombat to report the metrics in the Prometheus format which is shown here.

    All of this is configurable, of course. I didn’t speak about it now because this presentation is mainly going to be about the machine learning aspect of metric predictions. But I wanted to show you that from the documentation, you can explore, for example, all of the metric capabilities.

    Please find the WombatOAM documentation here .

    We also monitor and have integration with Phoenix, Elixir, RabbitMQ, Riak, MongooseIM, and so on. The full list of available metrics will be in the documentation.

    The next presentation is going to be about the machine learning tool.

    Arnold- the machine learning tool

    Tamás Lengyel : We started developing Arnold about a year ago. First, we started building it for Wombat only, but later it became a separate component from Wombat.

    We are using Arnold for time-series forecasting, anomaly detection, and analysing the incoming metric values using the Axon library.

    First, I want to mention the Nx library which is the native tensors implementation for Elixir. You can think of it as the NumPy for Elixir. Nx has a GPU acceleration that is built with Google XLA, and it’s natively implemented inside Elixir. Axon was built on top of the Nx library. Therefore, it has a Nx-powered neural network interface and this is the tool that we used for creating Arnold. You can think of it as the TensorFlow of Elixir. Currently, both libraries are heavily in development, and while Nx has a stable release version, 0.1.0., Axon does not have one yet. So no official release for that.

    Main features

    What are the main features of Arnold? As I mentioned, it is a separate component. It has a RestAPI for communication with the outside world. So not only nodes, Elixir or Erlang nodes, can communicate with it, but a Python application or any kind of application that can make the RestAPI calls can communicate with Arnold. We implemented multiple prediction methods and we’ll talk about them later. We call them simple and complex methods. We have dynamic alarms and load balancing, and inside Wombat, we implemented metrics filtering as well, not to overload the tool.

    The structure

    It’s a simplified structure now. There are three main components of Arnold which is the first.

    One is the sensors where the metrics are stored and all the incoming metrics are gathered and preprocessed before sending them to the neural network and the training algorithm.

    We are storing the incoming metrics in Mnesia with the help of a separate record library called Memento . We have three tags for each metric which are hourly, daily, and weekly. Each tag has a constant value, which is the number of values that we should gather before we start the training algorithm. Wombat sends the hourly metrics every minute. Then we make an average of the last 15 minutes of metrics and then we call that one daily metric. When we reach a certain threshold defined by the tag, we are going to send it to the neural network for training.

    The training algorithm takes Axon models. The prediction methods are decided on whether we have a trained neural network or not. That’s how we can determine if we should use the Simple or Complex method.

    The complex ones are the neural networks and the simple ones are statistical tools and models. Mainly, we use them for instant predictions and analysis tools for the alarms.

    What algorithms are used?

    For forecasting, we use Exponential smoothings, the single , the double , and the triple . We use the single one if we cannot detect any trend or seasonality. The double is used when we can detect the trend component only, and we use the triple Exponential Smoothings when we detect seasonality as well. For trend detection, we use the Mann-Kendall Test . For seasonality detection, we use pattern matching. We are trying to find a correlation between a predefined small seasonal value and our current values. If we have any kind of correlation, then we say that we have seasonality in that metric.

    When we have enough data, we send it to the training algorithm and then we can switch to the complex neural network-based predictions and forecasting. For alarms, we use linear correlation to see when a metric has any kind of relationship with other metrics, so that it could be easier to find the root cause of a possible problem.

    Feeding data into Arnold

    If you have a node, in our case, Wombat, which uses these API calls, then we have to use the following query parameters, the node ID, and the metric name. In a JSON body, we specify the type, the value, and a unique timestamp. So the type can be any kind of type that is present in Wombat as well. But it can be a single integer or float. It can be a histogram duration, meter, or spiral, and you can send it in a row format. Arnold will handle the processing of it. In the same way, as we input data into Arnold, we can fetch data as well with the prediction route.

    We specify the node ID, the metric name, and a tag which can be hourly, daily, or weekly. We also specify a forecast horizon that will be covered later. Arnold will send back a JSON with the prediction values as a four-element list of lists. So it has a list and it has four separate lists inside of it. This way it’s easier to show it on via a graph library like Highchart in JavaScript. We have an analysis of whether we can raise an alarm or not, a message about the value if it crossed the expected range along with the amount, and, of course, the correlation data.

    The training process

    The first step is to gather data. Arnold’s manager sends the data to the correct sensors with a timestamp-value two element tuple. The manager is responsible for getting the correct sensor from the load balancer. One sensor is responsible for one metric. So if we send 200 metrics, then we are going to have 200 sensors. A sensor stores the data for that given tag until their threshold is reached.

    For example, we start training for the hourly metrics, which are sent from Wombat every minute, when we gather 180 metrics. That’s three hours of data in total. But it can be increased to five hours, six hours. It depends on the user. These sensors are saved every five seconds by the manager. Also, the manager does the training checks. Basically when we reach the tag threshold, the manager checks or marks that sensor for training. Then we start the training algorithm or we start the training process where the first step is the data preprocessing.

    First, we have to extend the features with the time of tags. So you can see here the logarithmic scale of the raw timestamp value. As you can see, it’s increasing.

    It’s not usable or understandable for the neural network. We have to transform that with the sine and cosine functions. As you can see here, the blue line represents one hour. So two peaks are considered as one hour.

    Let’s imagine there is a value that is sent at 11:50. That value after transforming the data is going to be -0.84, and if we go forward in time, then we will reach 12:50, 13:50, the transformed data will always be the same. It’s always going to return with this transformation, -0.84 so that the neural network can translate it whether the incoming values are following an increasing or decreasing trend, or whether it has seasonality in a time period of an hour, and so on. Of course, we did that for the hourly metrics, the daily metrics which is the red line, and for the weekly metrics as well which is the yellow one.

    The next step is splitting the data. We use 80% for the training and as an option, we can use 20% for testing purposes to see how our training model is performing. After splitting the data, we have to normalise them. We use the mean and the standard deviation for normalisation.

    The algorithm or the formula that we are using.

    From each value, we are subtracting the mean and then dividing it by a standard deviation. We use Nx built-in functions for that, the Nx mean, and the standard deviation, which was not present in version 0.1.0 but will be in the next release. Currently, we are using our own implementation for standard deviation.

    The next step is creating the dataset. So we are gonna zip the features with the target values. Of course, we have optional values here like the batch size which is by default is 32 and we can shuffle the data as well for better training purposes. The last step is to send it to the training algorithm. But first, before sending, we need to have a model. We have SingleStep, and MultiStep models and they are easily extendable. Currently, we are using a single-step dense model, but there is a linear model as well.

    After we send our dataset, and data to the training algorithm, we use the model to start the training on the client’s machine. In this algorithm, this function will return the model state. After that, we can enter the test function as well. So finish time depends on the number of values we have and the performance of the machine it is running on. It can take from 10 minutes to an hour to train the neural network.

    Here you can see what it looks like inside Wombat.

    So as you can see, here we have the actual values for different metrics, then we have the expected ranges for the predictions.

    You can see here what happens if one metric or two crosses their expected range. Here we are using Exponential Smoothings and they are calculated all of the values before the current timestamp, including the current one as well. It’s going to adapt as it goes. As the actual values are going down, the predictions are going to follow that trend. So two alarms raised because we have two metrics that crossed their expected ranges.

    From Wombat, we can simply configure it. We have a port, a forecast horizon and as I said, we can filter the metrics that we would like to send for training. The port is necessary for the RestAPI communication. The forecast horizon defines how many metrics we want to forecaste after the current timestamps. So in the case of Wombat, hourly metrics mean that, if we set the horizon to five, it means we will have five minutes of metrics ahead of the current timestamp. For the daily one, as they are calculated every 15 minutes, it means that a forecast horizon with the value of 5 results in 5 times 15, 1 hour and 15 minutes worth of metrics ahead of the current timestamp. For the weekly, it means, 5 hours ahead of the current timestamp because the weekly metrics are calculated every hour. So we will have a lot of data for those types as well.

    The resources we have used are the TensorFlow documentation and tutorials because it’s really easy to integrate those models and concepts into Axon. Of course, I used  Axon and Nx documentations, “ Forecasting: Principles and Practices ” book. I used the second edition, but the third edition is available as well. It’s really interesting and it tells you a lot of cool stuff about how they did time series, data forecasting when neural networks were not available, how to use with it statistics like ARIMA, seasonal ARIMA, exponential smoothings, how they compose the data into a separate component.

    It was very interesting to read I learned a lot of cool stuff that was very helpful in the creation of Arnold. I used the Erlang Ecosystem Foundation Slack Channel and Machine Learning Channel where I could contact the creators of both libraries. And the time series forecasting methods from influx data because that’s where the idea came of instant friction to combine exponential smoothings with neural networks.

    What are the plans for Arnold?

    We are cleaning it up and we are implementing unit tests as well so that we can automate the testing process and the release process. We would like to have Prometheus integration to have an optional training method. So we won’t have dynamic learning, but with the help of this integration, we can instantly send a lot of data to Arnold and we don’t have to use simple predictions. We can immediately start the training and we can use neural networks.

    We are open sourcing the project which is available now on GitHub and also in the documentation, and a Wiki guide on how you can contribute.

    We have a long README where I’m trying to gather how Arnold works and how you can use it, how to compile it from source code or you can just download an already prepackaged compressed file. We have the wiki as well on how you can contribute and the structure is still under development. And, of course, we have the whole documentation for Arnold at esl.github.io/arnold.

    We can see Arnold running in the background. As you can see, we have the expected ranges, the actual values, and the predictions as well. And I’m just gonna do a quick garbage collection so that it will trigger alarms and I can show you one.

    If you want to use Arnold, in Wombat, you just have to manually configure it at the data export page and you don’t have to download Arnold separately or start it separately. It’s all handled by the integration. So basically, no additional manual work is needed for that.

    Two metrics crossed their expected ranges and we can see two alarms were raised. And we can see that a metric is out of range, the detailed information can be found in the additional info that process memory is currently lower than the expected range by that amount of bytes. We can see the total memory as well and as you can see, we have a positive correlation… For the process memory, we have a positive correlation with total memory. And for the total memory, we have a positive correlation with the process memory.

    Wombat’s new UI

    Janos Sandor : There will be a new UI for Wombat. We’ve been working on this since the old UI became overwhelmed, too complex, and hard to maintain. Contained a lot of deprecated JS libraries and was hard to make proper E2E test cases. The new UI will use the Angular library and official angular-based extensions. This is almost built from the ground and we wanted to keep only the necessary parts.

    The base design is provided by the Angular Material official add-on library. It has lots of built-in animated and nice-looking web elements with icons. Almost everything could be imported from its modules that we used in the previous UI. And it will be easier to build custom themes later on.

    Instead of Javascript, all the source files are written in Typescript . Its compiler is a huge help in finding bugs and avoiding race-conditions.

    We kept the “front-page” dashboard view. We can combine metrics, graphs, alarms, and statistics here.

    We can move these panels, we can resize them, and can add more panels, or we can switch to different front pages.

    The side menu provides the primary way of navigating between the main views. (Before we had the top toolbar, but now we have a side menu.)

    On Topology we can see the information about the nodes.

    Logs can be listed on another view, called ‘Logs’. We can set up an auto-refresh, and filter the logs. We can check them. If the log message was too long, it would be split into more parts and the user could load them all or one-by-one.

    We have a different page to check the raised alarms.

    The new dashboard has a feature for the right-click (context) menu. The context menu is different on each page. There are some persistent menu items, like adding nodes or getting to the configurations.

    Metrics page looks almost the same as before. We can visualise metric graphs just like on the old UI. There is a live-mode to update the graph continuously.

    We have the tools page. We can check the process manager. We can see the process information and also we can monitor processes. Of course, we have a table visualizer. We can read the content of the ETS Tables.

    In the configuration menu, we have the ‘Data explore’ menu where we can configure the integrations.

    The new UI has another new feature. It has a dark mode. We can switch to dark mode.

    We can create new families, manage the nodes, and remove nodes or families.

    Telemetry.

    Mohamed Ali Khechine : We rely on telemetry to expose certain metrics. For example, by default, Wombat gets its Phoenix metrics by the telemetry ones and similarly to the Ecto. We also have a telemetry plugin that creates metrics that you customised through telemetry. So basically, if you have telemetry metrics which are events that expose values and have specific event names and so on, Wombat will create metrics based on them and they will, of course, be shown here. So in the same way as exometer, when you create an exometer metric, Wombat will also pick it up and expose it as a metric that you can subsequently basically expose in the Prometheus format and, of course, show it in the Grafana or anywhere else. I hope I answered the question.

    The post WombatOAM & the machine learning library appeared first on Erlang Solutions .

    • chevron_right

      ProcessOne: ejabberd 22.05

      news.movim.eu / PlanetJabber • 17 May, 2022 • 12 minutes

    A new ejabberd release is finally here! ejabberd 22.05 includes five months of work, 200 commits, including many improvements (MQTT, MUC, PubSub, …) and bug fixes.

    • Improved MQTT, MUC, and ConverseJS integration
    • New installers and container
    • Support Erlang/OTP 25

    When upgrading from the previous version please notice: there are minor changes in SQL schemas, the included rebar and rebar3 binaries require Erlang/OTP 22 or higher, and make rel uses different paths. There are no breaking changes in configuration, and only one change in commands API.

    A more detailed explanation of those topics and other features:

    New Indexes in SQL for MUC

    Two new indexes were added to optimize MUC. Those indexes can be added in the database before upgrading to 22.05, that will not affect older versions.

    To update an existing database, depending on the schema used to create it:

    • MySQL ( mysql.sql or mysql.new.sql ):
    CREATE INDEX i_muc_room_host_created_at ON muc_room(host(75), created_at);
    CREATE INDEX i_muc_room_subscribers_jid USING BTREE ON muc_room_subscribers(jid);
    
    • PostgreSQL ( pg.sql or pg.new.sql ):
    CREATE INDEX i_muc_room_host_created_at ON muc_room USING btree (host, created_at);
    CREATE INDEX i_muc_room_subscribers_jid ON muc_room_subscribers USING btree (jid);
    
    • SQLite ( lite.sql or lite.new.sql ):
    CREATE INDEX i_muc_room_host_created_at ON muc_room (host, created_at);
    CREATE INDEX i_muc_room_subscribers_jid ON muc_room_subscribers(jid);
    
    • MS SQL ( mssql.sql ):
    CREATE INDEX [muc_room_host_created_at] ON [muc_registered] (host, nick)
        WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);
    CREATE INDEX [muc_room_subscribers_jid] ON [muc_room_subscribers] (jid);
    

    Fixes in PostgreSQL New Schema

    If you moved your PostgreSQL database from old to new schema using mod_admin_update_sql or the update_sql API command, be aware that those methods forgot to perform some updates.

    To fix an existing PostgreSQL database schema, apply those changes manually:

    ALTER TABLE archive DROP CONSTRAINT i_archive_sh_peer;
    ALTER TABLE archive DROP CONSTRAINT i_archive_sh_bare_peer;
    CREATE INDEX i_archive_sh_username_peer ON archive USING btree (server_host, username, peer);
    CREATE INDEX i_archive_sh_username_bare_peer ON archive USING btree (server_host, username, bare_peer);
    
    DROP TABLE carboncopy;
    
    ALTER TABLE push_session DROP CONSTRAINT i_push_session_susn;
    CREATE UNIQUE INDEX i_push_session_susn ON push_session USING btree (server_host, username, service, node);
    
    ALTER TABLE mix_pam DROP CONSTRAINT i_mix_pam;
    ALTER TABLE mix_pam DROP CONSTRAINT i_mix_pam_us;
    CREATE UNIQUE INDEX i_mix_pam ON mix_pam (username, server_host, channel, service);
    CREATE INDEX i_mix_pam_us ON mix_pam (username, server_host);
    
    ALTER TABLE route DROP CONSTRAINT i_route;
    CREATE UNIQUE INDEX i_route ON route USING btree (domain, server_host, node, pid);
    
    ALTER TABLE mqtt_pub DROP CONSTRAINT i_mqtt_topic;
    CREATE UNIQUE INDEX i_mqtt_topic_server ON mqtt_pub (topic, server_host);
    

    API Changes

    The oauth_revoke_token API command has changed its returned result. Check oauth_revoke_token documentation.

    API Batch Alternatives

    If you use the command delete_old_messages periodically and noticed it can bring your system to an undesirable state with high CPU and memory consumption…

    Now you can use delete_old_messages_batch , which performs the operation in batches, by setting the number of messages to delete per batch and the desired rate of messages to delete per minute.

    Two companion commands are added: delete_old_messages_status to check the status of the batch operation, and abort_delete_old_messages to abort the batch process.

    There are also new equivalent commands to delete old MAM messages.

    Erlang/OTP and Elixir

    From now, Erlang/OTP 25 is supported. As that’s a brand new version, for stable deployments you may prefer to use 24.3 or other lower version.

    Notice that ejabberd can be compiled with Erlang as old as 19.3, but the rebar and rebar3 binaries included with ejabberd 22.05 require at least Erlang 22. This means that, to compile ejabberd 22.05 with those tools using an Erlang version between 19.3 and 21.3, you should get yourself a compatible rebar/rebar3 binary. If your operating system doesn’t provide a suitable one, you can download the old ones: rebar from ejabberd 21.12 and rebar3 from ejabberd 21.12 .

    Regarding Elixir supported versions:

    • Elixir 1.4 or higher is supported for compilation, but:
    • Elixir 1.10 is required to build OTP releases ( make rel and make dev )
    • Elixir 1.11 is required to run make relive
    • Elixir lower than 1.11.4 requires Erlang lower than 24 to build OTP releases

    mod_conversejs

    mod_conversejs was introduced in ejabberd 21.12 to serve a simple page for the Converse.js XMPP web browser client.

    Several improvements in mod_conversejs now allow a simpler configuration, and more customization at the same time:

    • The options now support the @HOST@ keyword
    • The options now support auto , which uses local or remote Converse files
    • The Converse’s auth and register options are set based on ejabberd’s configuration
    • default_domain option now has @HOST@ as default value, not the first defined vhost
    • conversejs_options : New option to setup additional options for Converse
    • conversejs_resources : New option to serve converse.js files (no need to setup an additional web server)

    For example, if you downloaded Converse, now you can setup WebSocket, mod_conversejs , and serve Converse without additional web server, in an encrypted port, as simple as:

    listen:
      -
        port: 443
        module: ejabberd_http
        tls: true
        request_handlers:
          /websocket: ejabberd_http_ws
          /conversejs: mod_conversejs
    
    modules:
      mod_conversejs:
        conversejs_resources: "/home/ejabberd/conversejs-9.0.0/package/dist"
    

    With that configuration, Converse is available in https://localhost/conversejs

    More details in the mod_conversejs documentation .

    New Installers

    For many years, the release of a new ejabberd source code package was accompanied with binary installers, built using InstallBuilder and CEAN, and available in the ProcessOne Downloads page.

    Since this ejabberd 22.05, there are new installers that use a completely different build method:

    • they are built using the tools provided in PR 3781
    • they use the most recent stable dependencies
    • they are available for linux/amd64 and linux/arm64 architectures
    • they are built automatically using the Installers Workflow
    • for stable releases, they are available for download in the ejabberd GitHub Releases
    • they are built also for every commit in master branch, and available for download in the results of Installers Workflow
    • if the installer is ran by root, it installs in /opt/ejabberd* and setups systemd service
    • if ran by a regular user, it asks installation path

    However, compared to the old installers, those new installers:

    • do not ask for domain: now you must edit ejabberd.yml and set the hosts option
    • do not register the first Jabber account and grant admin rights: you must do it yourself

    Please give those new installers a try, and comment any problem, improvement or ideas.

    New Container Image

    In addition to the ejabberd/ecs Docker container image published in Docker Hub , there is a new container image published in ejabberd GitHub Packages .

    Its usage is similar to the ejabberd/ecs image, with some benefits and changes worth noting:

    • it’s available for linux/amd64 and linux/arm64 architectures
    • it’s built also for master branch, in addition to the stable ejabberd releases
    • it includes less customizations to the base ejabberd compared to ejabberd/ecs
    • it stores data in /opt/ejabberd/ instead of /home/ejabberd/

    See its documentation in CONTAINER .

    If you used previous images from that GitHub Packages registry please note: until now they were identical to the ones in Docker Hub, but the new 22.05 image is slightly different: it stores data in /opt/ejabberd/ instead of /home/ejabberd/ . You can update the paths to the container volumes in this new image, or switch to Docker Hub to continue using the old same images.

    Source Code Package

    Until now, the source code package available in the ProcessOne Downloads page was prepared manually together with the binary installers. Now all this is automated in GitHub, and the new source code package is simply the same one available in GitHub Tags .

    The differences are:

    • instead of tgz it’s now named tar.gz
    • it contains the .gitignore file
    • it lacks the configure and aclocal.m4 files

    The compilation instructions are slightly improved and moved to a separate file: COMPILE.md

    New make relive

    This new make relive is similar to ejabberdctl live , but without requiring to install or build an OTP release: compile and start ejabberd immediately!

    Quickly put:

    • Prepare it with: ./autogen.sh && ./configure --with-rebar=./rebar3 && make
    • Or use this if you installed Elixir: ./autogen.sh && ./configure --with-rebar=mix && make
    • Start without installing (it recompiles when necessary): make relive
    • It stores config, database and logs in _build/relive/
    • There you can find the well-known script: _build/relive/ejabberdctl
    • In that erlang shell, recompile source code and reload at runtime: ejabberd_admin:update().

    Please note, when make relive uses Elixir’s Mix instead of Rebar3, it requires Elixir 1.11.0 or higher.

    New GitHub Workflows

    As you may notice while reading these release notes, there are new github workflows to build and publish the new installers and the container images, in addition to the Common Tests suite.

    The last added workflow is Runtime. The Runtime workflow ensures that ejabberd compiles with Erlang/OTP 19.3 up to 25, using rebar, rebar3 and several Elixir versions. It also checks an OTP release can be built, started, register an account, and stop ejabberd.

    See its source code runtime.yml and its results .

    If you have troubles compiling ejabberd, check if those results reproduce your problem, and also see the steps used to compile and start ejabberd using Ubuntu.

    Translations Updates

    The German, Portuguese, Portuguese (Brazil), Spanish and Catalan translations are updated and completed. The French translation was greatly improved and updated too.

    Documentation Improvements

    Some sections in the ejabberd Documentation are improved:

    ChangeLog

    Core

    • C2S: Don’t expect that socket will be available in c2s_terminated hook
    • Event handling process hook tracing
    • Guard against erlang:system_info(logical_processors) not always returning a number
    • domain_balancing : Allow for specifying type only, without specifying component_number

    MQTT

    • Add TLS certificate authentication for MQTT connections
    • Fix login when generating client id, keep connection record ( #3593 )
    • Pass property name as expected in mqtt_codec (fixes login using MQTT 5)
    • Support MQTT subscriptions spread over the cluster ( #3750 )

    MUC

    • Attach meta field with real jid to mucsub subscription events
    • Handle user removal
    • Stop empty MUC rooms 30 seconds after creation
    • default_room_options : Update options configurable
    • subscribe_room_many_max_users : New option in mod_muc_admin

    mod_conversejs

    • Improved options to support @HOST@ and auto values
    • Set auth and register options based on ejabberd configuration
    • conversejs_options : New option
    • conversejs_resources : New option

    PubSub

    • mod_pubsub : Allow for limiting item_expire value
    • mod_pubsub : Unsubscribe JID on whitelist removal
    • node_pep : Add config-node and multi-items features ( #3714 )

    SQL

    • Improve compatibility with various db engine versions
    • Sync old-to-new schema script with reality ( #3790 )
    • Slight improvement in MSSQL testing support, but not yet complete

    Other Modules

    • auth_jwt : Checking if an user is active in SM for a JWT authenticated user ( #3795 )
    • mod_configure : Implement Get List of Registered/Online Users from XEP-0133
    • mod_host_meta : New module to serve host-meta files, see XEP-0156
    • mod_mam : Store all mucsub notifications not only message notifications
    • mod_ping : Delete ping timer if resource is gone after the ping has been sent
    • mod_ping : Don’t send ping if resource is gone
    • mod_push : Fix notifications for pending sessions (XEP-0198)
    • mod_push : Keep push session ID on session resume
    • mod_shared_roster : Adjust special group cache size
    • mod_shared_roster : Normalize JID on unset_presence ( #3752 )
    • mod_stun_disco : Fix parsing of IPv6 listeners

    Dependencies

    • autoconf: Supported from 2.59 to the new 2.71
    • fast_tls: Update to 1.1.14 to support OpenSSL 3
    • jiffy: Update to 1.1.1 to support Erlang/OTP 25.0-rc1
    • luerl: Update to 1.0.0, now available in hex.pm
    • lager: This dependency is used only when Erlang is older than 22
    • rebar2: Updated binary to work from Erlang/OTP 22 to 25
    • rebar3: Updated binary to work from Erlang/OTP 22 to 25
    • make update : Fix when used with rebar 3.18

    Compile

    • mix release : Copy include/ files for ejabberd, deps and otp, in mix.exs
    • rebar3 release : Fix ERTS path in ejabberdctl
    • configure.ac : Set default ejabberd version number when not using git
    • mix.exs : Move some dependencies as optional
    • mix.exs : No need to use Distillery, Elixir has built-in support for OTP releases ( #3788 )
    • tools/make-binaries : New script for building Linux binaries
    • tools/make-installers : New script for building command line installers

    Start

    • New make relive similar to ejabberdctl live without installing
    • ejabberdctl : Fix some warnings detected by ShellCheck
    • ejabberdctl : Mention in the help: etop , ping and started / stopped
    • make rel : Switch to paths: conf/ , database/ , logs/
    • mix.exs : Add -boot and -boot_var in ejabberdctl instead of adding vm.args
    • tools/captcha.sh : Fix some warnings detected by ShellCheck

    Commands

    • Accept more types of ejabberdctl commands arguments as JSON-encoded
    • delete_old_mam_messages_batch : New command with rate limit
    • delete_old_messages_batch : New command with rate limit
    • get_room_occupants_number : Don’t request the whole MUC room state ( #3684 , #1964 )
    • get_vcard : Add support for MUC room vCard
    • oauth_revoke_token : Add support to work with all backends
    • room_unused_* : Optimize commands in SQL by reusing created_at
    • rooms_unused_... : Let get_all_rooms handle global argument ( #3726 )
    • stop|restart : Terminate ejabberd_sm before everything else to ensure sessions closing ( #3641 )
    • subscribe_room_many : New command

    Translations

    • Updated Catalan
    • Updated French
    • Updated German
    • Updated Portuguese
    • Updated Portuguese (Brazil)
    • Updated Spanish

    Workflows

    • CI: Publish CT logs and Cover on failure to an external GH Pages repo
    • CI: Test shell scripts using ShellCheck ( #3738 )
    • Container: New workflow to build and publish containers
    • Installers: Add job to create draft release
    • Installers: New workflow to build binary packages
    • Runtime: New workflow to test compilation, rel, starting and ejabberdctl

    Full Changelog

    All changes between 21.12 and 22.05

    ejabberd 22.05 download & feedback

    As usual, the release is tagged in the Git source code repository on GitHub .

    The source package and installers are now available in GitHub Release / Tags . To check the *.asc signature files, see How to verify ProcessOne downloads integrity .

    The Docker image is in Docker Hub , and a new Container image at GitHub Packages .

    If you suspect that you’ve found a bug, please search or fill a bug report on GitHub Issues .

    The post ejabberd 22.05 first appeared on ProcessOne .
    • chevron_right

      JMP: Togethr: Soprani.ca Social

      news.movim.eu / PlanetJabber • 11 May, 2022 • 2 minutes

    Last week we launched a sister product from the same team that brings you JMP: Togethr .  Why are we launching a second product?  Why now?  What does this have to do with the mission of JMP in particular, or the Sopranica project in general?

    Togethr is a managed hosting platform for small Fediverse instances.  It is powered by the ActivityPub protocol that powers Mastodon, PeerTube, and so many others.  While there are several social networking solutions that build on XMPP (just like JMP does), and indeed we use one for this blog, we chose to go with something else for Togethr.  Does that mean we don’t have hope for XMPP in the social space?  No, rather it is an admission that the largest network for people to interact with in this way exists on ActivityPub-compatible software, and people need a solution they can use today .

    As it grows, Togethr gives us the “skin in the game” motivation to bridge these worlds.  We are not the only ones interested in bridging the XMPP and ActivityPub worlds together, in fact the Libervia project is currently working on a grant to produce a first version of a gateway, that should be generally usable later this year.  We hope to eventually roll out an update that makes every Togethr instance seamlessly be both ActivityPub and XMPP without anyone needing to change their address.

    Why not wait until “everything is ready” to go live with XMPP and ActivityPub at the same time?  Well, people need a solution.  Many people fleeing silos or otherwise being attracted to federated social networking find that self-hosting is too complicated, or they just don’t have the time to dedicate to it.  Many of these people end up creating an account on a giant volunteer-run instance, joining yet another silo (albeit a nicely federated one) run by admins they don’t know with financial and mental pressures they cannot understand.

    Togethr gives people looking to federate their digital social networking experience full control without requiring systems administration knowledge or time.  Our team not only keeps the instance running, but provides support for users who may not be familiar with the software or the fediverse in general and need help getting everything set up.  However, there is no lock-in and people can easily move to another host or self-hosting at any time.  For example, if someone got an instance example.party and created the user person they would have address person@example.party just like you would expect on any Fediverse instance.  However, since they control the domain they could move to a different host or self-host, point the domain at the new instance, copy over their data, and no one has to “follow me at my new address”, everything just keeps working.

    While we believe that single-user instances are the pinnacle of federation, Togethr does not limit the way people want to use it.  People may have family or friends they want to share posts with, who might not be motivated to join the Fediverse but will accept a personal invitation.  So every Togethr instance allows the customer to invite whoever they would like to join them on the instance, in order to smooth the onboarding for friends and family.  We hope that this can provide an option for people looking to take control over more of their digital life.

    • wifi_tethering open_in_new

      This post is public

      blog.jmp.chat /b/togethr-sopranica-social

    • chevron_right

      Gajim: Gajim 1.4.0

      news.movim.eu / PlanetJabber • 11 May, 2022 • 2 minutes

    After more than a year of development, it’s finally time to announce the release of Gajim 1.4.0! 🎉 Gajim 1.4 series comes with a completely redesigned message window and conversation management. Workspaces allow you to organize your chats to keep matters separate where needed. These changes were only possible by touching a lot of Gajim’s code base, and we appreciate all the feedback we got from you.

    What’s New

    The new Gajim version comes with a completely redesigned main window. This window offers a sidebar containing workspaces, where you can organize all of your chats. Workspaces have been explained in detail last year . Each workspace holds a list of currently opened chats for both 1:1 chats and group chats. This makes it easy for you to keep matters separate. To make things simple and easy to use, we decided to migrate to a single window approach for Gajim. Chats opened via chat list will be displayed right next to it, keeping the window compact.

    Gajim’s new main window

    Gajim’s new main window

    The way Gajim displays messages had not been changed for years. The previous approach had many limitations, but it was hard to replace it. Gajim 1.4 comes with a new approach, where each message is a separate ‘row’, which you can see in the above screenshot. This approach does not only look much cleaner, it also enables us to implement new features in the future, thinking of message reactions, replies, and so on.

    For these changes to be implemented, we had to touch and refactor a good part of Gajim’s code base. Please report any issue you find! We appreciate your feedback.

    Windows users please note: Windows builds are now based on Python 3.9, which does not run on Windows 7 or older.

    More Changes

    New

    • Redesigned Contact Info and Group Chat Info windows
    • Redesigned Group Chat Creation window
    • Full compatibility with XEP-0393 Message Styling
    • Real-time message styling in the chat input box
    • URL Image Preview, Plugin Installer, Syntax highlighting, and AppIndicator plugins have been integrated into Gajim
    • Support for XEP-0425 Message Moderation in group chats
    • Administrators can now define setting overrides

    Changes

    • Reworked notification system
    • History manager has been replaced by Gajim’s internal search
    • ‘Note to myself’ feature: write messages to your own contact (e.g. to another device)
    • Improved Windows installer
    • Improved contrast for light and dark themes
    • Bookmark management window has been removed (all actions are still available in Gajim’s user interface)
    • XEP-0174 Serverless Messaging via Zeroconf has been removed
    • Client certificate setup has been removed
    • User Mood ( XEP-0107 ) and User Activity ( XEP-0108 ) have been removed

    Fixes

    Over 120 issues have been fixed in this release

    Have a look at the changelog for the complete list.

    Gajim

    As always, don’t hesitate to contact us at gajim@conference.gajim.org or open an issue on our Gitlab .

    • wifi_tethering open_in_new

      This post is public

      gajim.org /post/2022-05-11-gajim-1.4.0-released/

    • chevron_right

      Paul Schaub: Creating an OpenPGP Web-of-Trust Implementation – A Series

      news.movim.eu / PlanetJabber • 6 May, 2022 • 4 minutes

    I am excited to announce that PGPainless will receive funding by NGI Assure to develop an implementation of the Web-of-Trust specification proposal!

    https://nlnet.nl/assure/

    The Web-of-Trust (WoT) serves as an example of a decentralized authentication mechanism for OpenPGP. While there are some existing implementations of the WoT in applications such as GnuPG, their algorithms are often poorly documented. As a result, WoT support in client applications is often missing or inadequate.

    This is where the aforementioned specification comes into play. This document strives to provide a well-documented description of how to implement the WoT in an interoperable and comprehensible way. There is already an existing implementation by the Sequoia-PGP project (Neal, the author of the specification is also heavily involved with Sequoia) which can serve as a reference implementation.

    Since I imagine implementing the Web-of-Trust isn’t a straight-forward task (even though there is now a specification document), I decided to dedicate a series of blog posts to go along with my efforts. Maybe this helps others implementing it in the future.

    What exactly is the Web-of-Trust?

    The essential problem with public key infrastructure (PKI) is not to obtain the encryption keys for contacts, but rather verify that the key you have of a contact really is the proper key and not that of an attacker. One straight-forward solution to this is used by every user of the internet every day. If you visit a website on the internet, the web server of the site presents your browser with its TLS certificate. Now the browser has to figure out, if this certificate is trustworthy. It does so by checking if there is a valid trust-path from one of its root certificates to the sites certificate. Your browser comes with a limited set of root-certificates already preinstalled. This set was agreed upon by your browsers/OS vendor at some point. These root certificates are (mostly) managed by corporations who’s business model is to vouch for your servers authenticity. You pay them so that they testify to others that your TLS certificate is legitimate.

    In this case, a trust-path is a chain of certifications from the trusted root certificate down to the sites TLS certificate. You can inspect this chain manually, by clicking the lock icon in your browsers task bar (at least on Firefox). Below is a visualization of the TLS certificate chain of this blog’s TLS certificate.

    The certificate “ISRG Root X1” belongs to let’s encrypt , a not-for-profit CA that very likely is embedded in your browser already. R3 is an intermediate certificate authority of let’s encrypt. It certified my blogs TLS certificate. Since during the certificate renewal process let’s encrypt made sure that my server controls my domain, it has some degree of confirmation that blog.jabberhead.tk in fact belongs to me. This step can be called manual identity verification. As a result, it can therefore attest the legitimacy of my TLS certificate to others.

    One property of this model is that its centralized. Although there is a number of root certificates (hundreds in fact, check your /etc/ssl/certs/ directory!), it is not trivial to set up your own, let alone get browser/OS vendors to include it in their distributions.

    Now lets take a look at the Web-of-Trust instead. The idea that describes the difference between the centralized TLS model and the WoT best, is that people trust people instead of corporations . If Alice trusts and vouches for Bob, and Bob trusts and vouches for Charlie, Alice could transitively trust Charlie. These trust paths can get arbitrarily long and the whole network of trust paths is what we call the Web-of-Trust. Instead of relying on a more-or-less trustworthy certificate authority to attest key authenticity, we gather evidence for the trustworthiness of a key in our social circle.

    This model can be applied to corporate environments as well by the way. Let’s say FooBank is using the Web-of-Trust for their encrypted email traffic. FooBanks admin would be tasked with keeping a list of the email addresses of all current employees and their encryption keys. They would then certify these keys by signing them with a company key which is kept secure. These certification signatures are valid as long as the employee is working at the bank. Other employees would in return sign the company key and mark it as trustworthy. Now they can build a trust path from their own key to that of each other current employee. In that sense, the CA model can be seen as a special case of the Web-of-Trust.

    The main problem now is to find an algorithm for determining whether a valid trust path exists between our trust-root and the certificate of interest. You might wonder “What is the trust-root? I thought the WoT comes without centralized trust in a single entity?”. And you are right. But we all trust ourselves, don’t we? And we trust ourselves to decide whom to trust. So to realize the WoT, we define that each user has their own “trust-root” certificate, which is a single certificate that certifies “trusted introducers”. This is the start of the trust-path. In case of FooBank, Employee Albert might for example have a personal trust-root certificate that certifies FooBanks CA key, as well as that of Alberts wive Berta. Now Albert can securely message any FooBank employee, as well as his wive, since there are trust-paths available from his trust-root to those contacts.

    Luckily, the problem of finding an algorithm to determine trust-paths is already solved by the Web-of-Trust specification. All that’s left to do is to understand and implement it. That cannot be that hard, can it?

    To be continued…

    • wifi_tethering open_in_new

      This post is public

      blog.jabberhead.tk /2022/05/06/creating-an-openpgp-web-of-trust-implementation-a-series/