Reply
New Member
Posts: 35
Registered: ‎07-06-2014
Kudos: 18
Solutions: 1
Accepted Solution

Lets Encrypt and UniFi controller

With the public beta launch of Lets Encrypt just around the corner, I was wondering if anyone knows how to used properly signed certificates with the UniFi controller?

 

I'd like to get a LE cert for the domain where my controller lives. Then I can avoid all the cert errors I get every time I log in.

 

Further, the web control panel runs on port 8443. Is there a way to bind it to 443 instead? Reason is that many corporate firewalls don't allow me to access services on 8443. I'd like to standardise it.

 

I have several other domains on the server also running on 443, so it'd have to work with them too. I use Nginx as the web server for those.

 

Thanks


Accepted Solutions
Highlighted
New Member
Posts: 35
Registered: ‎07-06-2014
Kudos: 18
Solutions: 1

Re: Lets Encrypt and UniFi controller

[ Edited ]

Here's a basic guide for what I did on Ubuntu.

 

First things first, you want to make sure you can setup your sever to get HTTPS/SSL keys from Lets Encrypt. There are many guides on the internet now that you can follow. But in summary, I'd recommend using the webroot method with Nginx.

 

That means the server doens't need to shutdown to launch the LetsEncrypt server for authorisation. It'll also make renewing the keys in three months easier/more automatable.

 

The basic command: 

 

 

./letsencrypt-auto --server https://acme-v01.api.letsencrypt.org/directory -a webroot --webroot-path /var/www/default/html/ --domain example.com certonly

 

 

It also requires setting up a location block for Nginx. Here's what I've got:

 

 

location /.well-known/acme-challenge {
    alias /var/www/default/html/.well-known/acme-challenge;
    location ~ /.well-known/acme-challenge/(.*) {
        add_header Content-Type application/jose+json;
    }
}

 

 

I saved that location block in the /etc/nginx/snippets folder, and then include it in every domain config that I need to use Lets Encrypt for, including my Unifi controller setup. 

 

For example:

 

 

include /etc/nginx/snippets/letsencryptauth.conf;

 

 

 Once you've successfully set up your domain, with authorisation, you'll be able to get a SSL certificate for that domain. 

 

Now you've got to proxy the domain to the (running) Unifi controller.

 

 

    location / {
        proxy_pass https://example.com:8443/;
    }

Basically, all that means is that all requests to the secure (https) domain, proxy to port 8443 - which is where the controller is running.

 

 

But we've got a problem, because the controller uses its own (self-signed) certificate which leads to problems with the proxying. 

 

Luckily, there's a solution for Nginx called ssl_trusted_certificate! This is telling Nginx that you can trust this certificate and process the request. However, you've got to go and extract the certificate from the Java (controller) keystore, convert it into something Nginx can read and copy that to the Nginx configuration folder.

 

At :

 

 

/var/lib/unifi

 

lies the keystore you'll need. It is - funnily enough - called keystore

 

The tool (which should be installed) keytool, will help. Run the command:

 

 

sudo keytool -list -v -keystore keystore

It'll ask for the password. I just push enter.

 

 

Then you'll see the self-signed certificate used by the Unifi controller. For example, mine says:

 

 

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: unifi

Bingo!

 

 

Now we need to extract it, and convert it.

 

Extraction first.

 

 

sudo keytool -export -keystore keystore -alias unifi -file cert.cer

 

 

That will extract the certificate to the /var/lib/unifi directory, call it cert.cer.  But it's not ready for use yet. You'll need to convert it. We need to turn to OpenSSL for that.

 

sudo openssl x509 -inform der -in cert.cer -out unifi.pem

This will convert the java exported .cer file into something Nginx can use (unifi.pem).

 

