Install Realm Object Server

macOS

On macOS, this installation is as simple as downloading a file:

Download the macOS bundle

Navigate to your downloads folder and open the “realm-mobile-platform” folder.

Start Realm Object Server by double-clicking the file start-object-server.command. This file will open a terminal window and start Realm Object Server for you.

Linux

Under Linux, Realm’s package repositories are managed through a service called PackageCloud. Run the following commands to set up the package repositories, then install and start Realm Object Server:

# Setup Realm's PackageCloud repository
curl -s https://packagecloud.io/install/repositories/realm/realm/script.rpm.sh | sudo bash

# Install the Realm Object Server
sudo yum -y install realm-object-server-de

# Enable and start the service
sudo chkconfig realm-object-server on
sudo service realm-object-server start
# Setup Realm's PackageCloud repository
curl -s https://packagecloud.io/install/repositories/realm/realm/script.rpm.sh | sudo bash

# Install the Realm Object Server
sudo yum -y install realm-object-server-de

# Enable and start the service
sudo systemctl enable realm-object-server
sudo systemctl start realm-object-server
# Setup Realm's PackageCloud repository
curl -s https://packagecloud.io/install/repositories/realm/realm/script.deb.sh | sudo bash

# Update repositories
sudo apt-get update

# Install the Realm Object Server
sudo apt-get install realm-object-server-de

# Enable and start the service
sudo systemctl enable realm-object-server
sudo systemctl start realm-object-server

We also provide public AMIs for Amazon EC2, based on Ubuntu 16.04. For details on the difference between Paravirtual and HVM see this guide.

  Paravirtual HVM
ap-northeast-1 (Tokyo) ami-fae9879d ami-f8e9879f
eu-west-1 (Ireland) ami-74103607 ami-891137fa
us-east-1 (N. Virginia) ami-e6939df1 ami-04979913

You can launch these AMIs just as any other Amazon EC2 AMI. Make sure you open port 22/TCP (ssh) and 9080/TCP (dashboard and client access). The default SSH user is ubuntu.

Setting Up the Realm Dashboard

You will need access to a web browser either on the local Linux machine, or remotely over the network. If you are using a remote browser, you will need to know the network IP address or hostname of the server you just installed ROS on. Replace localhost with the appropriate IP address or hostname in the URL below.

Open a new browser window and go to http://localhost:9080. The login page for the Realm Dashboard will be displayed. If your Linux server is not your local machine, replace localhost with the IP address of your server.

Create an admin user by entering your email and password. After registering, you can log in using these credentials.

The Realm Dashboard will show you the status of the Realm Object Server, including active network connections, active Realms, and the amount of network traffic being generated by connected apps.

Configuring The Server

Realm Object Server includes a configuration file in YAML format that comes with sensible defaults for a development environment. The configuration file can be edited to customize the installation and make it production-ready. In the following we will refer to the configuration file as configuration.yml.

The various configuration options available in configuration.yml are described below. The default location of the configuration file depends on your platform:

The configuration file is in /etc/realm/configuration.yml.

The configuration file is in realm-object-server/object-server inside your Realm Mobile Platform folder.

Paths in the configuration file can be either absolute or relative. If relative, they are resolved according to the current working directory. We recommend always using absolute paths to avoid confusion.

Mandatory settings

A few options are mandatory to set in order to be able to start Realm Object Server. We recommend specifying these in configuration.yml, but they can also be given as command line arguments.

The mandatory configuration defines:

  1. An existing directory where Realm Object Server will store all its files,
  2. Paths to a key pair used for securing access to ROS to only allow authenticated clients to access it. The keys given must be in PEM format and they must be a matching pair.

Here is a summary of the settings:

Configuration key CLI argument Description
storage.root_path --root Path to the directory where ROS will store all its data files
auth.public_key_path --public-key Path to the public key (stored in PEM format) used to authenticate client tokens
auth.private_key_path --private-key Path to the private key (stored in PEM format) used to authenticate client tokens

Network

In its default configuration Realm Object Server runs internal backend services as well as a proxy module. The backend services are only reachable from the host running the server, and all traffic to them are passed through the proxy module which listen on all interfaces. The following diagram should explain the default configuration:

