Using hosted version of Cloud9 with HTTPS


#1

I’d like to be able to host cloud9 from a home server & access it anywhere. I have a Let’s Encrypt certificate to use. Is there a way to do this?


#2

Hi,

You cannot use the hosted version on c9.io for this, however you could check out the Cloud9 SDK which is free for non-commercial use: https://github.com/c9/core


#3

Sorry for not being more specific. That’s actually what I’m using. I got it installed on a Raspberry Pi 3b (and it works great!). I’ve also been able to host a web page on the same device with Apache and a TLS certificate from Let’s Encrypt. I’ve also purchased a domain and setup dynamic DNS (home internet, no static IP).

Also, I start the c9 server with this command:
node server.js -l 0.0.0.0 -p 80 -a <username>:<password> &

Thanks!


#4

I’m getting closer. I’m able to host a node.js server over TLS with the help of these answers:

However, I’m not sure where to put this code (I have zero knowledge of node.js). It doesn’t look like it would go in core/server.js. Any help here would be great.

Oh, and the other issue is that when using an example script, I had to run it as root in order for it to be able to read the certificates. I was able to run the Cloud9 SDK with my user account listening on port 8181, and use an iptables command to redirect port 80 traffic to 8181. So now the issue is running the Cloud9 SKD as the user account and still have it able to read the TLS certs.

Edit:
So I found this article that looks like it’ll walk me through using Nginx as a reverse proxy to serve up HTTPS. I was thinking about using Apache for this since I already have it installed, but I’ve been reading some good things about Nginx. I’ll try this out & report back on how it goes.


#5

Speaking as an operational engineer working with node projects (c9.io namely ;))

I would just add a reverse proxy on the same machine to front the SSL. Node has had many vulnerabilities in the past in their SSL library, something more mature like nginx/haproxy/apache would be more suitable, and can be configured in a couple lines, and requires no modification of the upstream code.

If you already have apache set up, the reverse proxy setup is simple. Something like this would do it (presuming you have vhosts set up already, otherwise just change the port/name/etc):

<VirtualHost *:80>
	ServerAdmin foo@example.com
	ServerName <%= @title %>
	ServerAlias <%= @title %>
	Redirect / https://<%= @title %>/
</VirtualHost>

<VirtualHost *:443>
	ServerAdmin foo@example.com
	ServerName <%= @title %>
	ServerAlias <%= @title %>
	ErrorLog "/var/log/httpd/<%= @title %>_error.log"
	TransferLog "/var/log/httpd/<%=@title %>_access.log"

	SSLEngine On
	SSLCertificateFile    /etc/ssl/certs/<%= @title %>.crt
	SSLCertificateKeyFile /etc/ssl/private/<%= @title %>.pem
	SSLCertificateChainFile /etc/ssl/certs/sub.class1.server.ca.pem
	SSLCACertificateFile /etc/ssl/certs/ca.pem
	ProxyPass / <%= @destination %>/ retry=0
	ProxyPassReverse / <%= @destination %>/
	<% if /http:/.match(destination) -%>
	RequestHeader append X-Forwarded-Proto "https"
	<% end -%>
</VirtualHost>

#6

Thanks! I’m still new to web hosting. Would that be in the /etc/apache2/sites-available/000-default.conf file?

Also, how would I then start the Cloud9 SDK node.js server? Would I still use whatever high port number to prevent from running as root (e.g. port 8181)? How would apache know to direct the traffic there?


#7

In case anyone wants to know, I followed the DigitalOcean article in one of my previous posts (https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-16-04#manage-application-with-pm2) to get this working. The only thing I did differently is the pm2 start command.

I used: pm2 start /home/<user>/core/server.js -- -w ~/workspace/ -l 0.0.0.0 -p 8080 -a <username>:<password>

Having the -- in there allowed me to start pass the arguments to the server script and not the pm2 command.


#8

Sorry to come back to this after so long, but I’m finally getting around to working on this again. I’m able to get apache to act as a reverse proxy & point to my cloud9 SDK over HTTP. But I can’t seem to get it to work over HTTPS. Your example here does’t seem to work. In fact, the apache2 service won’t run giving errors.

When I try using these lines:

ProxyPass / <%= @destination %>/ retry=0
ProxyPassReverse / <%= @destination %>/

The apache error says, “Invalid ProxyPass|ProxyPassMatch parameter. Parameter must be in the form ‘key=value’.”

When I try using these lines:

<% if /http:/.match(destination) -%>
RequestHeader append X-Forwarded-Proto "https"
<% end -%>

The apache error says, “Expected < /%> but saw < /VirtualHost>” (I had to add spaces to get these tags to show up)

Originally, I was trying to follow this article:

I had my 000-default.conf file looking like this:

<VirtualHost *:80>
        ServerAdmin admin@domain.com
        DocumentRoot /var/www/html
        ServerName domain.com
        ServerAlias www.domain.com
        Redirect / https://domain.com/
</VirtualHost>

<VirtualHost *:443>
        SSLEngine On
        SSLCertificateFile    /etc/letsencrypt/live/domain.com/cert.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/domain.com/privkey.pem
        SSLCertificateChainFile /etc/letsencrypt/live/domain.com/chain.pem

        ProxyPreserveHost On
        ProxyPass / http://127.0.0.1:8080/
        ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>

I should also mention that putting those last 3 Proxy lines in the VirtualHost *:80 section & removing the Redirct works. Apache will point me to my cloud9 SDK, but over HTTP of course.


#9

Ok, I figured out what the issue was. I realized that there were other sites enabled that needed to be removed. I had to a2dissite 000-default-le-ssl.conf and a2dissite default-le-ssl.conf not realizing that apache was looking at those configurations as well. I didn’t think about it before because other changes I made to the 000-default.conf file were being reflected. Just not the ProxyPass.


#10

couldn’t find a solution for actually using the built in functions of c9 sdk so here is what I did.

In your letsencrypt live certificate folder convert your privkey.pem to an rsa encrypted key with the following

openssl rsa -in privkey.pem -out privkey_rsa.pem

you can test this to see if it still matches if the outputs of the following 2 commands match

openssl rsa -noout -modulus -in privkey_rsa.pem | openssl md5
openssl x509 -noout -modulus -in fullchain.pem | openssl md5

next you need to create a file that combines your newly generated rsa private key with the fullchain cert.
touch combined_key.pem | cat privkey_rsa.pem fullchain.pem >> combined_key.pem

start server by adding the --secure <path/combined_key.pem> to arguments

node server.js -l 0.0.0.0 -p 8443 -a username:pass --secure ./combined_key.pem


#11

Thanks for the reply! Using node server.js --help doesn’t reveal that --secure option.


#12

No Problem was trying to find answers for it everywhere dug through the code
found what i needed in the following:

to determine the certificate requirements i found this first but also found it in the script with the options(below)
c9sdk/scripts/create-cert.sh

and for the secure option i found that in the standalone.js file lines 113-120
c9sdk/configs/standalone.js

if (argv.secure) {
var certPath = path.isAbsolute(argv.secure) ? argv.secure : path.join(__dirname, “…”, argv.secure);
var key = require(“fs”).readFileSync(certPath , “utf8”);
config.secure = {
key: key.match(/^(-+BEGIN RSA PRIVATE KEY[\s\S]*END RSA PRIVATE KEY-+)/m)[0],
cert: key.match(/^(-+BEGIN CERTIFICATE[\s\S]*END CERTIFICATE-+)/m)[0],
};
}


#13

Thanks that helped a lot !!!