Autonnel v0.1.0

Installation

Run Autonnel with one docker compose command, or from a source checkout.


There are two ways to run Autonnel, and they answer different questions.

  • Run it as a product (recommended): one docker compose up, no Node toolchain, no external database. Start here.
  • Run it from source: clone the repository. Use this when you intend to modify Autonnel itself, or want to deploy to Cloudflare Workers.

Path 1: Docker (about 2 minutes)

curl -O https://raw.githubusercontent.com/autonnel/autonnel/master/docker-compose.yml
docker compose up

Open http://localhost:4321. On a fresh install every admin URL redirects to the /setup wizard: create the admin account, set your site name and default timezone, and you land in the dashboard.

That is the entire boot sequence. The compose file starts Postgres, applies the database schema with a one-shot schema service, then starts Autonnel.

What you do not need to boot

Nothing in the list below is required to get to the dashboard. Each one is configured later in the admin UI under Settings, and only if you use the feature that needs it:

Feature you wantWhat to configure
Products and ordersSettings → Ecommerce: Shopify, WooCommerce or Picocart
Taking paymentsSettings → Payments: Stripe or PayPal
Media uploads in the editorSettings → Storage: any S3-compatible bucket (R2, S3, Wasabi, B2, MinIO)
Order receipts, recall emailsSettings → Email provider: SMTP, Resend or AWS SES
AI page generation, AI analysisSettings → LLM: any OpenAI-compatible endpoint

Before you expose it publicly

Create a .env file next to docker-compose.yml:

AUTH_SESSION_SECRET=$(openssl rand -hex 32)
CREDENTIALS_ENCRYPTION_KEY=$(openssl rand -base64 32)
ADMIN_DOMAIN=admin.example.com

AUTH_SESSION_SECRET and CREDENTIALS_ENCRYPTION_KEY are required whenever NODE_ENV is not development/test, which is the case inside the published image. The compose file ships insecure development defaults so the first run needs zero configuration; replace them before anything faces the internet. Generate each once and keep it stable: rotating them invalidates active sessions and makes stored provider credentials unreadable.

ADMIN_DOMAIN decides which hostnames serve the admin UI. Every other hostname serves the storefront, which is the safe failure mode for a commerce product. The port is ignored when matching, so localhost covers localhost:4321. Comma-separated lists and a single-label wildcard (*.example.com) are supported.

Upgrading

docker compose pull
docker compose up -d

The one-shot schema service re-runs on every up, so a schema change that ships with a new image is applied before the app starts.

Using your own Postgres

Point DATABASE_URL at it and drop the db service. Any Postgres works: Neon, Supabase, RDS, Railway, or your own instance.

docker run -p 4321:4321 \
  -e DATABASE_URL="postgresql://user:pass@host:5432/autonnel" \
  -e ADMIN_DOMAIN="admin.example.com" \
  -e AUTH_SESSION_SECRET="$(openssl rand -hex 32)" \
  -e CREDENTIALS_ENCRYPTION_KEY="$(openssl rand -base64 32)" \
  ghcr.io/autonnel/autonnel:latest

Apply the schema once against a new database:

docker run --rm ghcr.io/autonnel/autonnel:latest \
  node_modules/.bin/prisma db push --schema=./prisma/schema.prisma \
  --url "postgresql://user:pass@host:5432/autonnel"

The runtime image does not ship prisma.config.ts, so Prisma takes the datasource from --url instead of DATABASE_URL.

Available tags: :latest (most recent stable), :1.3.0 (exact version, recommended for production), :1.3 (auto-update on patches), :1 (auto-update on minor and patches). Images are multi-arch (linux/amd64, linux/arm64) and include a HEALTHCHECK against /api/health.

Optional: Postgres with pg_duckdb

The funnel stats page aggregates page-visit rows, which accumulate quickly on funnels that buy traffic. A Postgres with the pg_duckdb extension makes those aggregations noticeably faster. Without it everything still works, the queries just get slower as data grows.

No widely available hosted provider ships pg_duckdb at the time of writing. If you want it, swap the db service image in docker-compose.yml for pgduckdb/pgduckdb:postgres-17-main. Setup is otherwise unchanged.

