agersant / polaris

Polaris is a music streaming application, designed to let you enjoy your music collection from any computer or mobile device.
MIT License
1.46k stars 83 forks source link

HTTPS support #118

Open Limeth opened 3 years ago

Limeth commented 3 years ago

Since polaris exposes a login form, it would be desirable if the application had support for HTTPS, so that credentials aren't sent unencrypted.

agersant commented 3 years ago

Hello and thanks for caring about Polaris!

I agree this is a very desirable feature. I looked into it a couple years ago and could not find a solution that satisfied all my requirements:

I will look into this again at some point. In the mean time, I know some users work around this by deploying Polaris behind a nginx reverse proxy (which can be configured to handle HTTPS traffic).

stukkat commented 3 years ago

I realise this is a little late, but I was recently looing to do something similar and thought I'd share my experience. For anyone looking to do this with apache it's quite a simple fix. Just create a new virtual host for your domain and add the following.

For just a regular reverse proxy

<VirtualHost *:80>
   ProxyPreserveHost On
   ProxyPass / http://127.0.0.1:5050/
   ProxyPassReverse / http://127.0.0.1:5050/
   ServerName polaris.my.domain
</VirtualHost>

For SSL

<VirtualHost *:443>
  ServerName polaris.my.domain
   ProxyPreserveHost On
   ProxyPass / http://127.0.0.1:5050/
   ProxyPassReverse / http://127.0.0.1:5050/
    SSLProxyEngine on
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/server.crt
    SSLCertificateKeyFile /etc/ssl/private/server.key
</VirtualHost>

Restart apache and it should be ready to go.

lnicola commented 3 years ago

Oh, right, let me contribute too. If you're using Nginx, you can use this as a starter config:

upstream polaris {
    server 127.0.0.1:5050 fail_timeout=0;
    keepalive 32;
}

server {
    listen 443 ssl http2;
    server_name polaris.mydomain.tld; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/polaris.mydomain.tld/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/polaris.mydomain.tld/privkey.pem; # managed by Certbot
    ssl_trusted_certificate /etc/letsencrypt/live/polaris.mydomain.tld/cert.pem;
    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains" always;

    if ($scheme != "https") {
        return 301 https://$host$request_uri;
    }

    location = /robots.txt {
        alias /tank/robots.txt;
    }

    location / {
        proxy_buffering off;
        proxy_read_timeout 300;
        proxy_connect_timeout 300;
        # proxy_redirect off;
        # proxy_set_header Host $http_host;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_pass http://polaris;
    }
}

server {
    if ($host = polaris.mydomain.tld) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80;
    server_name polaris.mydomain.tld;
    return 404; # managed by Certbot
}

See https://letsencrypt.org/ for obtaining a certificate.

lnicola commented 3 years ago

One solution to offer this in Polaris would be to use a crate like https://crates.io/crates/acme-micro. Personally, I wouldn't use it though, since the reverse proxy solution works better for me.

@stukkat you can use fenced code blocks for code snippets.

stukkat commented 3 years ago

@stukkat you can use fenced code blocks for code snippets.

Thanks for that @lnicola, please forgive my github noobishness :P

agersant commented 3 years ago

One solution to offer this in Polaris would be to use a crate like https://crates.io/crates/acme-micro. Personally, I wouldn't use it though, since the reverse proxy solution works better for me.

This is exactly what I would want to bundle in Polaris, if it wasn't for the OpenSSL dependency. I had that library as a dependency in the early days of Polaris and it was a constant headache for building and distributing on Windows.

Lyamc commented 3 years ago

SOZU

use https://github.com/sozu-proxy/sozu-acme for configuring Let's Encrypt Using a symbolic link so that if sozu is ever updated through cargo, you won't have to copy it every time

cargo install sozu
sudo ln -s $HOME/.cargo/bin/sozu /usr/bin/sozu
sudo mkdir -p /etc/sozu
sudo nano /etc/sozu/sozu.toml
saved_state = "./state.json"
log_level = "info"
log_target = "stdout"
log_access_target = "file:///var/log/sozu-access.log"
command_buffer_size = 16384
max_command_buffer_size = 163840
worker_count = 2
worker_automatic_restart = true
handle_process_affinity = false
max_connections = 500
max_buffers = 500
buffer_size = 16384
tls_provider = "rustls"
activate_listeners = true

[[listeners]]
protocol = "http"
address = "0.0.0.0:80"

[[listeners]]
protocol = "https"
address = "0.0.0.0:443"
tls_versions = ["TLSv1.2", "TLSv1.3"]

[applications]
[applications.Polaris]
protocol = "http"
https_redirect = true
frontends = [
  { address = "0.0.0.0:80", hostname = "play.example.com" },
  { address = "0.0.0.0:443", hostname = "play.example.com", certificate = "/public/example.com/example.com.crt", key = "/public/example.com/example.com.key" }
]

backends = [
  { address = "127.0.0.1:5050" }
]

Create systemd service

