{"id":51413958,"url":"https://github.com/kfuras/n8n-production-platform","last_synced_at":"2026-07-04T17:05:44.843Z","repository":{"id":360939760,"uuid":"1126609340","full_name":"kfuras/n8n-production-platform","owner":"kfuras","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-05T08:07:11.000Z","size":80,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-05T09:03:24.745Z","etag":null,"topics":["docker","docker-compose","n8n","traefik"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kfuras.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-02T08:50:49.000Z","updated_at":"2026-06-05T07:01:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/kfuras/n8n-production-platform","commit_stats":null,"previous_names":["kfuras/n8n-production-platform"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/kfuras/n8n-production-platform","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kfuras%2Fn8n-production-platform","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kfuras%2Fn8n-production-platform/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kfuras%2Fn8n-production-platform/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kfuras%2Fn8n-production-platform/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kfuras","download_url":"https://codeload.github.com/kfuras/n8n-production-platform/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kfuras%2Fn8n-production-platform/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35129344,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-04T02:00:05.987Z","response_time":113,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-compose","n8n","traefik"],"created_at":"2026-07-04T17:05:44.183Z","updated_at":"2026-07-04T17:05:44.834Z","avatar_url":"https://github.com/kfuras.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# N8N Production Stack with Self-Hosted Toolkit\n\n[![n8n](https://img.shields.io/badge/n8n-EA4B71?style=for-the-badge\u0026logo=n8n\u0026logoColor=white)](https://n8n.io/)\n[![Traefik](https://img.shields.io/badge/Traefik-24A1C1?style=for-the-badge\u0026logo=traefikproxy\u0026logoColor=white)](https://traefik.io/)\n[![PostgreSQL](https://img.shields.io/badge/PostgreSQL-4169E1?style=for-the-badge\u0026logo=postgresql\u0026logoColor=white)](https://www.postgresql.org/)\n[![Docker](https://img.shields.io/badge/Docker-2496ED?style=for-the-badge\u0026logo=docker\u0026logoColor=white)](https://www.docker.com/)\n[![Hetzner](https://img.shields.io/badge/Hetzner-D50C2D?style=for-the-badge\u0026logo=hetzner\u0026logoColor=white)](https://www.hetzner.com/cloud)\n\nSelf-hosted n8n automation stack on a single Hetzner VPS. This repo holds the\nDocker Compose stack (the deployment payload). Provisioning and deployment are\nhandled by the companion Infrastructure-as-Code repo\n[**n8n-hetzner-deploy**](https://github.com/kfuras/n8n-hetzner-deploy)\n(OpenTofu + Ansible). All external traffic terminates at Traefik v3 with\nautomatic Let's Encrypt TLS.\n\n---\n\n## What Gets Created\n\n- **N8N** - Workflow automation platform with a dedicated PostgreSQL database\n- **Traefik** - Reverse proxy with automatic SSL certificates via Let's Encrypt\n- **Optional Services** - BaseRow, NocoDB, MinIO, Kokoro TTS, NCA Toolkit, Postiz (toggled per deployment)\n- **Ubuntu server** with Docker and security hardening (provisioned by the deploy repo)\n- **Pinned, auto-updated images** - the n8n version is pinned and bumped weekly by CI (see below)\n\n---\n\n## Cost Comparison\n\n| Service                   | SaaS Monthly Cost | Self-Hosted      | Savings          |\n|---------------------------|-------------------|------------------|------------------|\n| TTS (ElevenLabs/OpenAI)   | $22-$330         | $0 (Kokoro)      | $22-$330        |\n| Storage (AWS S3)          | $23+             | $0 (MinIO)       | $23+            |\n| Automation (Zapier)       | $20-$600         | $0 (n8n)         | $20-$600        |\n| Video processing (API)    | $15-$250         | $0 (NCA Toolkit) | $15-$250        |\n| Database (Airtable)       | $20-$54          | $0 (NocoDB/Baserow) | $20-$54      |\n| Social publishing (Buffer)| $6-$120          | $0 (Postiz)      | $6-$120         |\n| **Total**                 | **$106-$1,674/mo**| **EUR 9.99/mo** | **$96-$1,664/mo** |\n\nRuns on a single Hetzner VPS (from EUR 9.99/month) with 20 TB traffic included.\n\n---\n\n## How It's Deployed\n\nDeployment is **pull-based Infrastructure-as-Code**, driven entirely from the\n[n8n-hetzner-deploy](https://github.com/kfuras/n8n-hetzner-deploy) repo:\n\n1. **OpenTofu** provisions the Hetzner server, firewall, and DNS expectations.\n2. **Ansible** (`make deploy`) configures the host, clones this repo onto the\n   server, generates secrets, and brings the stack up with Docker Compose.\n3. Re-running `make deploy` is **idempotent** - it fast-forwards the server to\n   the latest commit of this repo only when there is something new, then\n   reconciles the running containers.\n\nYou do not deploy from this repo directly; you change the stack here, and the\ndeploy repo rolls it out.\n\n### Secrets\n\n- Secrets are **generated on the server** on first deploy (`openssl rand`) and\n  written to `~/stack/.env` with `0600` permissions.\n- **No real secrets are committed to git** - only [`secrets/production.env.example`](secrets/production.env.example), the template of expected keys.\n- The `N8N_ENCRYPTION_KEY` is the critical value: if lost, stored n8n\n  credentials become unreadable. Back it up off-server (e.g. a password\n  manager) after the first deploy.\n- See the deploy repo for how secrets and per-service values are seeded.\n\n### Configure (keys you set)\n\nIn the deploy repo's variables / on first run:\n\n- `DOMAIN` - your domain name\n- `HOME_IP` - your IP address (used for optional service allowlisting)\n- (Optional) `SKOOL_EMAIL`, `SKOOL_PASSWORD`, `SKOOL_GROUP_ID` - for personal Skool automation workflows\n\nAfter DNS propagates, open `https://n8n.yourdomain.com`.\n\n---\n\n## Automated n8n Updates\n\nA weekly GitHub Action ([`.github/workflows/update-n8n.yml`](.github/workflows/update-n8n.yml))\nkeeps the pinned n8n image current:\n\n- Runs Mondays 06:00 UTC (plus manual `workflow_dispatch`).\n- Checks Docker Hub for the newest **stable** `n8nio/n8n` tag (ignores `latest`/`next`/`nightly`/`-rc`).\n- If newer than the pinned tag, it bumps `docker-compose.yml`, opens a PR, and auto-merges it.\n- This only updates the repo; the new version rolls out on the next `make deploy`.\n\n---\n\n## Service URLs\n\n- **N8N**: `https://n8n.yourdomain.com` (UI and webhooks)\n- **BaseRow**: `https://baserow.yourdomain.com`\n- **NocoDB**: `https://nocodb.yourdomain.com`\n- **MinIO Console**: `https://minio-console.yourdomain.com`\n- **Postiz**: `https://postiz.yourdomain.com`\n\n(Only the subdomains for enabled services are routed.)\n\n---\n\n## Day-to-Day Operations\n\n### Modify the stack\n\n```bash\n# Edit a compose file, then commit and push\nnano docker-compose.yml\ngit commit -am \"Update stack\"\ngit push\n# Roll out from the deploy repo:\n#   cd ../n8n-hetzner-deploy \u0026\u0026 make deploy\n```\n\n### Rotate or change a secret\n\nSecrets live in `~/stack/.env` on the server (not in git). SSH to the host,\nedit the value, and restart:\n\n```bash\nnano ~/stack/.env\ndocker compose --env-file ~/stack/.env up -d\n```\n\n### View logs\n\n```bash\ndocker compose logs -f n8n-core\ndocker compose ps\n```\n\n---\n\n## Security\n\n- **No secrets in git** - only a template of expected keys is committed; real values are generated server-side.\n- **TLS everywhere** - Traefik v3 with automatic Let's Encrypt certificates.\n- **Host hardening** - SSH key-only auth and firewalling, provisioned via cloud-init in the deploy repo.\n- **Optional IP allowlisting** - sensitive service subdomains can be restricted to `HOME_IP`.\n- **Least exposure** - `.env` is `0600`; Ansible secret tasks use `no_log` so values never appear in deploy output.\n\n\u003e Note: Docker requires a plaintext `.env` at runtime, so secrets exist in\n\u003e cleartext on the host while containers run. This is inherent to self-hosted\n\u003e compute and is mitigated by least-privilege host access, not eliminated.\n\n---\n\n## Use Cases\n\n- Automated video content creation\n- AI-powered Telegram assistant\n- Email and calendar automations\n- Batch data processing\n- High-volume text-to-speech (300+ requests/day)\n- No-code database applications\n- Social media content scheduling\n\n---\n\n## Links\n\n- [Blog](https://kjetilfuras.com)\n- [LinkedIn](https://www.linkedin.com/in/kjetil-furas/)\n\n---\n\nBuilt by Kjetil Furås. Questions? Open an issue.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkfuras%2Fn8n-production-platform","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkfuras%2Fn8n-production-platform","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkfuras%2Fn8n-production-platform/lists"}