Configuration

System Configuration

CARTA backend permissions

The user under which the CARTA controller is running (assumed to be carta) must be given permission to use sudo to start carta_backend processes as any authenticated user and stop running carta_backend processes belonging to authenticated users. We provide a kill script which is only able to kill processes matching the name carta_backend. This makes it possible to restrict what processes the carta user is permitted to kill:

#!/bin/bash
# This script is a safe way to allow a user to kill specific commands of other users via sudo
COMMAND_TO_MATCH="carta_backend"

# Gets the child PID of the command (because it is run via sudo)
CHILD_PID=`pgrep -P $1`
# Gets the command name of the process to be killed
COMMAND_OF_PID=`ps -p $CHILD_PID -o comm=`

# Only allow processes with the same command name to be killed
if [ "$COMMAND_OF_PID" == "$COMMAND_TO_MATCH" ]; then
    kill -9 $CHILD_PID
    exit $?
else
    echo "$COMMAND_OF_PID does not match $COMMAND_TO_MATCH"
    exit 1
fi

To provide the carta user with these privileges, you must make modifications to the sudoers configuration. An example sudoers config is provided. This example allows the carta user to run carta_backend only as users belonging to a specific group (assumed to be carta-users), in order to deny access to unauthorized accounts:

# customise this file to fit your environment using visudo /etc/sudoers.d/carta_controller

# carta user can run the carta_backend command as any user in the carta-users group without entering password
carta ALL=(%carta-users) NOPASSWD:SETENV: /usr/bin/carta_backend

# carta user can run the kill script as any user in the carta-users group without entering password
carta ALL=(%carta-users) NOPASSWD: /usr/local/bin/carta-kill-script

Warning

Please only edit your sudoers configuration with visudo or equivalent.

Note

Older versions of sudo do not support the --preserve-env=VARIABLE argument. If your version of sudo is too old, set "preserveEnv" to false in your controller configuration, and add Defaults env_keep += "CARTA_AUTH_TOKEN" to your sudoers configuration.

Authentication

The controller signs and validates tokens with SSL keys. You can generate a private/public key pair in PEM format using openssl:

cd /etc/carta
openssl genrsa -out carta_private.pem 4096
openssl rsa -in carta_private.pem -outform PEM -pubout -out carta_public.pem

A public/private keypair is used to authenticate access tokens. OIDC authentication requires an additional symmetric encryption key for refresh tokens. LDAP or PAM authentication uses the same public/private keypair both for access tokens and for refresh tokens. If you use the default encryption algorithm, you can again use openssl to generate the needed key:

openssl rand -base64 32 > /etc/carta/symm.key

PAM may be configured to use the host’s local UNIX user authentication, or to communicate with a local or remote LDAP server. If the UNIX module is used for authentication, the carta user must be given read-only access to /etc/shadow. This is not required if you use PAM’s LDAP module or the direct LDAP authentication method.

Nginx

We strongly suggest serving over HTTPS and redirecting HTTP traffic to HTTPS, especially if handling authentication internally. If you use nginx as a proxy, you can use this configuration example as a starting point to redirect incoming traffic from port 443 to port 8000:

server {
    listen 443 ssl;
    ssl on;
    server_name my-carta-server.com;
    ssl_certificate /etc/nginx/ssl/cert.pem; 
    ssl_certificate_key /etc/nginx/ssl/key.pem;
    location / {
        proxy_set_header   X-Forwarded-For $remote_addr;
        proxy_pass http://localhost:8000/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

server {
    server_name my-carta-server.com;    
    if ($host = my-carta-server.com) {
        return 301 https://$host$request_uri;
    }
    listen 80 ;
    listen [::]:80 ;
    return 404;
}

Please ensure that you include a trailing / when hosting the controller on a subdirectory (e.g. location /carta/).

You can also use other HTTP servers, such as Apache. Please ensure that they are set up to forward both standard HTTP requests and WebSocket traffic to the correct port.

Directories

By default, the controller attempts to write log files to the /var/log/carta directory. Please ensure that this directory exists and that the carta user has write permission.

Controller configuration

Controller configuration is handled by a configuration file in JSONC (JSON with JavaScript style comments) format, adhering to the CARTA controller configuration schema. An example controller configuration file is provided:

{
    "$schema": "./config_schema.json",
    "authProviders": {
        "pam": {
            "publicKeyLocation": "/etc/carta/carta_public.pem",
            "privateKeyLocation": "/etc/carta/carta_private.pem",
            "issuer": "my-carta-server.com"
        }
    },
    "database": {
        "uri": "mongodb://localhost:27017",
        "databaseName": "CARTA"
    },
    "serverPort": 8000,
    "serverInterface": "localhost",
    "processCommand": "/usr/bin/carta_backend",
    "killCommand": "/usr/local/bin/carta-kill-script",
    "rootFolderTemplate": "/home/{username}",
    "baseFolderTemplate": "/home/{username}",
    "dashboard": {
        "bannerColor": "#d2dce5",
        "backgroundColor": "#f6f8fa",
        "bannerImage": "/path/to/my/image.svg",
        "infoText": "Welcome to the CARTA server.",
        "loginText": "<span>Please enter your login credentials:</span>",
        "footerText": "<span>If you have any problems, comments or suggestions, please <a href='mailto:test@test.com'>contact us.</a></span>"
    }
}

By default, the controller assumes the config file is located at /etc/carta/config.json, but you can change this with the --config or -c command line argument when running the controller.

Configuration may also be added in separate files in a config.d directory in the same parent directory as the specified config file. Each file in this directory must be a valid configuration file. Any files found will be processed in alphabetical order, after the main configuration file.

The controller automatically executes the backend with the --no_http flag, to suppress the backend’s built-in HTTP server. If the logFileTemplate configuration option is set, --no_log is also used to suppress user-level logs. --port is used to override the default port. --top_level_folder and a positional argument are used to set the top-level and starting data directories for the user, as specified in the rootFolderTemplate and baseFolderTemplate options, respectively.

To specify additional backend flags, we recommend editing a global backend preferences file. Most commandline arguments to the backend are also recognised as configuration options. The additionalArgs field in the controller configuration file can be used for any debug options which are not, and to disable the local or global configuration files.

If you use an external authentication system, you may need to translate a unique ID (such as email or username) from the authenticated external user information to an internal system user. You can do this by providing a user lookup table, which is watched by the controller and reloaded whenever it is updated:

# comment lines start with a #
user1@institute.ac user1
user2@institute.ac user2
# multiple usernames can be mapped to the same system user
user1_alt@trusted.domain user1

You can alter the controller’s dashboard appearance by adjusting the dashboard field in the config file. You can change the banner image and background, and add login instructions or institutional notices.

The httpOnly flag can be used to disable secure signing of authentication tokens. This should only be used during initial deployment and testing, or debugging.

The controller assumes it is running at the root directory of your subdomain by default. If you would prefer to run on a subdirectory, you will need to specify the dashboardAddress and apiAddress values (relative to your subdomain) explicitly. For example, if you are hosting CARTA at https://subdomain.domain.com/carta/version/v3-beta/, you would need to include the following in your config file:

{
    "apiAddress": "/carta/version/v3-beta/api",
    "dashboardAddress": "/carta/version/v3-beta/dashboard"
}

Backend configuration

The global configuration file for the CARTA backend is located at /etc/carta/backend.json. A per-user configuration file can also be placed in each user’s local CARTA preferences directory (typically .carta or .carta-beta in the user’s home directory, depending on how the CARTA backend was installed). On a multi-user system, if users have write access to this location, you may wish to disable the use of per-user configuration files, to prevent users from bypassing the root directory configuration set by the controller. This must be done through the additionalArgs field in the controller configuration.

The backend configuration file must adhere to the CARTA backend configuration schema. An example backend configuration file is provided:

{
    "$schema": "https://cartavis.org/schemas/preference_backend_schema_2.json",
    "idle_timeout": 14400,
    "omp_threads": 8,
    "exit_timeout": 0,
    "initial_timeout": 30
}

Testing the configuration

To test the configuration of the controller, you can use the built-in test feature. Run carta-controller --verbose --test <username> as the carta user (or whichever user has the added sudoers permissions). <username> should be a user in the carta-users group. The expected output looks like this:

Checking config file /etc/carta/config.json
Adding additional config file config.d/pam.json
No top-level folder was specified. Reverting to default location
Testing configuration with user alice
Password for user alice:
✔ Checked PAM connection for user alice
✔ Verified uid (1000) for user alice
✔ Generated access token for user alice
✔ Checked database connection
✔ Checked log writing for user alice
✔ Read frontend index.html from /custom/frontend/path/build
[
'running sudo --preserve-env=CARTA_AUTH_TOKEN -n -u alice /usr/bin/carta_backend --no_http --debug_no_auth --port 3499 --top_level_folder /usr/share/carta --no_log /usr/share/carta'
]
[2024-01-19 08:30:05.888Z] [CARTA] [info] /usr/bin/carta_backend: Version 4.1.0
[2024-01-19 08:30:05.888Z] [CARTA] [info] Listening on port 3499 with top level folder /usr/share/carta, starting folder /usr/share/carta, and 8 OpenMP worker threads
✔ Backend process started successfully
[2024-01-19 08:30:07.850Z] [CARTA] [info] 0x561f1a635180 ::Session (1235524527:1)
[2024-01-19 08:30:07.850Z] [CARTA] [info] Session 1235524527 [127.0.0.1] Connected. Num sessions: 1
✔ Backend process accepted connection
[ 'running sudo -u alice ./scripts/carta_kill_script.sh 54275' ]
✔ Backend process killed correctly
Controller tests with user alice succeeded

Note

If you run the controller from a source directory using npm, use -- to ensure that any commandline parameters are passed to the controller and not to npm. For example: npm run start -- --verbose --test alice.