I Followed That Tutorial Exactly. Here Is What Happened Next.
The Docker container came up clean. I know because I watched the logs scroll past in the terminal, the n8n startup sequence printing each service initialisation in order, database connection established, encryption key loaded, server listening on port 5678. I opened the browser, typed localhost:5678, and the n8n interface loaded. I felt the specific satisfaction of a thing that was supposed to work, working. I had followed the tutorial carefully. Everything was correct.
The webhooks did not work. None of them. Ever.
It took me the better part of a day to understand why, and the reason is something that the tutorial that has been shared two hundred thousand times, the one everyone links in the Discord when someone asks how to get started, handles in a single line near the bottom of the setup section. It says to set the WEBHOOK_URL environment variable to your public domain. What it does not say, because it is written by someone for whom this is obvious, is that if you do not set this variable, n8n generates webhook URLs using whatever host it detects from the incoming request, which inside a Docker container on a remote server is typically the container’s internal hostname or localhost, neither of which is reachable from the internet, and both of which will accept a test execution inside the n8n interface because the test runner is making the request from inside the same network, and will fail silently in production because the external service sending the webhook payload gets a connection refused on a URL that resolves to nothing.
So the tutorial is not wrong. It is just written in a sequence that puts the critical information after the moment of apparent success, which is the most dangerous place to put critical information, because most people stop reading carefully once the thing appears to be working.
I want to be fair about what that tutorial actually does well, because I have seen people dismiss it for not covering production edge cases when its stated purpose is to get someone from zero to a running instance on a weekend, and for that it is genuinely solid. The Docker Compose structure it uses is clean. The environment variable conventions are correct. The volume mounting for persistent data is handled properly in the current version, which was not always true of earlier iterations where a container restart would wipe your workflows and credentials and you would discover this the hard way on a Monday morning. The explanation of why you need an external database for anything beyond personal use, rather than the default SQLite, is clear and honest and correct.
What no tutorial of this type can fully cover, because the problems only exist in context, is the reverse proxy layer. My setup uses nginx in front of n8n, which is standard, and the tutorial covers this with a configuration block that works correctly for basic setups. What it does not cover is what happens when your nginx configuration has a location block that does not pass the original host header through to n8n, because then n8n receives requests that look like they are coming from localhost even when they are arriving from your public domain, and the WEBHOOK_URL environment variable you carefully set is correct but n8n is still generating internal URLs for certain operations because the host detection is happening upstream of the environment variable check. I spent three hours on this. The fix was adding proxy_set_header Host $host to the nginx location block. Four tokens. Three hours.
The SSL situation has its own chapter. Certbot works as described. The initial certificate issues without problems. What the tutorial does not mention is that the certbot auto-renewal cron job, in certain Docker setups, will renew the certificate successfully but not reload nginx, because the reload command references the nginx process outside the container and the signal does not propagate correctly into the containerised nginx service. Your certificate expires. Your instance goes HTTPS-dark. Your production workflows that authenticate via webhook start failing with SSL errors that are logged on the client side, not on yours, and you find out because a client asks why their Typeform submissions stopped processing four days ago.
Make.com, for what it is worth, does not have this problem, because Make.com’s SSL infrastructure is their problem and not yours. That is a real advantage if you are billing for reliability rather than for control. The people who recommend n8n self-hosting for every use case regardless of the client’s technical tolerance are not being honest about the maintenance surface you are taking on. There are clients for whom a fifty-dollar-a-month Make.com bill is cheaper than the actual cost of my time when something breaks at the infrastructure layer.
What the 200,000 shares tell you is that the tutorial answers a real question well. What they do not tell you is which question it answers. It answers: how do I get n8n running in a container. It does not answer: how do I run n8n reliably in production for workflows that other people depend on. Those are related questions but they are not the same question, and the gap between them is where the real work lives.
The tutorial is the beginning of the education. The volume mounting error at 3am that takes down a client’s lead intake workflow is the rest of it. Do not mistake finishing the tutorial for being ready for production. Nobody who has actually run this in production would make that mistake twice.
Olaitan Oladipo holds a BSc in Sociology from Olabisi Onabanjo University. He is a self-taught automation builder who has spent years inside n8n doing the work that most tutorials skip: debugging OAuth errors at 2am, migrating client automations from Make.com mid-project, fighting reverse proxy misconfigurations on AWS EC2, and figuring out through trial and error what actually holds up in production versus what only looks clean in a demo.
He is not a developer by training and not a SaaS founder. He is the person in the Discord server who actually answers the question instead of linking to the docs.
His writing on n8n Automation Tutorial covers self-hosting, AI agent workflows, tool comparisons, and the security vulnerabilities the automation industry would rather not discuss. He has built AI-assisted invoice approval flows using OpenAI function calling, connected Claude via HTTP Request nodes, and holds considered opinions about Zapier, Make.com, LangChain, and CrewAI that their marketing teams would not appreciate.
He writes for people who are technical enough to follow a tutorial but experienced enough to want the honest version.
