What happens to your code.
Plain language. No marketing-grade vagueness. Here's the whole pipeline, from drop to running.
Upload and build pipeline
Your project is zipped and inspected in the browser before anything uploads. You see the file count and the detected framework before clicking publish. Anonymous deploys cap at 50 MB; signed-in deploys at the size your plan allows (Starter 50 MB, Basic 200 MB, Pro 500 MB).
The upload travels over HTTPS to api.canner.ca, where the build worker extracts it inside a per-deployment scratch directory. Builds run as the project's own Linux user (canner-<slug>) under a transient systemd unit with ProtectSystem=strict, PrivateTmp=yes, RestrictNamespaces=yes, and a cgroup memory cap matching your plan. The rebuild phase (which runs any allowlisted native-module postinstall scripts) runs with PrivateNetwork=yes — fresh netns, only the loopback interface — so build-time lifecycle scripts cannot reach the internet, Postgres, Redis, or the platform API.
When the build finishes, the source archive and scratch directory are deleted. Only the compiled runtime bundle is kept on disk.
Runtime isolation
Each project runs as its own Linux user under its own systemd unit (tenant@<slug>.service). No two tenants share a process tree, a UID, a home directory, or a writable file system path. A misbehaving tenant cannot read another tenant's files, environment, or database — host-level iptables rules block lateral movement to the platform API (4001), Postgres (5432), and Redis (6379) for every non-platform UID.
The runtime starts from an immutable bundle at /opt/canner/apps/<slug>/<deployment_id>. Updates atomic-swap a new bundle into place; rollback hard-links a previous bundle. The runtime never writes to its own bundle directory.
Database security
Every project that needs Postgres gets its own database with its own credentials. Connections route through PgBouncer; the tenant role has no access to other tenants' databases, system catalogs, or superuser functions.
Connection strings are injected at build time via the DATABASE_URL environment variable. They are never logged in build output, never echoed to clients, and never stored anywhere except inside the per-tenant runtime env file (mode 0640, owned root:canner-<slug>).
Environment variables
Variables you set in the dashboard are encrypted at rest in the platform database using pgcrypto. They are decrypted only at build time and runtime, injected into the build sandbox / tenant runtime process, and never returned in plaintext from the API after they are written (the dashboard shows redacted previews).
Variables marked sensitive at creation are additionally scrubbed from build logs — their values are matched and replaced with [REDACTED] before any line is written to the build_log column. The log streamer the dashboard uses reads from build_log, so scrubbing is enforced on the write side, not on display.
Infrastructure
Canner runs on Web Hosting Canada VPS instances in Montreal, Quebec. The host firewall is iptables + fail2ban; only ports 22 (SSH), 80, and 443 are reachable from the public internet. SSH is key-only — password authentication is disabled — and root login is disabled for everything except a small, IP-restricted recovery channel kept for disaster recovery.
Automatic security updates run nightly via unattended-upgrades for the Debian security pocket. TLS certificates for canner.ca, *.app.canner.ca, and customer-attached custom domains are issued and renewed automatically by Caddy via Let's Encrypt — no manual rotation, no expired-certificate window.
Daily Postgres backups run at 03:30 local and are mirrored off-host via a pull-down script. Redis is authenticated; BullMQ is configured noeviction so build queue state is never lossy under memory pressure.
Responsible disclosure
If you find a security issue, email security@canner.ca with a description and reproduction steps. We will acknowledge within two business days and keep you updated until the issue is resolved.
We do not currently run a paid bug-bounty programme, but credit (with permission) is given on the changelog for any disclosure that results in a fix.
Read more about how Canner is structured.
Security covers the day-to-day. Sovereignty covers the legal jurisdiction your data sits under.