Applications AWS

Relaticle 3.8.2 on AWS User Guide

| Product: Relaticle 3.8.2 on Ubuntu 24.04 on AWS

Overview

This guide covers launching and using the Relaticle 3.8.2 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg ERP and CRM listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.

Relaticle is an open source customer relationship management platform built on Laravel, Filament and Livewire. It keeps companies, people and opportunities with tasks and notes, lets each team define its own custom fields, imports and exports CSV files, and gives every team its own workspace. A REST API (/api/v1, with personal access tokens) and an MCP server (/mcp, for AI assistants, with OAuth) expose the same records to other tools.

The cloudimg image is a hardened, ready-to-use Relaticle server:

  • The upstream release. Relaticle 3.8.2 from its GitHub tag, verified against its SHA-256. No Relaticle source file is modified. Its PHP dependencies are installed from the tag's own lock file and its front end is compiled from the tag's own lock file, unchanged (no known advisory in either). SOURCE.txt lists exactly what is not shipped.
  • No default login. No account exists on the image. First boot creates a CRM administrator, admin@cloudimg.local, owner of the workspace My Workspace, and a system administrator, sysadmin@cloudimg.local, each with its own random password unique to your instance. APP_KEY (Laravel's encryption key), the passkey secret, the Passport OAuth key pair and the PostgreSQL password are also generated on your instance. Until first boot has finished, neither nginx nor PHP starts.
  • HTTPS from the first boot. nginx serves Relaticle on 443 with a certificate generated on your instance (an end-entity certificate, not a certificate authority). Port 80 redirects to HTTPS. The server's name is set from the instance's EC2 public DNS name at first boot, and requests for any other name are dropped. You can change it to your own domain.
  • PostgreSQL 16 on the local socket only. The database server does not listen on any network port. Relaticle connects over the Unix socket with its own role, which owns only the relaticle database. The image ships no database cluster at all: the cluster, its keys and its roles are created on your instance.
  • Hardened web tier. PHP runs as its own unprivileged user on a Unix socket only nginx can reach, with every way of starting a program disabled. nginx passes Relaticle the real client address from the connection, never a header a client sends, limits sign-in and password-reset requests per address (Relaticle also throttles an address after five failed sign-ins), refuses cross-site requests to the routes that change state on a link (impersonation and the OAuth redirects), and refuses the front controller path, Horizon, Telescope, the debug bar, configuration, logs and the source tree. Debug mode is off and the environment is production.
  • Outbound integrations off until you configure them. Mail goes to Relaticle's log until you set an SMTP server. The AI assistant, Google and Microsoft sign-in, the e-mail and calendar integration, billing, error reporting and analytics are switched off, and no credential for any outside service is on the image.
  • Egress backstop. The relaticle user (the web application, the queue worker, the scheduler and every command run through relaticle-artisan) cannot reach the instance metadata service, link-local, loopback, reserved or multicast addresses, any IPv6 address, or any private address inside your VPC. A URL typed into Relaticle therefore cannot be used to probe your network. You can allow specific in-VPC hosts (Step 12).
  • Metadata service blocked. nginx, PHP, PostgreSQL, the queue worker, the scheduler and the first-boot service cannot reach the EC2 instance metadata service. The AMI requires IMDSv2.
  • Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.

What is on the image: Relaticle 3.8.2 (AGPL-3.0), PHP 8.5 FPM and CLI (from the ondrej/php PPA, as Relaticle requires PHP 8.4 or later), PostgreSQL 16, nginx, nftables, cloud-init and the AWS Systems Manager agent, all from Ubuntu 24.04 except Relaticle and PHP. Node.js and Composer are not on the image.

Default user: ubuntu · Architecture: x86_64 · Recommended instance type: m5.large (2 vCPUs, 8 GiB). A t3.large is enough for a small team.

Prerequisites

  • An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet.
  • A security group that allows TCP 22 (SSH) from your own networks only, TCP 443 from wherever your users are, and TCP 80 (redirects to HTTPS). No other port is needed.
  • For production, a DNS name you control (for example crm.example.com) and, ideally, a certificate from a certificate authority. Until then the instance uses its EC2 public DNS name with its own self-signed certificate.
  • For invitations, password resets and e-mail verification, an SMTP server or a service such as Amazon SES (Step 10).

Connecting to your instance

Operating system SSH user
Ubuntu 24.04 ubuntu

Step 1: Launch the instance

Launch from the AWS Marketplace page (choose the Relaticle 3.8.2 on Ubuntu 24.04 version), or with the AWS CLI using the AMI ID shown on the listing's launch page:

aws ec2 run-instances --image-id ami-xxxxxxxxxxxxxxxxx --instance-type m5.large \
  --key-name my-key --security-group-ids sg-xxxxxxxx --subnet-id subnet-xxxxxxxx \
  --metadata-options HttpTokens=required,HttpEndpoint=enabled \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=relaticle}]'