Proxy config diagram

In the following we show how to change this default configuration.

Backend Services

Realm Object Server internally starts two backend services. The sync service is responsible for core synchronization functionality, and listens on port 27800. The http service handles requests for authentication and the dashboard and listens on port 27080. By default, the services only listen on the host’s IPv4 loopback address (127.0.0.1) and requests are routed through the proxy module.

Should you wish to disable the proxy module and let backend services listen to all IPv4 and IPv6 interfaces this can be achieved by setting the appropriate listen_address to ::. Similarly, the listening ports can be changed by modifying the appropriate listen_port.

Here is a summary of the settings:

Configuration key Default Description
network.sync.listen_address 127.0.0.1 Address the sync service should bind to
network.sync.listen_port 27800 Port the sync service should bind to
network.http.listen_address 127.0.0.1 Address the http service should bind to
network.http.listen_port 27080 Port the sync service should bind to

Proxy module

The included transparent proxy module dispatches all incoming traffic to the appropriate backend service. This proxy is capable of handling both HTTP, WebSocket, HTTPS and Secure WebSocket traffic (but exclusively traffic destined for the Realm Object Server, this is not a general purpose proxy). In the default configuration, the HTTP proxy listens on all IPv4 and IPv6 interfaces on port 9080, but the HTTPS proxy is disabled. Both variants of the proxy can be enabled simultaneously.

If you wish, you can disable the included proxy module and replace it with a standalone proxy installation or use ROS by exposing the backend services on the network for direct client access.

Here is a summary of the proxy’s configuration settings:

Configuration key Default Description
proxy.http.enable true Set to false to disable the HTTP Proxy
proxy.http.listen_address :: Supply an interface address, 0.0.0.0 for all IPv4 interfaces or :: for all IPv4 and IPv6 interfaces
proxy.http.listen_port 9080 Supply an alternative port for the HTTP Proxy
proxy.https.enable false Set to true to enable the HTTPS Proxy
proxy.https.listen_address :: Supply an interface address, 0.0.0.0 for all IPv4 interfaces or :: for all IPv4 and IPv6 interfaces
proxy.https.listen_port 9443 Supply an alternative port for the HTTPS Proxy
proxy.https.certificate_path   Path to the HTTPS Proxy’s certificate file, in PEM format
proxy.https.private_key_path   Path to the HTTPS Proxy’s private key file, in PEM format

If you wish to enable the HTTPS Proxy, you must provide certificate and private key files in PEM format by setting the proxy.https.certificate_path and proxy.https.private_key_path options. The certificate cannot be self-signed.

Logging

Realm Object Server logs messages information about its state and progress. Logs can be written to the console or to a file depending on the logging.path configuration, and the logging detail can be tuned by changing the logging.level option.

The default value for logging.path depends on the platform:

Logs are written to /var/log/realm-sync.log.

Logs are output on the terminal that launched Realm Object Server.

The value for logging.level can be one of 9 possible values:

logging.level Detail level
all all possible messages
trace used to trace protocol and internal server state
debug internal server debugging messages
detail shows summary of synchronization transactions
info good for production (default)
warn log only warning messages
error log only errors
fatal errors that cause the ROS to exit
off all output suppressed

Here is a summary of the settings:

Configuration key Default macOS Default linux Description
logging.path   /var/log/realm-sync.log Path to the file where logs should be written. If no value is set, output is written to stdout/stderr.
logging.level info info The amount of detail in the log output, see valid values above

Access Control

Realm Object Server includes access control mechanisms to restrict which users are allowed to sync against which Realm files. There are two concepts: Authentication and Authorization. In order to grant some user access to a Realm, Realm Object Server authenticates the user to verify the identity of the user, and authorizes that the user has the correct permissions to access the Realm. More specifically:

  • Realm Object Server uses configurable authentication providers to validate user credentials and authenticate users. A client connects to the server using some user credentials, and these are given to an appropriate provider for validation. If the credentials are valid, the user is granted access to Realm Object Server. A new user account is created if the credentials are not coupled to an existing account.
  • After the client is granted access as a user, it can request read or write access to a specific path identifying a Realm. If the user has the requested access permissions for the given path, the user is authorized to access the Realm, and normal sync operations can begin.

