Publish a domain with HTTPS on your VPS: nginx, certificates, and the daily 502

Published on 2026-08-25 by frfrand

Cómo publicar un dominio en un VPS con certificado SSL: qué hace realmente Let's Encrypt, por qué el orden de los pasos importa, cómo leer los logs de nginx para diagnosticar un 502 y cómo hacerlo todo conversando con una IA. Cubre crear_dominio_vps, verificar_dominio_vps, activar_dominio_vps, ver_nginx_dominio_vps, editar_nginx_dominio_vps y ver_logs_nginx_vps.

Publish a domain with HTTPS on your VPS: nginx, certificates, and the daily 502

Putting a domain into production with HTTPS is a few steps that are almost always done in the wrong order, and that's where the frustration comes from: the certificate fails, a 502 appears, and no one knows if the problem is the DNS, the proxy, or the application.

In ArduMaker there is also a twist that explains most of the stumbling blocks, and this guide covers it first: your VPS is a container inside a shared parent host, and the three things needed to publish a domain —the certificate, the edge nginx, and the port redirection— live on that host, not on your machine. Understanding where each thing happens makes the rest almost obvious.

Tools covered: crear_dominio_vps, listar_dominios_vps, verificar_dominio_vps, activar_dominio_vps, eliminar_dominio_vps, ver_nginx_dominio_vps, editar_nginx_dominio_vps, ver_logs_nginx_vps, and from the neighboring area listar_redirecciones_vps and crear_redireccion_vps, which in practice are part of the same procedure.

All of them take company_id in addition to vps_id. If you don't know which one it is, listar_empresas tells you, and ver_contexto_inicial returns all the companies, projects, and VPSs your session can see at once.

First things first: your VPS is not alone on the machine

Almost everything that confuses you when publishing a domain on ArduMaker is clarified by understanding one single thing: there are two layers, and you manage the top one.

The parent host. It is the physical, shared machine, with the public IP. There live three things you never touch: the edge nginx that terminates HTTPS, the certificates (certbot runs there, not on your VPS) and the port redirects that connect the world with your machine. You do not have access to that layer, and it is on purpose: it is shared with other clients.

Your VPS. It is an LXC container inside that host. There run your applications, your systemd services, your tasks, your Linux users and, if you want, your own internal nginx. All of that is yours and you manage it entirely.

The practical consequence, and it is the most important of this guide:

Your VPS does not have its own public IP. The IP that the internet sees is the parent host's IP, shared. What makes your application reachable is not the IP: it is a port redirect. The host opens one of its ports and connects it against a port inside your container.

internet  →  IP del host padre  →  nginx de borde (TLS)  →  127.0.0.1:<puerto del host>
                                                                    ↓  redirección
                                                          tu VPS  →  127.0.0.1:<puerto del container>

Each VPS also starts with its own DNS name, in the style <slug>.arducloud.com, with an A record pointing to the parent host's IP. That name is the one you later use as destination when connecting a custom domain.

Keep the diagram in mind. The three most common errors in this guide are, at their core, the same error: confusing the internal port of the VPS with the host port.

Two different paths, and it's good to know which one you're on

Publishing a domain is not a single procedure: there are two, and they behave very differently.

Path A — a subdomain of ArduMaker's default zone

This is the short path. crear_dominio_vps creates, in ArduMaker's zone in Cloudflare, a proxied CNAME that points to your VPS's DNS name. You don't need to touch any registrar.

And here's what almost nobody knows: in this path no certificate is issued. The domain is covered by the default zone's certificate, which already exists on the parent host. That's why there's also no prior DNS verification, no ACME validation, and no Let's Encrypt weekly limits to respect. You activate it and it works.

Two form restrictions worth knowing in advance, because the tool rejects them: the subdomain can have one or two parts (app.arducloud.com or app.cliente.arducloud.com, no more), and each part needs at least 3 alphanumeric characters.

Path B — your own domain

Here the order matters, and a lot.

activar_dominio_vps runs certbot certonly --standalone on the parent host. "Standalone" means certbot itself spins up a server on port 80 to respond to Let's Encrypt's challenge: to do so, it stops nginx, issues the certificate, and restarts it. It's not a file served by your application at /.well-known/acme-challenge/ — your VPS plays no role in the validation at all.

From this it follows the same thing the classical order said, but for the right reason: Let's Encrypt will query your domain's DNS and hit the IP it finds. If that IP is not the parent host where certbot runs, validation fails. DNS first, activation second. And yes: failed attempts count against the weekly per-domain limit.

The correct order, then:

  1. Point the domain, with an A record to the parent host IP or —more conveniently— with a CNAME to the VPS DNS name (<slug>.arducloud.com).
  2. Verify with verificar_dominio_vps before activating.
  3. Activate with activar_dominio_vps, which issues the certificate and writes the edge nginx.

