Introduction
If you’re the kind of developer or IT tinkerer who likes to have things under your own control, running self-hosted n8n on your own machine is a fantastic option. Instead of relying on someone else’s cloud, you can spin up a local instance, secure it with HTTPS, and point a clean subdomain to it — all while keeping your workflows and data private.
This setup is especially great if you’re comfortable with a bit of hands-on work. You’ll need some basic familiarity with Docker, domain names, port forwarding, and SSL certificates to, but nothing too overwhelming. Once you understand the flow, it’s actually a pretty smooth process.
The best part? Running n8n locally is free. You’ll only need to pay for your domain name (if you don’t already own one). In this guide, we’ll walk through creating a subdomain, pointing it to your local host, generating a trusted SSL certificate with Let’s Encrypt, and configuring self-hosted n8n to serve securely over HTTPS.
By the end, you’ll have your very own developer-grade automation platform running at something like n8n.yourdomain.com — ready to handle webhooks and workflows just like a cloud service, but with full ownership and zero monthly hosting bills.
Prerequisites
Before we roll up our sleeves and start spinning up containers, let’s make sure you have a few basics covered. This setup isn’t plug-and-play for absolute beginners — it’s aimed at folks who have a little bit of developer or IT background. You don’t need to be a DevOps wizard, but some familiarity will make the process a whole lot smoother.
Here’s what you’ll need to have ready:
- A domain name — This is the only thing that may cost you a bit of money. You’ll use it to create a subdomain like
n8n.yourdomain.comso your local instance can be reached via domain name from anywhere. You can get one from godaddy.com. - Access to your DNS provider — You should have this access with the domain named purchased , so you can add or edit DNS records (A or CNAME) for your subdomain.
- A Linux machine to run self-hosted n8n (preferred). Ubuntu 24.04 would do just fine.
- Docker and Docker Compose installed on your machine — n8n runs beautifully in a container, and Docker makes it easy to keep things clean and isolated.Refer to here to get it installed.
- A server or local machine (Linux like Ubuntu will do) with:
- Access to your home modem/router – to configure port forwarding and firewall rules
- A basic understanding of SSL/TLS certificates — nothing too deep, just enough to know what they are and where they go.
- A bit of comfort using the command line.
If you can check off that list, you’re in a great spot. The rest of this guide will walk you through each step, from creating a subdomain to seeing your very own secure n8n instance live on the web.
Create a Subdomain for Self-Hosted n8n
First things first — we need a place on the internet to point to your local n8n instance. The cleanest way to do that is by creating a subdomain like n8n.yourdomain.com. Think of it as giving your local server its own front door on the web.
<<Please note>> You need to have already purchased a domain name from a DNS provider such as godaddy.com prior to creating a subdomain for n8n. This is one of the prerequisites above.
Log in to your DNS provider
This is where you manage your domain name.
This could be Cloudflare, GoDaddy, Namecheap, or wherever your domain lives.
Create a new DNS record.
- Type: A
- Name:
n8n(or whatever you want your subdomain to be) - Value: your server’s public IP address (or the IP of the machine where n8n will run)
- TTL: you can leave the default or set something like
3600seconds.
Save your changes and give DNS a bit of time to propagate.
If your machine is behind a home router, make sure you’ve set up port forwarding for ports 80 (HTTP) and 443 (HTTPS) to your local machine. This step is crucial for receiving traffic from the outside world — and for Let’s Encrypt to issue a valid SSL certificate.
If you are unsure of your public IP, you can simply Google “What is my IP“, and you it should see an IPv4 address that is accessible publicly. This is the address you will use in creating a new DNS record above.
<<Important>> If your machine is behind a home router, your modem’s public IP address may change if it reboots. If that is the case, you will need a dynamic DNC service to update this IP address automatically when it changes. This is out of the scope of this guide. Please keep that in mind!
By the end of this step, your subdomain should be pointing straight to your server. Nothing fancy will show up yet — but that’s exactly what we’ll fix in the next steps.
Run Self Hosted n8n with Docker (Using a Dedicated Volume)
Let’s set up n8n in a way that keeps your data safe, clean, and easy to manage. Instead of mounting a folder from your host machine, we’ll create a named Docker volume just for n8n.
This gives your workflows, credentials, and settings a nice, isolated home — and makes future upgrades much smoother.
Create a dedicated Docker volume
docker volume create n8n_data
This creates a persistent storage volume that lives outside the container’s lifecycle.
Run n8n with the named volume attached
docker run -it --rm \
--name n8n \
-p 5678:5678 \
-v n8n_data:/home/node/.n8n \
docker.n8n.io/n8nio/n8n
Here’s what’s happening:
-p 5678:5678exposes n8n on port 5678.-v n8n_data:/home/node/.n8nmounts the named volume so your data survives container restarts.--rmcleans up the container when you stop it (but not the volume).--name n8ngives the container a nice, easy-to-reference name.docker.n8n.io/n8nio/n8nis the official n8n image from the n8n Docker registry.
Check if n8n is running
docker ps
then open your favorite browser and navigate to this URL:
http://localhost:5678
If all goes well, you’ll see the n8n UI up and running
Optional: You can stop or restart the container anytime with:
docker stop n8n # or docker restart n8n
or redeploy with different parameters to the original run command — your workflows and credentials will still be there because they live in the n8n_data volume.
Next, we’ll add a secure front door to your instance with HTTPS by grabbing a free SSL certificate from Let’s Encrypt.
Get an SSL Certificate with Let’s Encrypt
Right now, your self-hosted n8n instance is running locally over plain HTTP. That’s fine for testing on your own machine — but once you want to expose it to the internet, you really need HTTPS.
Why? Because many third-party APIs — including Google and Telegram Messenger LLP — will reject any webhook or callback to an unsecured endpoint. They only communicate with trusted and valid HTTPS URLs backed by a recognized Certificate Authority. Using Let’s Encrypt is a quick and free way to get that trust without buying a commercial certificate.
Here’s how to set it up
Install Certbot
Certbot is the easiest way to get and manage Let’s Encrypt certificates.
On Ubuntu or Debian:
sudo apt update sudo apt install certbot
If you’re on a different OS, check the official Certbot instructions for your environment.
Make sure ports 80 and 443 are open
Let’s Encrypt needs to verify your subdomain by connecting to your server.
- On a home network, port forward ports 80 and 443 to your machine. This requires you to login to your modem and find the port forwarding setting. Consult your modem’s manual on how to add a port-forwarding rule.
- You need to find out the local IP address of machine that will host n8n, on Ubuntu, you can find it out with
ifconfigcommand. - You should set a static lease for this machine so your modem always leases the same IP address to it
- and then you will add port forward rules for ports 80 and 443 to this machine.
- You need to find out the local IP address of machine that will host n8n, on Ubuntu, you can find it out with
- A Linux machine like Ubuntu comes with a firewall, so let’s make sure the ports are allowed:
sudo ufw allow 80 sudo ufw allow 443
This step is critical — if Let’s Encrypt can’t reach your server, it can’t issue the certificate.
Request the SSL certificate
Run Certbot in standalone mode
sudo certbot certonly --standalone -d n8n.yourdomain.com
Replace n8n.yourdomain.com with your real subdomain.
If everything checks out, you’ll get a valid certificate issued by Let’s Encrypt, stored by default in:
/etc/letsencrypt/live/n8n.yourdomain.com/
The important files are:
fullchain.pem— your certificate + CA chainprivkey.pem— your private key
Verify your files
Check your cert directory:
sudo ls -l /etc/letsencrypt/live/n8n.yourdomain.com/
You should see:
cert.pem chain.pem fullchain.pem privkey.pem README
These files are what we’ll mount into the Docker container to enable HTTPS.
<<Please Note>> Let’s Encrypt certificates expire every 90 days. We’ll set up automatic renewal later so you don’t have to worry about it.
By the end of this step, you have a valid and trusted SSL certificate that will make your n8n subdomain behave like any other secure production service — ready to receive API calls from the outside world.
Configure n8n with HTTPS
You’ve got your shiny new SSL certificate from Let’s Encrypt — now let’s actually use it to make self-hosted n8n accessible over a secure, trusted HTTPS connection.
This step is important not just for encryption, but also for trust:
Platforms like Google and Telegram Messenger LLP will flat-out reject webhooks that don’t use a valid, trusted HTTPS endpoint. Self-signed certs won’t work here.
We’ll configure n8n to serve HTTPS traffic directly using the certificate and private key you just generated.
Stop any running n8n container
If you still have the previous container running, stop it first:
docker stop n8n
This will cleanly shut it down (since we used --rm, it’ll also remove the container but keep your data in the n8n_datavolume).
Mount the certificate and key
Your certs should be at:
/etc/letsencrypt/live/n8n.yourdomain.com/
These files are:
- owned by root
- locked down with strict permission
- not directly readable inside a docker container
So instead of mounting them directly, it’s a better (and safer) practice to make a copy of the certificate and private key into a dedicated folder with proper permissions for n8n.
First, create a folder to store the copied certs:
sudo mkdir -p /opt/n8n/certs
Then copy the certificate and key:
sudo cp /etc/letsencrypt/live/n8n.yourdomain.com/fullchain.pem /opt/n8n/certs/server.crt sudo cp /etc/letsencrypt/live/n8n.yourdomain.com/privkey.pem /opt/n8n/certs/server.key
Next, set the correct permissions:
sudo chown root:docker /opt/n8n/certs/server.* sudo chmod 640 /opt/n8n/certs/server.*
What this does:
- Keeps the original Let’s Encrypt files secure
- Ensures the n8n container can read the cert and key
- Reduces the chance of accidental permission errors during container startup
Finally, mount the copied certs into your n8n container:
docker run -d \ --name n8n \ -p 443:5678 \ -v n8n_data:/home/node/.n8n \ -v /opt/n8n/certs/server.crt:/certs/server.crt:ro \ -v /opt/n8n/certs/server.key:/certs/server.key:ro \ -e N8N_PROTOCOL=https \ -e N8N_HOST=n8n.yourdomain.com \ -e WEBHOOK_URL=https://n8n.yourdomain.com \ -e SSL_CERT=/certs/server.crt \ -e SSL_KEY=/certs/server.key \ docker.n8n.io/n8nio/n8n
Here’s what’s new:
-p 443:5678means any incoming traffic on port 443 on your machine will be routed to port 5678 inside the docker container.-v ...server.crtand-v ...server.keymount your SSL cert and key.-e N8N_PROTOCOL=httpstells n8n to serve HTTPS.-e N8N_HOSTsets the hostname (important for generating correct webhook URLs in n8n).-e SSL_CERTandSSL_KEYpoint n8n to your cert files.
Visit your secure subdomain
Open your browser and head to:
https://n8n.yourdomain.com
If everything’s set up correctly, you should see a valid HTTPS connection with the green padlock (or equivalent).
You can also verify with:
curl -I https://n8n.yourdomain.com
You should get a 200 OK response with no SSL errors.
At this point, your self hosted n8n instance is:
- Running locally in Docker
- Accessible through a clean subdomain
- Protected by a trusted HTTPS certificate
If not, review the steps above, or send me a message so I could help you out.
Next up, we’ll make sure your certs stay fresh and don’t expire by setting up automatic renewal.
Set Up Automatic SSL Renewal
Right now your n8n instance is secured with a valid HTTPS certificate from Let’s Encrypt, but Let’s Encrypt certificates expire every 90 days.
If you don’t renew them, your nice shiny green padlock will suddenly turn into a scary browser warning and external services like Google or Telegram Messenger LLP will stop sending webhooks to your instance.
Check that Certbot is already installed
We installed Certbot earlier, but let’s double-check it’s available:
certbot --version
If you get a version number, you’re good to go. If not, just reinstall it:
sudo apt update sudo apt install certbot
Run a renewal Test
Before automating anything, make sure renewal works cleanly:
sudo certbot renew --dry-run
This simulates the renewal process without making any real changes. If it says “Congratulations, all renewals succeeded,” you’re good to move on. If it fails, double-check the following:
- That ports 80 and 443 are open
- DNS is resolving correctly for your subdomain
- Your server can reach Let’s Encrypt’s servers
Set up Cron Job for Auto Renewal
Let’s Encrypt recommends renewing about every 60 days. On most systems, Certbot already sets up a daily systemd timer, but you can also add your own cron job for extra assurance.
Open cron editor
sudo crontab -e
And add
0 3 * * * certbot renew --quiet && cp /etc/letsencrypt/live/n8n.yourdomain.com/fullchain.pem /opt/n8n/certs/server.crt && cp /etc/letsencrypt/live/n8n.yourdomain.com/privkey.pem /opt/n8n/certs/server.key && chown root:docker /opt/n8n/certs/server.* && chmod 640 /opt/n8n/certs/server.* && docker restart n8n
Here’s what it does:
- Runs at 3:00 AM every day
- Silently renews the certificate if needed
- Copy the certificate and the key files to /opt/n8n/certs
- Update the permissions
- Restart the n9n container so it picks up the new certificate
The much better way is to move the commands to a dedicated bash script and have the cron call the script instead. I will leave that to you. 😀
Access n8n Securely and Publicly
With everything setup, your self-hosted n8n should be accessible via your sub domain via https, you can now go ahead and register a new account and get started with creating your own AI agent!


