Skip to main content

Installation

RUBIN-T is installed by deploying a set of Docker containers on server hardware. Building components from source is not required: every component is delivered as a ready-made container image.

The containers and their purpose are described under Technical architecture.

1. System requirements

User workstationsServer hardware
Operating systemAny OS supporting current browsersUbuntu 24.04
Processor2 cores4 cores at 2.4 GHz or faster
Memory4 GB or more32 GB or more
Disk50 GB or more1 TB SSD or more
BrowserYandex Browser, Google Chrome, Mozilla Firefox, Microsoft Edge (no more than one year old)

Requirements depend on the volume and content of the data RUBIN-T will work with. Where the video subsystem is used, disk space is calculated from the number of cameras and the archive retention depth, and a graphics accelerator is recommended for real-time recognition.

2. Preparing the server

2.1 Installing Docker

sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

echo "deb [arch=$(dpkg --print-architecture) \
signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin

Verifying the installation:

docker --version
docker compose version

2.2 Creating the installation directory

sudo mkdir -p /opt/rubin-t
cd /opt/rubin-t

This directory holds the service definition file docker-compose.yml and the environment file .env.

2.3 Access to the image registry

Images are published to a private registry. Credentials are supplied by the software vendor.

docker login <registry-address>
ParameterPurpose
<registry-address>The address of the container image registry supplied by the vendor
UsernameThe account used to access the registry
PasswordThe password or access token for the registry

3. The environment file

Variable values are set in the .env file in the installation directory. The file holds passwords and keys and must be readable only by its owner:

touch /opt/rubin-t/.env
chmod 600 /opt/rubin-t/.env
caution

Variable values are deliberately omitted from this document. Passwords, keys and addresses are chosen at installation time and must not match the values from examples or test environments. The .env file must not be sent over open channels or committed to version control.

3.1 Image registry and version

VariablePurpose
REGISTRYThe container image registry address
IMAGE_TAGThe tag (version) of the images being installed

3.2 Application database

VariablePurpose
POSTGRES_DBThe application database name
POSTGRES_USERThe DBMS user for the application database
POSTGRES_PASSWORDThe password of that DBMS user

3.3 Telematics database

VariablePurpose
TRACCAR_DB_NAMEThe telematics server's database name
TRACCAR_DB_USERThe DBMS user for the telematics database
TRACCAR_DB_PASSWORDThe password of that DBMS user

3.4 Road graph database

VariablePurpose
OSM_DB_NAMEThe road graph service's database name
OSM_DB_USERThe DBMS user for the road graph database
OSM_DB_PASSWORDThe password of that DBMS user

3.5 Message broker

VariablePurpose
RABBITMQ_USERThe message broker user name
RABBITMQ_PASSWORDThe message broker user password
RABBITMQ_VHOSTThe broker virtual host in which the software's queues are created

3.6 Application server

VariablePurpose
RAILS_ENVThe application server's run mode; production for production use
RAILS_MASTER_KEYThe key that decrypts the application's encrypted settings. Supplied by the vendor; without it the application server will not start
DATABASE_URLThe application database connection string, postgis://<user>:<password>@<host>:<port>/<database>
RABBITMQ_URLThe message broker connection string, amqp://<user>:<password>@<host>:<port>/<vhost>
ADMIN_PASSWORDThe password of the administrator account created during initial database initialisation
COOKIE_SECUREWhether session cookies are sent only over a secure connection. Set to true when serving over HTTPS
TRACCAR_API_BASEThe base address of the telematics server API
TRACCAR_USERNAMEThe account used to access the telematics server API
TRACCAR_PASSWORDThe password of that account
OSM_SSO_SECRETThe shared secret for single sign-on between the application server and the road graph service. Must match the value given to the graph service

3.7 Telematics server

VariablePurpose
CONFIG_USE_ENVIRONMENT_VARIABLESWhether the telematics server reads its configuration from environment variables
DATABASE_DRIVERThe JDBC driver class for the DBMS
TRACCAR_DATABASE_URLThe JDBC connection string to the telematics database
DATABASE_USERThe DBMS user for the telematics server
DATABASE_PASSWORDThe password of that user

3.8 Road graph service

VariablePurpose
OSM_DATABASE_URLThe road graph database connection string
RAILS_RELATIVE_URL_ROOTThe path prefix under which the service is published behind the reverse proxy
PIDFILEThe path to the process identifier file

3.9 Video subsystem

VariablePurpose
FRIGATE_RTSP_USERThe account used to connect to camera video streams over RTSP
FRIGATE_RTSP_PASSWORDThe password for that connection
FRIGATE_MQTT_USERThe account used to publish video analytics events to the message broker
FRIGATE_MQTT_PASSWORDThe password for that account

3.10 Web server

VariablePurpose
RAILS_APPThe application server address and port to reverse-proxy to
OSM_BACKENDThe road graph service address and port
FRIGATE_BACKENDThe video subsystem address and port
GO2RTC_BACKENDThe stream publishing service address and port
TRACCAR_BACKENDThe telematics server address and port
RABBITMQ_BACKENDThe message broker management interface address and port
SWAGGER_BACKENDThe API description service address and port
HTTP_PORTThe server port on which the web interface is published

4. The service definition file

Create docker-compose.yml in the installation directory. Every parameter is substituted from the .env file.

x-app-env: &app-env
RAILS_ENV: ${RAILS_ENV}
RAILS_MASTER_KEY: ${RAILS_MASTER_KEY}
DATABASE_URL: ${DATABASE_URL}
RABBITMQ_URL: ${RABBITMQ_URL}
ADMIN_PASSWORD: ${ADMIN_PASSWORD}
COOKIE_SECURE: ${COOKIE_SECURE}
TRACCAR_API_BASE: ${TRACCAR_API_BASE}
TRACCAR_USERNAME: ${TRACCAR_USERNAME}
TRACCAR_PASSWORD: ${TRACCAR_PASSWORD}
OSM_SSO_SECRET: ${OSM_SSO_SECRET}

x-app-common: &app-common
image: ${REGISTRY}/sl-api:${IMAGE_TAG}
restart: always
environment:
<<: *app-env
depends_on:
migrate:
condition: service_completed_successfully
database:
condition: service_healthy
rabbitmq:
condition: service_started

x-osm-env: &osm-env
RAILS_ENV: ${RAILS_ENV}
DATABASE_URL: ${OSM_DATABASE_URL}
OSM_SSO_SECRET: ${OSM_SSO_SECRET}
RAILS_RELATIVE_URL_ROOT: ${RAILS_RELATIVE_URL_ROOT}
PIDFILE: ${PIDFILE}

services:
database:
image: ${REGISTRY}/postgis:16-master
container_name: db
restart: always
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 20s
timeout: 5s
retries: 20
start_period: 30s

database-traccar:
image: ${REGISTRY}/timescale-pg16:${IMAGE_TAG}
container_name: db_traccar
restart: always
environment:
POSTGRES_DB: ${TRACCAR_DB_NAME}
POSTGRES_USER: ${TRACCAR_DB_USER}
POSTGRES_PASSWORD: ${TRACCAR_DB_PASSWORD}
TIMESCALEDB_TELEMETRY: "off"
volumes:
- db_traccar_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${TRACCAR_DB_USER} -d ${TRACCAR_DB_NAME}"]
interval: 5s
timeout: 5s
retries: 20
start_period: 30s

database-osm:
image: ${REGISTRY}/timescale-pg16:${IMAGE_TAG}
container_name: db_osm
restart: always
environment:
POSTGRES_DB: ${OSM_DB_NAME}
POSTGRES_USER: ${OSM_DB_USER}
POSTGRES_PASSWORD: ${OSM_DB_PASSWORD}
TIMESCALEDB_TELEMETRY: "off"
volumes:
- db_osm_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${OSM_DB_USER} -d ${OSM_DB_NAME}"]
interval: 5s
timeout: 5s
retries: 20
start_period: 30s

rabbitmq:
image: ${REGISTRY}/rabbitmq:${IMAGE_TAG}
container_name: rabbitmq
restart: always
command: >
sh -c "rabbitmq-plugins enable --offline rabbitmq_management rabbitmq_mqtt &&
rabbitmq-server"
environment:
RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER}
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD}
RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_VHOST}
volumes:
- rabbitmq_data:/var/lib/rabbitmq

migrate:
image: ${REGISTRY}/sl-api:${IMAGE_TAG}
container_name: migrate
restart: "no"
environment:
<<: *app-env
depends_on:
database:
condition: service_healthy
rabbitmq:
condition: service_started
command: bundle exec rails db:prepare

osm-migrate:
image: ${REGISTRY}/openstreetmap-website:${IMAGE_TAG}
container_name: osm-migrate
restart: "no"
environment:
<<: *osm-env
tmpfs:
- /tmp/pids
depends_on:
database-osm:
condition: service_healthy
command: bundle exec rails db:prepare

traccar:
image: ${REGISTRY}/traccar:${IMAGE_TAG}
container_name: traccar
restart: always
environment:
CONFIG_USE_ENVIRONMENT_VARIABLES: ${CONFIG_USE_ENVIRONMENT_VARIABLES}
DATABASE_DRIVER: ${DATABASE_DRIVER}
DATABASE_URL: ${TRACCAR_DATABASE_URL}
DATABASE_USER: ${DATABASE_USER}
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
depends_on:
database-traccar:
condition: service_healthy