A warning about verificar_dominio_vps: it is more permissive than it seems. If the name resolves to the host IP, it returns OK (a_record). If it resolves via CNAME to the VPS name, it also returns OK (cname). But if it resolves to any other IP —the typical case of a domain proxied by Cloudflare, where the world sees Cloudflare's IPs and not yours— it also returns OK, marked as proxy_forwarded. The only case that truly fails is when the name does not resolve to anything.

In other words: an OK from verificar_dominio_vps confirms that the name exists in DNS, not that it always reaches your host. If the domain is proxied and the orange cloud points to another server, the verification passes and the certificate still fails. When in doubt, check the verify_method it returns: proxy_forwarded means "I couldn't verify it", not "it's fine".

Other tools in the area:

listar_dominios_vps shows which domains of the edge nginx correspond to this machine. It matches them by host port, and for each domain it tells you which host port it points to and —the useful piece of data— which port inside the container that host port corresponds to (puerto_in_vps). It's the fastest way to reconstruct the full path of a published site.

eliminar_dominio_vps performs the removal: it deletes the DNS record if it was under the default zone and cleans up the edge nginx configuration. It does not delete the certificate — the response states this explicitly (ssl_cert_deleted: false). If you publish the same name again later, the certificate is still there.

The errors you will see, and what each one means

When something fails after publishing, the error code tells you quite a bit more than it seems.

502 Bad Gateway — nginx is alive, but there's no one on the other side. The most frequent and the least understood. Nginx received the request, tried to forward it, and got no response. In this architecture, the 502 has an extra cause that doesn't exist on a common server: the application may be perfect, and what's missing is the redirection. The edge nginx points to a host port; if that port isn't connected to the correct port inside the container, the 502 appears even if your app is listening flawlessly. Before touching the app, check listar_redirecciones_vps.

504 Gateway Timeout — the application is alive but takes too long. Nginx connected, but there was no response in time. A local clarification: the edge nginx already comes with timeouts of 360 seconds. If you get a 504, it's not that the timeout is too short — six minutes without responding is a stuck query or a blocked process, and that's where you need to look.

404 serving the wrong site — you're missing the server_name. If when entering your domain you see another site, nginx didn't find a block matching that name and fell back to the default site. It's a server_name problem, not a DNS problem.

Invalid or "not secure" certificate in the browser. The certificate covers exactly the names for which it was issued. If it was issued for midominio.com and you access www.midominio.com, the browser rightly protests.

The three nginx tools, and which is which

Here is the misunderstanding that wastes the most time, so it's worth saying it straight: these tools do not all operate on the same nginx.

activar_dominio_vps, listar_dominios_vps and eliminar_dominio_vps work on the edge nginx, on the parent host. It is the one that terminates HTTPS and decides which host port each domain goes to. There is no tool to read or manually edit that file: it is managed with activar_dominio_vps and nothing else. You also cannot read its logs.

ver_nginx_dominio_vps, editar_nginx_dominio_vps and ver_logs_nginx_vps work on the nginx inside your VPS. That one is entirely yours: they read and write /etc/nginx/sites-available/<dominio>.conf inside the container, and the logs they return are /var/log/nginx/<dominio>_access.log and _error.log, also inside the container.

The practical consequence, in two points:

  • If you published a domain only with activar_dominio_vps, ver_logs_nginx_vps won't find anything. Those log files exist only if your VPS's internal nginx serves that domain and declares them. It's not a tool error: it's that the traffic is being logged by the edge nginx, in a layer you don't have access to.
  • editar_nginx_dominio_vps does not change which host port the edge points to. If you want a published domain to point to another application, what you need to change is the redirection or reactivate the domain against another host port, not rewrite the file from inside.

When to use each path, then:

  • One domain, one application, one port → activar_dominio_vps and you're done. You don't need nginx inside the VPS for anything.
  • Multiple routes, multiple apps, custom rules behind the same domain → activate the domain against the port where your internal nginx listens, and use editar_nginx_dominio_vps for all fine routing. There ver_logs_nginx_vps will give you logs, because yours is the one serving.

About editar_nginx_dominio_vps: it is a complete file replacement, not a patch. Always ask the AI to first read the current configuration, apply the change to that content, and write the entire result. What it does include is a safety net worth knowing: before writing it makes a backup, then validates with nginx -t and reloads, and if validation or reload fails it reverts on its own —file and symlink— and returns the nginx error to you. You won't be left without nginx on the VPS due to a syntax error.

A detail that saves useless work: the edge nginx already comes with client_max_body_size 100M, WebSocket headers (Upgrade / Connection) and X-Forwarded-* headers set. If your problem is that large files cannot be uploaded or a WebSocket does not connect, that is already solved at the edge: what may be limiting it is your internal nginx or the application, not the layer you don't see.