Summary
Running n8n on your own machine gives you full control, zero hosting cost, and the ability to build powerful automations under your own domain. Here’s what we covered:
- Set Up Your Environment
- Make sure you own a domain name and can configure DNS.
- Prepare basic tools: Docker, port forwarding, and SSL knowledge.
- Use a Subdomain for n8n
- Create a subdomain like
n8n.yourdomain.comand point it to your server’s public IP.
- Create a subdomain like
- Deploy n8n in Docker with Persistent Storage
- Create a dedicated volume using:
docker volume create n8n_data - Run the container with mounted storage so your workflows survive restarts.
- Create a dedicated volume using:
- Secure with HTTPS Certificates
- Use Let’s Encrypt to issue free SSL certificates.
- Make a safe copy of
fullchain.pemandprivkey.peminto/opt/n8n/certs. - Set proper permissions and mount these files into the container.
- Configure Firewall & Port Forwarding
- Open and forward ports 80 and 443 to your server to allow certificate issuance and secure traffic.
- Automate Certificate Renewal
- Schedule
certbot renewwith a cron job. - Use a simple shell script to copy the new certs, fix permissions, and restart the n8n container.
- This ensures your site stays valid and trusted.
- Schedule
- Why HTTPS Is Crucial
- APIs like Google, Telegram Messenger LLP, Slack, and Stripe require trusted HTTPS endpoints.
- Without a valid cert, webhooks will fail.
- Ready to Build!
- Test your domain at
https://n8n.yourdomain.com. - and build your automations confidently.
- Test your domain at

Hi, I’m Cary — a tech enthusiast, educator, and author, currently a software architect at Hornetlabs Technology in Canada. I love simplifying complex ideas, tackling coding challenges, and sharing what I learn with others.