English · العربية · Français · Русский · Українська · हिन्दी · Deutsch · Español · Italiano · Português · Bahasa Indonesia · Türkçe · 简体中文 · Tiếng Việt
Self-hosted audiences, campaigns, templates, automations and delivery from your own server. This repository distributes the compiled runtime, not the full source monorepo.
desktop preview">
Try the interactive demo (no real messages, hosted builders or paid results).
Quickstart: fresh Ubuntu 24.04/26.04
On a new server without an existing Campaigns installation, run:
sudo apt-get update
sudo apt-get install -y git
git clone https://github.com/sendrepute/sendrepute-campaigns.git
cd sendrepute-campaigns
./setup.sh
Setup asks which access mode to use and reuses working Docker/Compose; on a fresh supported Ubuntu server without Docker, it requests consent to install Ubuntu's packages. It does not remove Snap Docker or bypass AppArmor. Do not clone over an existing installation; see Update.
CAMPAIGNS READY FOR OWNER SETUP means the app is healthy inside its container, not that owner setup is complete or public HTTPS has been verified. For HTTPS, first verify the printed installation page from another network: it must have a valid, trusted certificate with no browser warnings. If the certificate is pending or invalid, do not enter any secrets.
For a new owner, the one-time token is required, not optional. Once your chosen access is ready, run this on the VPS from the project directory:
sudo docker compose exec campaigns cat /var/lib/sendrepute-campaigns/installer-token
Omit sudo if your Docker account does not require it. Copy the command output
and paste it into the Setup token field on the printed installation page.
Fill in the owner details and corresponding Public URL ending in /campaigns/,
then complete SendRepute activation and owner setup in the wizard. Setup does
not print the token automatically. Never put it in a URL or share it; keep
the token, .env and logs private. An already installed workspace does not
need another setup token.
Choose access
- HTTPS domain (recommended): setup starts the included Caddy proxy.
Enter a subdomain you control, for example
campaigns.example.com(replace with your own), with no scheme, port or path. Point that hostname's DNSArecord to this server, allow TCP 80/443 and check the trusted certificate externally. UseAAAAonly with working IPv6. - Local / SSH tunnel: binds the app to VPS loopback. Open it through a
trusted SSH tunnel from your computer; your laptop's
localhostis not the VPS. - Public IP + HTTP: explicitly consent to unencrypted access on port 8080. Passwords, tokens and sessions can be intercepted; not for secure production deployment.
See the setup command cookbook for exact commands, options, local SSH tunneling, diagnostics and warnings.
Moving from HTTP to HTTPS
Back up first. Point your actual hostname to the VPS, free/open TCP 80/443 and confirm its DNS works. On the VPS, in the existing project directory:
./setup.sh --mode https --host campaigns.sendrepute.com
Replace campaigns.sendrepute.com with your hostname (campaign and
campaigns are different DNS names). Confirm the exposure change when asked;
setup starts Caddy but does not rewrite the installed workspace's saved Public
URL. After verifying HTTPS externally, change that URL in Workspace
Settings to https://YOUR_HOSTNAME/campaigns/. If using Cloudflare, use
Full (strict), never Flexible. See the
migration steps
before changing a live installation.
Download v0.1.44
Administrators can check for stable GitHub releases in Workspace Settings. Official versioned Release archive and SHA-256 checksum attachments are preferred. If those expected attachments are absent, the checker can instead resolve the same stable release tag in the official repository to its immutable commit and validate that commit's bounded downloads/ checksum manifest. Repository download links are pinned to that commit, not a movable tag or branch. Invalid or duplicate expected attachments never permit this fallback. Settings displays an update notice, download/checksum links and the documented manual server update command for an existing Git clone; it never installs, extracts or executes a download. Back up the installation first, then follow the operator upgrade and restart procedure. Archive installations must follow the separate archive upgrade instructions and verify the downloaded bytes against the checksums. GitHub failures, absent or malformed publication metadata, and unknown installed versions are reported as unavailable, never as up to date. New release archives include their installed version metadata; older installations without this metadata cannot claim to be current. Release publishing and checksums are separate operator steps, not performed by the application.
Prefer a versioned archive? Download the ZIP
or tar.gz,
verify the SHA-256 checksums,
extract, and run ./setup.sh there. These are repository downloads, not
GitHub Release binary attachments; Code → Download ZIP is a different
snapshot. See the v0.1.44 release notes.
Additional tracking hostnames
With the included HTTPS/Caddy installation already running, open Domains, create a hostname challenge, add its A/AAAA record pointing to this server and the exact displayed TXT ownership record, then click Check DNS and verify. Campaigns automatically adds the verified hostname to the same managed proxy and reuses the primary certificate when its SAN covers that hostname, otherwise requesting an automatic certificate. Repeat for multiple hostnames; no per-domain shell commands or proxy edits are required, and the primary installation hostname and certificate settings are unchanged. Choose the desired verified hostname independently in each campaign's Tracking domain dropdown.
DNS approval, loaded proxy configuration, and working public HTTPS are shown separately. Loading a configuration does not prove ACME issuance or public reachability. Covered Origin CA names require Cloudflare proxying and are not directly browser-trusted. DNS and ports 80/443 must reach the existing proxy; Cloudflare must permit ACME and remain Full (strict). External proxies/Tunnels require operator configuration. If the managed proxy is not running or the primary hostname is missing, additions remain queued until that installation-level problem is resolved. No insecure SSL fallback is performed.
Previously approved routes are retained when a selectable domain is deleted
or its challenge rotated, so delivered links are not silently revoked.
Keep their DNS and certificate renewal available. Preserve the PostgreSQL
approval ledger and HTTPS/Caddy volumes during upgrades/backups. Manual-primary
certificate installations may briefly interrupt connections during a
controlled Caddy-only update/restart. See the packaged SMTP-TRACKING.md
for status definitions, historic-link retention, and failure/retry boundaries.
Update
Back up first; see Back up. On the VPS, inside your existing Git clone (not a fresh clone), inspect local changes, then run:
git status --short
git pull --ff-only && ./setup.sh --mode resume
resume preserves the existing access mode, including HTTPS. If pull refuses,
reconcile edits rather than force-resetting. Preserve .env, the same Compose
project, PostgreSQL and application volumes, and encryption key. Never run
docker compose down -v against real data. For archive upgrades, use the
upgrade instructions, not a new clone over the
installation.
Back up
Preserve the full PostgreSQL database, application data/encryption key,
private .env and HTTPS/Caddy state. Follow the
complete Docker backup commands,
then keep encrypted, access-controlled off-host copies. An in-app JSON export
is not an infrastructure backup and omits the retained HTTPS approval ledger,
including approved hostnames whose selectable domain rows were deleted.
For opt-in scheduled encrypted off-host backups, use the included
backup.sh, backup.conf.example and systemd examples. Nothing is scheduled
or enabled by setup. Install age and configure an existing off-host mounted
directory or restricted SFTP destination. Leave both age settings blank:
the first interactive backup creates its recovery file automatically and asks
you to save a separate safe copy before proceeding. Later backups reuse it;
there are no key-generation commands or public-key values to copy into config.
The host keeps a protected copy to verify each backup; never store your
independent recovery copy beside the encrypted backup archives.
See automated backups
for prerequisites, safe activation, verification and recovery. From the installed
directory, ./backup.sh status shows last attempt, last success and archive;
it remains readable if the age identity or backup tools are unavailable, provided
the operator-owned private config and local spool/status file are intact.
./backup.sh verify /private/path/archive.tar.age checks decrypt, manifest and
PostgreSQL format without restoring data.
Restore
Restore only from a verified, matching PostgreSQL and data-volume backup; the in-app JSON export omits delivery jobs, audit events and other runtime state. Restoring can overwrite newer data or resume queued mail. Follow the isolated restore steps before any production cutover.
More information
- Installation and setup commands — all flags, HTTPS/HTTP, manual Docker or Node.js paths, token and troubleshooting.
- Operations, backup and restore — upgrades and recovery.
- Security and deliverability — SMTP, SPF/DKIM/DMARC, consent and production checks.
- Standalone server contract — integration details.
Activation validates a separately issued SendRepute API key; no deposit is required for activation, and local management is free. Optional hosted AI and classification require their own entitlement or credit and explicit price consent; demo AI does not perform paid results. Delivery goes from your server to your configured SMTP relay/provider, not a central SendRepute SMTP proxy.
Release boundary
The release includes the compiled browser, server, delivery and customer-API bridge, public customer SDK, migrations and docs. It excludes the main SendRepute site and scanner, database contents, secrets, source maps, tests and development toolchain. Component and third-party license terms still apply; self-hosting grants no hosted-service license or inbox-placement guarantee.
Comments