Trackily Docs

Installation

Deux chemins : binaire Node natif (le plus rapide à essayer) ou docker compose (le plus propre pour la prod). Les deux marchent identiquement — choisis selon ton serveur.

Dashboard Trackily après installation

À quoi ça sert

Trackily est livré en deux saveurs :

  • Binaire pkg — un seul fichier trackily qui contient Node.js + le code + les assets. Tu copies, tu lances, c'est plié. Idéal pour un VPS simple ou pour tester en local.
  • Docker Composetrackily + postgres + (optionnellement) Caddy pour le SSL auto. C'est le mode recommandé pour la prod parce que la base est isolée, les certs persistent, et un docker compose up -d suffit pour repartir après reboot.

Dans les deux cas, la base PostgreSQL est gérée par toi (Trackily ne ship pas Postgres en dur dans le binaire). Trackily ouvre la connexion via DATABASE_URL, applique toutes les migrations au boot (table par table, idempotent) et crée le user admin si la table users est vide.

Pré-requis

Composant Version mini Notes
Node.js 22.14.0 Requis seulement pour le mode binaire / dev. Le mode Docker ship Node dans l'image.
PostgreSQL 14 16-alpine recommandé. Neon, Supabase et Render fonctionnent (SSL est auto-détecté via l'URL).
RAM 1 GB 2 GB recommandés si tu utilises l'AI landing builder.
Ports 3000 + 80/443 si tu actives AUTO_SSL=true (Caddy reverse proxy).

Variables d'environnement

Trackily lit son .env au boot via dotenv. Voici les variables qui comptent vraiment :

# ─── Obligatoires ───────────────────────────
DATABASE_URL=postgres://trackily:secret@localhost:5432/trackily
ADMIN_PASSWORD=ChangeMoiUnMotDePasseLong          # ≥ 8 caractères, sinon refus de démarrer

# ─── Recommandées ───────────────────────────
PORT=3000                                          # défaut 3000
BASE_URL=https://tracker.exemple.com               # URL publique (utilisée pour les postbacks, magic links, etc.)
SECRETS_MASTER_KEY=                                # 32 bytes hex ; chiffre les API keys en DB (AES-256-GCM)
LICENSE_KEY=                                       # voir « Licence et modes de fonctionnement » ci-dessous
LICENSE_SERVER_URL=https://license.trackily.online # défaut ; doit rester le serveur officiel (réponses signées)

# ─── Sécurité ───────────────────────────────
ADMIN_CSP_STRICT=true                              # CSP stricte avec nonces sur /admin (recommandé)

# ─── Docker / Caddy ─────────────────────────
AUTO_SSL=true                                      # active Caddy + Let's Encrypt sur les ports 80/443
DB_PASSWORD=trackily_secure_2024                   # mot de passe Postgres (utilisé par docker-compose)

ADMIN_PASSWORD est vérifié au boot : moins de 8 caractères ou variable manquante = [FATAL] et le process s'arrête. C'est volontaire pour éviter de booter avec un défaut faible. Voir server.js:626.

SECRETS_MASTER_KEY : si elle est absente, le code retombe sur ADMIN_PASSWORD pour dériver la clé de chiffrement. Ça marche, mais changer le mot de passe admin rendrait alors tous les secrets stockés indéchiffrables. Définis-la explicitement (openssl rand -hex 32) — le script d'installation le fait automatiquement.

LICENSE_SERVER_URL accepte uniquement le serveur officiel en pratique : depuis la vérification de signature, chaque verdict de licence est signé en Ed25519 et validé côté client contre une clé publique intégrée au binaire. Un serveur tiers ne peut pas produire une signature acceptée — l'instance passera en mode restreint. Ne change cette variable que si le support te le demande.

DATABASE_URL est nettoyé automatiquement (les paramètres sslmode et channel_binding sont retirés et reconstruits selon l'hôte). Voir database.js:4.

Si l'URL contient neon.tech, supabase, render.com ou sslmode=require, le SSL est activé en mode rejectUnauthorized: false. Pour un Postgres self-hosted dans le même réseau, laisse DATABASE_URL sans sslmode — la connexion sera en clair (LAN privé).

Option A — Binaire natif

C'est le chemin le plus court pour tester.

# 1. Cloner / récupérer le repo
git clone https://github.com/ton-org/trackily.git
cd trackily

# 2. Installer les deps
npm install

# 3. Configurer .env
cat > .env <<EOF
DATABASE_URL=postgres://trackily:secret@localhost:5432/trackily
ADMIN_PASSWORD=MonMotDePasseLongEtFort
PORT=3000
BASE_URL=http://localhost:3000
EOF

# 4. Préparer la base (Postgres doit déjà tourner)
createdb -U postgres trackily

# 5. Lancer
npm start

Au premier boot tu verras dans les logs :

[DB] Applying migrations…
[DB] Migration v1 applied
[DB] Migration v2 applied
… (jusqu'à la dernière version)
[DB] Seeded built-in cloaking workflow: "VPN Blocker (Built-in)"
[Auth] Admin user seeded: admin@trackily.local
[License] Valid — Plan: pro | Expires: 29/06/2027 | Features: 21
[License] Hub response signature verified
[Automizer] Starting rule engine (60s interval)
[Trackily] Listening on http://localhost:3000

Sans clé de licence, la ligne [License] diffère selon le mode de lancement :

# depuis les sources (dev) — toutes les fonctionnalités
[License] No LICENSE_KEY set — running in development mode (all features)

# binaire distribué — mode restreint, le tracking tourne
[License] No LICENSE_KEY — RESTRICTED mode: Automizer and AI optimisation are
          disabled. Add your license key in Settings → License to unlock…

Ouvre http://localhost:3000/admin → voir Première connexion.

Mode dev (auto-reload)

npm run dev

Lance le serveur avec node --watch — chaque modif d'un .js redémarre Trackily. Utile pour développer un MCP tool ou tweaker un template.

Build d'un binaire standalone

npm run build:linux      # binaire Linux x64
npm run build:mac        # binaire macOS x64
npm run build:all        # les deux

Sort un fichier dist/trackily (~50 MB compressé GZip) qui n'a besoin que de DATABASE_URL et ADMIN_PASSWORD dans l'env pour tourner. Pas de node_modules à shipper.

Option B — Docker Compose

Recommandé pour la prod. Fichier livré dans dist/docker-compose.yml :

version: "3.8"
services:
  trackily:
    build: .
    restart: always
    ports:
      - "${PORT:-3000}:3000"
      - "80:80"     # Requis pour AUTO_SSL=true
      - "443:443"   # Requis pour AUTO_SSL=true
    env_file: .env
    depends_on:
      - postgres
    volumes:
      - trackily-data:/app/data
      - caddy-data:/data        # Certs Caddy (persistants)
  postgres:
    image: postgres:16-alpine
    restart: always
    environment:
      POSTGRES_DB: trackily
      POSTGRES_USER: trackily
      POSTGRES_PASSWORD: ${DB_PASSWORD:-trackily_secure_2024}
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:
  trackily-data:
  caddy-data:

Lancer

cd dist/
cat > .env <<EOF
DATABASE_URL=postgres://trackily:trackily_secure_2024@postgres:5432/trackily
ADMIN_PASSWORD=MonMotDePasseLongEtFort
DB_PASSWORD=trackily_secure_2024
BASE_URL=https://tracker.exemple.com
AUTO_SSL=true
EOF

docker compose up -d
docker compose logs -f trackily

Le Dockerfile (récap)

FROM ubuntu:22.04
RUN apt-get update && apt-get install -y \
    ca-certificates curl debian-keyring debian-archive-keyring \
    apt-transport-https gnupg && \
    # install Caddy depuis le repo officiel
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg && \
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list && \
    apt-get update && apt-get install -y caddy
WORKDIR /app
COPY trackily /app/trackily
COPY public /app/public
COPY Caddyfile /app/Caddyfile
COPY start.sh /app/start.sh
RUN chmod +x /app/trackily /app/start.sh
EXPOSE 3000 80 443
CMD ["/app/start.sh"]

L'image embarque Caddy pour faire reverse proxy + SSL automatique Let's Encrypt. Si AUTO_SSL=false (ou non défini), Caddy n'est pas lancé et Trackily écoute directement sur ${PORT}.

Le start.sh

#!/bin/bash
set -e

if [ "${AUTO_SSL}" = "true" ]; then
  echo "[Trackily] Auto-SSL activé — Caddy sur ports 80/443"
  caddy start --config /app/Caddyfile --adapter caddyfile
else
  echo "[Trackily] Auto-SSL désactivé — Trackily direct sur ${PORT:-3000}"
fi

exec /app/trackily

Licence et modes de fonctionnement

Trackily ne se bloque jamais brutalement. Une licence absente, expirée ou révoquée fait glisser l'instance le long d'une échelle, et le tracking continue de tourner à chaque échelon.

Mode Ce qui marche Ce qui s'arrête
full tout
restricted tracking, admin, rapports Automizer, Traffic AI, fonctions premium
read_only (après 3 j) tracking, consultation toute écriture dans l'admin
locked (après 14 j) tracking l'admin, sauf login et renouvellement

Le plan de données n'est jamais coupé. /c, /s, /lp et les postbacks répondent dans tous les modes, y compris locked. Une campagne en cours ne perd jamais un clic à cause d'un problème de licence.

Sans LICENSE_KEY :

  • Binaire distribué → démarre en restricted. Le tracking et l'admin fonctionnent, les moteurs payants non. Colle ta clé dans Settings → License pour débloquer.
  • Depuis les sources (dev) → toutes les fonctionnalités, inchangé.

Si le serveur de licences est injoignable, l'instance continue sur son dernier verdict connu pendant 72 h (période de grâce), puis dégrade. Une panne réseau ne coupe donc pas ton tracker.

Le hub est réinterrogé toutes les 6 h : une licence renouvelée reprend effet sans redémarrage.

Le premier boot en détail

Trackily fait beaucoup au démarrage. Dans l'ordre :

  1. Charge .env via dotenv.
  2. Vérifie ADMIN_PASSWORD — fatal si < 8 caractères.
  3. Connecte Postgres via pg.Pool. Si la base n'existe pas, ça plante avec un message explicite.
  4. Applique les migrations une par une. Chaque migration vérifie sa propre version dans la table schema_migrations et skip si déjà appliquée. Tu peux relancer Trackily 100 fois — rien ne sera dupliqué.
  5. Seed les données built-in :
    • Le workflow de cloaking "VPN Blocker (Built-in)" (voir database.js:3931).
    • Le user admin admin@trackily.local avec le mot de passe de ADMIN_PASSWORD (voir database.js:3248).
    • Les conversion types Keitaro-style (lead, sale, rebill, etc.).
  6. Vérifie la licence via license-client.js : charge d'abord le dernier verdict en cache (pour survivre à un hub injoignable au démarrage), interroge le serveur, vérifie la signature Ed25519 du verdict, puis applique le mode correspondant. Le boot ne s'interrompt jamais à cause de la licence — il démarre dans le mode approprié et le log l'annonce.
  7. Démarre les moteurs autorisés par le plan — Automizer (boucle 60s, voir automizer.js:16) et l'optimisation IA ne se lancent qu'en mode full.
  8. Enregistre les outils Autopilot/MCP (~205 tools — voir MCP).
  9. Écoute sur PORT.

Postgres : trois setups recommandés

Postgres local (binaire ou Docker single-container)

DATABASE_URL=postgres://trackily:secret@localhost:5432/trackily

Le plus simple. Sauvegardes via pg_dump cron.

Postgres managé (Neon / Supabase / Render)

DATABASE_URL=postgres://user:pass@ep-cool-name.neon.tech/trackily?sslmode=require

Trackily détecte le hostname et active automatiquement SSL. Aucune autre conf à faire.

Postgres dans le même Docker network (mode docker compose)

DATABASE_URL=postgres://trackily:trackily_secure_2024@postgres:5432/trackily

Le hostname postgres est résolu par le DNS interne de Docker. Pas de SSL nécessaire (LAN privé).

Erreurs courantes

  • [FATAL] ADMIN_PASSWORD env var is required and must be at least 8 characters — t'as oublié ADMIN_PASSWORD dans .env, ou il fait moins de 8 caractères. Refus volontaire de booter.
  • error: password authentication failed for user "trackily" — le user Postgres existe mais le mot de passe ne matche pas. Vérifie DATABASE_URL vs le POSTGRES_PASSWORD du container.
  • ECONNREFUSED 127.0.0.1:5432 — Postgres n'est pas démarré ou n'écoute pas sur l'adresse. pg_isready -h localhost pour vérifier.
  • Port 80/443 déjà pris quand AUTO_SSL=true — un Nginx ou Apache local mange déjà les ports. Soit tu arrêtes l'autre service, soit tu désactives Caddy et tu mets Trackily derrière ton reverse proxy existant.
  • Tables vides après reboot — si tu utilises Docker sans volume nommé pour Postgres, les données disparaissent. Le docker-compose.yml fourni utilise un volume pgdata exprès pour éviter ça.
  • RESTRICTED mode alors que ta licence est valide — l'instance n'a pas pu joindre le serveur de licences au démarrage et n'avait aucun verdict en cache (première installation). Vérifie que le serveur sort bien vers https://license.trackily.online (pare-feu, proxy). Le tracking fonctionne pendant ce temps ; corrige la sortie réseau et redémarre.
  • SIGNATURE CHECK FAILED dans les logs — le verdict reçu n'est pas signé par le serveur officiel. Presque toujours un LICENSE_SERVER_URL modifié, ou un proxy qui réécrit la réponse. Remets la valeur par défaut.
  • License bound to different instance — la clé est déjà activée sur un autre serveur. Une licence = une instance. Contacte le support pour la ré-associer (Rebind) si tu as migré de machine.
  • Téléchargement 403 pendant install.sh — la licence est expirée, suspendue ou révoquée : les mises à jour sont coupées. Renouvelle depuis le portail.

Télémétrie

Ton instance communique avec le serveur de licences (LICENSE_SERVER_URL). Voici ce qui est transmis.

Données opérationnelles — clé de licence, identifiant d'instance, hostname, IP serveur, version, disponibilité, et des compteurs agrégés (clics, campagnes actives, utilisateurs, conversions, revenu total). C'est ce qui maintient ta licence valide, déclenche les notifications de mise à jour et permet au support de reproduire un bug.

Benchmark d'offres anonyme — nom de l'offre, domaine de destination, réseau, geo, et par jour : conversions et revenu. Ces données alimentent un benchmark des offres qui performent sur l'ensemble du parc.

Une offre n'est affichée qu'à partir de 5 instances distinctes qui la font tourner, et le benchmark ne montre jamais quel compte fait tourner quelle offre. Les données de tes visiteurs et de tes leads (emails, IP, informations personnelles) ne sont jamais transmises.

Voir aussi