sudo nano /etc/systemd/system/sozu.service
[Unit]
Description=Sozu Reverse Proxy System Daemon
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/sozu start -c /etc/sozu/sozu.toml
StandardOutput=append:/var/log/sozu.log
StandardError=append:/var/log/sozu-error.log
Restart=on-failure
RestartSec=3

[Install]
WantedBy=multi-user.target

Enable and start the service

sudo systemctl daemon-reload
sudo systemctl enable --now sozu

HAPROXY

sudo apt install -y haproxy
sudo nano /etc/haproxy/haproxy.conf
frontend http
    bind 0.0.0.0:80 alpn h2
    bind :::80 alpn h2
    mode http
    http-request redirect scheme https unless { ssl_fc }

frontend https
    bind 0.0.0.0:443 alpn h2 ssl crt /public/example.com/example.com.combined.pem
    bind :::443 alpn h2 ssl crt /public/example.com/example.com.combined.pem

### If using Let's Encrypt SSL Certificates, proxy will forward ACME Challenge
    acl letsencrypt-acl path_beg /.well-known/acme-challenge/
    use_backend letsencrypt-backend if letsencrypt-acl

    acl live-acl hdr(host) -i play.example.com
    use_backend  polaris-backend if live-acl

### Let's Encrypt certbot requests get sent to this <url>:<port>
backend letsencrypt-backend
    server letsencrypt 127.0.0.1:8888

backend polaris-backend
   server polaris 127.0.0.1:5050

Enable service

sudo systemctl enable --now haproxy
Ash645 commented 2 years ago

ProxyPreserveHost On

I realise this is a little late, but I was recently looing to do something similar and thought I'd share my experience. For anyone looking to do this with apache it's quite a simple fix. Just create a new virtual host for your domain and add the following.

For just a regular reverse proxy

<VirtualHost *:80>
   ProxyPreserveHost On
   ProxyPass / http://127.0.0.1:5050/
   ProxyPassReverse / http://127.0.0.1:5050/
   ServerName polaris.my.domain
</VirtualHost>

For SSL

<VirtualHost *:443>
  ServerName polaris.my.domain
   ProxyPreserveHost On
   ProxyPass / http://127.0.0.1:5050/
   ProxyPassReverse / http://127.0.0.1:5050/
    SSLProxyEngine on
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/server.crt
    SSLCertificateKeyFile /etc/ssl/private/server.key
</VirtualHost>

Restart apache and it should be ready to go.

Hey @stukkat ! Sorry for the bump, but I'm running apache as well, but it has nextcloud listening to 80 and 443. So I added the following on Apache's conf file-

ProxyPass /polaris http://localhost:5050/

<Location /polaris> ProxyPreserveHost On ProxyPassReverse /

But this opens a black site for me, nothing is displayed. Any pointers is appreciated!

Donien commented 1 year ago

For anyone having trouble getting ssl to work using apache (reverse proxy)

I've struggled with that for a bit myself. I basically had the same directives @stukkat used and added AllowEncodedSlashes On to my config.
That made it work for me.

<VirtualHost *:443>
    ServerName polaris.probe.local
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:5050/
    ProxyPassReverse / http://127.0.0.1:5050/

    SSLProxyEngine on
    SSLEngine on
    SSLCertificateFile  /etc/ssl/certs/ssl-cert-snakeoil.pem
    SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

    AllowEncodedSlashes On
</VirtualHost>

<VirtualHost *:80>
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:5050/
    ProxyPassReverse / http://127.0.0.1:5050/
    ServerName polaris.my.domain
</VirtualHost>
pjbroad commented 1 year ago

I'm new to polaris. I'm running it in a docker container and trying to get it working behind nginx. With the most basic of nginx configs, its appears to work but tracks will randomly be cut short. When this happens, the browser (firefox) shows the error NS_ERROR_NET_PARTIAL_TRANSFER. I'm using the latest nginx, firefox and polaris (from the git hub repo). I do not appear to have the same issue if I connect directly to the polaris service on port 5050, bypassing the nginx proxy.

I tried using the settings from the suggested config from @lnicola but have the same issue. I've tried many variants of similar settings but none resolve the issue. Is there any tried and tested nginx config example?

Lyamc commented 1 year ago

@pjbroad

I suggest creating a new issue for this, since this appears to be either due to your specific nginx configuration, or the Firefox browser itself.

Before creating a new issue, try chrome, and try Firefox, and try one of the Polaris apps. Mention the platforms on each that were tested (Windows, Linux, Android, iOS).

Lyamc commented 1 year ago

Also, for what its worth, I don't believe polaris should worry about acme integration.

If polaris should do anything, it should just create a self-signed certificate (Rustls) in some ./ssl directory and use that. Anyone who is reverse-proxying who needs SSL can ignore the cert check, anyone not reverse proxying can ignore the "untrusted cert", and if they care they can get their own certs and use those instead.

pjbroad commented 1 year ago

Thanks @Lyamc. I agree that Polaris does not need to so anything itself for ssl. I was just hoping someone would have a known working nginx config, ssl or not. I'm trying in another browser for now. I'll give the Android app a good test too.