Move the unifi.pem file to /etc/nginx/ (or where ever you'd like to keep it). I keep mine at /etc/nginx/ssl/default/.

 

Now you've got to add this line to your Nginx domain config file. 

 

 

ssl_trusted_certificate /etc/nginx/ssl/default/unifi.pem;

Do a nginx reload, and if you've set up the https certs property and you'll have Nginx proxying to the Unifi Controller with an https certificate.

 

 

 EDIT (10 April 2016)

 

It appears that for Unifi controller version 4 software (and possibly 3) this also needs including in the location block:

 

	location / {
		proxy_pass https://example.com:8443;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
	}

 

 

Thanks to jliechty for that.

 

 

Useful links:

 

 

 

 

 

 

 

View solution in original post


All Replies
New Member
Posts: 21
Registered: ‎07-17-2013
Kudos: 1
Solutions: 2

Re: Lets Encrypt and UniFi controller

New Member
Posts: 35
Registered: ‎07-06-2014
Kudos: 18
Solutions: 1

Re: Lets Encrypt and UniFi controller

[ Edited ]

Thanks for that. 

 

When LE opens up publically, I'll give it a shot and see what I can do. 

 

The only issue is that LE certs are valid for 90 days, so to avoid doing an import every 3 months, I'll have to find a way to import_cert via a script. 

 

Anyway, I'll report back once it's open.

 

EDIT: It has occured to me I could use Nginx to proxy requests to Unifi. I presume that would allow Nginx to control the SSL, and solve my non-standard port issue?

 

EDIT2: I've had a little bit of success on this since posting. I think I've worked out how to do the proxy, which will likely solve the SSL and Lets Encrypt question too. This site helped. If you're a visitor from the future, I'll write up a quick guide to help out and post here soon.

 

EDIT3: I got round to writing it up. Here's the solution.

Emerging Member
Posts: 50
Registered: ‎10-14-2015
Kudos: 8
Solutions: 2

Re: Lets Encrypt and UniFi controller

I'm also working on the instructions for Centos 6 with the Unifi controller. Hopefully I'll make some progress soon.

 

This is what I have so far

 

cd /usr/src

yum install epel-release

wget https://centos6.iuscommunity.org/ius-release.rpm
rpm -Uvh ius-release*.rpm

yum install python27 python27-devel python27-setuptools python27-tools python27-virtualenv augeas-libs dialog gcc libffi-devel openssl-devel

git clone https://github.com/letsencrypt/letsencrypt

cd letsencrypt

./bootstrap/centos.sh

./letsencrypt-auto certonly

However I'm getting another error.

 

IMPORTANT NOTES:

- The following 'urn:acme:error:connection' errors were reported by

   the server:

 

   Domains: <domain removed from log>

   Error: The server could not connect to the client for DV

New Member
Posts: 35
Registered: ‎07-06-2014
Kudos: 18
Solutions: 1

Re: Lets Encrypt and UniFi controller

I have worked out how to do it. It involves extracting the current (self-signed) certificate from the java keystore, converting it into something the webserver (nginx, in my case) can read, setting it as a trusted certificate, and proxying everything though from nginx to the network controller. 

 

I will get around to explaining it one day, if anyone is interested. 

New Member
Posts: 11
Registered: ‎09-09-2013
Kudos: 1

Re: Lets Encrypt and UniFi controller

Hi, great news. yes I am very much interested in a setp by step guide. the real interest is for the guest portal. thanks
Emerging Member
Posts: 105
Registered: ‎02-21-2015
Kudos: 19
Solutions: 2

Re: Lets Encrypt and UniFi controller

I, too, would love to learn how this can be accomplished and would greatly appreciate any write-ups you have time to share. Thanks in advance!

 

- Rob

Emerging Member
Posts: 48
Registered: ‎01-09-2015
Kudos: 4
Solutions: 1

Re: Lets Encrypt and UniFi controller

Subscribing.  

 

I would like to do the same thing as well.  I'll play around later today and post my findings.  

 

Happy new year all!

 

 

Regular Member
Posts: 536
Registered: ‎07-17-2012
Kudos: 124
Solutions: 5
Contributions: 1

Re: Lets Encrypt and UniFi controller

I would also like to do this.

 

Would be neat if Ubiquiti built support in for this out of the box at some point

Highlighted
New Member
Posts: 35
Registered: ‎07-06-2014
Kudos: 18
Solutions: 1

Re: Lets Encrypt and UniFi controller

[ Edited ]

Here's a basic guide for what I did on Ubuntu.

 

First things first, you want to make sure you can setup your sever to get HTTPS/SSL keys from Lets Encrypt. There are many guides on the internet now that you can follow. But in summary, I'd recommend using the webroot method with Nginx.

 

That means the server doens't need to shutdown to launch the LetsEncrypt server for authorisation. It'll also make renewing the keys in three months easier/more automatable.

 

The basic command: 

 

 

./letsencrypt-auto --server https://acme-v01.api.letsencrypt.org/directory -a webroot --webroot-path /var/www/default/html/ --domain example.com certonly

 

 

It also requires setting up a location block for Nginx. Here's what I've got:

 

 

location /.well-known/acme-challenge {
    alias /var/www/default/html/.well-known/acme-challenge;
    location ~ /.well-known/acme-challenge/(.*) {
        add_header Content-Type application/jose+json;
    }
}

 

 

I saved that location block in the /etc/nginx/snippets folder, and then include it in every domain config that I need to use Lets Encrypt for, including my Unifi controller setup. 

 

For example:

 

 

include /etc/nginx/snippets/letsencryptauth.conf;

 

 

 Once you've successfully set up your domain, with authorisation, you'll be able to get a SSL certificate for that domain. 

 

Now you've got to proxy the domain to the (running) Unifi controller.

 

 

    location / {
        proxy_pass https://example.com:8443/;
    }

Basically, all that means is that all requests to the secure (https) domain, proxy to port 8443 - which is where the controller is running.

 

 

But we've got a problem, because the controller uses its own (self-signed) certificate which leads to problems with the proxying. 

 

Luckily, there's a solution for Nginx called ssl_trusted_certificate! This is telling Nginx that you can trust this certificate and process the request. However, you've got to go and extract the certificate from the Java (controller) keystore, convert it into something Nginx can read and copy that to the Nginx configuration folder.

 

At :

 

 

/var/lib/unifi

 

lies the keystore you'll need. It is - funnily enough - called keystore

 

The tool (which should be installed) keytool, will help. Run the command:

 

 

sudo keytool -list -v -keystore keystore

It'll ask for the password. I just push enter.

 

 

Then you'll see the self-signed certificate used by the Unifi controller. For example, mine says:

 

 

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: unifi

Bingo!

 

 

Now we need to extract it, and convert it.

 

Extraction first.

 

 

sudo keytool -export -keystore keystore -alias unifi -file cert.cer

 

 

That will extract the certificate to the /var/lib/unifi directory, call it cert.cer.  But it's not ready for use yet. You'll need to convert it. We need to turn to OpenSSL for that.

 

sudo openssl x509 -inform der -in cert.cer -out unifi.pem

This will convert the java exported .cer file into something Nginx can use (unifi.pem).

 

Move the unifi.pem file to /etc/nginx/ (or where ever you'd like to keep it). I keep mine at /etc/nginx/ssl/default/.

 

Now you've got to add this line to your Nginx domain config file. 

 

 

ssl_trusted_certificate /etc/nginx/ssl/default/unifi.pem;

Do a nginx reload, and if you've set up the https certs property and you'll have Nginx proxying to the Unifi Controller with an https certificate.

 

 

 EDIT (10 April 2016)

 

It appears that for Unifi controller version 4 software (and possibly 3) this also needs including in the location block:

 

	location / {
		proxy_pass https://example.com:8443;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
	}

 

 

Thanks to jliechty for that.

 

 

Useful links:

 

 

 

 

 

 

 

Regular Member
Posts: 636
Registered: ‎01-06-2012
Kudos: 394
Solutions: 21
Contributions: 2

Re: Lets Encrypt and UniFi controller

Well, I finally tried the instructions. As someone who had never set up nginx before, there was a lot of guesswork and mashing up of generic nginx configuration guides needed, along with trial and error and copious amounts of swearing, to get to a marginally working setup, but I am now finally able to pull up my UniFi controller with https on port 443 and not get a certificate warning, so that's very good. Or, I should say, it works well in Firefox. But if I try to load it in Chrome or Safari, I get the login screen with no certificate errors, but the controller rejects my username and password (which work fine in Firefox, thank you very much). I'm already in over my head on the SSL proxy setup, so I have not the slightest clue how to even begin troubleshooting...

New Member
Posts: 35
Registered: ‎07-06-2014
Kudos: 18
Solutions: 1

Re: Lets Encrypt and UniFi controller

Post your nginx server config blocks and I'll see if I can see anything you could tune up.

Regular Member
Posts: 636
Registered: ‎01-06-2012
Kudos: 394
Solutions: 21
Contributions: 2

Re: Lets Encrypt and UniFi controller

[ Edited ]

Thanks! I'm sure something is not quite right, but I know so little that I'm not sure what that might be...

 

server {
	listen 80 default_server;
	listen [::]:80 default_server ipv6only=on;

	root /usr/share/nginx/html;
	index index.html index.htm;

	server_name localhost;

	location / {
		try_files $uri $uri/ =404;
	}

	include /etc/nginx/snippets/letsencryptauth.conf;
}

server {
	listen 443;
	server_name server.mydomain.com;

	root html;
	index index.html index.htm;

	ssl on;
	ssl_certificate /etc/letsencrypt/live/server.mydomain.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/server.mydomain.com/privkey.pem;

	ssl_trusted_certificate /etc/nginx/ssl/unifi.pem;

	ssl_session_timeout 5m;

	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
	ssl_prefer_server_ciphers on;

	location / {
		proxy_pass https://server.mydomain.com:8443/;
	}
}
New Member
Posts: 35
Registered: ‎07-06-2014
Kudos: 18
Solutions: 1

Re: Lets Encrypt and UniFi controller

[ Edited ]

I'm not an expert, but try deleting the root and index lines from both server blocks.

 

Ie (port 80):

 

root /usr/share/nginx/html;
index index.html index.htm;

and (port 443)

 

root html;
index index.html index.htm;

 

Also, why is your port 80 block server_name:

 

server_name localhost;

How'd that go?

 

Regular Member
Posts: 636
Registered: ‎01-06-2012
Kudos: 394
Solutions: 21
Contributions: 2

Re: Lets Encrypt and UniFi controller

I disabled the lines you mentioned and changed the server name on port 80 to the appropriate domain. After restarting nginx, trying to login on a fresh browser showed no improvement. Firefox still works fine, but both Safari and Chrome reject my password with no other visible errors.

Regular Member
Posts: 636
Registered: ‎01-06-2012
Kudos: 394
Solutions: 21
Contributions: 2

Re: Lets Encrypt and UniFi controller

[ Edited ]

Ok, so it turns out that the change I needed to make Webkit-based browsers happy was the addition of three lines in the location part of the https server block:

	location / {
		proxy_pass https://server.mydomain.com:8443;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
	}

It seems to be happy now. Thanks for your assistance, including your original documentation, for being the first as far as I can see to describe how to make this work!

 

(I now ponder whether setting up a redirect to the https side from the http side would break letsencrypt's ability to verify the files that it places on the server with the auto script. I'm thinking yes, but I'm wondering if there's a way...)

New Member
Posts: 35
Registered: ‎07-06-2014
Kudos: 18
Solutions: 1

Re: Lets Encrypt and UniFi controller

A redirect shouldn't hurt it, so long as you've got the letsencrypt.conf block included.

 

It should work by sending all traffic (ie, location /) to the redirect, except /.well-known/acme-challenge traffic which is LE's verification.

 

My port 80 block is like this and it works perfectly.

 

 

    include /etc/nginx/snippets/letsencryptauth.conf;

    location / {
        return 301 https://example.com$request_uri;
    }

 

 

 

 

Regular Member
Posts: 636
Registered: ‎01-06-2012
Kudos: 394
Solutions: 21
Contributions: 2

Re: Lets Encrypt and UniFi controller

That works perfectly. Thanks!

Member
Posts: 149
Registered: ‎10-06-2015
Kudos: 45
Solutions: 4

Re: Lets Encrypt and UniFi controller

I found this link while searching, pretty neat way to setup https://www.reddit.com/r/Ubiquiti/comments/43v23u/using_letsencrypt_with_the_unifi_controller/ 

External Portal supporting Facebook Login and Email collection

http://www.spotipo.com

https://discuss.spotipo.com

Emerging Member
Posts: 50
Registered: ‎10-14-2015
Kudos: 8
Solutions: 2

Re: Lets Encrypt and UniFi controller

[ Edited ]

So to finish instructions for Centos 6, I installed nginx and got that running.

 

I have not mastered getting the nginx and letsencrypt auto cert renew yet. I've been standalone with certonly option.

 

./letsencrypt-auto certonly

 

I created a file so that renewals go quickly.

 

nano /etc/letsencrypt/cli.ini


# This is an example of the kind of things you can do in a configuration file.
# All flags used by the client can be configured here. Run Let's Encrypt with
# "--help" to learn more about the available options.

# Use a 4096 bit RSA key instead of 2048
rsa-key-size = 4096

# Always use the staging/testing server
#server = https://acme-staging.api.letsencrypt.org/directory
server = https://acme-v01.api.letsencrypt.org/directory

# Uncomment and update to register with the specified e-mail address
email = myemail@domain.com

# Uncomment to use a text interface instead of ncurses
text = True

# Uncomment to use the standalone authenticator on port 443
authenticator = standalone

# Uncomment to use the webroot authenticator. Replace webroot-path with the
# path to the public_html / webroot folder being served by your web server.
#authenticator = webroot
#webroot-path = /var/www/html

domain = unifi.mydomain.com
# agree-dev-preview = True
renew-by-default = True

 

So Intall nginx by doing this:

  

yum install nginx

mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.old

openssl dhparam -out /etc/nginx/dhparams.pem 2048

nano /etc/nginx/conf.d/unifi.conf

Then paste this into it changing the references to "unifi.mydomain.com". Note I didn't need to export the java cert like others have needed.

 

 

 

server_tokens off;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";

server {
  listen 80 default_server;
  server_name unifi.mydomain.com;
  return 302 https://unifi.mydomain.com$request_uri;
}

server {
  listen 443;
  server_name unifi.mydomain.com;


   ssl_certificate /etc/letsencrypt/live/unifi.mydomain.com/cert.pem;
   ssl_certificate_key /etc/letsencrypt/live/unifi.mydomain.com/privkey.pem;

  ssl on;
  ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM$
  ssl_prefer_server_ciphers on;
  ssl_dhparam /etc/nginx/dhparams.pem;

  resolver 8.8.8.8;
  #  couldn't use this option in Centos
  #  ssl_trusted_certificate /etc/letsencrypt/live/unifi.mydomain.com/fullchain.pem;

  add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";

  location / {
    proxy_pass https://unifi.mydomain.com:8443/;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
  }
}

I left everything in /etc/nginx/nginx.conf as stock.

 

Startup nginx

 

service nginx start

You should now be able to access your unifi server with your Lets Encrypt cert. 

 

To do renewals:

 

service nginx stop
service iptables stop
cd /usr/src/letsencrypt
./letsencrypt-auto certonly
service iptables start
service nginx start

 

Reply