First boot takes about a minute once the instance is up: it creates the PostgreSQL cluster and the database, mints the keys, runs Relaticle's migrations, creates the two administrators and the certificate. The web interface stays offline until that has finished.

Step 2: Connect to your instance

ssh -i my-key.pem ubuntu@<public-ip>

Step 3: Check the services

systemctl is-active postgresql@16-main.service nginx.service php8.5-fpm.service relaticle-queue.service relaticle-egress-guard.service
sudo ss -ltnp | awk 'NR==1 || /:(22|80|443|5432) /'
sudo ss -lxp | grep -E 'relaticle-fpm|PGSQL'
active
active
active
active
active
State  Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0      511          0.0.0.0:443       0.0.0.0:*    users:(("nginx",pid=240676,fd=7),("nginx",pid=240675,fd=7),("nginx",pid=232138,fd=7))
LISTEN 0      4096         0.0.0.0:22        0.0.0.0:*    users:(("sshd",pid=817,fd=3),("systemd",pid=1,fd=210))
LISTEN 0      511          0.0.0.0:80        0.0.0.0:*    users:(("nginx",pid=240676,fd=5),("nginx",pid=240675,fd=5),("nginx",pid=232138,fd=5))
LISTEN 0      511             [::]:443          [::]:*    users:(("nginx",pid=240676,fd=8),("nginx",pid=240675,fd=8),("nginx",pid=232138,fd=8))
LISTEN 0      4096            [::]:22           [::]:*    users:(("sshd",pid=817,fd=4),("systemd",pid=1,fd=215))
LISTEN 0      511             [::]:80           [::]:*    users:(("nginx",pid=240676,fd=6),("nginx",pid=240675,fd=6),("nginx",pid=232138,fd=6))
u_str LISTEN 0      4096                       /run/php/relaticle-fpm.sock 411544            * 0    users:(("php-fpm8.5",pid=236192,fd=10),("php-fpm8.5",pid=235968,fd=10),("php-fpm8.5",pid=235730,fd=10),("php-fpm8.5",pid=235295,fd=10),("php-fpm8.5",pid=232133,fd=8))
u_str LISTEN 0      200                  /var/run/postgresql/.s.PGSQL.5432 406009            * 0    users:(("postgres",pid=223692,fd=6))

Only SSH, HTTP and HTTPS listen on the network. PostgreSQL (5432) listens only on its Unix socket, and so does PHP.

Step 4: Get your addresses and the administrator passwords

First boot writes everything you need to sign in to a file only root can read:

sudo cat /root/relaticle-credentials.txt
# Relaticle 3.8.2 - generated on first boot by relaticle-firstboot.service
# These credentials are unique to this instance; none was baked into the image. Keep this file secret.

RELATICLE_URL=https://ec2-44-202-112-14.compute-1.amazonaws.com/app/login
RELATICLE_ADMIN_EMAIL=admin@cloudimg.local
RELATICLE_ADMIN_PASSWORD=<24 random letters and digits>
RELATICLE_SYSADMIN_URL=https://ec2-44-202-112-14.compute-1.amazonaws.com/sysadmin/login
RELATICLE_SYSADMIN_EMAIL=sysadmin@cloudimg.local
RELATICLE_SYSADMIN_PASSWORD=<24 random letters and digits>
RELATICLE_TLS_SHA256=<the certificate SHA-256 fingerprint>
...
  • RELATICLE_URL is the CRM's sign-in page.
  • RELATICLE_ADMIN_EMAIL / RELATICLE_ADMIN_PASSWORD sign in to the CRM as the administrator of My Workspace.
  • RELATICLE_SYSADMIN_URL and RELATICLE_SYSADMIN_EMAIL / RELATICLE_SYSADMIN_PASSWORD sign in to the system administration panel, which manages every user and workspace on the server (Step 7).
  • RELATICLE_TLS_SHA256 is the fingerprint of the instance's own certificate. Your browser will warn that the certificate is not trusted; compare the fingerprint it shows with this one before you continue. Replace it with a certificate from a certificate authority for your own name when you can (Step 13).

