When running Feathers with PM2, calling app.get('property') returns invalid values.
config/default.js:
const serverMode = process.env['serverMode'] || 'worker'
module.exports = {
serverMode
}
src/app.js
const feathers = require('@feathersjs/feathers')
const configuration = require('@feathersjs/configuration')
const express = require('@feathersjs/express')
const app = express(feathers())
// Load app configuration
app.configure(configuration())
module.exports = app
src/index.js:
const app = require('./app')
// Feathers will return an invalid value here.
const serverMode = app.get('serverMode')
const server = app.listen(3000)
server.on('listening', () => {
console.info('Server started.', {serverMode})
})
ecosystem.config.js (the pm2 config file):
// Options reference: https://pm2.io/doc/en/runtime/reference/ecosystem-file/
module.exports = {
apps: [{
name: 'api',
script: 'src/index.js',
env: {
NODE_ENV: 'development',
NODE_APP_INSTANCE: 0,
serverMode: 'api'
}
}
]
}
Install pm2 with npm install -g pm2
Run pm2 from the project root (same directory as ecosystem.config.js):
pm2 start
Inspect the logs with pm2 logs --lines 100
The logs should show 0|api | Server started. { serverMode: 'api' }
The logs is showing 0|api | Server started. { serverMode: '{}' }
Tell us about the applicable parts of your setup.
Module versions (especially the part that's not working):
"@feathersjs/configuration": "^4.5.1",
"@feathersjs/express": "^4.5.1",
"@feathersjs/feathers": "^4.5.1",
NodeJS version: 12.16.0
Operating System:
Ubuntu 18
Browser Version: Not relevant.
React Native Version:
Module Loader: require
I have found the root cause of this issue.
The issue happens because one of the defined properties has the same name as another environment variable created by PM2 (the api variable).
I inspected the code for @feathersjs/configuration and found the place where the conversion takes place:
@feathersjs/configuration/lib/index.js version 4.5.1:
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const debug_1 = __importDefault(require("debug"));
const path_1 = __importDefault(require("path"));
const config_1 = __importDefault(require("config"));
const debug = debug_1.default('@feathersjs/configuration');
const separator = path_1.default.sep;
function init() {
return (app) => {
const convert = (current) => {
const result = Array.isArray(current) ? [] : {};
Object.keys(current).forEach(name => {
let value = current[name];
if (typeof value === 'object' && value !== null) {
value = convert(value);
}
if (typeof value === 'string') {
if (value.indexOf('\\') === 0) {
value = value.replace('\\', '');
}
else {
// WARNING: This line could introduce issues! It would be better to use a special syntax for denoting reusing environment variables, like '${envName}'.
if (process.env[value]) {
value = process.env[value];
}
if (value.indexOf('.') === 0 || value.indexOf('..') === 0) {
// Make relative paths absolute
value = path_1.default.resolve(path_1.default.join(config_1.default.util.getEnv('NODE_CONFIG_DIR')), value.replace(/\//g, separator));
}
}
}
result[name] = value;
});
return result;
};
const env = config_1.default.util.getEnv('NODE_ENV');
const conf = convert(config_1.default);
if (!app) {
return conf;
}
debug(`Initializing configuration for ${env} environment`);
Object.keys(conf).forEach(name => {
const value = conf[name];
debug(`Setting ${name} configuration value to`, value);
app.set(name, value);
});
return conf;
};
}
exports.default = init;
if (typeof module !== 'undefined') {
module.exports = Object.assign(init, module.exports);
}
//# sourceMappingURL=index.js.map
I had to change the ecosystem.config.js and rewrite the name of the application:
// Options reference: https://pm2.io/doc/en/runtime/reference/ecosystem-file/
module.exports = {
apps: [{
name: 'api-server', // THIS LINE HAS BEEN CHANGED TO FIX THE ISSUE.
script: 'src/index.js',
env: {
NODE_ENV: 'development',
NODE_APP_INSTANCE: 0,
serverMode: 'api'
}
}
]
}
I would suggest changing the behavior of Feathers/Configuration in order to avoid possible issues.
If a config file want to declare a variable that uses the environment variable, it could do something like:
serverURL: "${SERVER_URL}"
@daffl, please have a look here, it's an important issue that can cause subtle bugs.
@averri does the local auth works with pm2? I had to ask you here because I am also trying to deploy using pm2 and runs but local auth with rest api always returns 'Invalid login', even with right credentials.
But if i run it with forever or npm it works.
Hi @yohane55, yes, it does work for sure. I'm now using pm2 frequently. Here is one example of my ecosystem.config.js:
// Options reference: https://pm2.io/doc/en/runtime/reference/ecosystem-file/
module.exports = {
apps: [{
name: 'api-server',
script: 'src/',
watch: ['src'],
listen_timeout: 30000,
node_args: "--inspect --inspect-port=5000",
env: {
NODE_ENV: 'development',
NODE_APP_INSTANCE: 0,
serverMode: 'api',
useRedis: false,
redisURI: 'redis://localhost:6379',
bindPort: 4000,
useRateLimiter: true
}
},
{
name: 'worker-server',
script: 'src/',
watch: ['src'],
listen_timeout: 30000,
node_args: "--inspect --inspect-port=5001",
env: {
NODE_ENV: 'development',
NODE_APP_INSTANCE: 1,
serverMode: 'worker',
useRedis: false,
redisURI: 'redis://localhost:6379',
bindPort: 4001,
useRateLimiter: false
}
}
]
}
Do you have an authentication hook? If no, configure one and debug the before.all to see what credentials are coming from the client. You may also note something very important - in the configuration of the authentication service you need to escape the username field like this:
authentication: {
...
local: {
usernameField: "\\username",
passwordField: "password"
}
},
@averri Thank you so much and you are right I had to escape"\\username" and now it is working fine.
I have this problem with a feather app initially built with the version 2.
So I tried to upgrade to v4 but I still have this problem. I don't have the any serverMode in my app and if I try to change the name nothing changes.
With the username escaped properly the authentication is still not working on my instance of feathers when started by pm2.
With npm start or node src/ all good. As soonas i change the start to be made by pm2 authentication return not Authorized all the times.
Running on Linux, not windows.
@daffl Can you help ?