Hosted automation services bill per task, and the meter runs on things that aren't even work. A flow that checks a feed every five minutes is 8,640 runs a month before it has done anything useful. Run the same flow on your own server and the bill is the server.
Activepieces is an open-source automation builder — triggers, steps, branches, a few hundred ready-made integrations, plus code steps when the ready-made ones run out. The community edition is MIT-licensed, and it runs fine on one small server with Docker Compose.
Which plan
We installed it on a test server and measured. The stock compose file starts the app and five workers: about 2.6–3 GB of RAM together with Postgres and Redis. Cut it to one worker and it drops to around 1.6 GB.
| What you run | Plan |
|---|---|
| A few personal flows, one worker | Micro-IP — 2 vCPU, 2 GB, 25 GB ($10/mo), add swap |
| The default setup: five workers, team flows, webhooks | Small-IP — 4 vCPU, 4 GB, 35 GB ($16/mo) |
| Many runs at once, heavy code steps | Medium-IP — 6 vCPU, 6 GB, 45 GB ($20/mo) |
Take a plan with its own IPv4. Webhooks are the main reason to self-host this, and the services that call them must reach ports 80 and 443; on NAT plans only the SSH port is reachable from outside. Locations are Germany and Finland — availability is shown at checkout. Pay in crypto if you like; there's no KYC.
Install
Point a domain — say flows.example.com — at the server first. Then, as root on Ubuntu 24.04 or Debian 12:
curl -fsSL https://get.docker.com | sh
git clone --depth 1 https://github.com/activepieces/activepieces.git
cd activepieces
sh tools/deploy.sh
deploy.sh copies .env.example to .env and fills in random secrets. Before the first start, change two lines in .env and one in the compose file:
sed -i 's|^AP_FRONTEND_URL=.*|AP_FRONTEND_URL=https://flows.example.com|; s|^AP_TELEMETRY_ENABLED=.*|AP_TELEMETRY_ENABLED=false|' .env
sed -i "s|- '8080:80'|- '127.0.0.1:8080:80'|" docker-compose.yml
The first line is the one that matters. AP_FRONTEND_URL isn't only for links in the UI: the workers connect to the app through it. Leave it at http://localhost:8080 and every worker container looks for the app inside itself, can't find it, and your flows never publish. We hit exactly that: „Socket.IO connection error“ in the worker logs, a publish request that hung, and webhooks answering 404. With the real domain in place, the same flow published and the webhook ran.
The sed on docker-compose.yml keeps port 8080 on localhost. Docker's published ports go around ufw, so without it the app would be open on a raw port next to your HTTPS.
On Micro-IP, also drop to one worker:
sed -i 's/replicas: 5/replicas: 1/' docker-compose.yml
Now HTTPS and the start:
apt install -y caddy
cat > /etc/caddy/Caddyfile <<'EOF'
flows.example.com {
reverse_proxy 127.0.0.1:8080
}
EOF
systemctl reload caddy
ufw allow 22/tcp && ufw allow 80/tcp && ufw allow 443/tcp && ufw enable
docker compose -p activepieces up -d
Give it half a minute, then open https://flows.example.com and create your account straight away. The first sign-up owns the platform; after that, sign-up is invite-only.
Check that webhooks work
Create a flow with the Webhook trigger (Catch Webhook), add any step, publish it. The trigger panel shows the URL. Fire a test event at it:
curl -X POST https://flows.example.com/api/v1/webhooks/YOUR_FLOW_ID \
-H 'content-type: application/json' \
-d '{"event":"payment.paid","amount":16}'
You should get a 200, and the run appears under Runs as succeeded. If you get 404 instead, go back and check AP_FRONTEND_URL.
Day-two notes
- Updates. The compose file pins an exact version (
0.92.2at the time of writing). Change the tag indocker-compose.yml, thendocker compose -p activepieces pull && docker compose -p activepieces up -d. Skim the release notes first; automation tools love renaming things. - Backups. Flows, connections and run history live in the Postgres volume. Dump it on a schedule and keep the copy off the server — the connections hold your API tokens for other services.
- Code steps aren't sandboxed in this setup (
AP_EXECUTION_MODE=UNSANDBOXED). It's your server and your flows, so that's acceptable. It stops being acceptable the moment you let people you don't trust build flows.
If you already know n8n, the idea is the same — see VPS for n8n. Pick the editor you find easier to think in; both are happy on the same plans.
Related
- VPS for n8n — the other big self-hosted automation tool
- Self-host multiple services on one VPS — Activepieces next to your app and a dashboard, one IP
- VPS for Docker
- How to add swap on a VPS
- How to configure a ufw firewall
Comments
No comments yet. Be the first.