Step 5: Run the self-test

The image includes an end-to-end test. Over HTTPS on the instance it checks that port 80 redirects, that the front controller path, Horizon, the debug bar, the configuration file, the data and the sources are refused, that the health check answers, that the CRM refuses a request without a session, that both administrators sign in through Relaticle's own sign-in forms, and that a wrong password and common default passwords are refused:

sudo relaticle-cred-roundtrip
RELATICLE_ROUNDTRIP_OK https 301 + no index.php/Horizon/debugbar/env/data/sources + healthz + CRM closed without a session + CRM administrator sign-in (Relaticle's two-step form) + system-administrator sign-in + wrong and default passwords refused

Step 6: Sign in to the CRM

Open RELATICLE_URL in your browser and check the certificate fingerprint. Relaticle's sign-in is two steps: enter RELATICLE_ADMIN_EMAIL and choose Continue, then enter RELATICLE_ADMIN_PASSWORD.

The Relaticle sign-in page, Welcome to Relaticle, with the e-mail address admin@cloudimg.local entered and a Continue button

The first time you sign in, Relaticle opens a short workspace setup: it asks what you will use Relaticle for and offers to invite teammates (invitations are sent by e-mail, so they need Step 10 first; you can skip that step). After the setup you land on the workspace's Home page:

The Relaticle Home page for My Workspace with a Welcome, Administrator heading, an Ask anything box, an empty Tasks panel with a New task button, the navigation for Home, People, Companies, Opportunities, Tasks and Notes, and a Get started checklist

Relaticle keeps you signed in on that browser (its sign-in always uses "remember me"). To change a password, run one of these on the instance. The first generates a new random password; the second reads yours (20 to 72 letters and digits, with upper case, lower case and a digit) from the terminal, never from the command line. Either way every session of that account is signed out and the new password is written to /root/relaticle-credentials.txt. Add --sysadmin to change the system administrator's password instead:

sudo relaticle-set-password
sudo relaticle-set-password --sysadmin
# Type <new-password> at the prompt; nothing is echoed.
read -rs -p 'New Relaticle password: ' P; echo
printf '%s\n' "$P" | sudo relaticle-set-password --stdin; unset P

Change the administrator's name and e-mail address from the avatar at the top right. Once you have stored the passwords somewhere safe, you can delete the two _PASSWORD lines from /root/relaticle-credentials.txt.

Sign-up. Relaticle's sign-in page always offers to create an account for an address it does not know. On this image a new account must verify its e-mail address before it can open the CRM, and no mail leaves the instance until you configure SMTP, so a stranger who signs up gets an unverified account that cannot reach any data. Once mail is configured anyone who can reach the page could sign up and get an empty workspace of their own (never yours), so restrict port 443 to your users' networks (Step 14) and remove unwanted accounts in the system administration panel.

Step 7: Work with companies, people and opportunities

Companies, People and Opportunities are tables you can search, filter, sort and extend with your own columns. New company (or New person, New opportunity) adds a record; Import / Export loads or saves CSV files. Tasks and Notes attach to any record, and Settings in the workspace menu holds custom fields, members and the workspace's API access tokens.

The Relaticle Companies table for My Workspace with the columns Company, Account Owner, Created By, Creation Date, Last Update, ICP and Domains, a No companies message, a Search box and the Import / Export and New company buttons

The system administration panel at RELATICLE_SYSADMIN_URL lists every user and workspace on the server. Sign in with RELATICLE_SYSADMIN_EMAIL and RELATICLE_SYSADMIN_PASSWORD; at the first sign-in Relaticle requires the system administrator to enrol an authenticator app (a TOTP code) before the panel opens.

The Relaticle System Admin sign-in page with Email address and Password fields, a Remember me box and a Sign in button

The Ask anything box and Ask Rela are Relaticle's AI assistant. It needs an OpenAI or Anthropic API key and a Redis server, neither of which is on the image, so it does not answer until you add both.

Step 8: The queue worker and the scheduler

Relaticle runs imports, notifications and other background work through a queue. On this image the queue worker is the relaticle-queue service, and the scheduler is the relaticle-schedule.timer, which runs Relaticle's scheduled housekeeping every minute. Both run as the unprivileged relaticle user:

systemctl show -p User -p ActiveState -p SubState relaticle-queue.service
sudo relaticle-artisan schedule:list
systemctl show -p UnitFileState relaticle-schedule.timer
User=relaticle
ActiveState=active
SubState=running

  0    * * * *  php artisan import:cleanup ....... Next Due: 1 minute from now
  0    * * * *  php artisan app:purge-pending-uploads  Next Due: 1 minute from now
  0    0 * * *  php artisan queue:prune-batches --hours=24  Next Due: 9 hours from now
  0    0 * * *  php artisan invitations:cleanup ... Next Due: 9 hours from now
  0    0 * * *  php artisan activitylog:clean --force  Next Due: 9 hours from now
  0    0 * * *  php artisan model:prune --model='App\Models\Notification'  Next Due: 9 hours from now
  */5  * * * *  php artisan chat:expire-pending-actions  Next Due: 1 minute from now
  */10 * * * *  php artisan chat:release-orphaned-reservations  Next Due: 1 minute from now
  0    * * * *  php artisan chat:purge-unsent-attachments  Next Due: 1 minute from now
  0    * * * *  php artisan chat:reset-credits ... Next Due: 1 minute from now
  0    0 * * 0  php artisan disposable:update ...... Next Due: 6 days from now
  0    * * * *  php artisan tor:update-exit-nodes  Next Due: 1 minute from now
  0    2 * * *  php artisan subscribers:reconcile --limit=500  Next Due: 11 hours from now
  0    0 * * *  php artisan app:purge-scheduled-deletions  Next Due: 9 hours from now
  0    * * * *  php artisan notifications:send-task-digest  Next Due: 1 minute from now
  0    * * * *  php artisan notifications:send-setup-nudge  Next Due: 1 minute from now

UnitFileState=enabled

The scheduler is switched on on a new instance. Two of its tasks fetch public lists that Relaticle uses to protect its sign-up form: disposable:update downloads a list of disposable e-mail domains once a week (from cdn.jsdelivr.net), and tor:update-exit-nodes downloads the list of Tor exit nodes every hour (from check.torproject.org). Neither sends any data about your instance. The mailbox and calendar synchronisation tasks and the health checks are not scheduled, because those features are off.

Step 9: Relaticle's command line

relaticle-artisan runs Relaticle's own artisan commands as the relaticle user, with the same metadata block and egress backstop as the web tier:

sudo relaticle-artisan --version
sudo relaticle-artisan about --only=environment
Laravel Framework 13.40.0

  Environment ................................................................
  Application Name ................................................. Relaticle
  Laravel Version .................................................... 13.40.0
  PHP Version ......................................................... 8.5.12
  Composer Version ......................................................... -
  Environment ..................................................... production
  Debug Mode ............................................................. OFF
  URL .............................. ec2-44-202-112-14.compute-1.amazonaws.com
  Maintenance Mode ....................................................... OFF
  Timezone ............................................................... UTC
  Locale .................................................................. en

Step 10: Send e-mail and turn on other integrations

Out of the box Relaticle writes outgoing mail (invitations, password resets, e-mail verification and notification digests) to its log instead of sending it. To send through your mail server or a service such as Amazon SES, edit /etc/relaticle/env as root and set the mail values:

MAIL_MAILER=smtp
MAIL_HOST=email-smtp.us-east-1.amazonaws.com
MAIL_PORT=587
MAIL_SCHEME=smtp
MAIL_USERNAME=<your SMTP user name>
MAIL_PASSWORD=<your SMTP password>
MAIL_FROM_ADDRESS=crm@example.com
MAIL_FROM_NAME=Relaticle

Then clear Relaticle's cached configuration and restart PHP and the queue worker:

sudo relaticle-artisan config:clear
sudo systemctl restart php8.5-fpm relaticle-queue

The same file holds the other integrations, all empty or false on a new instance: OPENAI_API_KEY or ANTHROPIC_API_KEY for the AI assistant (which also needs Redis), GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET and MICROSOFT_CLIENT_ID/MICROSOFT_CLIENT_SECRET with RELATICLE_FEATURE_SOCIAL_AUTH=true for Google and Microsoft sign-in, and RELATICLE_FEATURE_EMAIL_INTEGRATION=true for the mailbox and calendar integration (which also needs those OAuth credentials). The file is readable by root and the relaticle group only. If a server you configure has a private address inside your VPC, allow it first (Step 12).

API and MCP. Each user can create personal access tokens for the REST API under Settings > Access tokens. The MCP server at /mcp refuses every request without a token; AI assistants obtain one through OAuth, and Relaticle publishes its OAuth metadata (/.well-known/oauth-authorization-server) and accepts OAuth client registrations (/oauth/register) from anyone, as the MCP specification expects. A registered client still gets no access until a signed-in user approves it.

Step 11: The setup wizard, workspaces and members

Each workspace has its own members, records and custom fields. Invite teammates from Invite teammates at the bottom of the navigation (this needs mail, Step 10); each invited person signs in with their own address and password. A user who signs up on their own (once mail is configured and their address is verified) works in a workspace of their own, never in yours, until a member of your workspace invites them.

Step 12: Allow hosts inside your VPC

The egress backstop stops the relaticle user (the web application, the queue worker, the scheduler and relaticle-artisan) from connecting to any address in your VPC's own address ranges, which it reads from the instance metadata at every boot. Public addresses work as usual. You can see the ranges, and that the metadata service is refused to Relaticle while public sites are not:

sudo nft list set inet cloudimg_relaticle_egress vpc4 | grep elements
sudo -u relaticle curl -s -m 5 -o /dev/null -w 'metadata: %{http_code}\n' http://169.254.169.254/latest/meta-data/ || true
sudo -u relaticle curl -s -m 5 -o /dev/null -w 'public HTTPS: %{http_code}\n' https://www.cloudimg.co.uk/ || true
        elements = { 172.31.0.0/16 }
metadata: 000
public HTTPS: 200

If Relaticle must reach a host inside the VPC (an SMTP relay or a VPC interface endpoint on a private address), add its address or CIDR, one per line, to /etc/cloudimg/relaticle-egress-allow.conf and apply it. This restarts PHP and the queue worker with the new rules:

echo '172.31.10.25' | sudo tee -a /etc/cloudimg/relaticle-egress-allow.conf >/dev/null
sudo systemctl restart relaticle-egress-guard
sudo nft list set inet cloudimg_relaticle_egress allow4 | grep elements
        elements = { 172.31.10.25 }

Only the addresses you list are opened; the metadata service, link-local, loopback, reserved and multicast ranges and IPv6 stay refused whatever the file says.

Step 13: Use your own domain and certificate

Point a DNS name at the instance (an Elastic IP is a good idea), then:

sudo relaticle-set-hostname <your-domain>

This creates a new self-signed certificate for the name, pins nginx to it (other names are dropped), sets Relaticle's APP_URL (used in links in its e-mails and in the OAuth metadata) and the cross-site guard, and updates the URLs and fingerprint in /root/relaticle-credentials.txt. To use a certificate from a certificate authority, replace /etc/nginx/ssl/relaticle.crt and relaticle.key (keep the key 0600 root) and run sudo systemctl reload nginx.

Step 14: Restrict access to your networks

Limit who can reach the web interface in the instance's security group. For example, to allow HTTPS only from your office network:

aws ec2 authorize-security-group-ingress --group-id sg-xxxxxxxx --protocol tcp --port 443 --cidr <your-mgmt-cidr>
aws ec2 revoke-security-group-ingress --group-id sg-xxxxxxxx --protocol tcp --port 443 --cidr 0.0.0.0/0

Relaticle throttles sign-in from a client address after five failed attempts (for the CRM and the system administration panel alike) and locks an e-mail address after ten failed attempts in fifteen minutes, and nginx separately rate limits requests for the sign-in and password-reset pages per client address.

Step 15: Check the security posture

U=$(sudo sed -n 's/^RELATICLE_URL=//p' /root/relaticle-credentials.txt); U=${U%/app/login}
C=/etc/nginx/ssl/relaticle.crt
for p in app/login sysadmin/login healthz up; do
  curl -s --cacert "$C" -o /dev/null -w "GET /$p: %{http_code}\n" "${U}/$p"
done
for p in index.php index.php/app/login .env horizon telescope _debugbar/open storage/logs/laravel.log composer.json; do
  curl -s --cacert "$C" -o /dev/null -w "GET /$p: %{http_code}\n" "${U}/$p"
done
curl -s --cacert "$C" -o /dev/null -w 'GET /impersonate/1 from another site: %{http_code}\n' -H 'Sec-Fetch-Site: cross-site' "${U}/impersonate/1"
curl -s -o /dev/null -w 'GET http://: %{http_code}\n' "${U/https:/http:}/app/login"
curl -sk -o /dev/null -w 'GET with an unknown Host: %{http_code}\n' -H 'Host: not-this-server.example' https://127.0.0.1/ || true
for i in $(seq 1 12); do curl -s --cacert "$C" -o /dev/null -w '%{http_code} ' "${U}/app/login"; done; echo
systemctl show -p IPAddressDeny nginx.service php8.5-fpm.service postgresql@16-main.service relaticle-queue.service
sudo -u postgres psql -At -c "SHOW listen_addresses" -c "SHOW ssl"
curl -s http://127.0.0.1/healthz; echo
GET /app/login: 200
GET /sysadmin/login: 200
GET /healthz: 200
GET /up: 200
GET /index.php: 404
GET /index.php/app/login: 404
GET /.env: 404
GET /horizon: 404
GET /telescope: 404
GET /_debugbar/open: 404
GET /storage/logs/laravel.log: 404
GET /composer.json: 404
GET /impersonate/1 from another site: 403
GET http://: 301
GET with an unknown Host: 000
200 200 200 200 200 200 200 200 200 429 429 429
IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128

IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128

IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128

IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128

off
ok
  • The front controller path (/index.php/...), the configuration file, Horizon, Telescope, logs, the debug bar and the source files are refused. Relaticle's code, configuration and data live outside the web root. A link from another site cannot start an impersonation or an OAuth redirect (403). Requests for any name other than the configured one are dropped (000: nginx closes the connection).
  • The twelve quick requests for the sign-in page show nginx's per-address limit (429).
  • IPAddressDeny is the metadata-service block on nginx, PHP, PostgreSQL and the queue worker; the scheduler and the first-boot service have the same one.
  • PostgreSQL's listen_addresses is empty (no network listener at all) and it needs no TLS.
  • http://127.0.0.1/healthz returns ok for a monitoring agent on the instance.

Step 16: Back up your data

Your data is the PostgreSQL database plus uploaded files in /var/lib/relaticle/storage/app and /var/lib/relaticle-public. Keep /etc/relaticle/env too: its APP_KEY decrypts the values Relaticle stores encrypted, and a backup restored without it cannot read them. Copy them to files only root can read, and keep copies off the instance (for example in an encrypted S3 bucket):

sudo sh -c 'umask 077; sudo -u postgres pg_dump --format=custom relaticle > /var/backups/relaticle-db-$(date +%F).dump'
sudo sh -c 'umask 077; tar -C /var/lib -czf /var/backups/relaticle-files-$(date +%F).tar.gz relaticle/storage/app relaticle-public'
sudo sh -c 'umask 077; cp /etc/relaticle/env /var/backups/relaticle-env-$(date +%F)'
sudo ls /var/backups/ | grep relaticle
relaticle-db-2026-11-08.dump
relaticle-env-2026-11-08
relaticle-files-2026-11-08.tar.gz

To restore into a new instance of the same version, stop nginx, PHP-FPM, relaticle-queue and relaticle-schedule.timer, restore the dump into the relaticle database with sudo -u postgres pg_restore --clean --if-exists --no-owner --role=relaticle -d relaticle <dump>, unpack the files archive into /var/lib, put your APP_KEY line into /etc/relaticle/env, and start the services again.

EBS snapshots of the instance are a simple way to keep point-in-time copies of the whole server.

Step 17: Updates

Ubuntu, PHP and PostgreSQL security updates install automatically (unattended upgrades). New Relaticle releases are published as new versions of this listing: launch the new version, stop its services, copy your database, uploads and the APP_KEY line of /etc/relaticle/env across (keeping the new instance's own database password and APP_URL), then run sudo relaticle-artisan migrate --force and start the services again.

Step 18: Licences and source

ls /usr/share/doc/relaticle/
sed -n '1,8p' /usr/share/doc/relaticle/SOURCE.txt
INTEGRATION-EXCEPTION.md
LICENSE
SOURCE.txt
frontend-packages.txt
Relaticle 3.8.2 on Ubuntu 24.04 by cloudimg - source and changes

Upstream: the Relaticle 3.8.2 tag archive, https://github.com/Relaticle/relaticle/archive/refs/tags/v3.8.2.tar.gz
(sha256 0a09918b650a30ca8c63c81e91a8c328082b4ef984c5841c114f9bf04ee90ce1; GitHub tag v3.8.2, commit ec974bf30a54f0c20935b134e845f1046e1b22be).
Licence: GNU Affero General Public License v3 (LICENSE, shipped here and in /var/www/relaticle), with upstream's additional
permission in INTEGRATION-EXCEPTION.md. No Relaticle source file is modified. CORRESPONDING SOURCE (AGPL section 13):
the unmodified source is the tag above, https://github.com/Relaticle/relaticle/tree/v3.8.2; the build steps
below reproduce this tree from it.

Relaticle is licensed under the GNU Affero General Public License v3 by its authors, with an additional integration permission (INTEGRATION-EXCEPTION.md). The AGPL asks that users who interact with the software over a network can get its source: the image runs Relaticle unmodified, and its complete corresponding source is the public Relaticle v3.8.2 tag, which SOURCE.txt names together with the exact build steps. If you modify Relaticle on your instance, the AGPL requires you to offer your modified source to its users.

The upstream repository also contains packages/Cloud, a package under Relaticle's own commercial "Relaticle Cloud License" that runs relaticle.com's hosted service (billing and its marketing site). It is not open source and is not on this image; the open source core never loads it. The image contains no paid or proprietary extension. SOURCE.txt lists everything else that is not shipped (tests, development notes and scripts, sample configuration, agent and lint tooling, the Docker files, the front-end build inputs and Apache files).

Security notes

  • Secrets. The two administrator passwords are in /root/relaticle-credentials.txt until you remove them; Relaticle stores only their bcrypt hashes. APP_KEY, the passkey secret and the PostgreSQL password are in /etc/relaticle/env, readable by root and the relaticle group only (not by the web server). The Passport OAuth private key is in /var/lib/relaticle/storage (0600 relaticle) and the TLS key in /etc/nginx/ssl/relaticle.key (root only). No secret is on any command line, in a systemd unit or in a log.
  • Client addresses. nginx gives Relaticle the address of the connection; forwarding headers sent by clients are replaced or removed. Behind a load balancer every request therefore comes from the load balancer's address.
  • PHP. The PHP pool runs as relaticle, is confined to Relaticle's code, data and configuration directories, and cannot start programs. The code in /var/www/relaticle is owned by root and read-only to PHP.
  • Uploads. Files under /storage/ are served with a sandboxing Content-Security-Policy and are never executed.
  • Outbound connections. Anything Relaticle fetches (the two public lists in Step 8, and the mail server and integrations you configure) is fetched by the relaticle user, which the egress backstop keeps away from the metadata service and your VPC's private addresses (Step 12).

Support

cloudimg provides support for this image by email at support@cloudimg.co.uk. Relaticle's source, releases and issue tracker are at github.com/Relaticle/relaticle.