RS Supabase
Most of the Supabase processes, plus MinIO for object storage, and Cantaloupe as a IIIF server.
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.

A full setup requires five DNS records pointing to your instance’s public IP:
https://server.example.com - Main serverhttps://client.example.com - Client applicationhttps://portainer.example.com - Container managementhttps://pgadmin.example.com - Database administrationhttps://minio.example.com - Object storageFor optional plugin-ner:
https://trigger.example.com - Trigger.dev dashboardBegin by creating a new droplet in your Digital Ocean account.

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

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

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

Review your settings and create the droplet.

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

Connect to your server:
ssh root@your_server_ipUpdate the system:
apt updateapt upgradeCreate a new user with sudo privileges:
adduser recogitousermod -aG sudo recogitoConfigure UFW firewall:
ufw app listufw allow OpenSSHufw enableufw statusBest 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.
exitssh recogito@your_server_ipInstall and configure the web server:
sudo apt updatesudo apt install nginxAdjust firewall for web traffic:
sudo ufw allow 'Nginx Full'sudo ufw statusVerify Nginx is running:
systemctl status nginxTest by navigating to http://your_server_ip - you should see the Nginx welcome page.

Verify Git is installed:
git --versionInstall via SNAP:
sudo snap install dockerInstall Node Package Manager:
sudo apt install npmClone the repository:
git clone --depth 1 https://github.com/recogito/recogito-studio.gitcd ./recogito-studioCopy and edit environment variables:
cp ./docker/.env.example ./docker/.envnano ./docker/.env
Update these required values in your .env file:
Generate JWT secret:
openssl rand -base64 36
https://client.example.com)openssl rand -base64 24Copy and customize Nginx configuration files:
You will need 5 URLs for this setup
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.
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 URLAccess-Control-Allow-Origin headers with your client URLRepeat for remaining services:
sudo cp ./nginx.minio.example.com /etc/nginx/sites-available/minio.[yourdomain].comsudo cp ./nginx.pgadmin.example.com /etc/nginx/sites-available/pgadmin.[yourdomain].comsudo cp ./nginx.portainer.example.com /etc/nginx/sites-available/portainer.[yourdomain].comAdd WebSocket support to /etc/nginx/nginx.conf:
sudo nano /etc/nginx/nginx.confAdd to http block:
map $http_upgrade $connection_upgrade { default upgrade; '' close;}Create symbolic links:
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:
sudo nginx -tsudo systemctl restart nginxInstall Certbot:
sudo snap install core; sudo snap refresh coresudo snap install --classic certbotsudo ln -s /snap/bin/certbot /usr/bin/certbotGenerate certificates for each domain:
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:
sudo systemctl status snap.certbot.renew.servicesudo certbot renew --dry-runExecute the installation script:
sudo bash ./install-self-hosted-docker.shRespond “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:
admin@example.comORG_ADMIN_PW in your .env fileNavigate to your server URL (https://server.example.com) for Supabase studio access:
supabaseDASHBOARD_PASSWORD in your .env fileNote: 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.
# fresh clonegit clone --single-branch --branch main --depth 1 https://github.com/recogito/recogito-studio
# or, if you already have it checked outcd recogito-studiogit checkout maingit pullIn addition, pull the most recent, stable versions of the recogito-client and recogito-server repositories from GitHub.
cd ..
# fresh clonesgit clone --single-branch --branch main --depth 1 https://github.com/recogito/recogito-clientgit clone --single-branch --branch main --depth 1 https://github.com/recogito/recogito-server
# or, if you already have them checked outcd recogito-clientgit checkout maingit pull
cd ../recogito-servergit checkout maingit pull
cd ..config.jsonReplace 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.
rm -f ./recogito-client/src/config.jsoncp ./recogito-studio/docker/config/config.json ./recogito-client/src/config.jsoncd ./recogito-client.envEnsure 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.
rm -f .envcp ../recogito-studio/docker/.env .envset -a && source .env && set +aInstruct 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.
docker build --no-cache -t recogito-studio-client:latest .cd ..config.jsonBecause 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.
rm -f ./recogito-server/config.jsoncp ./recogito-studio/docker/config/config.json ./recogito-server/config.jsoncd ./recogito-serverDownload the necessary Node.js packages required to run the migration scripts locally.
npm installThen, use the Supabase CLI tool to push any new SQL schema changes directly into your running PostgreSQL database.
PGSSLMODE=disable npx supabase db push --db-url postgresql://postgres:$POSTGRES_PASSWORD@localhost:$POSTGRES_PORT/postgres --include-allFinally, 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.
node ./create-default-groups.js -f ./config.jsoncd ..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.
cd ./recogito-studio/dockerdocker compose -f ./docker-compose.yml -f ./docker-compose.client.yml up -d --force-recreate clientcd ../..Feel free to delete the recogito-client and recogito-server repositories, as they are no longer needed.
rm -rf ./recogito-client/rm -rf ./recogito-server/Future documentation will cover: