Skip to content

Linux

This section describes how to deploy Canvus server 26.4.0 using containers on Linux. Linux is the supported host platform for production container deployments; the combined, postgres, and media images are all Linux containers.

Note

Supported distributions: Ubuntu 22.04+, Debian 12+, RHEL 9+, Fedora 38+, CentOS Stream 9+.

System requirements

  • RAM: 4 GB minimum, 8 GB recommended. Under load the combined container needs headroom beyond the C++ server itself. Running below 4 GB has been observed to trigger out-of-memory kills.
  • 2 CPU cores minimum (4 recommended)
  • 20 GB disk space minimum (50 GB recommended for production with asset uploads)
  • Internet connection for initial image download
  • UDP port range 40000-40100 reachable from clients if you have enabled the coming-soon WebRTC video streaming feature (disabled by default)

Install Podman

Ubuntu / Debian:

sudo apt update
sudo apt install -y podman podman-compose

RHEL / Fedora / CentOS Stream:

sudo dnf install -y podman podman-compose

Verify:

podman --version
# Should show podman version 3.0+ (4.0+ recommended)

Container registry access

Canvus Server images are hosted on the MultiTaction public container registry and pull anonymously --- no registry login is required for a standard deployment.

Note

sudo is required for all Podman commands. Podman uses separate container namespaces for root and non-root users. Since sudo is needed for privileged port binding (ports 80/443), all Podman commands must use sudo consistently --- mixing sudo podman ... and podman ... will make containers appear missing.

Download the compose file

wget https://canvus-downloads.multitaction.com/server/podman-compose.yml

Note

In 26.4.0 the compose file download host moved from the S3 bucket to canvus-downloads.multitaction.com (served via Cloudflare R2). Old canvus-downloads.s3.amazonaws.com links will be retired.

What's in the compose file

The 26.4.0 compose file deploys two services by default on an internal bridge network (canvus-network):

  • postgres (container name canvus-postgres) --- PostgreSQL, pinned to 17.11, with the Canvus schema. Listens on canvus-network:5432 only; no host port is published. The standalone installers bundle a different PostgreSQL major version (18.6) --- see PostgreSQL version note.
  • canvus (container name canvus-combined) --- the C++ server, including an in-process Go gateway that serves the unified React web-client directly. There is no separate Node.js process. Publishes host ports 80 (HTTP redirect → 443) and 443 (HTTPS).

A third service, canvus-media (container name canvus-media, mediasoup SFU for WebRTC and FFmpeg for HLS transcoding), ships commented out of the default compose file. WebRTC video streaming is a coming-soon feature and is disabled by default (CANVUS_WEBRTC_ENABLED=false). Once you uncomment canvus-media and enable WebRTC, it publishes the UDP range 40000-40100 for WebRTC media, and canvus-combined relays WebRTC signaling to it over ws://canvus-media:4443/ws?peerId=server-relay.

Image paths (the compose file pins the images it uses to the :stable channel):

  • docker.multitaction.com/mt-public/canvus-server-images/combined:stable
  • docker.multitaction.com/mt-public/canvus-server-images/postgres:stable
  • docker.multitaction.com/mt-public/canvus-server-images/media:stable --- only pulled once you uncomment canvus-media.

See Container image tags and channels to pin a specific version or track the pre-release channel instead.

Configure the deployment

Edit podman-compose.yml before starting. At minimum, change these values:

In the canvus service:

environment:
  CANVUS_EXTERNAL_URL: https://canvus.example.com
  CANVUS_ADMIN_EMAIL: admin@yourcompany.com
  CANVUS_ADMIN_PASSWORD: YourSecurePassword123!
  POSTGRES_PASSWORD: a-strong-database-password

In the postgres service (must match the password above):

environment:
  POSTGRES_PASSWORD: a-strong-database-password

For testing, https://localhost works as the external URL. The server generates a self-signed certificate automatically.

WebRTC video streaming (coming soon)

WebRTC video streaming is not yet feature-complete and is disabled by default in 26.4.0. The canvus service's CANVUS_WEBRTC_ENABLED and CANVUS_WEBRTC_MEDIA_URL environment variables, and the entire canvus-media service block, ship commented out of the default compose file.

To try it ahead of general availability, uncomment the canvus-media service and the two CANVUS_WEBRTC_* env vars on the canvus service, then set:

CANVUS_WEBRTC_ENABLED: "true"
CANVUS_WEBRTC_MEDIA_URL: ws://canvus-media:4443/ws?peerId=server-relay

The ?peerId=server-relay query parameter is required --- the SFU rejects signaling connections that omit it.

If your server sits behind NAT (typical production deployment), set ANNOUNCED_IP on the canvus-media service to the host's public IP so WebRTC peers can reach the SFU:

canvus-media:
  environment:
    ANNOUNCED_IP: 203.0.113.1

Create data directory

sudo mkdir -p /canvus-data

The containers create these subdirectories automatically on first start:

  • /canvus-data/config/ --- server configuration (mt-canvus-server.ini, .session-secret)
  • /canvus-data/certs/ --- TLS certificates (self-signed auto-generated on first start)
  • /canvus-data/assets/ --- uploaded canvas content (images, PDFs, videos)
  • /canvus-data/backups/ --- server and database backups
  • /canvus-data/logs/ --- server logs
  • /canvus-data/licenses/ --- Canvus license files (.html, or legacy .cslicense)
  • /canvus-data/mipmaps/ --- pre-computed image mipmaps
  • /canvus-data/postgres/ --- PostgreSQL data directory

The in-process gateway persists its session secret at /canvus-data/config/.session-secret so login sessions survive container restarts.

Start services

sudo podman-compose up -d

Note

sudo is required for two reasons:

  1. Privileged port binding --- rootless Podman cannot map host ports below 1024 (ports 80 and 443). External Canvus clients require HTTPS on port 443.
  2. Namespace consistency --- containers started with sudo are only visible to sudo commands.

The first startup takes longer because it pulls the images, generates a TLS certificate, creates the database schema, and creates the admin user. Subsequent starts complete in about 30-60 seconds.

Verify

Check that containers are running:

sudo podman-compose ps

You should see canvus-postgres and canvus-combined running (plus canvus-media if you have enabled WebRTC). The health check for canvus-combined may take up to 2 minutes on first start.

Open https://localhost in your browser. The request lands on the C++ server's in-process gateway, which serves the unified React web-client directly. Accept the self-signed certificate warning and login with the admin credentials you set above.

Landing-page behavior

In 26.4.0 the entry point at https://<your-server>/ is served in-process by the C++ server --- there is no separate Node.js process. The in-process gateway serves the unified React web-client (SPA) directly for all web requests, while routing REST API calls and WebSocket endpoints internally within the same process.

Backup, restore, and migration

For routine backups, see Server backup and restore. To move a 3.x or 26.x standalone server into containers, use the same Canvus backup and restore commands as follows.

Before you start

Use a container release that includes PostgreSQL 18 and the same or a newer Canvus Server version than your standalone installation. See migration prerequisites.

1. Back up the standalone server

Ask users to finish editing, then stop the old Canvus Server service. Leave its PostgreSQL service running for the backup. Canvus saves automatically; there is no manual save step.

On a 26.x Linux standalone server:

sudo runuser -u canvus -- /opt/canvus/bin/mt-canvus-server --backup

On a 3.x Linux server:

sudo -H -u mt-canvus-server /opt/mt-canvus-server/bin/mt-canvus-server --backup

For a Windows source, use the Windows backup command.

Wait for the backup to complete successfully and note the folder printed by the command. Copy that whole folder to a safe location outside the old installation. It contains mt-canvus-backup-metadata.json, db_dump.sql and the backed-up assets; do not copy just the SQL file.

Also save your mt-canvus-server.ini, license file and any TLS certificate/key files separately. The Canvus backup does not include them. See file locations for where to find them.

2. Remove the old installation if reusing the machine

If the container will run on the same machine, uninstall the old Canvus server and any legacy Canvus dashboard, then reboot. For 26.x, follow the standalone uninstall/reboot instructions, stopping before the reinstall step. The legacy 3.x Linux server package is mt-canvus-server3.

Use package removal, not a data purge. Keep the backup and saved configuration/license files outside the installation being removed.

If moving to a different machine, leave the old installation intact and its Canvus service stopped.

3. Install and configure the containers

Follow the installation steps above, through Start services and Verify. This creates the destination database, mounted directories and container configuration. Do not add real content to this new server: the restore replaces its existing Canvus data.

Then, from the directory containing podman-compose.yml, stop only Canvus. Leave PostgreSQL running:

sudo podman-compose stop canvus

4. Copy the backup and saved files

Copy the backup folder into /canvus-data/backups/. The example calls the destination folder migration; use a new folder, not one containing a previous backup. Replace /path/to/backup-folder with the complete backup folder saved in step 1:

sudo cp -a /path/to/backup-folder /canvus-data/backups/migration

The metadata file should now be /canvus-data/backups/migration/mt-canvus-backup-metadata.json.

Copy the saved INI alongside the generated configuration, and the license file into the license directory. Replace the example source paths with your saved files:

sudo cp /path/to/mt-canvus-server.ini /canvus-data/config/mt-canvus-server.ini.standalone
sudo cp /path/to/license-file /canvus-data/licenses/

Use mt-canvus-server.ini.standalone as a reference to bring your site settings into /canvus-data/config/mt-canvus-server.ini. Keep the new container's database settings and filesystem paths; do not replace the generated INI wholesale with the old one. If using your own TLS certificate, copy its files as described under SSL certificates. A license tied to the old host may need reactivation.

5. Restore the Canvus backup

Run the server's restore command in a temporary container using the same image, configuration, database connection and mounted folders as the installed canvus service:

sudo podman-compose run --rm --no-deps \
  --entrypoint /opt/canvus/bin/mt-canvus-server \
  canvus --restore --backup-path /var/lib/mt-canvus-server/backups/migration

The host folder /canvus-data/backups/migration appears inside the container as /var/lib/mt-canvus-server/backups/migration. That is why --backup-path uses the longer path. The restore reads the backup metadata and restores the database and assets together; no separate SQL import or asset copy is needed.

Wait for the command to finish successfully before continuing. If it reports an error or does not return, leave Canvus stopped and contact MultiTaction support with the output.

6. Restart and check

sudo podman-compose start canvus
sudo podman-compose ps

Sign in with an account from the old server. Check that your canvases, folders and media are present, then reconnect the clients. When migrating from 3.x, update the clients to 26.x too. Keep the original backup until you have checked the new server.

SSL certificates

Self-signed (default): The server generates a self-signed certificate on first startup. Browsers will show a security warning.

Production certificates: Place your CA-signed certificates in /canvus-data/certs/ before starting:

sudo cp your-certificate.pem /canvus-data/certs/server.cert.pem
sudo cp your-private-key.pem /canvus-data/certs/server.key.pem
sudo cp your-chain.pem /canvus-data/certs/server.chain.pem

Then start (or restart) the containers.

License activation

Via dashboard (recommended):

  1. Navigate to https://your-server/admin/settings/license
  2. Login with admin credentials
  3. Enter your activation key and click Activate

Via environment variable:

Set CANVUS_LICENSE_KEY in the canvus service before first startup.

Offline activation:

Generate the request in the dashboard (Admin area > Settings > License > Offline activation request), upload it at https://ls2026.multitaction.com/keys/<activation-key>, and download the license file. Upload that file on the same dashboard page, or place it (.html, or legacy .cslicense) in /canvus-data/licenses/ and restart. Full steps: licensing.

Management

# Start / stop / restart
sudo podman-compose up -d
sudo podman-compose stop
sudo podman-compose restart

# View logs
sudo podman-compose logs -f canvus-combined
sudo podman-compose logs -f canvus-postgres
# sudo podman-compose logs -f canvus-media   # only if you have enabled WebRTC

# Check status
sudo podman-compose ps

# Update to latest version
sudo podman-compose pull
sudo podman-compose down
sudo podman-compose up -d

Image tags and channels

Public images use named channels: :stable (recommended; the newest generally-available release, and what the compose file pins to), :latest (the tag tooling pulls with no explicit tag; on this registry it points at the same build as :dev, not at :stable, so always set the tag explicitly), :<version> (an immutable pin such as :26.6.0 for a reproducible deployment), and :dev (pre-release builds, for testing only). Keep combined and postgres on the same tag (and media too, if you have enabled WebRTC). See Container image tags and channels for the full description and the upgrade procedure.

Behind a reverse proxy

If another service (Traefik, nginx) already uses ports 80/443, use unprivileged ports:

environment:
  CANVUS_HTTPS_PORT: 8443
  CANVUS_EXTERNAL_URL: https://canvus.example.com

ports:
  - "8080:80"      # HTTP redirect (always port 80 inside container)
  - "8443:8443"    # HTTPS (matches CANVUS_HTTPS_PORT)

Note

The HTTP-to-HTTPS redirect always listens on port 80 inside the container. The left side of the port mapping controls the host port.

Configure your reverse proxy to forward to these ports. If you have enabled the coming-soon WebRTC feature, do not proxy the UDP 40000-40100 range --- WebRTC media must reach canvus-media directly; forward those UDP ports at the firewall instead.

Troubleshooting

Port already in use:

sudo ss -tlnp | grep :443

Stop the conflicting service or use unprivileged ports.

Permission denied on /canvus-data:

sudo chown -R $(id -u):$(id -g) /canvus-data

On RHEL/Fedora/CentOS, the :Z suffix on volume mounts handles SELinux relabeling automatically. The :Z suffix is safely ignored on Ubuntu/Debian.

Container not found:

If podman ps shows nothing but sudo podman ps shows your containers, you have a namespace mismatch. Use sudo consistently.

Database connection issues:

sudo podman exec -it canvus-postgres pg_isready -U canvus -d canvus

WebRTC video not working:

WebRTC video streaming is not yet feature-complete and is disabled by default in 26.4.0 --- see WebRTC video streaming (coming soon). If you have enabled it:

# Confirm canvus-media is healthy and the SFU is listening
sudo podman-compose logs canvus-media | grep -i "sfu\|listening\|ready"

# Confirm server-relay signaling connected from canvus-combined
sudo podman-compose logs canvus-combined | grep -i webrtc

If clients outside the host cannot receive media, check that UDP 40000-40100 is open at the firewall and that ANNOUNCED_IP on canvus-media matches the host's reachable IP.

Combined container OOM-killed:

Increase host RAM or the container memory limit. Canvus 26.4.0 requires 4 GB minimum and 8 GB is recommended for production.