TÚ: Publicá app.cliente.com en el VPS 9, la app corre en el 3000.

IA: listar_redirecciones_vps(company_id = 3, vps_id = 9) -> no hay ninguna redirección contra el puerto 3000

"Ojo con un paso que falta. Tu app escucha en el 3000 adentro del container, pero el nginx que termina el HTTPS vive en el host padre y solo sabe hablar con puertos del host. Necesito crear la redirección primero, si no el dominio queda publicado contra el puerto equivocado y vas a ver un 502."

TÚ: Dale.

IA: crear_redireccion_vps(company_id = 3, vps_id = 9, container_port = 3000) -> { "host_port": 21874, "container_port": 3000, "protocol": "tcp" }

verificar_dominio_vps(company_id = 3, vps_id = 9, domain = "app.cliente.com") -> el nombre no resuelve

"El dominio todavía no apunta a ningún lado. Antes de activar hay que apuntarlo: un A a la IP del host padre, o —más cómodo— un CNAME a <slug>.arducloud.com, que ya tiene el A correcto.

Si activo ahora, certbot corre en el host, la validación de Let's Encrypt no encuentra el dominio y el intento fallido cuenta contra el límite semanal."

[más tarde]

TÚ: Listo, ya puse el CNAME.

IA: verificar_dominio_vps(company_id = 3, vps_id = 9, domain = "app.cliente.com") -> { "matches_host": true, "verify_method": "cname" }

activar_dominio_vps(company_id = 3, vps_id = 9, domain = "app.cliente.com", host_port = 21874) -> certificado emitido, nginx de borde configurado

"Publicado con HTTPS. El camino queda así: app.cliente.com -> host padre :21874 -> tu VPS :3000."

TÚ: Entro y me da 502.

IA: listar_dominios_vps(company_id = 3, vps_id = 9) -> app.cliente.com -> puerto del host 21874 puerto_in_vps: container_port 3000

ejecutar_comando_vps(company_id = 3, vps_id = 9, script = "ss -lntp | grep -E ':(3000|3001)'") -> la app está escuchando en el 3001, no en el 3000

"El camino de red está bien armado: el dominio va al 21874 del host y ese puerto entra al 3000 del container. El que no está es el 3000: la app arrancó en el 3001.

Dos opciones: cambio el puerto de la app, o creo una redirección contra el 3001 y reactivo el dominio contra el puerto del host que salga. ¿Cuál preferís?"

Frequently asked questions

Does my VPS have its own public IP? No. The IP that the internet sees is the parent host's IP, shared with other VPSs. What makes your machine reachable is a port forwarding. Each VPS does have its own DNS name (<slug>.arducloud.com) with an A record to that IP, and it is the most convenient destination for a CNAME from your domain.

Why does certificate issuance fail? Because the DNS does not point to the parent host's IP where certbot runs. Check the DNS first; blind retries consume quota from Let's Encrypt's weekly limit. And remember that an OK from verificar_dominio_vps with verify_method: proxy_forwarded means "the name resolves but I could not confirm that it reaches here", not "everything is fine".

Does a subdomain of the ArduMaker zone also issue a certificate? No, and that is why it is the fast path: it is covered by the default zone certificate, which already exists on the host. Without ACME validation and without weekly limits.

Do certificates renew automatically? Let's Encrypt certificates last 90 days and are designed to renew automatically, on the parent host. Since that layer is not yours, it is not something you manage — but it is worth confirming that a site still has a valid certificate before a week is left, not after.

I have a 502, should I restart nginx? Almost never is it the solution, and besides, the nginx that matters here is usually the edge one, which you cannot restart. Check three things in this order: that the redirection exists against the correct port (listar_redirecciones_vps), that the domain is pointed to that port of the host (listar_dominios_vps) and that the app is effectively listening.

Can I read the logs of the nginx that terminates HTTPS? No. ver_logs_nginx_vps reads the nginx inside your VPS. If you published the domain only with activar_dominio_vps, there are no logs to read on your side — the traffic is logged by the host layer. If you want your own logs per domain, put your internal nginx in the path.

Do I need a separate certificate for www? The certificate covers the exact names for which it was issued. If you want to serve the domain with and without www, both names must be contemplated, each with its own activation.

Can I edit nginx by hand? The one inside your VPS, yes, and sometimes it is necessary. Editing replaces the entire file, so read the current configuration before writing the new one — although if the new one does not validate, the change reverts itself.

How do I connect the MCP? By adding https://mcp.ardumaker.com/mcp in a compatible client and authorizing it with your account.


Part of the series of guides on the MCP tools of ArduMaker. The previous guide covers DNS, records and propagation.

  • nginx
  • SSL
  • HTTPS
  • Lets Encrypt
  • certificados
  • MCP
  • ArduMaker
  • reverse proxy

Keep reading

All articles · VPS plans