Path 2: Run from source

Use this path when you intend to modify Autonnel itself, or want to deploy to Cloudflare Workers. Prerequisites: Node.js 22 or later and a PostgreSQL database.

npm create autonnel@latest my-funnel
cd my-funnel

This clones the Autonnel repository into my-funnel, removes the git history and renames the package. It is not an interactive wizard and it does not write a .env for you.

cp .env.example .env   # set DATABASE_URL and ADMIN_DOMAIN
pnpm install           # the repository is pnpm-managed
npm run db:push        # sync the schema in prisma/schema.prisma
npm run dev

Install with pnpm 10 or later. The repository ships pnpm-lock.yaml and pins dependency overrides in pnpm-workspace.yaml; npm install resolves a different tree and ignores those pins.

Open the dev server and complete the /setup wizard, exactly as on the Docker path.

If you only want to run Autonnel, prefer the Docker path above: it needs no Node toolchain and no external database.

Deployment

Node.js (standalone)

npm run build        # production build
npm run start        # start production server

Runs on any host with Node 22+: a VPS, Fly.io, Render, Railway, a bare EC2 instance. Set PORT and HOST if your platform requires a specific binding.

Docker

Covered above. Use it when you want a reproducible image to push to a registry, run on Kubernetes, or hand to a platform that takes containers as input (ECS, Cloud Run, Fly.io, Coolify, Dokku).

Do not bake DATABASE_URL into an image you build yourself. Pass it at run time or through your orchestrator’s secret manager.

Cloudflare Workers

Effectively zero cost for most funnels. Workers static assets are unmetered, and the Worker itself stays within Cloudflare’s free tier for typical funnel traffic.

The repository ships the full Workers toolchain: a worker entry with the cron scheduled handler (src/cf-worker.ts), wrangler.toml generation, KV cache wiring and Hyperdrive for Postgres.

npm run dev:cf       # dev server against the Workers runtime
npm run build:cf     # production build for Workers (also generates wrangler.toml)
npm run preview:cf   # local preview with wrangler dev
npm run deploy:cf    # build + wrangler deploy

Before the first deploy:

  1. Authenticate: npx wrangler login.
  2. Create a KV namespace for caching: npx wrangler kv namespace create CACHE_KV. Copy the namespace ID.
  3. Create a Hyperdrive config for your Postgres: npx wrangler hyperdrive create autonnel-db --connection-string="postgresql://...". Copy the config ID.
  4. In .env, set CF_WORKER_NAME, CF_KV_NAMESPACE_ID and CF_HYPERDRIVE_CONFIG_ID.
  5. Push secrets: npx wrangler secret put DATABASE_URL, then the same for AUTH_SESSION_SECRET and CREDENTIALS_ENCRYPTION_KEY. Add ADMIN_DOMAIN and any other env vars the same way.
  6. Run npm run deploy:cf.

Cron jobs, background queue work and caching all run inside the same Worker. Cron triggers are read from the installed autonnel package at build time, so upgrading keeps them in sync. wrangler.toml is generated from wrangler.toml.template: edit the template, not the generated file.

Admin accounts

There is no open registration. The first account is created by the /setup wizard on first visit. Additional users join with an invitation issued from Settings → Users.

For headless installs, create the first admin without visiting the browser:

docker compose exec app node dist/cli/index.js admin:create you@example.com 'a-strong-password'

Doing this before the first visit skips the wizard’s account step. On a source checkout the same command is npx autonnel admin:create, run from the project directory. See the CLI reference.

Caveats

  • Autonnel syncs schema with db:push, not db:migrate. Running db:migrate creates a migrations directory that conflicts with the schema shipped in the repository.
  • Edits to prisma/schema.prisma in a source checkout conflict on every upgrade. Plugins have a supported schema-extension mechanism; use that instead.
  • db:push is non-destructive for additive changes. If an upgrade removes a column, Prisma warns but does not drop it. Back up production data before upgrading.
  • On Cloudflare Workers, Node-only dependencies are excluded from the bundle automatically. Custom Node-only dependencies may need to be configured as externals in the adapter config.