Orafila Documentation Book a demo

Document 7 of 13

Installation

Delivery options, step-by-step installation, external database, configuration.

For whom: IT

This document explains how Orafila is put into service: the delivery options, installation on a server with the Docker package, the optional external database, a trial run on a computer and the configuration reference.

The step-by-step guides with screenshots of the cloud providers, written also for people who are not system administrators, are in the package:

  • Deployment on Oracle Cloud (in Italian): a free Always Free VM, suitable for demos and pilots;
  • Deployment on DigitalOcean (in Italian): a paid Droplet, also suitable for customers in production;
  • External database (in Italian).

1. Delivery options

Managed service Dedicated installation
Who manages the server The Orafila provider The provider or the company's IT, on the server the company chooses
What the company receives The application's address, the company code and an invitation link for the first administrator A complete installation, possibly with several companies (for example the companies of a group)
Installation None for the company An Ubuntu server with Docker, about 2-3 hours the first time (almost all of it waiting)
Updates and backups Taken care of by the provider One command to update; automatic nightly backups once configured
AI keys The provider's or the company's, depending on the contract The company's, with its own direct contract with the AI provider

In both cases the application is the same and each company's data is kept separate by the database. With the managed service the company starts from step 8 of this document and then from Getting started with a company.

2. Before you start

  • An Ubuntu 24.04 server (or 22.04) that meets the requirements in Requirements and architecture, reachable via SSH with a key.
  • A domain name whose DNS you can change (for example psa.yourcompany.com) and an e-mail address for registering the HTTPS certificates.
  • The release address of Orafila and, if the Orafila provider uses them, the server's access credentials (Client ID and Client Secret): the provider sends them (step 4).
  • A password manager in which to save the keys generated by the installation. It is essential.
  • Optional: an Anthropic, OpenAI or Google API key for AI; an S3-compatible bucket for the copy of the backups; an account with an external monitoring service (for example Healthchecks.io and an uptime service).

From here on, commands that start with deploy/ are typed on the server, from the orafila folder.

3. Creating the server and the DNS

  1. Create the server with the provider you have chosen, preferably in a European Union region. The Oracle and DigitalOcean guides describe every screen.
  2. In the provider's firewall open inbound TCP 80, TCP 443 and UDP 443 from everywhere, and TCP 22 (SSH) preferably only from your IP address.
  3. In the domain's DNS create an A record with the chosen name (for example psa) pointing to the server's public IP. Before going on, the name must answer with the right IP (nslookup psa.yourcompany.com).

4. Downloading the package

Orafila is downloaded with the installer: it takes the latest version from the release server, checks its digital signature (the proof that the package comes from the Orafila provider and that nobody has altered it) and creates the orafila folder. Instead of https://rilasci.orafila.com, use the release address the provider gave you:

cd ~
curl -fsSLO https://rilasci.orafila.com/install.sh
bash install.sh
cd orafila

If the provider sent you the installer's fingerprint, before bash install.sh check that sha256sum install.sh prints the same one. If the release server is protected, the installer asks for the Client ID and Client Secret and saves them in deploy/.env: updates need them too. No sudo is needed and nothing changes outside the orafila folder. If the installer reports that the signature does not match, do not go on and tell the Orafila provider.

5. Preparing the server

sudo deploy/setup-host.sh