frigate:
image: ${REGISTRY}/frigate:stable
container_name: frigate
restart: always
environment:
FRIGATE_RTSP_USER: ${FRIGATE_RTSP_USER}
FRIGATE_RTSP_PASSWORD: ${FRIGATE_RTSP_PASSWORD}
FRIGATE_MQTT_USER: ${FRIGATE_MQTT_USER}
FRIGATE_MQTT_PASSWORD: ${FRIGATE_MQTT_PASSWORD}
volumes:
- frigate_config:/config
- frigate_media:/media/frigate

osm-web:
image: ${REGISTRY}/openstreetmap-website:${IMAGE_TAG}
container_name: osm-web
restart: always
environment:
<<: *osm-env
tmpfs:
- /tmp/pids
depends_on:
osm-migrate:
condition: service_completed_successfully
command: bundle exec rails s -p 3000 -b 0.0.0.0

app:
<<: *app-common
container_name: app
command: bundle exec rails server -b 0.0.0.0 -p 3000
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/up"]
interval: 30s
timeout: 10s
retries: 10
start_period: 20s

worker:
<<: *app-common
container_name: worker
command: bundle exec rails solid_queue:start

position-consume:
<<: *app-common
container_name: position-consume
command: bundle exec rake rabbitmq:consume:positions

position-cache-consume:
<<: *app-common
container_name: position-cache-consume
command: bundle exec rake rabbitmq:consume:position_cache

event-consume:
<<: *app-common
container_name: event-consume
command: bundle exec rake rabbitmq:consume:events

video-consume:
<<: *app-common
container_name: video-consume
command: bundle exec rake rabbitmq:consume:frigate

web:
image: ${REGISTRY}/sl-web:${IMAGE_TAG}
container_name: web
restart: always
environment:
RAILS_APP: ${RAILS_APP}
OSM_BACKEND: ${OSM_BACKEND}
FRIGATE_BACKEND: ${FRIGATE_BACKEND}
GO2RTC_BACKEND: ${GO2RTC_BACKEND}
TRACCAR_BACKEND: ${TRACCAR_BACKEND}
RABBITMQ_BACKEND: ${RABBITMQ_BACKEND}
SWAGGER_BACKEND: ${SWAGGER_BACKEND}
ports:
- "${HTTP_PORT}:80"
depends_on:
app:
condition: service_healthy
osm-web:
condition: service_started

volumes:
db_data:
db_traccar_data:
db_osm_data:
rabbitmq_data:
frigate_config:
frigate_media:

5. Installation procedure

5.1 Pulling the images

cd /opt/rubin-t
docker compose pull

The command downloads the images of every service from the registry.

VariableRole in this command
REGISTRYThe registry the images are pulled from
IMAGE_TAGThe version of the images pulled

5.2 Starting the database servers and the message broker

docker compose up -d database database-traccar database-osm rabbitmq
VariableRole in this command
POSTGRES_DBThe name of the application database being created
POSTGRES_USERThe application database user being created
POSTGRES_PASSWORDThat user's password
TRACCAR_DB_NAMEThe name of the telematics database being created
TRACCAR_DB_USERThe telematics database user
TRACCAR_DB_PASSWORDThat user's password
OSM_DB_NAMEThe name of the road graph database being created
OSM_DB_USERThe road graph database user
OSM_DB_PASSWORDThat user's password
RABBITMQ_USERThe broker user being created
RABBITMQ_PASSWORDThat user's password
RABBITMQ_VHOSTThe broker virtual host created at start-up

Wait for the database servers to reach the healthy state:

docker compose ps

5.3 Initialising the database schemas

docker compose run --rm migrate
VariableRole in this command
DATABASE_URLThe application database whose schema is created
RAILS_MASTER_KEYThe key decrypting the application settings
RAILS_ENVThe run mode determining which settings apply
ADMIN_PASSWORDThe password of the administrator account created on first initialisation
docker compose run --rm osm-migrate
VariableRole in this command
OSM_DATABASE_URLThe road graph database whose schema is created
RAILS_ENVThe road graph service's run mode
PIDFILEThe path to the process identifier file

The migration containers exit when finished and do not stay running.

5.4 Starting the telematics server and the video subsystem

docker compose up -d traccar frigate
VariableRole in this command
CONFIG_USE_ENVIRONMENT_VARIABLESMakes the telematics server read its configuration from the environment
DATABASE_DRIVERThe JDBC driver class the telematics server uses
TRACCAR_DATABASE_URLThe telematics server's connection to its database
DATABASE_USERThe DBMS user for the telematics server
DATABASE_PASSWORDThat user's password
FRIGATE_RTSP_USERThe account used to connect to camera streams
FRIGATE_RTSP_PASSWORDThat account's password
FRIGATE_MQTT_USERThe account publishing video analytics events to the broker
FRIGATE_MQTT_PASSWORDThat account's password