Authentication

Authentication providers allow developers to utilize third-party authentication mechanisms to control access to Realm apps that go beyond Realm’s own username/password mechanism. Realm supports Facebook, Google, and Apple’s iCloud.

These third-party providers currently operate at the single-server level, and will need to be set up on each server that needs to make use of a given authentication mechanism. The setup is done by providing a set of key-value pairs that identify the authentication mechanism and the required keys/secrets.

This information goes into the auth.providers section of the Realm configuration.yml file.

Below are examples that demonstrate how to integrate each of these third-party authentication providers and where applicable links to the developer pages for those services. Complete examples of all autentication providers can be found in the Realm Object Server configuration.yml file.

Password

  • Username/Password authentication is always enabled

Google

Getting Google OAuth2.0 API Access; enter the client ID key in the google stanza:

google:
  clientId: '012345678901-abcdefghijklmnopqrstvuvwxyz01234.apps.googleusercontent.com'

Facebook

Facebook Authentication does not require any configuration besides enabling the facebook provider. Facebook client tokens received by Realm Object Server will be checked for validity against the Facebook APIs (so ROS needs to be able to contact those). Enabling facebook authentication is done as follows:

facebook: {}

iCloud

iCloud is only available on Apple platforms (iOS, tvOS, watchOS, and macOS).

In order to access CloudKit using Realm Object Server, you will need to create a public key, then connect to Apple’s CloudKit web dashboard and create a CloudKit access key for your application. These keys will be then used to configure the Realm Object Server’s CloudKit authentication module for a specific Realm.

The steps to accomplish this are:

  1. Create a private key using the generateCloudKitCert.sh script. This script can be found in /etc/realm under Linux installations, and in the realm-object-server directory of the macOS distribution. To generate a key, open a terminal window, navigate to the appropriate directory for your distribution, and run /bin/sh generateCloudKitCert.sh. The output from the command will be a base64 public key string; save it.

  2. Generate a CloudKit access key. Using your Apple developer account, log in to Apple’s CloudKit Dashboard; select the application for which you would like to generate an access key.

  3. In the left-hand side of the dashboard, select “API Access”, and then in the middle section, select the drop-down menu (its default setting is “API Tokens”) and select “Server-to-Server Keys”. Select “Add Server-to-Server Key”.

Generating an access key with the CloudKit Dashboard

On the panel that is revealed, give the new key a name, and paste in the public key text generated in Step 1 above. Click “Save” in the lower right corner.

After a few seconds, a key will be generated and displayed in the “Key ID” section across the top of page - this is the key ID needed to configure the Realm CloudKit authentication module.

Security note: Create a new private key for each application you plan on using with Realm CloudKit authentication. Reusing private keys can compromise all Realms using the shared key if the private key itself becomes compromised or needs to be revoked.

In addition to the Key ID from Apple, you will need the CloudKit Container name of your CloudKit app (this will be on the application’s page on the Dashboard), the private key you generated in Step 1, and the Realm App ID for your app.

An example of a fully configured CloudKit stanza will look like this:

cloudkit:
  ## The Key ID from CloudKit.
  key_id: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'

  ## The path to the certificate.
  private_key_path: 'cloudkit_eckey.pem'

  ## The container identifier, in reverse domain name notation.
  container: "iCloud.io.realm.exampleApp.ios"

  ## The environment in which CloudKit should be used. The default is
  ## 'development'. For production deployment on the App Store, you must
  ## specify 'production'.
  environment: 'development'

Authorization

Realm Object Server includes an authorization mechanism which allows controlling which users are granted read or write permissions for specific Realms. This can be used, for example, to create collaborative apps where multiple users write to the same Realm. It can also be used to share data in a publisher/subscriber scenario where a single writing user shares data with many users with read permissions.

In the following we will discuss the technical implementation of the authorization system. The fundamental abstraction is the permission, which is a unique relation between a User and a Realm containing three boolean flags that describes what the user is allowed to do with the Realm:

  • mayRead indicates that the user is allowed to read from the Realm,
  • mayWrite indicates that the user is allowed to write to the Realm,
  • mayManage indicates that the user is allowed to change the permissions for the Realm.

