Skip to content

Self-Hosting Guide

Recogito-Studio is ready for self-hosting and these instructions detail the steps necessary for deployment on Ubuntu Linux, v24 (although many earlier versions will also work as well). The deployment strategy utilizes Docker, Docker Compose, and Nginx.

In the example below we will install Recogito Studio on a Digital Ocean Droplet. Digital Ocean is a well-regarded cloud hosting platform known for its ease of use and competitive pricing, but the instructions are easily translated to other cloud platforms or on-premises data centers.

RS Supabase

Most of the Supabase processes, plus MinIO for object storage, and Cantaloupe as a IIIF server.

RS Client

The client application of Recogito Studio, written in Astro JS.

Postgres

Postgres server with Supabase Vector process and pgAdmin for database management.

Portainer

Container management tool for managing and monitoring the Docker environment.

System Diagram

  • Trigger.dev - Background job system (required for plugin-ner)
  • Stanford CoreNLP - Natural Language Processor (required for plugin-ner)

A full setup requires five DNS records pointing to your instance’s public IP:

  • https://server.example.com - Main server
  • https://client.example.com - Client application
  • https://portainer.example.com - Container management
  • https://pgadmin.example.com - Database administration
  • https://minio.example.com - Object storage

For optional plugin-ner:

  • https://trigger.example.com - Trigger.dev dashboard
  • Operating System: Ubuntu Linux v24 (recommended)
  • Memory: Minimum 4GB
  • Storage: 50GB+ recommended
  • Network: Public IP address with DNS access

Begin by creating a new droplet in your Digital Ocean account.

Creating a DO Droplet

Choose Ubuntu (latest version) as your operating system and select appropriate region and datacenter.

Choose OS

Choose Basic shared CPU, Regular SSD with minimum: 4GB Memory, 2 CPUs, 80GB SSD.

Droplet Spec

Choose your preferred authentication method and enable automatic backups (recommended for production).

Choose Auth Method

Review your settings and create the droplet.

Create Droplet

Once created, note the IPv4 address for your new droplet.

All Created

Connect to your server:

Terminal window
ssh root@your_server_ip

Update the system:

Terminal window
apt update
apt upgrade

Create a new user with sudo privileges:

Terminal window
adduser recogito
usermod -aG sudo recogito

Configure UFW firewall:

Terminal window
ufw app list
ufw allow OpenSSH
ufw enable
ufw status

Best practice is to not utilize the root login except in special circumstances. Go ahead and exit the instance and SSH in with the new recogito user.

Terminal window
exit
ssh recogito@your_server_ip

Install and configure the web server:

Terminal window
sudo apt update
sudo apt install nginx

Adjust firewall for web traffic:

Terminal window
sudo ufw allow 'Nginx Full'
sudo ufw status

Verify Nginx is running:

Terminal window
systemctl status nginx

Test by navigating to http://your_server_ip - you should see the Nginx welcome page.

Nginx welcome

Verify Git is installed:

Terminal window
git --version

Install via SNAP:

Terminal window
sudo snap install docker

Install Node Package Manager:

Terminal window
sudo apt install npm

Clone the repository:

Terminal window
git clone --depth 1 https://github.com/recogito/recogito-studio.git
cd ./recogito-studio

Copy and edit environment variables:

Terminal window
cp ./docker/.env.example ./docker/.env
nano ./docker/.env

Nano Editor

Update these required values in your .env file:

  • POSTGRES_PASSWORD: Secure password (12+ characters, alphanumeric)
  • DASHBOARD_PASSWORD: Supabase dashboard password
  • ORG_ADMIN_PW: Initial superuser password (admin@example.com)

Generate JWT secret:

Terminal window
openssl rand -base64 36

Use Supabase JWT Generator:

