Installation guide
For a technically competent person who has never worked on this project. It installs Rampline on one Linux server with Docker, gets HTTPS for the main address and for customer domains, and ends with a verified installation. Plan about an hour.
Everything here uses your own accounts. Nothing depends on the original developer's servers or credentials.
1. What you need
| Item | Notes |
|---|---|
| A Linux server | 2 CPU cores and 4 GB RAM are enough to start. Ubuntu 24.04 LTS or Debian 12 are known-good choices. 40 GB disk plus room for uploads and backups. |
| Docker Engine 24+ with the Compose plugin | docker compose version must work. |
| A domain | For example app.example.com for the app. Its DNS must point at the server before you start (an A record, plus AAAA if the server has IPv6). |
| Ports 80 and 443 open | Caddy uses them for HTTPS and certificates. |
| Optional services | An email provider (SMTP, Resend or Postmark) for invitations, a Stripe account per selling workspace, an Anthropic API key for the AI features, an S3-compatible bucket for uploads. Each can be added later. |
Without Docker, see section 9.
2. Get the software
Unpack the release package and enter the folder:
tar -xzf rampline-0.1.0.tar.gz
cd rampline-0.1.0
sha256sum -c ../rampline-0.1.0.tar.gz.sha256 # when you received the checksum file
3. Configure
cp .env.production.example .env
Open .env and fill in every line that is not commented out:
| Variable | Value |
|---|---|
APP_URL | https://app.example.com |
APP_DOMAIN | app.example.com |
ACME_EMAIL | An address that receives Let's Encrypt notices |
SECRET_KEY, RATE_LIMIT_SALT | Each a new random value: openssl rand -base64 48 |
POSTGRES_PASSWORD, APP_DB_PASSWORD, SERVICE_DB_PASSWORD | Three different random values (at least 16 characters, letters and digits are safest in URLs: openssl rand -hex 24) |
Optional settings are commented out. Remove the # only for the ones you use: an empty value counts as set.
Store a copy of .env in your password manager. Without SECRET_KEY, a restored database cannot read the stored email and payment credentials.
4. Start
docker compose --profile proxy up -d --build
This builds the image (a few minutes the first time) and starts four containers:
| Container | Role |
|---|---|
db | PostgreSQL 17, data in the db volume |
app | The web app. On every start it applies pending database migrations and sets the passwords of the two database roles |
worker | Background jobs: emails, automations, checks, invoices, license revocation list |
caddy | HTTPS for APP_DOMAIN and for custom domains your customers add |
Check that all four run: docker compose ps. The app reports healthy after about a minute.
5. First-run setup
The setup page is protected by a one-time link that the app prints to its log:
docker compose logs app | grep setup
Open the link. If you set SETUP_TOKEN in .env, open https://app.example.com/setup?token=<that value> instead. Lost the link? docker compose exec app npm run setup:token prints a new one.
The wizard asks for three things:
- Administrator: your name, email and password. This account manages the installation, operators and licenses.
- Your platform: company name, optional product name (shown instead of Rampline), currency and time zone.
- Edition and license: Cloud (you host and sell subscriptions), white-label cloud (resellers run branded platforms on your installation) or Independent (a licensed copy). On the independent edition, paste the license you received (the text starting with
RL1.). You can also activate it later under Platform, Licenses.
After setup you are signed in on Platform, Installation, which lists what still needs attention.
6. Connect services
All optional. The installation page shows each one's state.
Email (invitations and platform mail)
Set one provider in .env, then docker compose up -d app worker:
- SMTP:
SMTP_HOST,SMTP_PORT,SMTP_SECURE,SMTP_USER,SMTP_PASS - Resend:
RESEND_API_KEY - Postmark:
POSTMARK_SERVER_TOKEN
plus SYSTEM_EMAIL_FROM, an address on a domain you verified with the provider (SPF and DKIM records at your DNS host). Until a provider is set, emails are recorded but not sent and invitation links are shown on screen.
Each workspace sets its own sender for campaigns and automations under Settings, Email sending.
Payments
Each selling workspace connects its own Stripe account under Settings, Payments (secret key and webhook secret from the Stripe dashboard, test keys first). The webhook URL to enter in Stripe is shown on that page. The built-in test provider works without any account, for trying checkouts with the published test card 4242 4242 4242 4242.
AI
Set ANTHROPIC_API_KEY (and optionally AI_MODEL, AI_PRICE_INPUT_PER_MTOK, AI_PRICE_OUTPUT_PER_MTOK for the cost ledger). Each workspace then switches AI on under Settings, AI, with a monthly budget.
File storage
Uploads live in the files volume by default. To use a bucket instead, set S3_BUCKET, S3_REGION, S3_ENDPOINT (for non-AWS services), S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY. Moving existing files into the bucket is a manual copy of the volume's content to the bucket under the same keys.
Optional communication providers
SMS, voice and messaging channels are not part of this version (docs/IMPLEMENTATION_STATUS.md).
7. Domains and HTTPS
- Main address: Caddy requests the certificate for
APP_DOMAINon first start. If the DNS record was not in place yet, fix it and rundocker compose restart caddy. - Custom domains of funnels and websites: a workspace adds the domain under Settings, Domains and gets two DNS records to create: a TXT record that proves ownership and a CNAME pointing at the app address (
APP_DOMAIN). Caddy requests a certificate on the first visit, after asking the app whether the name is registered. - White-label app domains: an operator sets an app domain under Branding (for example
app.reseller.com) and points its DNS at your server. Sign-in pages and emails on that host use the operator's branding.
Using your own reverse proxy instead of Caddy: start without the profile (docker compose up -d --build), proxy to 127.0.0.1:3000, forward X-Forwarded-For and X-Forwarded-Proto, and set TRUSTED_PROXY_HOPS to the number of proxies that append to X-Forwarded-For. For custom domains your proxy needs on-demand certificates; it can use GET /api/tls/ask?domain=<name> (200 means the name belongs to this installation).
8. Verify the installation
docker compose exec app npm run install:check -- --smoke
The environment check lists every setting with OK, review or fix. The smoke test then creates a temporary workspace, publishes a funnel, loads it over HTTPS, submits its form, pays a checkout with the built-in test provider, waits for the worker and deletes everything it created. Exit code 0 means the core path works.
Then set up backups (docs/OPERATIONS.md, section 1) and test a restore once.
9. Without Docker
Requirements: Node.js 22, PostgreSQL 15 or newer (17 recommended), a process manager (systemd, pm2), a reverse proxy with HTTPS.
npm ci
npm run build
# environment: everything from .env.production.example, plus
# DATABASE_ADMIN_URL=postgres://postgres:...@localhost:5432/postgres
# DATABASE_URL=postgres://rampline_app:<APP_DB_PASSWORD>@localhost:5432/rampline
# SERVICE_DATABASE_URL=postgres://rampline_service:<SERVICE_DB_PASSWORD>@localhost:5432/rampline
# DB_NAME=rampline NODE_ENV=production PORT=3000 STORAGE_DIR=/var/lib/rampline/storage
node scripts/db.mjs deploy # database, migrations, role passwords
npm start # web app (keep it running with your process manager)
npx tsx scripts/worker.ts # background worker, a second process
NEXT_PUBLIC_PRODUCT_NAME is built into the browser code: set it before npm run build. Operators can still override the product name per platform in Branding.
Platforms with one volume per service (Railway, Render)
Set RUN_WORKER=1 to run the worker inside the app container, so both reach the file volume. A complete Railway walk-through is in docs/OPERATIONS.md, section 9.
Managed PostgreSQL (AWS RDS, Google Cloud SQL, Azure, Supabase, Neon)
Point DATABASE_ADMIN_URL at the admin user and set DATABASE_SSL=require. The service role needs to bypass row-level security; if the provider refused that during the first migration, the installation check says so. Grant it in the provider's console: alter role rampline_service bypassrls; (on RDS the admin user can do this). Workspace imports (docs/OPERATIONS.md, section 5) need an admin user that may set session_replication_role.
10. When something goes wrong
docs/OPERATIONS.md, section 7, lists symptoms and fixes. The first two commands to run:
docker compose logs --tail=100 app worker
docker compose exec app npm run install:check