If you need to expose your local development web server to the Internet, there are multiple tools you can use. For example: ngrok, pagekite, forward, localtunnel, …

Or, you can build your own for free, if you have your own VPS. It can support SSL and works behind a NAT. Here is how.

Server setup

You will need an nginx server installed on your VPS and a domain name pointing to it, like dev.example.com.

Then add this (or similar) nginx configuration:

server {
    listen 80;
    server_name dev.example.com;
    rewrite ^ https://dev.example.com$request_uri? permanent;
}

server {
    listen 443 ssl http2;

    server_name dev.example.com;

    access_log off;
    error_log off;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header Host $http_host;
    }

    ssl_certificate /path/to/ssl/dev.example.com/fullchain.pem;
    ssl_certificate_key /path/to/ssl/dev.example.com/privkey.pem;
}

The interesting part is the proxy_pass. It will point dev.example.com to the local port 8000 on the server.

Make sure that the following option is allowed in the /etc/ssh/sshd_config and reload the SSH server if needed:

GatewayPorts clientspecified

Local setup

Now you need to create an SSH tunnel betweeen your local machine and the server.

On your development machine, put this function inside your .bashrc file (or .zshrc if you are using ZSH). In this example, me is a remote linux user for the SSH access into the VPS.

function devtunnel {
    ssh -nNT -R "127.0.0.1:8000:localhost:${1}" me@dev.example.com
}

This will forward the remote port 8000 to the local port specified as an argument; -n prevents reading from stdin, -N means that you do not want to execute remote commands, -T disables pseudo-tty allocation, and -R means reverse port forwarding.

Usage

After this setup, exposing your local development server is easy. If you are a Rails developer, you are running your local web server on the port 3000. To expose it publicly, run this locally:

devtunnel 3000

After that, you (or someone else) can visit dev.example.com to access your local server. Enjoy!