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 workstations | Server hardware | |
|---|---|---|
| Operating system | Any OS supporting current browsers | Ubuntu 24.04 |
| Processor | 2 cores | 4 cores at 2.4 GHz or faster |
| Memory | 4 GB or more | 32 GB or more |
| Disk | 50 GB or more | 1 TB SSD or more |
| Browser | Yandex 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>
| Parameter | Purpose |
|---|---|
<registry-address> | The address of the container image registry supplied by the vendor |
| Username | The account used to access the registry |
| Password | The 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
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
| Variable | Purpose |
|---|---|
REGISTRY | The container image registry address |
IMAGE_TAG | The tag (version) of the images being installed |
3.2 Application database
| Variable | Purpose |
|---|---|
POSTGRES_DB | The application database name |
POSTGRES_USER | The DBMS user for the application database |
POSTGRES_PASSWORD | The password of that DBMS user |
3.3 Telematics database
| Variable | Purpose |
|---|---|
TRACCAR_DB_NAME | The telematics server's database name |
TRACCAR_DB_USER | The DBMS user for the telematics database |
TRACCAR_DB_PASSWORD | The password of that DBMS user |
3.4 Road graph database
| Variable | Purpose |
|---|---|
OSM_DB_NAME | The road graph service's database name |
OSM_DB_USER | The DBMS user for the road graph database |
OSM_DB_PASSWORD | The password of that DBMS user |
3.5 Message broker
| Variable | Purpose |
|---|---|
RABBITMQ_USER | The message broker user name |
RABBITMQ_PASSWORD | The message broker user password |
RABBITMQ_VHOST | The broker virtual host in which the software's queues are created |
3.6 Application server
| Variable | Purpose |
|---|---|
RAILS_ENV | The application server's run mode; production for production use |
RAILS_MASTER_KEY | The key that decrypts the application's encrypted settings. Supplied by the vendor; without it the application server will not start |
DATABASE_URL | The application database connection string, postgis://<user>:<password>@<host>:<port>/<database> |
RABBITMQ_URL | The message broker connection string, amqp://<user>:<password>@<host>:<port>/<vhost> |
ADMIN_PASSWORD | The password of the administrator account created during initial database initialisation |
COOKIE_SECURE | Whether session cookies are sent only over a secure connection. Set to true when serving over HTTPS |
TRACCAR_API_BASE | The base address of the telematics server API |
TRACCAR_USERNAME | The account used to access the telematics server API |
TRACCAR_PASSWORD | The password of that account |
OSM_SSO_SECRET | The 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
| Variable | Purpose |
|---|---|
CONFIG_USE_ENVIRONMENT_VARIABLES | Whether the telematics server reads its configuration from environment variables |
DATABASE_DRIVER | The JDBC driver class for the DBMS |
TRACCAR_DATABASE_URL | The JDBC connection string to the telematics database |
DATABASE_USER | The DBMS user for the telematics server |
DATABASE_PASSWORD | The password of that user |
3.8 Road graph service
| Variable | Purpose |
|---|---|
OSM_DATABASE_URL | The road graph database connection string |
RAILS_RELATIVE_URL_ROOT | The path prefix under which the service is published behind the reverse proxy |
PIDFILE | The path to the process identifier file |
3.9 Video subsystem
| Variable | Purpose |
|---|---|
FRIGATE_RTSP_USER | The account used to connect to camera video streams over RTSP |
FRIGATE_RTSP_PASSWORD | The password for that connection |
FRIGATE_MQTT_USER | The account used to publish video analytics events to the message broker |
FRIGATE_MQTT_PASSWORD | The password for that account |
3.10 Web server
| Variable | Purpose |
|---|---|
RAILS_APP | The application server address and port to reverse-proxy to |
OSM_BACKEND | The road graph service address and port |
FRIGATE_BACKEND | The video subsystem address and port |
GO2RTC_BACKEND | The stream publishing service address and port |
TRACCAR_BACKEND | The telematics server address and port |
RABBITMQ_BACKEND | The message broker management interface address and port |
SWAGGER_BACKEND | The API description service address and port |
HTTP_PORT | The 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.
| Variable | Role in this command |
|---|---|
REGISTRY | The registry the images are pulled from |
IMAGE_TAG | The 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
| Variable | Role in this command |
|---|---|
POSTGRES_DB | The name of the application database being created |
POSTGRES_USER | The application database user being created |
POSTGRES_PASSWORD | That user's password |
TRACCAR_DB_NAME | The name of the telematics database being created |
TRACCAR_DB_USER | The telematics database user |
TRACCAR_DB_PASSWORD | That user's password |
OSM_DB_NAME | The name of the road graph database being created |
OSM_DB_USER | The road graph database user |
OSM_DB_PASSWORD | That user's password |
RABBITMQ_USER | The broker user being created |
RABBITMQ_PASSWORD | That user's password |
RABBITMQ_VHOST | The 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
| Variable | Role in this command |
|---|---|
DATABASE_URL | The application database whose schema is created |
RAILS_MASTER_KEY | The key decrypting the application settings |
RAILS_ENV | The run mode determining which settings apply |
ADMIN_PASSWORD | The password of the administrator account created on first initialisation |
docker compose run --rm osm-migrate
| Variable | Role in this command |
|---|---|
OSM_DATABASE_URL | The road graph database whose schema is created |
RAILS_ENV | The road graph service's run mode |
PIDFILE | The 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
| Variable | Role in this command |
|---|---|
CONFIG_USE_ENVIRONMENT_VARIABLES | Makes the telematics server read its configuration from the environment |
DATABASE_DRIVER | The JDBC driver class the telematics server uses |
TRACCAR_DATABASE_URL | The telematics server's connection to its database |
DATABASE_USER | The DBMS user for the telematics server |
DATABASE_PASSWORD | That user's password |
FRIGATE_RTSP_USER | The account used to connect to camera streams |
FRIGATE_RTSP_PASSWORD | That account's password |
FRIGATE_MQTT_USER | The account publishing video analytics events to the broker |
FRIGATE_MQTT_PASSWORD | That 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:
| Service | Purpose |
|---|---|
app | The application server handling application API requests |
worker | Background and periodic tasks: statistics, forecasts, notifications, synchronisation |
position-consume | Consumer of the vehicle position queue |
position-cache-consume | Consumer of the current position cache queue |
event-consume | Consumer of the monitoring event queue |
video-consume | Consumer of the video analytics message queue |
| Variable | Role in this command |
|---|---|
RAILS_ENV | The run mode of the application server and workers |
RAILS_MASTER_KEY | The key decrypting the application settings |
DATABASE_URL | The connection to the application database |
RABBITMQ_URL | The broker whose queues the consumers read from |
COOKIE_SECURE | Whether session cookies are restricted to secure connections |
TRACCAR_API_BASE | The telematics server API used to synchronise geofences and objects |
TRACCAR_USERNAME | The account used for that API |
TRACCAR_PASSWORD | That account's password |
OSM_SSO_SECRET | The 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
| Variable | Role in this command |
|---|---|
OSM_DATABASE_URL | The road graph service's connection to its database |
RAILS_RELATIVE_URL_ROOT | The path prefix the graph service is published under |
OSM_SSO_SECRET | The shared single sign-on secret with the application server |
PIDFILE | The path to the graph service's process identifier file |
RAILS_APP | The application server the web server proxies API requests to |
OSM_BACKEND | The road graph service address to proxy |
FRIGATE_BACKEND | The video subsystem address to proxy |
GO2RTC_BACKEND | The stream publishing service address to proxy |
TRACCAR_BACKEND | The telematics server address to proxy |
RABBITMQ_BACKEND | The broker management interface address |
SWAGGER_BACKEND | The API description service address |
HTTP_PORT | The 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.
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
| Variable | Role in this command |
|---|---|
COOKIE_SECURE | The 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
| Variable | Role in the upgrade commands |
|---|---|
IMAGE_TAG | The version being upgraded to |
REGISTRY | The registry the new images are pulled from |
DATABASE_URL, OSM_DATABASE_URL | The databases whose schemas the migrations apply to |
RAILS_MASTER_KEY | The 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
| Variable | Role in this command |
|---|---|
POSTGRES_USER | The DBMS user the dump runs as |
POSTGRES_DB | The 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
| Variable | Role in this command |
|---|---|
POSTGRES_USER | The DBMS user the restore runs as |
POSTGRES_DB | The 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
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)