Unless permissions are explicitly modified, only the owner of a Realm can access it. The only exception is admin users: They are always granted all permissions to all Realms on the server.

It is possible to modify both default user permissions as well as individual user permissions for a Realm. If a user requests access to a Realm for which it has no individual user permissions, the default user permissions for the Realm are used to determine if the user should be authorized. If neither individual user permissions nor default user permissions have been created, access is denied.

Admin-Realm

Realm Object Server has a single global admin-Realm. This is the authoritative data store containing the complete set of permissions for all Realm files and users controlled by the server. Request to access a Realm can only be authorized after checking the permissions stored in the admin-Realm.

Administering the Server

The Realm Object Server service uses standard service commands:

sudo service realm-object-server status
sudo service realm-object-server start
sudo service realm-object-server stop
sudo service realm-object-server restart

The Realm Object Server service definition uses standard systemctl commands:

sudo systemctl status realm-object-server
sudo systemctl start realm-object-server
sudo systemctl stop realm-object-server
sudo systemctl restart realm-object-server

To start the server double-click on the start-object-server.command file in the realm-mobile-platform directory you originally downloaded.

To stop the macOS version of the server, simply press CTL-C in the terminal window that was opened by the start-object-server.command.

The Realm Dashboard

Stats

The Realm Dashboard

The Realm Dashboard is an administrative interface to the Realm Object Server used to create/manage users and observe the performance of the Realm Object Server.

User management

An admin user can create users and grant or remove administrative privileges.

The Realm Browser

The Realm Browser is only available for macOS.

The Realm Browser allows developers to observe and edit Realms. The Realm Broswer can connect to either macOS or Linux instances of the Realm Object Server.

To use the Connect to Object Server option in Realm Browser, you must retrive your admin token that was automatically generated, under Linux the token can be view with:

cat /etc/realm/admin_token.base64

on macOS the token is stored in the realm-object-server folder.

Browsing Realms with the Realm Browser for macOS

Data Access

This feature is limited to our Professional and Enterprise editions. Learn more about them and start a free trial.

Realms can be accessed and changed server-side by using the Node.js api. When opening Realms using this api you need to provide a User object and sync url rather than a Realm path. You can obtain a User object from the admin token directly, or you can authenticate as an individual user by calling one of the create or login methods:

// open a realm using the admin user
let admin_user = Realm.Sync.User.adminUser('http://object-server-url:9080/', admin_token);
var realm = new Realm({
    sync: {
        user: admin_user, 
        url: 'realm://object-server-url:9080/~/my-realm'
    }, 
    schema: [{...}
    }]
});

// open a realm logging in as an individual user
Realm.Sync.User.login('http://object-server-url:9080/', 'username', 'password', (error, user) => {
  if (!error) {
    var realm = new Realm({
        sync: {
            user: user, 
            url: 'realm://object-server-url:9080/~/my-realm'
        }, 
        schema: [{...}
        }]
    });

    realm.write(() => {
        ...
    });
  }
});

Upgrading

macOS

Upgrades to the macOS version of the Object Server are delivered by a new macOS download bundle from Realm

Linux

Realm’s package service for stand-alone servers makes the upgrade process is very simple:

# Stop the service before upgrading
sudo service realm-object-server stop

# Install a new version if available
sudo yum -y upgrade realm-object-server-de

# Restart the server to continue operation
sudo service realm-object-server start
# Stop the service before upgrading
sudo systemctl stop realm-object-server

# Install a new version if available
sudo yum -y upgrade realm-object-server-de

# Restart the server to continue operation
sudo systemctl start realm-object-server
# Update the package definitions
sudo apt-get update

# Stop the service before upgrading
sudo systemctl stop realm-object-server

# Install a new version if available
sudo apt-get upgrade realm-object-server-de

# Restart the server to continue operation
sudo systemctl start realm-object-server

Uninstalling

Should you need to uninstall Realm Object Server, the process is straightforward. Back up your data, then run:

# Stop the service before uninstalling
sudo service realm-object-server stop

# Remove the packages
sudo yum -y erase realm-object-server-de
# Stop the service before uninstalling
sudo systemctl stop realm-object-server

