Hi there,
I’ve done a ridiculous amount of searching and IRC bothering on getting a lot of the Rock-On containers to work with nginx via reverse proxy all passed through SSL/HTTPS. I finally got a great set up working so I wanted to share with the rest of the world considering I found absolutely no configuration online as to what I wanted. This how-to is a work in progress, so please feel free to send me a message or comment on this page if there are any suggestions or if I’m blatantly providing misinformation!
Just fyi, if you don’t feel comfortable modifying your nginx.conf, just stick with the default config. Before starting, I would do a config backup via the GUI to save any changes you make, just to be safe.
So, the main problem I ran into was trying to get RocketChat to proxy externally. Since it’s built with Meteor which accesses a different Docker container to reference its assets, it made it almost impossible to use URI locations: ie;
location /chat {
proxy_pass http://192.168.1.35:3000/;
So, I used subdomains and everything seems to work pretty well.
Here’s my configuration, I’m using letsencrypt for my SSL certificate, and just modifying the local instance of the nginx conf located here:
/opt/rockstor/etc/nginx/nginx.conf
So you can generate your certificate any way you want, I used certbot which comes with the package letsencrypt and it makes it pretty easy:
letsencrypt certonly -d your-domain.com
Obviously replacing your-domain.com
with your own domain suffix. I created a wildcard cert, indicating that any domain prefix ie; chat, cloud, portal etc. .your-domain.com would work. This is necessary for getting the subdomains to work in nginx.
Enter in your necessary details and it should dump your chain in:
/etc/letsencrypt/live/your-domain.com/
I also recommend using a hosting company to register for dynamic DNS. Hurricane Electric, dyndns, freedns, etc all off free solutions. Once I created an account, I had chat.my-domain.com, cloud.my-domain.com, and a few others point to my public IP address as A records.
So now that you have your free SSL certificate generated, you can upload it to your Rockstor instance under System > SSL Certificate
. Just cat your full-chain.pem and your private key:
/etc/letsencrypt/live/your-domain.com/fullchain.pem
Take this and paste it into the input box on the GUI labeled Certifcate and take your private key in:
/etc/letsencrypt/live/your-domain.com/privkey.key
and paste it into the input box on the GUI labeled Private Key
A quick word about security; you absolutely never want to share your private key with anyone. I’d even go as far as to say that you should clear your clipboard after you’ve done this step just to make sure it’s not accidentally pasted somewhere public
You then update your certificate, and now Rockstor should be using your letsencrypt certificate to encrypt your server. It places these under:
/opt/rockstor/certs/
For extra security, we’re going to generate a Diffie-Hellman key exchange to make it a lot harder for people to get in if for some terrible reason they have your server keys:
openssl dhparam -out /opt/rockstor/certs/dhparam.pem 2048
So now lets modify your nginx.conf. First, back up your existing config, the following command moves your existing config to .backup so it essentially removes your active nginx.conf file, but there is a lot to paste into the new config which I’ll have below:
mv /opt/rockstor/etc/nginx/nginx.conf /opt/rockstor/etc/nginx/nginx.conf.backup
Now use your favorite editor to modify your existing nginx.conf:
vim /opt/rockstor/etc/nginx/nginx.conf
If you’re using vim, do a :set paste
to go to paste mode so you don’t get a bunch of line indentation problems. Now hit ‘i’ to insert and paste this in:
daemon off;
worker_processes 2;
events {
worker_connections 1024;
use epoll;
}
http {
include /opt/rockstor/etc/nginx/mime.types;
default_type application/octet-stream;
log_format main
'$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$gzip_ratio"';
client_header_timeout 10m;
client_body_timeout 10m;
send_timeout 10m;
connection_pool_size 256;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
request_pool_size 4k;
gzip on;
gzip_min_length 1100;
gzip_buffers 4 8k;
gzip_types text/plain;
output_buffers 1 32k;
postpone_output 1460;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 75 20;
ignore_invalid_headers on;
index index.html index.php;
# Servers
server {
listen 80;
server_name .your-domain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name main.your-domain.com;
ssl_certificate /opt/rockstor/certs/rockstor.cert;
ssl_trusted_certificate /opt/rockstor/certs/rockstor.cert;
ssl_certificate_key /opt/rockstor/certs/rockstor.key;
ssl_dhparam /opt/rockstor/certs/dhparam.pem;
ssl_buffer_size 8k;
ssl_session_timeout 1d;
ssl_session_cache builtin:1000 shared:SSL:50m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 10s;
add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload";
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;
location /site_media {
root /media/; # Notice this is the /media folder that we create above
}
location ~* ^.+\.(zip|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|mov) {
access_log off;
expires 30d;
}
location /static {
root /opt/rockstor/;
}
location /logs {
root /opt/rockstor/src/rockstor/;
}
location / {
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 75;
proxy_read_timeout 120;
proxy_pass http://127.0.0.1:8000/;
}
location /socket.io {
proxy_pass http://127.0.0.1:8001/socket.io;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
server {
listen 443 ssl;
server_name chat.your-domain.com;
error_log /var/log/nginx/rocketchat.access.log;
ssl_certificate /opt/rockstor/certs/rockstor.cert;
ssl_certificate_key /opt/rockstor/certs/rockstor.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # dont use SSLv3 ref: POODLE
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:3000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forward-Proto http;
proxy_set_header X-Nginx-Proxy true;
proxy_redirect off;
}
}
server {
listen 443 ssl;
server_name cloud.your-domain.com;
error_log /var/log/nginx/owncloud.access.log;
ssl_certificate /opt/rockstor/certs/rockstor.cert;
ssl_trusted_certificate /opt/rockstor/certs/rockstor.cert;
ssl_certificate_key /opt/rockstor/certs/rockstor.key;
ssl_dhparam /opt/rockstor/certs/dhparam.pem;
ssl_buffer_size 8k;
ssl_session_timeout 1d;
ssl_session_cache builtin:1000 shared:SSL:50m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 10s;
add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload";
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:8085;
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;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header Host $host;
}
}
}
The last step is to obviously modify your front end gateway/router to only have SSL/HTTPS open for incoming connections. Just go to your WAN settings and add SSL/443 to your port forwarding rules and have it point to your internal Rockstor server. Make sure you have a secure username/password configuration for your Rockstor front end GUI.
If anyone has a suggestion on how to bypass exposing the Rockstor GUI frontend, or think that this is a bad idea (I only have my username given GUI access and the password is intense) please let me know. I’m definitely not an nginx expert nor a Rockstor one, so any help is appreciated to make this instance more secure!
Then just restart your nginx service with:
service rockstor restart
Then test out your connections!
Regards,
exelan