DatonTech

[Demo] Building a self-hosted automation stack

Bekzad KopelovBekzad Kopelov
·

A temporary showcase post that exercises every block type: hero, rich text, code, media, gallery, video, tables, markdown, newsletter and ad space.

[demo] Laptop on a wooden desk next to a notebook
[demo] Close-up of a laptop keyboard

Building a self-hosted automation stack

From a blank VPS to scheduled workflows, tracing and backups in one weekend.

Why self-host at all?

Hosted automation tools are great until you hit rate limits, pricing tiers, or a workflow that needs to touch a private network. Owning the stack means you decide where the data lives. This post walks through the setup I use, with the config files inline.

The best automation is the one you forget exists, until the day it saves you an hour.

What we will build

  • A Docker host with Caddy for TLS
  • n8n for workflows, backed by Postgres
  • OpenTelemetry traces shipped to a collector
  • Nightly backups to S3-compatible storage

Inline code works too: run docker compose up -d and check the logs. Docs live at n8n.io.

[demo] Developer workspace with a laptop and coffee
The whole stack runs on one small VPS.

Step by step

  1. Provision the server and harden SSH
  2. Install Docker and the compose plugin
  3. Write the compose file below
  4. Point DNS at the box and let Caddy fetch certificates

Each step is small on purpose, so a failed step is easy to retry without starting over.

docker-compose.yml
1services:
2 n8n:
3 image: n8nio/n8n:latest
4 environment:
5 - DB_TYPE=postgresdb
6 - DB_POSTGRESDB_HOST=postgres
7 ports:
8 - "5678:5678"
9 postgres:
10 image: postgres:16
11 volumes:
12 - pgdata:/var/lib/postgresql/data
13volumes:
14 pgdata: {}

Minimal compose file for n8n and Postgres.

trace.ts
import { trace } from '@opentelemetry/api'
const tracer = trace.getTracer('workflows')
export async function runStep<T>(name: string, fn: () => Promise<T>): Promise<T> {
return tracer.startActiveSpan(name, async (span) => {
try {
return await fn()
} finally {
span.end()
}
})
}
Monthly cost comparison (approximate)
OptionCostLimits
Hosted plan$5010k executions
Self-hosted VPS$8CPU-bound only
Home server$3 powerYour uplink
[demo] Minimal desk setup with a monitor

Monitoring dashboard

[demo] Laptop and phone on a white desk

Workflow editor

[demo] Laptop with code on screen beside a plant

Trace view

backup-checklist.md

Backup checklist

  • Nightly pg_dump to object storage
  • Keep 7 daily and 4 weekly copies
  • Test a restore once a month

A backup you have never restored is only a hope.

pg_dump -Fc "$DATABASE_URL" | aws s3 cp - s3://backups/n8n-$(date +%F).dump
Which workflows run where
WorkflowTriggerRuns on
RSS digestCron, 07:00n8n
Invoice exportWebhookn8n
DB backupCron, 03:00Host cron
Example embedded video.
Advertisement

Wrapping up

That is the whole stack. Start small, add tracing early, and test your restores. If you build something similar, I would love to hear about it.

[demo] Hands typing on a laptop
Back to building.

Get the next post in your inbox

One email when something new ships.

#demo#automation#self-hosting