Dynamic Subdomain Management & Automated SSL with Node.js and Certbot

Search for a command to run...

No comments yet. Be the first to comment.
Claude is incredibly good at reasoning. But reasoning is only as useful as the context available to it. Your architecture might be in GitHub. Your notes might be in Obsidian. Your decisions might be b

Mind maps are an excellent addition to an MCP ecosystem when they help users understand relationships between data, tools, and reasoning. They should complement—not replace—traditional dashboards, tab
Most AI agents today depend heavily on cloud APIs. They're fast, but every request costs money, depends on an internet connection, and sends your data to external providers. Over the weekend, I experi
How I use Fable 5 to research, build, and maintain custom Claude Code plugins, marketplaces, agents, and skills—creating reusable AI tooling that works across every project. 01 · The problem with copy

The way people search is changing. Is your site ready? For the past two decades, SEO (Search Engine Optimization) was the undisputed king of web visibility. Rank on Google's first page and you win tr
Managing multiple subdomains dynamically while keeping the URL unchanged is a common requirement for SaaS platforms, multi-tenant applications, and personal website builders. Additionally, allowing users to add their own custom domains with automatic SSL (HTTPS) certificates ensures security and trust.
In this guide, we will explore:
Dynamically mapping subdomains to specific paths using Node.js.
Handling user-provided custom domains and automatically issuing SSL certificates using Certbot.
Using a reverse proxy to serve the correct content without URL changes.
To keep the URL (nishi.hello.com) unchanged while serving content from (hello.com/nishi), we need a reverse proxy. Instead of using Nginx, we will handle everything in Node.js.
npm install express http-proxy-middleware
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
// Middleware to handle subdomains
app.use((req, res, next) => {
const host = req.hostname; // e.g., "nishi.hello.com"
const mainDomain = "hello.com";
if (host.endsWith(`.${mainDomain}`)) {
const subdomain = host.split('.')[0]; // Extract the subdomain
if (subdomain !== "www") {
return createProxyMiddleware({
target: `https://${mainDomain}`,
changeOrigin: true,
pathRewrite: { '^/$': `/${subdomain}` },
})(req, res, next);
}
}
next(); // Continue to default routes if no subdomain
});
// Default main domain route
app.get('/', (req, res) => {
res.send('Welcome to hello.com!');
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
Add an A or CNAME record for *.hello.com pointing to your server.
Now, let’s allow users to connect their own domains (userdomain.com) and issue SSL certificates automatically.
sudo apt update
sudo apt install certbot python3-certbot-nginx -y
sudo setcap 'cap_net_bind_service=+ep' $(which node)
const express = require('express');
const { exec } = require('child_process');
const fs = require('fs');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
app.use(express.json());
const domains = {}; // Store user domains and target mappings
// Route to allow users to add their own domains
app.post('/add-domain', (req, res) => {
const { domain, target } = req.body;
if (!domain || !target) {
return res.status(400).json({ error: "Domain and target are required." });
}
// Store domain mapping
domains[domain] = target;
// Run Certbot to generate SSL certificate
exec(`sudo certbot certonly --nginx -d ${domain} --non-interactive --agree-tos --email admin@${domain}`, (err, stdout, stderr) => {
if (err) {
console.error(`Error generating SSL: ${stderr}`);
return res.status(500).json({ error: "SSL setup failed." });
}
console.log(`SSL issued for ${domain}`);
res.json({ message: `Domain ${domain} added with SSL.` });
});
});
// Middleware to proxy custom domains
app.use((req, res, next) => {
const host = req.hostname; // Get requested domain
if (domains[host]) {
return createProxyMiddleware({
target: domains[host],
changeOrigin: true
})(req, res, next);
}
next();
});
// Start HTTPS Server
const https = require('https');
const options = {
key: fs.readFileSync('/etc/letsencrypt/live/example.com/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/example.com/fullchain.pem'),
};
https.createServer(options, app).listen(443, () => {
console.log("Secure server running on port 443");
});
// Start HTTP server for Certbot challenges
app.listen(80, () => {
console.log("Server listening on port 80");
});
Users can add their domain via API:
curl -X POST http://yourserver.com/add-domain \
-H "Content-Type: application/json" \
-d '{"domain": "userdomain.com", "target": "https://example.com/user"}'
✔️ userdomain.com will now load example.com/user
✔️ HTTPS is automatically enabled
Before adding a domain, users must point their domain to your server:
nslookup userdomain.com
Ensure it resolves to your server’s IP.
Let’s Encrypt certificates expire every 90 days. Set up auto-renewal:
sudo crontab -e
Add:
0 0 * * * certbot renew --quiet
This renews SSL daily at midnight.
✅ Database Storage: Store user domains in a database instead of an object.
✅ Authentication: Require API keys or user authentication.
✅ Load Balancing: Use Cloudflare or AWS Load Balancer for better scaling.
🎯 Now, we have a fully dynamic subdomain and custom domain management system in Node.js!
🚀 Users can add their domains, get SSL automatically, and have their domain proxy to the correct content.
🔐 Certbot handles HTTPS security without manual intervention.
This setup is perfect for multi-tenant apps, SaaS platforms, and website builders. Want to improve it further? Let me know in the comments! 🚀