The script (5 to 15 minutes; it can be run again without harm):

  • recognises the provider (Oracle Cloud, DigitalOcean or another Ubuntu);
  • creates 2 GB of swap on servers with less than 3.5 GB of RAM;
  • updates Ubuntu and turns on automatic security updates;
  • installs Docker (from Docker's official repository), git, age and rclone;
  • opens ports 80 and 443 in the server's internal firewall, if it blocks them;
  • checks whether the outbound SMTP ports are blocked (465, 587) and suggests port 2525.

As a user other than root (for example ubuntu on Oracle), log out and back in with SSH so that the docker group applies to you too; docker ps must answer without errors.

6. Configuring and saving the keys

deploy/nova.sh init --domain psa.yourcompany.com --email it@yourcompany.com

The script creates deploy/.env (readable only by your user), generates all the passwords and secrets and creates the key for encrypting the backups in deploy/secrets/backup.agekey. If run again, it never changes the values already there.

Straight away, save in the password manager:

cat deploy/secrets/backup.agekey          # all of the content, lines with # included
grep '^APP_ENCRYPTION_KEY=' deploy/.env
cat deploy/.env                            # recommended: the whole configuration
  • Without the backups' private key the backups cannot be opened.
  • Without APP_ENCRYPTION_KEY, after a restore the two-step verification and the mailbox passwords can no longer be read.
  • Update the copy every time you change deploy/.env. Never send these keys by e-mail or in a chat.

AI (optional): to turn it on, write the key of at least one provider in deploy/.env (ANTHROPIC_API_KEY=, OPENAI_API_KEY= or GEMINI_API_KEY=, with no spaces after =). It is a good idea to also set a spending limit in the provider's console. You can also do this later: every change to deploy/.env is applied with deploy/nova.sh up.

7. Starting

deploy/nova.sh up

The script checks the memory, builds the image (10-15 minutes the first time), starts the database, applies the schema migrations, then starts the app, the mail worker and Caddy, and waits for the app to answer.

Checks:

  • deploy/nova.sh status: app, worker and db healthy, caddy running, migrate exited (normal: it has finished).
  • https://psa.yourcompany.com shows the padlock and the sign-in page (Company code, E-mail, Password).
  • https://psa.yourcompany.com/api/health answers {"status":"ok"}.

If the HTTPS certificate does not arrive: wait 2-3 minutes; check the DNS and ports 80/443 (also with sudo deploy/setup-host.sh --firewall-only); read deploy/nova.sh logs caddy (certificate obtained successfully means it is fine). After the fix, deploy/nova.sh up restarts the request straight away. Too many failed attempts in a row make Let's Encrypt block you for about an hour.

8. Activating the first company

Each company has a company code of 3 to 40 characters made of lower-case letters, digits and hyphens:

deploy/nova.sh tenant-create --name "Rossi Software Srl" --slug rossi \
  --admin-email anna.rossi@rossisoftware.it --admin-name "Anna Rossi"

The command creates the company, the seven default roles, the Assistenza queue (ticket prefix TCK) and the invitation for the first administrator, and prints the invitation link (https://psa.yourcompany.com/invite/...), valid for 7 days and only once. Send it to the administrator over a secure channel: Orafila does not send it by e-mail.

Useful options:

Option Effect
--lingua en Company in English: roles and queue with English names, documents and e-mails to customers in English, interface in English for the administrator
--queue-address assistenza@rossisoftware.it Address of the queue for the e-mail forwarding gateway (see Integrations)
--reinvite --slug rossi A new link for the first administrator, if the previous one has expired or been lost (the old one stops working); with --admin-email it also corrects the address

The administrator opens the link, chooses a password (at least 12 characters), signs in with company code, e-mail and password and turns on two-step verification. From there they carry on with Getting started with a company.

Sample data (optional, for a demo or for training): deploy/nova.sh sample-data --slug rossi fills every screen with made-up, recognisable data (ESEMPIO-... codes, @esempio.example addresses, two years of history); deploy/nova.sh sample-data --slug rossi --remove removes it without touching the real data. Remove it before working with real customers.

9. Configuring the backups

  1. Create an S3-compatible private bucket (Oracle Object Storage, DigitalOcean Spaces or another) and an access key limited to that bucket. On Oracle, add a retention rule that prevents files from being deleted for 29 days.
  2. In deploy/.env, fill in BACKUP_RCLONE_REMOTE and the RCLONE_CONFIG_... lines for your storage (the template deploy/env.example has ready-made blocks for Oracle and DigitalOcean).
  3. First test backup: deploy/nova.sh backup (it creates the backup, verifies it by decrypting it and copies it to the bucket). deploy/nova.sh backups lists the local and remote backups.
  4. Automatic backup every night at 02:30: deploy/nova.sh install-timer (check with systemctl list-timers nova-backup.timer).
  5. Recommended: a check on Healthchecks.io (period 1 day, grace 2 hours) with its address in BACKUP_PING_URL: if a night's backup does not arrive or fails, you receive an e-mail.
Variable Default Meaning
BACKUP_KEEP_LOCAL 7 Backups kept on the server
BACKUP_KEEP_REMOTE_DAYS 30 Days in the bucket (longer than the retention rule)
BACKUP_PING_URL empty Monitoring address called after every backup

10. External monitoring and restore test

  • Create an HTTPS availability (uptime) check on https://psa.yourcompany.com/api/health every 5 minutes, with an e-mail alert: the server cannot warn you if it is off.
  • Test the restore straight away, not on the day you need it: deploy/nova.sh restore nova-YYYYMMDDTHHMMSSZ.dump.age --yes (it takes a safety backup first). The complete rebuild on a new server (package, deploy/.env and keys from the password manager, restore from the bucket) is described in the providers' guides. See also Operations and maintenance.

11. External database (optional)

PostgreSQL usually runs in a container on the same server. For a managed database (high availability, backups and point-in-time recovery from the provider) or a company PostgreSQL server:

  1. After deploy/nova.sh init, copy the provider's CA certificate to deploy/db-ca.crt.
  2. In deploy/.env, fill in:
    NOVA_DB_HOST=database-server-name
    NOVA_DB_PORT=5432            # 25060 on DigitalOcean
    NOVA_DB_NAME=nova
    NOVA_DB_SSLMODE=verify-full  # or verify-ca; other values are refused
    NOVA_DB_CA_FILE=./db-ca.crt  # empty = public authorities, only with verify-full
    
  3. deploy/nova.sh db-setup: asks for the credentials of a database administrator (it does not save them) and creates the roles nova_owner, nova_app, nova_app_user, the database and, if the provider allows it, nova_backup for backups. The passwords reach the database as SCRAM verifiers, never in clear text.
  4. deploy/nova.sh up: checks the connection, stops the internal database (its volume is kept) and applies the migrations to the external database.

From then on, backup, restore, updates and tools work on the external database. To move the data of an installation that is already running, take a backup before filling in NOVA_DB_HOST, then run db-setup, restore and up. All the details, the common problems and the security checklist are in the guide External database (in Italian).

12. Trial run on a computer (without Docker)

For a technical evaluation or for development, on Linux or macOS with Node.js 22.18 or later and PostgreSQL 15 or later:

cd orafila
npm install
cp .env.example .env.local                  # then fill in the variables (see below)
sudo -u postgres scripts/setup-dev-db.sh    # roles nova_owner, nova_app, nova_app_user and database nova_dev
npm run db:migrate
npm run db:seed                             # demo data: companies "demo" and "altra"
npm run build && npm start                  # in another terminal: npm run mail:worker

Demo sign-in at http://localhost:3000: company demo, e-mail responsabile@demo.example (administrator), password Demo-Orafila-2026!; other roles with commerciale@, amministrazione@, magazzino@, marco.galli@ (technician), all @demo.example. These credentials are public and are valid only for the local trial: never use db:seed on a real installation.

13. Reference: server configuration (deploy/.env)

Variable Required Meaning
NOVA_DOMAIN yes Domain name, without https://
ACME_EMAIL yes E-mail address for the Let's Encrypt certificates
POSTGRES_PASSWORD, NOVA_OWNER_PASSWORD, NOVA_APP_PASSWORD yes (generated) Passwords of the database roles; up applies them to the database
APP_ENCRYPTION_KEY yes (generated) 32 bytes in base64 that encrypt the secrets; on a server that is already running it must never be regenerated
INBOUND_EMAIL_SECRET yes (generated) Secret of the e-mail forwarding gateway
ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY no Keys of the AI providers; one is enough
NOVA_AI_MODEL no Default agent for the companies that do not choose one (for example claude-sonnet-5-5; empty = Claude Opus 5.5)
MAIL_POLL_SECONDS no (60) How often, in seconds, the mailboxes are read (10 or more)
BACKUP_AGE_RECIPIENT yes (generated) Public key for encrypting the backups
BACKUP_KEEP_LOCAL, BACKUP_KEEP_REMOTE_DAYS, BACKUP_RCLONE_REMOTE, BACKUP_PING_URL, RCLONE_CONFIG_* no Retention and copying of the backups
NOVA_DB_HOST, NOVA_DB_PORT, NOVA_DB_NAME, NOVA_DB_SSLMODE, NOVA_DB_CA_FILE, NOVA_BACKUP_PASSWORD, NOVA_DB_CLIENT_IMAGE no External database

Format: one KEY=value line, with no spaces around =, comments on their own lines; a value containing $ goes in single quotes.

For an installation without the package (a local run or another platform) the app reads: DATABASE_URL (application role, subject to the isolation), ADMIN_DATABASE_URL (owner, only for migrations and tools), APP_ENCRYPTION_KEY, INBOUND_EMAIL_SECRET, APP_BASE_URL (public address for the invitation links), TRUST_PROXY=1 only behind a proxy that sets X-Forwarded-For, the AI keys and, with a database using TLS, ?sslmode=verify-full&sslrootcert=/path/to/ca.crt in the address plus NOVA_DB_REQUIRE_VERIFIED_TLS=1.

14. Reference: deploy/nova.sh commands

Command What it does
init [--domain D] [--email E] Creates .env with new secrets and the backup key (does not change the values already there)
db-setup Only with an external database: creates roles and database with the credentials of an administrator, which are not saved
up Builds the image and starts or restarts everything
install-timer Turns on the automatic backup every night at 02:30
status Services, external database, disk, memory, last backup, outgoing e-mails
logs [-f] [service...] Logs of app, worker, db, caddy, migrate
version Installed version and latest available version
update [--no-backup] [--version V] Downloads the new version from the release server and checks its signature, takes a backup and restarts (--version for a specific version)
tenant-create ... Activates a company and prints the invitation link
queue-address ... Assigns or removes the address of a queue for the forwarding gateway
sample-data --slug CODE [--remove] Adds or removes a company's sample data
backup An encrypted backup now, plus the remote copy if configured
backups Lists the local and remote backups
restore FILE --yes [--key K] [--no-safety-backup] Restores a backup, after a safety backup (--no-safety-backup only with an external database that nova.sh cannot back up, after a copy from the provider)
help List of commands

Never use docker compose down -v, docker volume rm or docker system prune --volumes: they delete the database.