Self-Host Activepieces with Docker Compose: Step-by-Step

by Fahim

I hit my breaking point with Zapier and Make when a simple database sync loop ate my entire monthly task quota in three hours. Paying hundreds of dollars for basic webhooks felt like a scam. So, I migrated everything to a self-hosted instance of Activepieces.

It’s a lightweight, open-source automation engine with a slick visual builder and native code steps. In this guide, I’ll walk you through setting up Activepieces on your own VPS using Docker Compose. We’ll configure the app container, back it with PostgreSQL and Redis, and secure it behind an Nginx reverse proxy with SSL.

Self-hosted Activepieces running on Docker Compose in a server terminal
Self-hosted Activepieces running on Docker Compose in a server terminal

Why I Ditched SaaS for Self-Hosted Activepieces

SaaS automation platforms charge you per step. If you run a workflow that loops through 100 database rows every hour, you’ll burn through your free tier before lunchtime. Self-hosting removes those arbitrary limits. Your only bottleneck is your server’s hardware.

Plus, keeping API keys and sensitive customer data on your own hardware is a massive security win. If you’re already building out a stack of self-hosted tools for developers, Activepieces slots right in alongside your existing databases and services.

Unlike bloated enterprise tools, Activepieces is incredibly light. The Node.js backend and Angular frontend run smoothly on a cheap virtual private server without hogging resources.

My Server Setup and Prerequisites

I spun up a basic VPS running Ubuntu 22.04 with 2 vCPUs and 4GB of RAM. While you can scrape by on 2GB, background workers and Postgres can spike during heavy executions. That extra headroom is worth the peace of mind.

Make sure you’ve got these installed before starting:

  • Docker (version 20.10 or higher)
  • Docker Compose (V2 plugin)
  • A domain name pointed at your server’s public IP address (for SSL)

If you need to install Docker, check out the official Docker Compose documentation. Once your server is ready, SSH in and let’s get organized.

I keep all my self-hosted apps in the /opt directory. Let’s create a folder for Activepieces and jump into it:

mkdir -p /opt/activepieces && cd /opt/activepieces

The Docker Compose Architecture

You can run Activepieces on SQLite for a quick test, but it’ll fall apart the moment you start running concurrent workflows or heavy loops. For a production-ready setup, we need a proper stack.

We’ll use three containers:

  • Activepieces: The main app container handling the UI, API, and workflow execution.
  • PostgreSQL: Stores your users, flows, history, and credentials.
  • Redis: Manages the background job queue and coordinates workers.

This architecture is very similar to how you’d self-host n8n with PostgreSQL. Offloading the queue to Redis ensures you won’t drop tasks even if the UI is lagging under heavy load.

Step 1: Writing the Docker Compose File

Let’s write the docker-compose.yml file to orchestrate our services, handle persistent volumes, and map our ports.

Fire up your favorite text editor:

nano docker-compose.yml

Paste the following config, replacing the placeholders with your actual passwords, generated keys, and domain:

version: '3.8' services: postgres: image: postgres:15-alpine container_name: activepieces_postgres restart: always environment: POSTGRES_DB: ${AP_POSTGRES_DATABASE} POSTGRES_USER: ${AP_POSTGRES_USER} POSTGRES_PASSWORD: ${AP_POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] interval: 5s timeout: 5s retries: 5 redis: image: redis:7-alpine container_name: activepieces_redis restart: always volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 5s retries: 5 activepieces: image: activepieces/activepieces:0.29.0 container_name: activepieces_app restart: always depends_on: postgres: condition: service_healthy redis: condition: service_healthy ports: - "127.0.0.1:8080:80" environment: AP_ENVIRONMENT: prod AP_ENCRYPTION_KEY: ${AP_ENCRYPTION_KEY} AP_JWT_SECRET: ${AP_JWT_SECRET} AP_POSTGRES_DATABASE: ${AP_POSTGRES_DATABASE} AP_POSTGRES_USER: ${AP_POSTGRES_USER} AP_POSTGRES_PASSWORD: ${AP_POSTGRES_PASSWORD} AP_POSTGRES_HOST: postgres AP_POSTGRES_PORT: 5432 AP_REDIS_URL: redis://redis:6379 AP_FRONTEND_URL: ${AP_FRONTEND_URL} AP_SANDBOX_RUN_EFFECT_TIMEOUT_MS: 600000 volumes: - activepieces_data:/usr/src/app/packages/backend/storage volumes: postgres_data: redis_data: activepieces_data:

Notice that I bound the Activepieces port to 127.0.0.1:8080:80. This keeps it closed to the public internet. We’ll route external traffic through Nginx later to handle SSL securely.

Step 2: Setting Up Your Environment Variables (.env)

Never hardcode passwords in your compose file. We’ll use a .env file to keep our secrets secure and separated from our infrastructure configuration.

First, we need to generate two secure, random strings: one for database encryption and one for the JWT secret. Run these commands to generate them:

