Without Docker

If you prefer to install RootDB without Docker you can install and configure all requirements directly on your server and then use a bash script to bootstrap the application.

Requirements

RootDB’s requirements are :

Ubuntu Server 22.04

Install all dependencies with these commands, as root user :

wget -O /usr/local/bin/semver https://raw.githubusercontent.com/fsaintjacques/semver-tool/master/src/semver \
     && chmod +x /usr/local/bin/semver \
     && apt install -y software-properties-common \
     && add-apt-repository -y ppa:ondrej/php \
     && apt update \
     && apt install -y memcached mariadb-server bzip2 bsdextrautils php8.2 php8.2-gd php8.2-bcmath php8.2-dom php8.2-fpm php8.2-gd php8.2-iconv php8.2-mbstring php8.2-memcached php8.2-curl php8.2-mysql php8.2-pgsql php8.2-zip nginx postgresql-client-common supervisor

Debian 12

Install all dependencies with these commands, as root user :

wget -O /usr/local/bin/semver https://raw.githubusercontent.com/fsaintjacques/semver-tool/master/src/semver \
    && chmod +x /usr/local/bin/semver \
    && apt install -y ca-certificates apt-transport-https software-properties-common wget curl lsb-release \
    && curl -sSL https://packages.sury.org/php/README.txt | sudo bash -x \
    && apt install -y memcached mariadb-server bzip2 bsdextrautils php8.2 php8.2-gd php8.2-bcmath php8.2-dom php8.2-fpm php8.2-iconv php8.2-mbstring php8.2-memcached php8.2-curl php8.2-mysql php8.2-pgsql php8.2-zip nginx postgresql-client-common supervisor

Services configuration

MariaDB

Here you should simply have an up and running MariaDB instance, with a a root user correctly configured.

You have, then, to setup grants for the RootDB API user :

CREATE DATABASE `rootdb-api`;

-- If RootDB is installed on the same server that hosts the database
GRANT USAGE ON `rootdb-api`.* TO 'rootdb_api_user'@'localhost' IDENTIFIED BY '<a_password>';
GRANT SELECT, INSERT, CREATE, UPDATE, DELETE, DROP, INDEX, ALTER, SHOW VIEW, LOCK TABLES ON `rootdb-api`.* TO `rootdb_api_user`@`localhost`;

