[{"data":1,"prerenderedAt":196},["ShallowReactive",2],{"seo-verification":3,"blog-installing-triggerdev-on-a-vps-self-hosted-automation-ma-en":6,"promo-bar-likely":195},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-installing-triggerdev-on-a-vps-self-hosted-automation-ma-en",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"noindex":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":27,"featuredImage":29,"bgImage":30,"posterImage":31,"relatedSolution":32,"intro":35,"sections":36,"ctaTitle":137,"ctaBody":138,"ctaButton":139,"ctaUrl":140,"relatedPosts":141},32,"installing-triggerdev-on-a-vps-self-hosted-automation",{"fr":12,"en":10,"ar":13,"es":14},"installer-trigger-dev-vps","تثبيت-triggerdev-على-خادم-vps-أتمتة-ذاتية-الاستضافة","instalar-trigger-dev-en-un-vps","Installing Trigger.dev on a VPS: complete self-hosted guide","Complete guide to installing Trigger.dev on a VPS: Docker, reverse proxy, secrets, workers and troubleshooting — completely free, no SaaS limits.",9,0,false,"2026-05-19T00:00:00+00:00","2026-11-04T16:30:25+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},2,"Automation","automatisation","bg-brand-action\u002F10 text-brand-action",[28],{"id":23,"name":24,"slug":25,"color":26,"icon":25},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Finstaller-trigger-dev-vps-poster.svg",{"categorySlug":33,"appSlug":34},"automation-workflows","trigger-dev","Trigger.dev is a background task orchestration platform built for developers: durable jobs, automatic retries and a real-time dashboard. By self-hosting it on a VPS, you get a completely free installation with no execution quota — no SaaS subscription, no execution quota. This guide covers the full setup from A to Z: prerequisites, secret generation, HTTPS reverse proxy, connecting your first TypeScript project and troubleshooting the most common errors.",[37,41,52,88,91,113,116,119,123,126,135],{"type":38,"title":39,"body":40},"h2","Why self-host Trigger.dev on a VPS","Trigger.dev replaces homemade queues (BullMQ, fragile crons, Lambdas that time out) with a unified platform: durable tasks, automatic retries, concurrency management and a real-time dashboard. The cloud version bills by the number of executions and limits job duration, which quickly becomes constraining for ETL processing, mass email sending or slow API calls.\n\nSelf-hosted on a VPS, you keep your workers on your side: your third-party API keys (OpenAI, Stripe, Resend) never pass through a third party, and your jobs can run for 10 minutes or several hours without being cut off. The stack relies on PostgreSQL, Redis and Docker, making it reproducible and easy to back up. The installation is **completely free**: no licence, no subscription — only the VPS cost applies.",{"type":42,"title":43,"items":44},"ul","What you gain by self-hosting",[45,46,47,48,49,50,51],"No limit on the duration or number of executions of your background tasks.","Your secrets (API keys, tokens) stay in your infrastructure, never on a third-party SaaS.","Predictable fixed cost: a single VPS instead of a bill that climbs with volume.","No public network hop if your workers run next to your database and your application.","Full control over versions, environment variables and log retention.","The ability to trigger jobs from your internal webhooks without exposing any external service.","Update at your own pace: you choose when to upgrade to a new version of Trigger.dev.",{"type":53,"title":54,"headers":55,"rows":59},"comparison","Trigger.dev self-hosted vs cloud: what actually changes",[56,57,58],"Criterion","Cloud (SaaS)","Self-hosted VPS",[60,64,68,72,76,80,84],[61,62,63],"Maximum job duration","Limited (a few minutes)","No duration limit",[65,66,67],"Cost at volume","Grows with executions","Fixed (monthly VPS)",[69,70,71],"Secrets \u002F API keys","Pass through the cloud","Stay in your infra",[73,74,75],"Updates","Automatic, imposed","At your own pace",[77,78,79],"Internal network access","Impossible without tunnel","Direct, no round-trip via the public Internet",[81,82,83],"Log retention","Limited by plan","Controlled by you",[85,86,87],"Initial setup","Zero configuration","~30 minutes (this guide)",{"type":38,"title":89,"body":90},"Hardware and software requirements","Trigger.dev is a relatively resource-hungry stack because it combines the web application, workers, PostgreSQL and Redis. Plan for a VPS with **at least 4 GB of RAM and 2 vCPU** for light production use; aim for 8 GB of RAM and 4 vCPU if you run many concurrent jobs or heavy processing. Allow 40 GB of SSD disk for the database, logs and Docker images.\n\nOn the software side: **Docker Engine 24+** and the Docker Compose v2 plugin (check with `docker compose version`), a domain name pointing to the VPS IP (for example `trigger.mydomain.com`), and port 443 open for HTTPS. Two secrets are essential: `MAGIC_LINK_SECRET` (passwordless authentication) and `ENCRYPTION_KEY` (32 hexadecimal characters, encrypts project environment variables). Generate them before you begin — they cannot be regenerated without breaking existing data.",{"type":92,"title":93,"steps":94},"steps","Install Trigger.dev with Docker in 6 steps",[95,98,101,104,107,110],{"title":96,"body":97},"Prepare the VPS and install Docker","Connect over SSH with a sudo user, update the system (`apt update && apt upgrade -y`) then install Docker in one command: `curl -fsSL https:\u002F\u002Fget.docker.com | sh`. Add your user to the docker group (`usermod -aG docker $USER`) to avoid always using `sudo`. Create a dedicated folder: `mkdir -p \u002Fopt\u002Ftrigger && cd \u002Fopt\u002Ftrigger`. Verify that Compose v2 is available with `docker compose version` — the output should show at least `v2.x.x`.",{"title":99,"body":100},"Fetch the official self-hosting stack","Clone the official repository: `git clone https:\u002F\u002Fgithub.com\u002Ftriggerdotdev\u002Ftrigger.dev \u002Fopt\u002Ftrigger\u002Fsrc`. Navigate to the deployment subfolder: `cd \u002Fopt\u002Ftrigger\u002Fsrc\u002Fdocker`. This directory contains the `docker-compose.yml` that orchestrates the web application (`webapp`), workers, PostgreSQL and Redis. Copy the example file to your configuration: `cp .env.example .env`. Do not launch anything before configuring the `.env` — the stack will refuse to start with default values.",{"title":102,"body":103},"Generate the secrets and configure the domain","Open `.env` in your editor and set at minimum these variables:\n\n- `ENCRYPTION_KEY`: `openssl rand -hex 16` (16 bytes = 32 hex chars)\n- `MAGIC_LINK_SECRET`: `openssl rand -hex 16` (same)\n- `LOGIN_ORIGIN`: `https:\u002F\u002Ftrigger.mydomain.com`\n- `APP_ORIGIN`: `https:\u002F\u002Ftrigger.mydomain.com`\n- `POSTGRES_PASSWORD`: a strong password (`openssl rand -base64 24`)\n- `REDIS_PASSWORD`: same\n\nLeave `DATABASE_URL` and `REDIS_URL` as-is if you use the internal Compose services — they reference Docker service names. Also set `SESSION_SECRET` with `openssl rand -hex 32`.",{"title":105,"body":106},"Launch the stack and create the first account","Start everything in the background: `docker compose up -d`. Follow the database migrations in real time: `docker compose logs -f webapp`. Wait for the message `Listening on port 3030` before continuing — migrations can take 30 to 60 seconds on first startup. Once the application has started, the signup magic link appears in the logs: copy it and open it in your browser to create the first admin account. If you missed the link: `docker compose logs webapp | grep magic`.",{"title":108,"body":109},"Expose the application via an HTTPS reverse proxy","Place Caddy in front of the application to handle TLS automatically. Create `\u002Fetc\u002Fcaddy\u002FCaddyfile` with this minimal content:\n\n```\ntrigger.mydomain.com {\n    reverse_proxy localhost:3030\n}\n```\n\nReload Caddy (`systemctl reload caddy`): Let's Encrypt issues the certificate in seconds. With nginx, create a vhost that proxies to `http:\u002F\u002F127.0.0.1:3030` and activate a certificate via `certbot --nginx`. Then verify that `https:\u002F\u002Ftrigger.mydomain.com` responds correctly before moving on.",{"title":111,"body":112},"Connect your first TypeScript project","In your Node.js project, install the SDK: `npm install @trigger.dev\u002Fsdk`. Authenticate the CLI against your instance: `npx trigger.dev@latest login --api-url https:\u002F\u002Ftrigger.mydomain.com`. Then create your first project in the dashboard, retrieve the project secret key (`sk_...`) and add it to your local `.env`: `TRIGGER_SECRET_KEY=sk_...`. Initialise the configuration with `npx trigger.dev@latest init` and deploy your first job with `npx trigger.dev@latest deploy`.",{"type":38,"title":114,"body":115},"Troubleshooting: common errors and their solutions","Here are the five most common errors encountered when installing Trigger.dev self-hosted.\n\n**`Error: ENCRYPTION_KEY must be 32 characters`** — You used `openssl rand -base64 16` instead of `openssl rand -hex 16`. The base64 form produces characters outside the hexadecimal character set. Regenerate with `-hex 16` (exactly 32 chars).\n\n**`webapp exited with code 1` on startup** — Check the full logs with `docker compose logs webapp`. Most common cause: incorrect `DATABASE_URL` or PostgreSQL not yet ready. Wait 10 seconds and restart with `docker compose restart webapp`.\n\n**The account creation magic link does not appear** — The application may have started before migrations finished. Restart `docker compose restart webapp` and watch the logs from the beginning. If the link is still absent, check that `LOGIN_ORIGIN` exactly matches your domain (no trailing slash).\n\n**`Failed to connect` in the CLI during `login`** — The reverse proxy is not yet active or DNS has not yet propagated to your VPS. Test locally with `curl http:\u002F\u002F127.0.0.1:3030\u002Fhealthcheck` from the VPS: if it responds, the issue is on the proxy or DNS side.\n\n**The job deploys but does not run** — Check that the workers are running: `docker compose ps` should show the `worker` service in `running` state. If the worker is stopped, `docker compose up -d worker` restarts it. Also check that `TRIGGER_SECRET_KEY` in your project matches the key of the correct project in the dashboard.",{"type":38,"title":117,"body":118},"Securing and maintaining your instance","A Trigger.dev instance exposes the dashboard and the API on the same domain. A few precautions reduce the attack surface without complicating operations.\n\n**Firewall**: block all ports except 22 (SSH), 80 and 443 (with `ufw allow` for each). Port 3030 must never be directly accessible from outside — it is reserved for the local reverse proxy.\n\n**Secret rotation**: `MAGIC_LINK_SECRET` can be rotated without breaking data. `ENCRYPTION_KEY`, however, encrypts project environment variables — rotation requires a data migration. Store them in a secrets manager (Bitwarden, 1Password or HashiCorp Vault).\n\n**Updates**: Trigger.dev publishes releases on GitHub. To update, pull the new version (`git pull` in `\u002Fopt\u002Ftrigger\u002Fsrc`), rebuild the images (`docker compose pull`) and restart (`docker compose up -d`). Database migrations are applied automatically at `webapp` startup.\n\n**Backups**: schedule a daily PostgreSQL dump to external storage. A minimal cron: `0 3 * * * docker exec trigger-postgres-1 pg_dump -U postgres trigger | gzip > \u002Fopt\u002Fbackups\u002Ftrigger-$(date +%F).sql.gz`.",{"type":120,"title":121,"body":122},"tip","Horizontal worker scalability","Isolate the workers from the web application on separate containers and limit their concurrency via the `WORKER_CONCURRENCY` variable (default: 10). For very CPU-hungry jobs, add a second VPS dedicated to workers pointing to the same PostgreSQL and Redis: you scale horizontally without touching the dashboard. Workers are stateless — they only need `DATABASE_URL`, `REDIS_URL` and `ENCRYPTION_KEY` to join the fleet. On a small VPS, start with `WORKER_CONCURRENCY=3` to avoid memory saturation during job spikes.",{"type":38,"title":124,"body":125},"Writing and deploying your first Trigger.dev job","A Trigger.dev job is a TypeScript function exported from a `trigger\u002F` file in your project. Here is a minimal example of a deferred email send:\n\n```typescript\nimport { task } from \"@trigger.dev\u002Fsdk\u002Fv3\";\n\nexport const sendWelcomeEmail = task({\n  id: \"send-welcome-email\",\n  run: async (payload: { userId: string; email: string }) => {\n    \u002F\u002F your sending logic here\n    await sendEmail(payload.email, \"Welcome!\");\n    return { sent: true };\n  },\n});\n```\n\nDeploy with `npx trigger.dev@latest deploy`. The dashboard then shows your job under the **Tasks** tab. Trigger a test run from the dashboard or from your code: `await sendWelcomeEmail.trigger({ userId: \"u1\", email: \"test@example.com\" })`. Automatic retries apply on error — configurable with the `retry` option on `task()`.\n\nFor long jobs (CSV import, image processing), use `wait.for()` to suspend execution and avoid blocking a worker during network pauses: Trigger.dev resumes the job where it left off, even after a container restart.",{"type":42,"title":127,"items":128},"Use cases best suited to self-hosting",[129,130,131,132,133,134],"**ETL processing**: import, transform and load large data volumes without timeouts.","**Mass transactional sends**: email or notification campaigns with controlled throttling.","**AI pipelines**: chained calls to OpenAI, Anthropic or Hugging Face with retry handling on rate-limits.","**Third-party integration sync**: Stripe webhooks, Shopify, HubSpot — without depending on an intermediary SaaS.","**Critical scheduled tasks**: replace fragile crons with jobs that have an execution history and alerts.","**PDF report generation or heavy exports**: multi-minute jobs with no duration limit.",{"type":120,"body":136},"Trigger.dev is **completely free when self-hosted**: no commercial licence is required for private or professional use on your own infrastructure. The MIT licence covers the open-source code. Only the proprietary code of the Enterprise version (SAML SSO, advanced audit logs) is excluded — for the vast majority of teams, the self-hosted community version is more than sufficient.","Deploy Trigger.dev in a few minutes","A ServOrbit Cloud VPS preconfigured with Docker, a domain and a ready SSL certificate lets you launch your self-hosted task orchestrator without tedious system configuration.","Order my Cloud VPS","\u002Fapplications\u002Fautomation-workflows\u002Ftrigger-dev",[142,161,179],{"id":143,"slug":144,"slugs":145,"title":149,"excerpt":150,"readTime":151,"views":152,"isPinned":19,"noindex":19,"publishedAt":153,"updatedAt":154,"category":155,"categories":156,"featuredImage":29,"bgImage":30,"posterImage":158,"relatedSolution":159},3,"install-n8n-on-vps-with-docker-complete-2026-guide",{"fr":146,"en":144,"ar":147,"es":148},"installer-n8n-vps","تثبيت-n8n-على-vps-مع-docker-دليل-شامل-2026","instalar-n8n-en-vps-con-docker","Install n8n on VPS with Docker: complete 2026 guide","Deploy n8n on VPS with Docker, reverse proxy and HTTPS. Covers V8 crash, 502 nginx, npm migration and execution security (GHSA-vrv8-j27g-g7cr advisory, August 2026).",19,4,"2026-06-05T00:00:00+00:00","2026-11-09T20:55:18+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},[157],{"id":23,"name":24,"slug":25,"color":26,"icon":25},"\u002Fblog\u002Fcovers\u002Finstaller-n8n-vps-poster.svg",{"categorySlug":33,"appSlug":160},"n8n",{"id":162,"slug":163,"slugs":164,"title":168,"excerpt":169,"readTime":152,"views":170,"isPinned":19,"noindex":19,"publishedAt":171,"updatedAt":172,"category":173,"categories":174,"featuredImage":29,"bgImage":30,"posterImage":176,"relatedSolution":177},24,"installing-node-red-on-a-vps-self-hosted-automation",{"fr":165,"en":163,"ar":166,"es":167},"installer-node-red-vps","تثبيت-node-red-على-خادم-vps-أتمتة-ذاتية-الاستضافة","instalar-node-red-en-un-vps","Installing Node-RED on a VPS: self-hosted automation","Install Node-RED on a VPS to automate your flow-based workflows, connect your APIs and IoT devices, all self-hosted and secure.",1,"2026-05-27T00:00:00+00:00","2026-11-04T16:30:24+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},[175],{"id":23,"name":24,"slug":25,"color":26,"icon":25},"\u002Fblog\u002Fcovers\u002Finstaller-node-red-vps-poster.svg",{"categorySlug":33,"appSlug":178},"node-red",{"id":180,"slug":181,"slugs":182,"title":186,"excerpt":187,"readTime":143,"views":18,"isPinned":19,"noindex":19,"publishedAt":188,"updatedAt":172,"category":189,"categories":190,"featuredImage":29,"bgImage":30,"posterImage":192,"relatedSolution":193},25,"installing-huginn-on-a-vps-self-hosted-automation",{"fr":183,"en":181,"ar":184,"es":185},"installer-huginn-vps","تثبيت-huginn-على-خادم-vps-أتمتة-ذاتية-الاستضافة","instalar-huginn-en-un-vps","Installing Huginn on a VPS: self-hosted automation","Install Huginn on a VPS to build agents that monitor the web, scrape pages and trigger actions, 100% self-hosted.","2026-05-26T00:00:00+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},[191],{"id":23,"name":24,"slug":25,"color":26,"icon":25},"\u002Fblog\u002Fcovers\u002Finstaller-huginn-vps-poster.svg",{"categorySlug":33,"appSlug":194},"huginn",true,1794270437009]