# Remove the packages
sudo yum -y erase realm-object-server-de
# Stop the service before uninstalling
sudo systemctl stop realm-object-server

# Remove the packages
sudo apt-get remove realm-object-server-de
# Stop the service before uninstalling
Press CTL-C in the controlling terminal window

# Remove the packages
Drag the realm-mobile-platform folder to the trash

Backup

The backup system

Realm provides a backup console command that backs up a running instance of the Realm Object Server. This command can be executed on a server without shutting it down, any number of times, in order to create an “at rest” backup that can be stored on long-term storage for safekeeping. In order to be as agnostic as possible regarding the way the backup will be persisted, the command simply creates a directory structure containing everything the server needs to get started again in the event of a disk failure.

It is recommended that the resulting directory is compressed and sent to an off-site location, such as Amazon S3 or Online C14.

The backup process consists of making a copy of all directories and Realm databases in the server’s data directory. The data that is backed up includes all the user Realms, all account and user information, and all other internal information used by the Realm Object Server.

Because Realms can be modified during the backup process, the backup command uses Realm’s transaction features to take a consistent snapshot of each Realm. However, since the server is running continuously, the backed up Realms do not represent the state of the server at one particular instant in time. A Realms added to the server while a backup is in progress might be completely left out of the backup. Such a Realm will be included in the next backup.

Usage of the backup command

realm-backup is an executable command used as

realm-backup SOURCE TARGET
  • SOURCE is the data directory of the Realm Object Server (typically configured in /etc/realm/configuration.yml under storage.root_path).
  • TARGET is the directory where the backup files will be placed. This directory must be empty or absent when the backup starts for safety reasons.

After the backup command completes, TARGET will be a directory with the same sub directory structure as SOURCE and a backup of all individual Realms.

Recovery from a server crash

If the data of a Realm Object Server is lost or otherwise corrupted, a new Realm Object Server can be restarted with the backed up data.

This is done by copying the TARGET directory of the latest backup into SOURCE while the server is stopped.

The server may only be started after the backup has been fully copied into SOURCE.

Handling server side data loss

Since the clients communicate with the server continuously, data could have been exchanged between a client and a server after the latest backup. When a server recovers from its latest backup, there could be an inconsistency in the synchronization between some clients and the recovered server. The Realm Object Server system can detect this inconsistency

In the case of inconsistencies, the client will receive, from the server, one of the error messages

  • 208 “Bad client file identifier (IDENT)”
  • 209 “Bad server version (IDENT, UPLOAD)”
  • 211 “Diverging histories (IDENT)”

After one of these errors, the client Realm cannot participate in further synchronization with the server.

The only way to continue synchronization with the server is to start all over from an empty Realm and let the server deliver data. Starting from an empty Realm could lead to data loss since the the original client Realm could contain data unknown to the server.

It is highly recommended to backup the server frequently to avoid the situation where synchronization must be restarted.

Conflict Resolution

One of the defining features of mobile is the fact that you can never count on being online. Loss of connectivity is a fact of life, and so are slow networks and choppy connections. But people still expect their apps to work!

This means that you may end up having two or more users making changes to the same piece of data independently, creating conflicts. Note that this can happen even with perfect connectivity as the latency of communicating between the phone and the server may be slow enough that they can end up creating conflicting changes at the same time.

What Realm does in this case is that it merges the changes after the application of specific rules that ensure that both sides always end up converging to the same result even, though they may have applied the changes in different order.

This means that you no longer have the kind of perfect consistency that you could have in a traditional database, what you have now is rather what is termed “strong eventual consistency”. The tradeoff is that you have to be aware of the the rules to ensure the consistent result you want, but the upside is that by following a few rules you can have devices working entirely offline and still converging on meaningful results when they meet.

At a very high level the rules are as follows:

  • Deletes always wins. If one side deletes an object it will always stay deleted, even if the other side has made changes to it later on.

  • Last update wins. If two sides has updated the same property, the value will end up as the last updated.

  • Inserts in lists are ordered by time. If two items are inserted at the same position, the item that was inserted first will end up before the other item. This means that if both sides append items to the end of a list they will end up in order of insertion time.

