From @boustanihani:
Please could anyone post the steps needed for configuring sails to use HTTPS and also redirect HTTP calls to HTTPS ?? Such important info is sadly still missing on the sails website!
Regards from Berlin
Hani
More than 4 months old~
So, did anybdy actually fix this issue?
My guess is no :confused:
So having this same issue here is how I worked around this issue. To force HTTPS for production only environments -
module.exports = {
policies:{
'*': 'isHTTPS'
}
};
```
module.exports = function(req, res, next) {
var schema = req.headers['x-forwarded-proto'] || '';
if (schema === 'https') {
// Already https; don't do anything special.
next();
} else {
// Redirect to https.
res.redirect('https://' + req.headers.host + req.url);
}
};
```
If you have this setup when you then lift sails with the --prod option it will
then force all requests from http to https.
sails lift --prod
or
node app.js --prod
In terms of setting up the ssl certs with sails.js - that will depend on your environment, if you use heroku for hosting, nothing you need to do in the sails configuration but if you are hosting say on your own server - you could update your config/env/production.js environmental config file to be -
var fs = require('fs');
module.exports = {
policies:{
'*': 'isHTTPS'
},
ssl : {
key: fs.readFileSync('path-to-key.key'),
cert: fs.readFileSync('path-to-crt.crt')
}
};
if (schema === 'https') was not working for me, so I changed it to if(req.secure) and also in bootstrap.js I had to write the code to listen to port 80.
if(sails.config.environment === "production" || sails.config.environment === "staging") {
http.createServer( sails.hooks.http.app ).listen( 80 );
}
You can also set port:80 on env/production.js
Not sure why this is closed. Is there any documentation that indicates the proper way to do this?
@dadepra @skullerj In some cases, you can solve this before any requests actually get to Sails, but if not, then you might add something like this in api/hooks/lifejacket/index.js:
/**
* Module dependencies
*/
var util = require('util');
var _ = require('@sailshq/lodash');
var flaverr = require('flaverr');
/**
* lifejacket hook
*
* @description :: A hook definition. Extends Sails by adding shadow routes, implicit actions, and/or initialization logic.
* @docs :: http://sailsjs.com/docs/concepts/extending-sails/hooks
*/
module.exports = function defineLifejacketHook(sails) {
return {
defaults: {
lifejacket: {
// Disabled by default. (e.g. for local dev)
ensureHttps: false,
// Must be set manually if `ensureHttps` is enabled.
// > Should be provided as a string, like `foo.example.com`.
host: undefined
}
},
configure: function (){
// If `ensureHttps` config was provided...
if (!_.isUndefined(sails.config.lifejacket.ensureHttps)) {
// Validate it.
if (!_.isBoolean(sails.config.lifejacket.ensureHttps)) {
throw flaverr({ name: 'Configuration Error' }, new Error('If provided, `sails.config.lifejacket.ensureHttps` must be set to either `true` or `false`. But instead got: '+util.inspect(sails.config.lifejacket.ensureHttps, {depth:null})));
}
}//>-•
// If `host` config was provided...
if (!_.isUndefined(sails.config.lifejacket.host)) {
// Validate it.
if (!_.isString(sails.config.lifejacket.host)) {
throw flaverr({ name: 'Configuration Error' }, new Error('`sails.config.lifejacket.host` must be configured as a string (like `foo.example.com`). But instead got: '+util.inspect(sails.config.lifejacket.host, {depth:null})));
}
// Coerce it.
sails.config.lifejacket.host = _.trimRight(sails.config.lifejacket.host, '/');
sails.config.lifejacket.host = sails.config.lifejacket.host.replace(/^https?:\/\//, '');
}
// Otherwise, if it wasn't provided, make sure that's actually OK.
// (if ensureHttps is enabled, then it is required)
else {
if (sails.config.lifejacket.ensureHttps) {
throw flaverr({ name: 'Configuration Error' }, new Error('Since `sails.config.lifejacket.ensureHttps` is enabled, a valid `sails.config.lifejacket.host` must be configured as a string (like `foo.example.com`). But instead got: '+util.inspect(sails.config.lifejacket.host, {depth:null})));
}
}//>-•
},
/**
* Runs when a Sails app loads/lifts.
*
* @param {Function} done
*/
initialize: function (done) {
sails.log.debug(
'Initializing `lifejacket` hook... '+
(sails.config.lifejacket.ensureHttps ? '(https auto-redirects are ENABLED!)' : '(but https auto-redirects are disabled)')
);
// If this is production, but `lifejacket.ensureHttps` is NOT enabled, then
// log a little warning message to the console.
if (!sails.config.lifejacket.ensureHttps && process.env.NODE_ENV === 'production') {
sails.log.warn('Detected production environment, but "https://" auto-redirects are disabled!');
sails.log.warn('(Set `sails.config.lifejacket.ensureHttps` to `true` to turn them on again.)');
sails.log.warn();
}//-•
// Be sure and call `done()` when finished!
// (Pass in Error as the first argument if something goes wrong to cause Sails
// to stop loading other hooks and give up.)
return done();
},
routes: {
before: {
'all /*': function (req, res, next) {
// console.log('x-forwarded-proto:', req.get('x-forwarded-proto'));
// console.log('sails.config.lifejacket.ensureHttps:', req.get('sails.config.lifejacket.ensureHttps'));
// If the `lifejacket.ensureHttps` setting is disabled, then anything goes.
if (!sails.config.lifejacket.ensureHttps) {
return next();
}//-•
// If is a virtual request from a socket, then anything goes.
if (req.isSocket) {
return next();
}//-•
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// But otherwise, this is an HTTP request of some kind, and we must be
// interested in redirecting it, since we're configured to do so.
//
// Therefore, we'll check this request and see if it was originally sent
// via the `http://` protocol. If so, we'll redirect it to `https://`.
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// If this is https://, then we're good.
// (we'll go ahead and allow the request through)
if (req.get('x-forwarded-proto') === 'https') {
return next();
}//-•
// Otherwise, this is an insecure request to `http://`.
// So redirect it to its `https://` cousin.
return res.redirect(301, 'https://'+sails.config.lifejacket.host+req.url);
}//</ all /* >
}//</.before>
}//</.routes>
};
};
Why not put nginx in front of your sails server to handle SSL negotiation and redirecting users to HTTPS and allow for SSL stapling and other options.
This is a much better solution for a production environment as nginx is directly coded in C and much more performant than node. You can also make use of it as a load balancer to forward requests to many Sails backend servers for scalability and it can handle caching and serving static assets which will free up your sails server to not do those things and handle requests that need actual processing.
@rachaelshaw,@CWyrtzen,@benedictchen,@brettimus,@obj63mc,@mlakkadshaw,@skullerj,@dansandland,@matthewwiesen: Hello, I'm a repo bot-- nice to meet you!
It has been 30 days since there have been any updates or new comments on this page. If this issue has been resolved, feel free to disregard the rest of this message and simply close the issue if possible. On the other hand, if you are still waiting on a patch, please post a comment to keep the thread alive (with any new information you can provide).
If no further activity occurs on this thread within the next 3 days, the issue will automatically be closed.
Thanks so much for your help!
Most helpful comment
Not sure why this is closed. Is there any documentation that indicates the proper way to do this?