En este post voy a documentar cómo montar Sublime POS 3 en un VPS con Ubuntu usando un dominio y SSL de modo que:

  • El sistema estará siempre detrás de https
  • El certificado SSL será obtenido de Let’s encrypt
  • Usaremos Nginx como proxy para esta tarea

Hasta este punto:

  • Ya tenemos el dominio comprado en Namecheap y configurado con un A Record con Host en @, Value en la IP del VPS y TTL en 30 min.
  • Ya se ha propagado el DNS, de modo que al acceder al dominio ya se traduce a la IP del VPS.
  • Sublime POS 3 ya está ejecutándose en el servidor en http://localhost:2106/static/#

No es obligatorio comprar el dominio en Namecheap, solo te estoy contando. Recuerda que no debes comprar nada más que el dominio y el VPS. No instales nada más.

En este caso usaré Ubuntu pero ya he usado Rocky Linux y funciona perfectamente

Entonces comencemos.

Instalando Nginx

Comencemos instalando Nginx en Ubuntu:

sudo apt update
sudo apt install nginx -y

Comprobamos que se haya instalado correctamente:

parzibyte@ubuntu-s-1vcpu-512mb-10gb-sfo3-01:~$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2025-08-27 18:21:45 CST; 1min 0s ago
       Docs: man:nginx(8)
    Process: 398686 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exite>
    Process: 398687 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status>
   Main PID: 398776 (nginx)
      Tasks: 2 (limit: 498)
     Memory: 4.5M
        CPU: 38ms
     CGroup: /system.slice/nginx.service
             ├─398776 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
             └─398779 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "">
parzibyte@ubuntu-s-1vcpu-512mb-10gb-sfo3-01:~$

Lo habilitamos:

sudo systemctl enable nginx

Ahora visitamos el dominio y nos debe mostrar la página de bienvenida de Nginx.

Configurar certificado SSL

Ahora instalamos certbot y el plugin para Nginx. Certbot nos permite hacer la instalación y renovación automática del certificado SSL.

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d ejemplo.com

En mi caso no necesito www así que lo he dejado así. Si quieres que también funcione con www entonces sería así:

sudo certbot --nginx -d ejemplo.com -d www.ejemplo.com

Eso te va a pedir tu correo y algunos datos. Luego te dirá algo como lo siguiente que va a cambiar en tu caso:

Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
Account registered.
Requesting a certificate for ejemplo.com

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/ejemplo.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/ejemplo.com/privkey.pem
This certificate expires on 2025-11-25.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

Deploying certificate
Successfully deployed certificate for ejemplo.com to /etc/nginx/sites-enabled/default
Congratulations! You have successfully enabled HTTPS on https://ejemplo.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
parzibyte@ubuntu-s-1vcpu-512mb-10gb-sfo3-01:~$

Si te dice Congratulations entonces es que ya quedó configurado. De nuevo, recuerda que debes probar en el dominio.

Todavía nos falta revisar si el renovador automático está habilitado. Para ello ejecutamos:

sudo systemctl status certbot.timer

La salida:

parzibyte@ubuntu-s-1vcpu-512mb-10gb-sfo3-01:~$ sudo systemctl status certbot.timer
● certbot.timer - Run certbot twice daily
     Loaded: loaded (/lib/systemd/system/certbot.timer; enabled; vendor preset: enabled)
     Active: active (waiting) since Wed 2025-08-27 18:27:42 CST; 4min 32s ago
    Trigger: Thu 2025-08-28 04:15:26 CST; 9h left
   Triggers: ● certbot.service

Aug 27 18:27:42 ubuntu-s-1vcpu-512mb-10gb-sfo3-01 systemd[1]: Started Run certbot twice daily.
parzibyte@ubuntu-s-1vcpu-512mb-10gb-sfo3-01:~$

Fíjate en que dice twice daily o sea 2 veces por día. Igualmente puedes ejecutar un dry run o ejecución en seco para simular la renovación y ver si todo va bien:

sudo certbot renew --dry-run

La salida es:

parzibyte@ubuntu-s-1vcpu-512mb-10gb-sfo3-01:~$ sudo certbot renew --dry-run
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/ejemplo.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Account registered.
Simulating renewal of an existing certificate for ejemplo.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded:
  /etc/letsencrypt/live/ejemplo.com/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
parzibyte@ubuntu-s-1vcpu-512mb-10gb-sfo3-01:~$

Lo importante es que diga Congratulations, all simulated renewals succeeded

Reenviar tráfico de Nginx a Sublime POS 3

Ahora solo queda usar la función de proxy de Nginx. Abrimos el archivo de configuración:

 sudo vim /etc/nginx/sites-available/default

Y como en mi caso solamente voy a usar Nginx como reverse proxy lo modifico de la siguiente manera.

Originalmente certbot genera la configuración algo así:

server {

        # SSL configuration
        #
        # listen 443 ssl default_server;
        # listen [::]:443 ssl default_server;
        #
        # Note: You should disable gzip for SSL traffic.
        # See: https://bugs.debian.org/773332
        #
        # Read up on ssl_ciphers to ensure a secure configuration.
        # See: https://bugs.debian.org/765782
        #
        # Self signed certs generated by the ssl-cert package
        # Don't use them in a production server!
        #
        # include snippets/snakeoil.conf;

        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;
    server_name ejemplo.com; # managed by Certbot


        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }

        # pass PHP scripts to FastCGI server
        #
        #location ~ \.php$ {
        #       include snippets/fastcgi-php.conf;
        #
        #       # With php-fpm (or other unix sockets):
        #       fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        #       # With php-cgi (or other tcp sockets):
        #       fastcgi_pass 127.0.0.1:9000;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #       deny all;
        #}


    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/ejemplo.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/ejemplo.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

Solo modifiqué la parte de location / así:

location / {
    proxy_pass http://localhost:2106;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

Revisamos si la configuración es correcta:

parzibyte@ubuntu-s-1vcpu-512mb-10gb-sfo3-01:/etc/nginx$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Reiniciamos el servicio:

sudo systemctl reload nginx

Y listo. Ahora se accede en dominio.com/static/. No pudo ser simplemente dominio.com porque el sistema expone, en su api, la ruta raíz como raíz de la API y a su vez la carpeta static como parte de esta.

Dicho con otras palabras es obligatorio servir la raíz del servidor, pues si se servía directamente /static entonces no había manera de ir una ruta arriba.

En cambio si se sirve simplemente / se puede ir tanto a /static como a las otras rutas definidas en la API

Por cierto, también tuve que modificar el cliente HTTP en http-common.js:

export const RUTA_SERVIDOR_CON_AUTH = `${window.document.location.origin}/auth/`;
const RUTA_SERVIDOR_SIN_AUTH = `${window.document.location.origin}/`;
Si el post ha sido de tu agrado te invito a que me sigas para saber cuando haya escrito un nuevo post, haya actualizado algún sistema o publicado un nuevo software. Facebook | X | Instagram | Telegram | También estoy a tus órdenes para cualquier contratación en mi página de contacto