Objects with primary keys

To ensure uniqueness of objects, you can assign them primary keys. Let’s say your app has a global “settings” object. If you just do a check on startup and add it if it does not exist, you can easily end up with two or more instances of the object as multiple instances of the app all adds their own version.

The solution here is to assign the object a primary key so that you communicate the intent of this being the same object, even if it is being created multiple times simultaneously. The system is smart enough to recognize default values, so that properties you have changed won’t be overwritten by later (empty) objects.

Strings

Not exposed in client API’s yet

Strings are special in that you can see them both as scalar values and as lists of characters. This means that you can set the string to a new string (replacing the entire string) or you can edit the string. If multiple users are editing the same string, you want conflicts to be handled at the character level (similar to the experience you would have in something like Google docs).

Counters

Not exposed in client API’s yet

Using integers for counting is also a special case. The way that most programming languages would implement an increment operation (like v += 1), is to read the value, increment the result, and then store it back. This will obviously not work if you have multiple parties doing it simultaneously (they may both read 10, increment it to 11, and when it merges you would get the result of 11 rather than the intended 12).

To support this common use case we offer a way to express the intent that you are incrementing (or decrementing) the value, giving enough hints to the merge that it can reach the correct result. Just as with the strings above, it gives you the choice of updating the entire value, or editing it in a way that conveys more meaning, and allow you to get more precise control of the conflict resolution.

Custom conflict resolution

The standard way to do custom conflict resolution is to just change the value into a list. Then each side can add its updates to the list and apply any conflict resolution rules it wants directly in the data model.

You can use this technique to implement max, min, first write wins, last write wins and pretty much any kind of resolution you can think of.

Troubleshooting

Check firewall rules for external access to the Realm Dashboard

Certain factors may impact external (non-localhost) access to the Realm Object Server’s synchronization facility, and the Realm Dashboard. In order to enable access, it may be necessary to open port 9080 on your server(s).

Using the standard Linux tools, these commands will open access to the port:

sudo iptables -A INPUT -p tcp -m tcp --dport 9080 -j ACCEPT
sudo service iptables save

Please refer to the CentOS 6 Documentation for more information regarding how to configure your firewall.

sudo firewall-cmd --get-active-zones
sudo firewall-cmd --zone=public --add-port=9080/tcp --permanent
sudo firewall-cmd --reload
sudo ufw allow 9080/tcp
sudo ufw reload

If your environment does not use your distribution’s standard firewall, you will have to modify these instructions to fit your environment.

Configuration Errors

Generally the default settings will work well for most installations. Most settings inside the Realm config file are commented out (the system has pre-programmed default values) and show examples of how they can be to customized. If the configuration file has been customized and there is a problem, error messages will be written to the default log location (in the terminal window under macOS or /var/log/realm-sync.log on Linux systems).

If the Realm Object Server will not start, an error in the configuration file is usually the cause. To debug the config file, you can use the built-in checker by starting a terminal and using:

realm-object-server --check-configuration /etc/realm/configuration.yml

If running under macOS, replace the configuration file path with the path to your configuration.yml.

When an error occurs, the server’s parser will print a detailed error message stating the problem and possibly highlighting the line the error occurred on. Once all errors (if any) were corrected, the server will start; stop the server by pressing ^C and then start it normally by rebooting the system or restarting the Realm Object Server using systemd on Linux or the start-object-server.command on macOS.

Error messages are usually self-explanatory, but here are some potential hints:

  • To be able to run ROS, the following settings are mandatory:
    • Storage root directory: Where Realm Object Server should store all its files. Please set storage.root_path or give the --root CLI argument. The directory must exist before ROS can start.
    • Authentication key pair: For securing access to ROS to only authenticated clients. Please set auth.private_key_path or give the --private-key CLI argument, and please set auth.public_key_path or give the --public-key CLI argument. The keys given must be in PEM format and they must be a matching pair.
  • The configuration for listening ports must not be overlapping, meaning that listen_port values must be unique in the file. Additionally, the ports must not be bound in another process.

  • The HTTPS proxy will only start if given paths to a valid certificate and private key in proxy.https.certificate_path and proxy.https.private_key_path. The certificate and private key must be in PEM format and they must be a matching pair. The certificate cannot be self-signed.