5.5 Starting the application server and the workers

docker compose up -d app worker \
position-consume position-cache-consume event-consume video-consume

The services started:

ServicePurpose
appThe application server handling application API requests
workerBackground and periodic tasks: statistics, forecasts, notifications, synchronisation
position-consumeConsumer of the vehicle position queue
position-cache-consumeConsumer of the current position cache queue
event-consumeConsumer of the monitoring event queue
video-consumeConsumer of the video analytics message queue
VariableRole in this command
RAILS_ENVThe run mode of the application server and workers
RAILS_MASTER_KEYThe key decrypting the application settings
DATABASE_URLThe connection to the application database
RABBITMQ_URLThe broker whose queues the consumers read from
COOKIE_SECUREWhether session cookies are restricted to secure connections
TRACCAR_API_BASEThe telematics server API used to synchronise geofences and objects
TRACCAR_USERNAMEThe account used for that API
TRACCAR_PASSWORDThat account's password
OSM_SSO_SECRETThe shared single sign-on secret with the road graph service

5.6 Starting the road graph service and the web server

docker compose up -d osm-web web
VariableRole in this command
OSM_DATABASE_URLThe road graph service's connection to its database
RAILS_RELATIVE_URL_ROOTThe path prefix the graph service is published under
OSM_SSO_SECRETThe shared single sign-on secret with the application server
PIDFILEThe path to the graph service's process identifier file
RAILS_APPThe application server the web server proxies API requests to
OSM_BACKENDThe road graph service address to proxy
FRIGATE_BACKENDThe video subsystem address to proxy
GO2RTC_BACKENDThe stream publishing service address to proxy
TRACCAR_BACKENDThe telematics server address to proxy
RABBITMQ_BACKENDThe broker management interface address
SWAGGER_BACKENDThe API description service address
HTTP_PORTThe server port the web interface is published on

5.7 Starting everything with one command

After the initial setup the whole stack starts with a single command:

docker compose up -d

The command uses every variable listed in section 3.

6. Verifying the installation

Container state:

docker compose ps

Every service should be running, and the application server and database servers should be healthy.

Checking that the application server responds:

docker compose exec app curl -f http://localhost:3000/up

Viewing a service's log:

docker compose logs -f app

Open the web interface in a browser at the server address and the port given by HTTP_PORT. Sign in as the administrator using the password set in ADMIN_PASSWORD.

caution

Change the administrator password after the first sign-in.

7. Publishing over a secure connection

For production use the web interface is published over HTTPS. The secure connection is terminated by an external reverse proxy that forwards requests to the port given by HTTP_PORT.

When serving over HTTPS, set COOKIE_SECURE to true and recreate the application server:

docker compose up -d --force-recreate app worker
VariableRole in this command
COOKIE_SECUREThe new secure-cookie setting applied as the containers are recreated

The reverse proxy must forward the Upgrade and Connection headers — without them the WebSocket connections that carry real-time data will not work.

8. Upgrading

cd /opt/rubin-t

# 1. Set the new version in IMAGE_TAG in the .env file
# 2. Pull the images of the new version
docker compose pull

# 3. Apply the database schema migrations
docker compose run --rm migrate
docker compose run --rm osm-migrate

# 4. Restart the services on the new images
docker compose up -d
VariableRole in the upgrade commands
IMAGE_TAGThe version being upgraded to
REGISTRYThe registry the new images are pulled from
DATABASE_URL, OSM_DATABASE_URLThe databases whose schemas the migrations apply to
RAILS_MASTER_KEYThe key decrypting the settings while migrations run

Back up the databases before upgrading.

9. Backup and restore

Backing up the application database:

docker compose exec -T database \
pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc > backup_app.dump
VariableRole in this command
POSTGRES_USERThe DBMS user the dump runs as
POSTGRES_DBThe application database being dumped

Back up the telematics database the same way (service database-traccar, variables TRACCAR_DB_USER and TRACCAR_DB_NAME) and the road graph database (service database-osm, variables OSM_DB_USER and OSM_DB_NAME).

Restoring:

docker compose exec -T database \
pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" --clean < backup_app.dump
VariableRole in this command
POSTGRES_USERThe DBMS user the restore runs as
POSTGRES_DBThe database being restored

The video archive and the video subsystem configuration live in the frigate_media and frigate_config volumes and are backed up with file-system backup tools.

10. Stopping and removing

Stopping while keeping the data:

docker compose down

Stopping and deleting the data:

docker compose down -v
danger

The -v flag deletes the volumes holding the databases and the video archive. The operation is irreversible; use it only when removing the installation entirely.

Printable version

The PDF edition of this document is available in Russian:

⬇ Download PDF (RU)