expose icon indicating copy to clipboard operation
expose copied to clipboard

self-hosting on a subdomain, any special configuration needed?

Open vesper8 opened this issue 4 years ago • 4 comments

I'm trying to get Expose (v1) to work on a subdomain.

I've set up Expose v1 on a VPS, I'm using v1 because I'm running php 7.4

Published the config, set up the nginx with a proxy pass, enabled SSL, and I can access my Expose dashboard by going to https://expose.mydomain.dev

Then on my client (my local dev) I've also installed the latest v1, I've published the config, edited the config and set the host to 'host' => 'expose.mydomain.dev',

From the client I can now expose share http://localhost --subdomain XYZ

And it creates a tunnel

Expose-URL:		https://XYZ.expose.mydomain.dev

I can access the local dashboard and it says

Waiting for requests on: https://XYZ.expose.mydomain.dev

On my server, in the dashboard it also shows the new site under https://expose.mydomain.dev/sites

Under the 'subdomain' column it shows

XYZ.expose.mydomain.dev:mycustomport

At this point the tunnel itself does not work at all.

I imagine I have to do something special if I want this to work on a subdomain.

If anyone knows what I must change I'd very much appreciate the insight!

Many thanks

vesper8 avatar Sep 30 '21 17:09 vesper8

Based on https://github.com/beyondcode/expose/issues/209

I realized I'm probably missing two things.

First I hadn't set a wildcard dns A record. I added that to Cloudflare now

On top of expose.mydomain.dev I also now have *.expose.mydomain.dev

And I also modified my nginx file to listen to both expose.mydomain.dev and *.expose.mydomain.dev

However unfortunately it still isn't working. I haven't configured the wildcard to work with Letsencrypt yet.. could that be what's causing me problems now? Does both the dashboard URL and the wildcard need to be configured with SSL?

vesper8 avatar Sep 30 '21 17:09 vesper8

For others coming here, please see (also) my second comment for an improved solution or rather some additional information: https://github.com/beyondcode/expose/issues/280#issuecomment-964348419

Hey, just some stranger here who successfully got expose running on a subdomain. You are right, you will need also a wildcard ssl certificate for your subdomain / domain, which you can retrieve via certbot from Letsencrypt. Depending on your domain provider, there exists a plugin for doing so, e.g. for cloudflare there exists one, probably you can follow this instructions: https://www.bjornjohansen.com/wildcard-certificate-letsencrypt-cloudflare. As an alternative, if there is no plugin for your domain provider or you just want to do it manually, you can also run:

certbot certonly -d *.expose.mydomain.dev --preferred-challenges dns --manual

Then you will get instructions to set a TXT record under the name _acme-challenge.expose.mydomain.dev with a specified value. When the cert retrieval process is done you should delete this record again. Afterwards your cert and key will lay probably under /etc/letsencrypt/live/expose.mydomain.dev-0001 given you have already requested a cert for expose.mydomain.dev, else it is probably /etc/letsencrypt/live/expose.mydomain.dev. In my case I use nginx as a reverse proxy for expose therefore I needed to extend my existing configuration which then looked like this:

server {
    server_name *.expose.mydomain.dev;

    listen 80;
    listen [::]:80;
    listen [::]:443 ssl; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/expose.mydomain.dev-0001/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/expose.mydomain.dev-0001/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass             http://127.0.0.1:8080;
        proxy_read_timeout     60;
        proxy_connect_timeout  60;
        proxy_redirect         off;

        # Allow the use of websockets
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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 https;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}
server {
    server_name expose.mydomain.dev;

    listen 80;
    listen [::]:80;
    listen [::]:443 ssl; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/expose.mydomain.dev/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/expose.mydomain.dev/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

    location / {
        proxy_pass             http://127.0.0.1:8080;
        proxy_read_timeout     60;
        proxy_connect_timeout  60;
        proxy_redirect         off;

        # Allow the use of websockets
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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 https;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Probably there is a shorter way for this config then duplicating the location directive, but I'm not that familiar with nginx. After reloading nginx everything should work. The only thing I recognized was that expose thinks the main subdomain (expose.mydomain.dev) itself is also a tunnel and therefore doesn't return the homepage but the 404 page.

jo-te avatar Nov 09 '21 11:11 jo-te

Hey, just some stranger here who successfully got expose running on a subdomain. You are right, you will need also a wildcard ssl certificate for your subdomain / domain, which you can retrieve via certbot from Letsencrypt. Depending on your domain provider, there exists a plugin for doing so, e.g. for cloudflare there exists one, probably you can follow this instructions: https://www.bjornjohansen.com/wildcard-certificate-letsencrypt-cloudflare. As an alternative, if there is no plugin for your domain provider or you just want to do it manually, you can also run:

certbot certonly -d *.expose.mydomain.dev --preferred-challenges dns --manual

Then you will get instructions to set a TXT record under the name _acme-challenge.expose.mydomain.dev with a specified value. When the cert retrieval process is done you should delete this record again. Afterwards your cert and key will lay probably under /etc/letsencrypt/live/expose.mydomain.dev-0001 given you have already requested a cert for expose.mydomain.dev, else it is probably /etc/letsencrypt/live/expose.mydomain.dev. In my case I use nginx as a reverse proxy for expose therefore I needed to extend my existing configuration which then looked like this:

server {
    server_name *.expose.mydomain.dev;

    listen 80;
    listen [::]:80;
    listen [::]:443 ssl; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/expose.mydomain.dev-0001/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/expose.mydomain.dev-0001/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass             http://127.0.0.1:8080;
        proxy_read_timeout     60;
        proxy_connect_timeout  60;
        proxy_redirect         off;

        # Allow the use of websockets
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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 https;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}
server {
    server_name expose.mydomain.dev;

    listen 80;
    listen [::]:80;
    listen [::]:443 ssl; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/expose.mydomain.dev/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/expose.mydomain.dev/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

    location / {
        proxy_pass             http://127.0.0.1:8080;
        proxy_read_timeout     60;
        proxy_connect_timeout  60;
        proxy_redirect         off;

        # Allow the use of websockets
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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 https;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Probably there is a shorter way for this config then duplicating the location directive, but I'm not that familiar with nginx. After reloading nginx everything should work. The only thing I recognized was that expose thinks the main subdomain (expose.mydomain.dev) itself is also a tunnel and therefore doesn't return the homepage but the 404 page.

Many thanks @jo-te ! That's super helpful!

vesper8 avatar Nov 09 '21 13:11 vesper8

Little edit in post: You can simply request one certificate from Letsencrypt for both *.expose.mydomain.dev and expose.mydomain.dev itself by specifying both when using certbot e.g.:

certbot certonly -d *.expose.mydomain.dev -d expose.mydomain.dev --preferred-challenges dns --manual

Then the server block remains much shorter:

server {
    server_name *.expose.mydomain.dev expose.mydomain.dev;

    listen 80;
    listen [::]:80;
    listen [::]:443 ssl; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/expose.mydomain.dev/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/expose.mydomain.dev/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass             http://127.0.0.1:8080;
        proxy_read_timeout     60;
        proxy_connect_timeout  60;
        proxy_redirect         off;

        # Allow the use of websockets
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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 https;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Maybe server_name *.expose.mydomain.dev; instead of server_name *.expose.mydomain.dev expose.mydomain.dev; is already sufficent.

jo-te avatar Nov 09 '21 17:11 jo-te

Closing this issue because it's old. Please feel free to open a new one if it's still relevant.

sschlein avatar Dec 21 '23 13:12 sschlein