openssl rand -hex 32

Copy those strings somewhere safe, then create your environment file:

nano .env

Add the following variables, replacing the placeholders with your actual passwords, generated keys, and domain:

# Database Configuration
AP_POSTGRES_DATABASE=activepieces
AP_POSTGRES_USER=ap_admin
AP_POSTGRES_PASSWORD=your_super_secure_db_password_here # Security Keys (Paste your generated 32-byte hex strings here)
AP_ENCRYPTION_KEY=your_generated_encryption_key_here
AP_JWT_SECRET=your_generated_jwt_secret_here # Application Settings
AP_FRONTEND_URL=https://automation.yourdomain.com

Make sure AP_FRONTEND_URL matches your domain exactly. Activepieces uses this to construct webhook URLs and handle OAuth redirects when you connect external apps.

Step 3: Booting Up (And Fixing the First Crash)

Now let’s spin everything up. Run this command to start the stack in the background:

docker compose up -d

Docker will pull the images and start the containers. Give it a minute, then check their status:

docker compose ps

When I first ran this, the Activepieces container got stuck in a crash-loop. I checked the logs to see what went wrong:

docker compose logs -f activepieces

The logs showed Activepieces failing to connect to PostgreSQL. Even though I used depends_on, the database container was ‘running’ but still initializing its internal files, meaning it wasn’t ready to accept connections yet.

To fix this, I added the healthcheck blocks to both PostgreSQL and Redis in the docker-compose.yml file above. This forces Docker Compose to wait until the database is actually accepting connections before starting the app. If you hit this crash, make sure your healthchecks are configured correctly.

Step 4: Setting Up Nginx and Let’s Encrypt

With the app running locally on port 8080, we need to expose it securely to the web. We’ll use Nginx as a reverse proxy and Let’s Encrypt for SSL.

First, install Nginx:

sudo apt update && sudo apt install -y nginx

Create a new server block configuration for Activepieces:

sudo nano /etc/nginx/sites-available/activepieces

Paste the following config, replacing automation.yourdomain.com with your domain:

server { listen 80; server_name automation.yourdomain.com; location / { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }
}

Don’t skip the Upgrade and Connection headers. Activepieces uses WebSockets to stream live execution logs to your browser while debugging, and without these, your logs will fail to load.

Enable the configuration and restart Nginx:

sudo ln -s /etc/nginx/sites-available/activepieces /etc/nginx/sites-enabled/
sudo systemctl restart nginx

Now, let’s grab an SSL certificate using Certbot. Install Certbot and its Nginx plugin:

sudo apt install -y certbot python3-certbot-nginx

Run Certbot to request the certificate. It’ll automatically update your Nginx config to force HTTPS redirects:

sudo certbot --nginx -d automation.yourdomain.com

Follow the prompts, and once it’s done, open your browser and head to your domain. You should see the Activepieces setup screen asking you to create your admin account.

Testing Your First Workflow

Once you register, you’ll land on the dashboard. The UI is clean, fast, and incredibly intuitive.

Let’s run a quick test to make sure the background workers are actually processing jobs:

  1. Click New Flow in the top right corner.
  2. Select the Webhook trigger and copy the generated webhook URL.
  3. Add a new step, choose the HTTP piece, and configure it to send a test request.
  4. Click Test Flow.

Because we configured Redis, the execution gets offloaded instantly to a background queue, keeping the UI snappy. If you’re building high-volume integrations, check out my guide on managing API integrations and webhooks to avoid hitting rate limits or running out of memory.

Frequently Asked Questions

How much RAM does Activepieces actually use?

At idle, the whole stack (Activepieces, Postgres, and Redis) hovers around 450MB of RAM. During heavy concurrent executions, that can spike to 1.2GB. I highly recommend a 2GB to 4GB VPS for production.

How do I update Activepieces to the latest version?

It’s super simple. Go to your project directory, open docker-compose.yml, and update the version tag on the Activepieces image. Then run:

docker compose pull activepieces
docker compose up -d

Activepieces handles migrations automatically on startup, so your data stays safe.

Can I use an external PostgreSQL database?

Absolutely. If you’re using a managed database service, just delete the postgres block from your docker-compose.yml and update the AP_POSTGRES_* variables in your .env file to point to your external instance.

How do I back up my Activepieces data?

You’ll need to back up your Postgres database and your .env file. You can run a quick pg_dump directly inside the running container:

docker compose exec postgres pg_dump -U ap_admin activepieces > backup.sql

Keep that backup.sql and your .env file stored safely offsite.

Next Steps for Your Automation Engine

Now that your self-hosted automation engine is up and running, you can build complex workflows without worrying about task limits or monthly bills.

If you plan to connect your flows to high-traffic APIs or custom webhooks, you’ll want to handle caching properly. Check out my guide on Redis caching in Node.js to learn how to optimize your custom scripts and keep your integrations running fast.

Official resources

all_in_one_marketing_tool