Securing Supabase

  • JWT_SECRET: Generated secret above
  • ANON_KEY: Generate with ANON_KEY payload
  • SERVICE_ROLE_KEY: Generate with SERVICE_KEY payload
  • SITE_URL: Your client domain (https://client.example.com)
  • ROOM_SECRET: Generate with openssl rand -base64 24
  • MINIO_ROOT_USER/PASSWORD: MinIO dashboard credentials
  • PGADMIN_ADMIN_EMAIL/PASSWORD: pgAdmin web access

Copy and customize Nginx configuration files:

You will need 5 URLs for this setup

  • A client URL for accessing the Recogito Studio client
  • A server URL for API calls
  • A MinIO URL for accessing the MinIO dashboard
  • A pgAdmin URL for accessing pgAdmin
  • A Portainer URL for accessing the Portainer UI
Terminal window
sudo cp ./nginx.client.example.com /etc/nginx/sites-available/<your client url>
sudo nano /etc/nginx/sites-available/<your client url>

Replace client.example.com with your actual client domain.

Terminal window
sudo cp ./nginx.server.example.com /etc/nginx/sites-available/<your server url>
sudo nano /etc/nginx/sites-available/<your server url>

Update:

  • server_name with your server URL
  • Access-Control-Allow-Origin headers with your client URL

Repeat for remaining services:

Terminal window
sudo cp ./nginx.minio.example.com /etc/nginx/sites-available/minio.[yourdomain].com
sudo cp ./nginx.pgadmin.example.com /etc/nginx/sites-available/pgadmin.[yourdomain].com
sudo cp ./nginx.portainer.example.com /etc/nginx/sites-available/portainer.[yourdomain].com

Add WebSocket support to /etc/nginx/nginx.conf:

Terminal window
sudo nano /etc/nginx/nginx.conf

Add to http block:

map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

Create symbolic links:

Terminal window
sudo ln -s /etc/nginx/sites-available/<your server url> /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/<your client url> /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/<your pgAdmin url> /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/<your MinIO url> /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/<your Portainer url> /etc/nginx/sites-enabled/

Test and restart:

Terminal window
sudo nginx -t
sudo systemctl restart nginx

Install Certbot:

Terminal window
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

Generate certificates for each domain:

Terminal window
sudo certbot --nginx -d <your client url>
sudo certbot --nginx -d <your server url>
sudo certbot --nginx -d <your pgAdmin url>
sudo certbot --nginx -d <your MinIO url>
sudo certbot --nginx -d <your portainer url>

Verify auto-renewal:

Terminal window
sudo systemctl status snap.certbot.renew.service
sudo certbot renew --dry-run

Execute the installation script:

Terminal window
sudo bash ./install-self-hosted-docker.sh

Respond “Yes” to database push when prompted.

Navigate to your client URL (https://client.example.com). You should see the Recogito Studio interface.

Sign in with:

  • Username: admin@example.com
  • Password: Value from ORG_ADMIN_PW in your .env file

Navigate to your server URL (https://server.example.com) for Supabase studio access:

  • Username: supabase
  • Password: Value from DASHBOARD_PASSWORD in your .env file

Note: Run these commands from your base project directory (the folder containing your recogito-studio repository) so the relative paths match up.

Note: Check the latest release for any version-specific upgrade notes that may be missing from this guide, such as new required environment variables.

To upgrade a self-hosted instance, pull the latest revision of the self-hosting recogito-studio repo to the server running the docker container.

Terminal window
# fresh clone
git clone --single-branch --branch main --depth 1 https://github.com/recogito/recogito-studio
# or, if you already have it checked out
cd recogito-studio
git checkout main
git pull

In addition, pull the most recent, stable versions of the recogito-client and recogito-server repositories from GitHub.

Terminal window
cd ..
# fresh clones
git clone --single-branch --branch main --depth 1 https://github.com/recogito/recogito-client
git clone --single-branch --branch main --depth 1 https://github.com/recogito/recogito-server
# or, if you already have them checked out
cd recogito-client
git checkout main
git pull
cd ../recogito-server
git checkout main
git pull
cd ..

Replace the default client configuration file with your live environment’s custom config.json.

If you have made any manual configuration changes (such as branding), ensure those are propagated here.

Terminal window
rm -f ./recogito-client/src/config.json
cp ./recogito-studio/docker/config/config.json ./recogito-client/src/config.json
cd ./recogito-client

Ensure all environment variables from ./docker/.env.example are in ./docker/.env, as new required variables may have been added since your install.

Copy your live .env file into the client code directory and export the variables to the shell. This is critical because the build process needs to read these variables (like SITE_URL) to securely configure the frontend.

Terminal window
rm -f .env
cp ../recogito-studio/docker/.env .env
set -a && source .env && set +a

Instruct Docker to build a new image named recogito-studio-client:latest from scratch. The --no-cache flag ensures no outdated code or configurations accidentally carry over into the new build.

Terminal window
docker build --no-cache -t recogito-studio-client:latest .
cd ..

Because the backend runs on a pre-built Supabase Postgres image, upgrading the server primarily means updating the database schema to match the latest application requirements.

The first step is to ensure the server config.json has all of the latest Roles and Policies, which should be up to date from the latest version of the recogito-studio repo.

Terminal window
rm -f ./recogito-server/config.json
cp ./recogito-studio/docker/config/config.json ./recogito-server/config.json
cd ./recogito-server

Download the necessary Node.js packages required to run the migration scripts locally.

Terminal window
npm install

Then, use the Supabase CLI tool to push any new SQL schema changes directly into your running PostgreSQL database.

Terminal window
PGSSLMODE=disable npx supabase db push --db-url postgresql://postgres:$POSTGRES_PASSWORD@localhost:$POSTGRES_PORT/postgres --include-all

Finally, run the create-default-groups.js script. This reads your config.json and automatically updates the PostgreSQL database roles and access policies to match the latest configuration.

Terminal window
node ./create-default-groups.js -f ./config.json
cd ..

With the new frontend image built and the database fully up to date, the final step is to swap out the old live application for the new one.

Instruct Docker Compose to specifically target the client container. It will gracefully shut down the old container and immediately spin up a new one using the fresh recogito-studio-client:latest image.

Terminal window
cd ./recogito-studio/docker
docker compose -f ./docker-compose.yml -f ./docker-compose.client.yml up -d --force-recreate client
cd ../..

Feel free to delete the recogito-client and recogito-server repositories, as they are no longer needed.

Terminal window
rm -rf ./recogito-client/
rm -rf ./recogito-server/

Future documentation will cover:

  • Configuration and UI customization
  • SMTP setup for notifications
  • Logging with Logflare integration
  • External Postgres database configuration
  • Production hardening and monitoring