-- If RootDB _is not_ installed on the same server that hosts the database. (change <rootdb_ip> by the server's IP where RootDB code is installed)
GRANT USAGE ON `rootdb-api`.* TO 'rootdb_api_user'@'<rootdb_ip>' IDENTIFIED BY '<a_password>';
GRANT  SELECT, INSERT, CREATE, UPDATE, DELETE, DROP, INDEX, ALTER, SHOW VIEW, LOCK TABLES ON `rootdb-api`.* TO `rootdb_api_user`@`<rootdb_ip>`;

Nginx

Frontend

Below an example for the frontend, using TLS with Certbot :

/etc/nginx/sites-available/<frontend.hostname.tld> ( download rootdb-frontend.hostname.tld )
 1 server {
 2     listen 443 ssl;
 3     listen [::]:443 ssl;
 4
 5     server_name <frontend.hostname.tld>;
 6     root        /path/to/frontend/;
 7     index       index.html;
 8
 9     ssl_certificate     /etc/letsencrypt/live/<hostname.tld>/fullchain.pem;
10     ssl_certificate_key /etc/letsencrypt/live/<hostname.tld>/privkey.pem;
11
12     # This block should go into a `ssl_options` file and included inside server block of all vhosts.
13     # Remove this line below if you are not using Certbot
14     ssl_dhparam         /etc/letsencrypt/ssl-dhparams.pem;
15     ssl_session_cache shared:le_nginx_SSL:10m;
16     ssl_session_timeout 1440m;
17     ssl_session_tickets off;
18     ssl_protocols TLSv1.2 TLSv1.3;
19     ssl_prefer_server_ciphers off;
20     ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA";
21
22     access_log /var/log/nginx/<frontend.hostname.tld>.access.log;
23     error_log  /var/log/nginx/<frontend.hostname.tld>.error.log;
24
25     large_client_header_buffers 4 32k;
26
27     location ~ ^.*fonts\/(.*)$ {
28         add_header          Access-Control-Allow-Origin *;
29         proxy_pass          http://<api.hostname.tld>/api/theme/fonts/$1;
30         proxy_http_version  1.1;
31         proxy_set_header    X-Real-IP           $remote_addr;
32         proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
33         proxy_set_header    X-Forwarded-Proto   $scheme;
34         proxy_set_header    X-NginX-Proxy       true;
35         proxy_set_header    Upgrade             $http_upgrade;
36         proxy_set_header    Connection          "upgrade";
37     }
38
39     location / {
40             try_files $uri @index;
41     }
42
43     location @index {
44         add_header Cache-Control "no-store, no-cache, must-revalidate";
45         expires 0;
46         try_files /index.html =404;
47     }
48 }
49
50 server {
51     listen 80;
52     listen [::]:80;
53
54     server_name <frontend.hostname.tld>;
55     return 301 https://$host$request_uri;
56 }

API

Below an example for the API, using TLS with Certbot :

/etc/nginx/sites-available/<api.hostname.tld> ( download rootdb-api.hostname.tld )
 1 server {
 2     listen 443 ssl;
 3     listen [::]:443 ssl;
 4
 5     server_name <api.hostname.tld>;
 6     root        /path/to/api/public/;
 7     index       index.php;
 8
 9     ssl_certificate     /etc/letsencrypt/live/<hostname.tld>/fullchain.pem;
10     ssl_certificate_key /etc/letsencrypt/live/<hostname.tld>/privkey.pem;
11
12     # This block should go into a `ssl_options` file and included inside server block of all vhosts.
13     # Remove this line below if you are not using Certbot
14     ssl_dhparam         /etc/letsencrypt/ssl-dhparams.pem;
15     ssl_session_cache shared:le_nginx_SSL:10m;
16     ssl_session_timeout 1440m;
17     ssl_session_tickets off;
18     ssl_protocols TLSv1.2 TLSv1.3;
19     ssl_prefer_server_ciphers off;
20     ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA";
21
22     access_log /var/log/nginx/<api.hostname.tld>.access.log;
23     error_log /var/log/nginx/<api.hostname.tld>.error.log;
24
25     location ~ \.php$ {
26         try_files                       $uri =404;
27         fastcgi_split_path_info         ^(.+\.php)(/.+)$;
28         fastcgi_pass                    unix:/var/run/php/php8.2-fpm.sock;
29         fastcgi_index                   index.php;
30         include                         fastcgi_params;
31         fastcgi_buffers                 16 16k;
32         fastcgi_buffer_size             32k;
33         fastcgi_param SCRIPT_FILENAME   $document_root$fastcgi_script_name;
34         fastcgi_param PATH_INFO         $fastcgi_path_info;
35         fastcgi_param DOCUMENT_ROOT     $realpath_root;
36         internal;
37     }
38
39     location / {
40         try_files $uri $uri/ /index.php?$query_string;
41         gzip_static on;
42     }
43 }
44
45 server {
46     listen 80;
47     listen [::]:80;
48
49     server_name <api.hostname.tld>;
50     return 301 https://$host$request_uri;
51 }

Websocket

Below an example for the Websocket proxy, using TLS with Certbot :

/etc/nginx/sites-available/<api.hostname.tld> ( download rootdb-api.hostname.tld )
 1 server {
 2     listen 443 ssl;
 3     listen [::]:443 ssl;
 4
 5     server_name <ws-api.hostname.tld>;
 6     root        /path/to/api/public/;
 7     index       index.php;
 8
 9     ssl_certificate     /etc/letsencrypt/live/<hostname.tld>/fullchain.pem;
10     ssl_certificate_key /etc/letsencrypt/live/<hostname.tld>/privkey.pem;
11
12     # This block should go into a `ssl_options` file and included inside all vhosts's server section.
13     # Remove this line below if you are not using Certbot
14     ssl_dhparam         /etc/letsencrypt/ssl-dhparams.pem;
15     ssl_session_cache shared:le_nginx_SSL:10m;
16     ssl_session_timeout 1440m;
17     ssl_session_tickets off;
18     ssl_protocols TLSv1.2 TLSv1.3;
19     ssl_prefer_server_ciphers off;
20     ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA";
21
22     access_log /var/log/nginx/<api.hostname.tld>.access.log;
23     error_log /var/log/nginx/<api.hostname.tld>.error.log;
24
25     location / {
26         proxy_http_version 1.1;
27         proxy_set_header Host $http_host;
28         proxy_set_header Scheme $scheme;
29         proxy_set_header SERVER_PORT $server_port;
30         proxy_set_header REMOTE_ADDR $remote_addr;
31         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
32         proxy_set_header Upgrade $http_upgrade;
33         proxy_set_header Connection "Upgrade";
34
35         proxy_pass http://0.0.0.0:8080;
36     }
37 }
38
39 server {
40     listen 80;
41     listen [::]:80;
42
43     server_name <api.hostname.tld>;
44     return 301 https://$host$request_uri;
45 }

Check your configuration and reload nginx :

nginx -t
systemctl restart nginx

PHP-FPM

You should probably raise the allowed memory for a PHP-FPM process in the php.ini file and also the size for a POST and uploaded file.

/etc/php/8.2/fpm/php.ini
memory_limit = 4000M
upload_max_filesize = 500M
post_max_size = 400M

Finally, check your PHP-FPM configuration and restart the process :

php-fpm8.2 -t
systemctl restart php8.2-fpm

Supervisor

Supervisor handle the websocket server and cron jobs. Here are the configuration files :

/etc/supervisor/conf.d/rootdb-websocket_server.conf ( download rootdb-api.hostname.tld )
 1[program:rootdb-reverb_server]
 2process_name=%(program_name)s_%(process_num)02d
 3command=php /path/to/api/artisan reverb:start
 4autostart=true
 5autorestart=true
 6stopasgroup=true
 7killasgroup=true
 8user=<www-data or httpd>
 9numprocs=1
10redirect_stderr=true
11stdout_logfile=/path/to/api/storage/logs//reverb_websocket.log
12stopwaitsecs=3600
/etc/supervisor/conf.d/rootdb-cron_scheduler.conf ( download rootdb-api.hostname.tld )
 1[program:rootdb-cron_scheduler]
 2process_name=%(program_name)s_%(process_num)02d
 3command=php /path/to/api/artisan schedule:run -q && exec /usr/bin/sleep 60
 4autostart=true
 5autorestart=true
 6stopasgroup=true
 7killasgroup=true
 8user=<www-data or httpd>
 9numprocs=1
10redirect_stderr=true

Firewall

By default, you have to open these ports : 80,443.

Logs

You should consider to logrotate theses logs files :

/path/to/api/storage/logs/laravel.log
/path/to/api/storage/logs/reverb_websocket.log

API & frontend code

Before installing RootDB code, make sure MariaDB is up and running, with grants for RootDB API user.

Code organization

For log, once installed, the code tree of your RootDB main directory will looks like this :

/path/to/www/rootdb
   ├── api -> /path/to/www/rootdb/archives/1.0.4/api
   │  └── .env -> /path/to/install_script_directory/api_env
   │
   ├── archives
   │  ├── 1.0.3
   │  │   ├── api
   │  │   └── frontend
   │  └── 1.0.4
   │      ├── api
   │      └── frontend
   │
   ├── frontend -> /path/to/www/rootdb/archives/1.0.4/frontend
   │  └── app-config.js -> /path/to/install_script_directory/app-config.js
   │
   ├── .rdb_initialized

How-to get the code

A bash script is available here : install.sh - which will simplify the code installation. It will :

  1. Check if software requirements and mandatory php modules are available on your system.

  2. Download latest RootDB archive.

  3. Extract the archive, organize API & Frontend environment files and boostrap RootDB database.

  4. Upgrade automatically to a new version of RootDB.

  5. Or rollback to a previous version.

You can run install.sh -h to see a list of available options.

How-to run install.sh

First create a install directory somewhere in a safe place on your server, and download these files below inside this directory :

Then update api_env & app-config.js to match your Nginx configuration.

Your installation directory should looks like :

/path/to/install_script_directory
   ├── api_env
   ├── app-config.js
   └── install.sh

Tip

To make the installation script executable, you can execute chmod +x install.sh

Then run the install script this way : ./install.sh
This will install RootDB inside this default directory path: /var/www/rootdb.
If you want to change this path, run the script like this: ./install.sh -d /path/to/your/rootdb