Operational Errors

Occasionally it can be useful for debugging purposes to check the Realm Object Server logs - which are in the terminal window on macOS or /var/log/realm-sync.log on Linux systems - ROS produces two specific classes of error and warning diagnostics that may be useful to system admins and developers.

Session Specific Errors

  • 204 “Illegal Realm path (BIND)”
    Indicates that the Realm path is not valid for the user.

  • 207 “Bad server file identifier (IDENT)”
    Indicates that the local Realm specifies a link to a server-side Realm that does not exist. This is most likely because the server state has been completely reset.

  • 211 “Diverging histories (IDENT)” Indicates that the local Realm specifies a server version that does not exists. This is most likely because the server state has been partially reset (for example because a backup was restored).

Client Level Errors

  • 105 “Wrong protocol version (CLIENT)”
    The client and the server use different versions of the sync protocol due to a mismatch in upgrading.

  • 108 “Client file bound in other session (IDENT)”
    Indicates that multiple sync sessions for the same client-side Realm file overlap in time.

  • 203 “Bad user authentication (BIND, REFRESH)”
    Indicates that the server has produced a bad token, or that the SDK has done something wrong.

  • 206 “Permission denied (BIND, REFRESH)”
    Indicates that the user does not have permission to access the Realm at the given path.

Event Handling

This feature is limited to our Professional and Enterprise editions. Learn more about them and start a free trial.

An exclusive feature of the Enterprise Edition of Realm Object Server is event handling capabilities. This functionality is provided in the server-side Node.js SDK, that is also used to access data managed by the Realm Object Server. The Node.js SDK offers a global event listener API which hooks into the Realm Object Server and allows you to observe changes across Realms. This could mean listening to every Realm for changes or Realms that match a specific pattern. For example, if your app architecture separated user settings data into a Realm unique for each user where the virtual path was /~/settings, then a listener could be setup to react to changes to any user’s settings Realm.

Whenever a change is synchronized to server, it will trigger a notification which allows you to run custom server-side logic in response to the change. The notification will inform you about the virtual path of the updated Realm and provide the Realm object and fine-grained information on which objects changed. The change set provides the object indexes broken down by class name for any inserted, deleted, or modified object in the last synchronized transaction.

The sample below listens for changes to a user-specific private Realm at the virtual path /~/private. It will look for updated Coupon objects in these Realms and verify their code, if it wasn’t verified yet and write the result of the verification into the isValid property of the Coupon object.

var Realm = require('realm');

var dirPath = '.'; // the Realms will be stored into a subdirectory `realms` within this path
var adminToken = '3x4mpl3T0k3n…';
var adminUser = Realm.Sync.User.adminUser('', adminToken);
Realm.Sync.setGlobalListener(dirPath, syncBaseUrl, adminUser, filter, handleChange);

// The filter callback restricts the observed Realm files to only the subset you
// are actually interested in. This is done in a separate step to avoid the cost
// of computing the fine-grained change set if it's not necessary.
function filter(virtualPath) {
  // e.g. via a regular expression on the virtual path
  return /^\/([0-9a-f]+)\/private$/.test(virtualPath);
}

// The handleChange callback is called for every observed Realm file whenever it
// has changes.
function handleChange(virtualPath, realm, changes) {
  // Extract the user ID from the virtual path, assuming that we're using
  // a filter which only subscribes us to updates of user-scoped Realms.
  var matches = virtualPath.match(/^\/([0-9a-f]+)\/private$/);
  var userId = matches[1];

  var coupons = realm.objects('Coupon');
  var couponIndexes = changes.Coupon.insertions;

  for (var couponIndex in couponIndexes) {
    var coupon = coupons[couponIndex];
    if (coupon.isValid !== undefined) {
      var isValid = verifyCouponForUser(coupon, userId);
      // Attention: Writes here will trigger a subsequent notification.
      // Take care that this doesn't cause infinite changes!
      realm.write(function() {
        coupon.isValid = isValid;
      });
    }
  }

  // Always explicitly close the Realm when you're done!
  realm.close();
}