When using the node-mysql npm package, is it possible to connect to the MySQL server using a SSH key instead of a password?
You can do the SSH tunnel component completely independently, and then point node-mysql (or any other sql client...) to your DB by using TCP tunneled over SSH.
Just set up your SSH tunnel like this
ssh -N -p 22 sqluser#remoteserverrunningmysql.your.net -L 33306:localhost:3306
Leave that going in the background (see articles like this for more in depth info).
Then just send any MySQL client to port 33306 on localhost. It will actually connect as though you are on your remote server and using port 3306.
Thanks so much Steve your answer help me alot. just to make it clearer use
ssh -f user#personal-server.com -L 2000:personal-server.com:25 -N
The -f tells ssh to go into the background just before it executes the command. This is followed by the username and server you are logging into. The -L 2000:personal-server.com:25 is in the form of -L local-port:host:remote-port. Finally the -N instructs OpenSSH to not execute a command on the remote system
To connect to mongo use whatever port you set as Local port (in this case the port is 2000)
For example let's say I want to connect on a remote server with IP 192.168.0.100 and mongo is running on port 27017.
Assume a user called elie with password eliepassword has access to ssh on port 22 I will have to do this
First run on the terminal the following :
ssh -f elie#192.168.0.100 -L 2002:127.0.0.1:27017 -N
In my mongo connection I will do :
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:2002/mydatabase');
module.exports = mongoose.connection;
I hope this makes it clear.
const mysql = require('mysql2');
const { Client } = require('ssh2');
const sshClient = new Client();
const dbServer = {
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE
}
const tunnelConfig = {
host: process.env.DB_SSH_HOST,
port: 22,
username: process.env.DB_SSH_USER,
password: process.env.DB_SSH_PASSWORD
}
const forwardConfig = {
srcHost: '127.0.0.1',
srcPort: 3306,
dstHost: dbServer.host,
dstPort: dbServer.port
};
const SSHConnection = new Promise((resolve, reject) => {
sshClient.on('ready', () => {
sshClient.forwardOut(
forwardConfig.srcHost,
forwardConfig.srcPort,
forwardConfig.dstHost,
forwardConfig.dstPort,
(err, stream) => {
if (err) reject(err);
const updatedDbServer = {
...dbServer,
stream
};
const connection = mysql.createConnection(updatedDbServer);
connection.connect((error) => {
if (error) {
reject(error);
}
resolve(connection);
});
});
}).connect(tunnelConfig);
});
Related
I'm trying to build and deploy my app to OVH server, my client doesn't want a cloud solution, he want to host it or deploy it on OVH (they told me OVH support Node.js) and to be honest i have no idea how to do it.
my project work fine in development, its a Real-time chat with socket.io and MySql and some package as knex, in front-end i worked with React.js ( which i have no problem with it right now )
I can provide more informations if needed. thx a lot
const app = require("express")();
var cors = require("cors");
app.use(cors());
const server = require("http").createServer(app);
const mysql = require("mysql");
const knex = require("knex")({
client: "mysql",
connection: {
host: "localhost",
user: "root",
password: "",
database: "chat_message",
},
});
const io = require("socket.io")(server, {
cors: {
origin: "*",
credentials: true,
},
});
app.get("/messages", function (request, result) {
knex
.select()
.table("messages")
.then((data) => result.send(data))
});
io.on("connection", (socket) => {
socket.on("messageClient", (sms) => {
knex("messages")
.insert({
message: sms.msg,
socket_id: sms.id,
dateMsg: sms.Temps,
ip: sms.ip,
name: sms.name,
})
.then((e) => console.log("data insert succees"));
socket.broadcast.emit("messageAll", sms);
});
});
server.listen(5000, () => console.log("Port: 5000"));
OVH is a private company and I'm not sure if this would be offtopic and more suitable to ask their own support. However you should know that shared hosting in general does not support long running processes like nodejs. They only support PHP on the server.
I'm struggling to connect a redis deployment to my nodejs app. Of course locally without the use of docker, it works well, so I'm at odds as to whether this is an issue to do with my code, or the way I've set up my docker compose file
Dockerfile:
FROM node:8
WORKDIR /app
COPY package.json /app
COPY . /app
RUN npm install
CMD ["npm", "start"]
EXPOSE 3000
docker-compose.yml
version: "3"
services:
web:
container_name: web-container
restart: always
depends_on:
- redis
build: .
ports:
- "3000:3000"
links:
- redis
redis:
container_name: redis-container
image: "redis:latest"
ports:
- "6379:6379"
volumes:
- ./data:/data
Redis Connection File (RedisService.js)
const redis = require("redis");
const client = redis.createClient();
const DbUtils = require("../../db_utils");
const {promisify} = require("util");
const getAsync = promisify(client.get).bind(client);
const existsAsync = promisify(client.exists).bind(client);
class RedisCache {
constructor () {
var connected;
// * Initiliase the connection to redis server
client.on("connect", () => {console.log("📒 Redis cache is ready"); connected = true;})
client.on("error", (e) => {console.log("Redis cache error:\n" + e); connected = false;});
}
async setData (id, data) {
// * Stringify data if it's an object
data = data instanceof Object ? JSON.stringify(data) : data;
client.set(id, data);
return true;
}
async getData (key) {
return getAsync(key).then(data => {
data = JSON.parse(data) instanceof Object ? JSON.parse(data) : data;
return data;
})
}
async exists (key) {
return existsAsync(key).then(bool => {
return bool;
})
}
// Returns status of redis cache
async getStatus () {
return this.connected;
}
}
module.exports = new RedisCache();
ERROR
Error: Redis connection to 127.0.0.11:6379 failed - connect ECONNREFUSED 127.0.0.11:6379
When you run your containers via docker-compose they are all connected to a common network. Service name is a DNS name of given container so to access redis container from web you should create the client like :
const client = redis.createClient({
port : 6379,
host : 'redis'
});
You have not configured the host so it uses the default one - 127.0.0.1. But from the point of view of your web container the redis is not running on the localhost. Instead it runs in it's own container which DNS name is redis.
The beginning (docker part) of this tutorial worked for me :
https://medium.com/geekculture/using-redis-with-docker-and-nodejs-express-71dccd495fd3
docker run -d --name <CONTAINER_NAME> -p 127.0.0.1:6379:6379 redis
then in the node server (like in official redis website example) :
const redis = require('redis');
async function start() {
const client = redis.createClient(6379,'127.0.0.1');
await client.connect();
await client.set('mykey', 'Hello from node redis');
const myKeyValue = await client.get('mykey');
console.log(myKeyValue);
}
start();
gun 0.8.8, Node.js-to-Node.js, Node.js-to-browser
I see the following error in browser console:
VM103:161 WebSocket connection to 'wss://127.0.0.1:8080/gun' failed: Error in connection establishment: net::ERR_INSECURE_RESPONSE
VM103:161 WebSocket connection to 'wss://10.42.0.56:8080/gun' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
And there are no messages on Node.js side.
Sorce code of my server:
const Hapi = require('hapi');
const Gun = require('gun');
const pem = require('pem');
pem.createCertificate({ days: 1, selfSigned: true }, function (err, keys) {
if (err) {
throw err
}
const server = new Hapi.Server;
var tls = {
key: keys.serviceKey,
cert: keys.certificate
};
server.connection({
port: 8080,
tls
});
server.connections.forEach(c => Gun({ web: c.listener, file: 'data.json' }));
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
reply('Server works!');
}
});
server.start();
})
In order to make gun work with a self-signed certificate you need two things:
Lunch browser ignoring the certificate errors. For example, Chrome
google-chrome --ignore-certificate-errors
Put the following process option in Node.js code
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
or add the environment variable
export NODE_TLS_REJECT_UNAUTHORIZED=0
I tried to connect the DB via MySQL Java Script as below:
var mysql = require('mysql');
var con = mysql.createConnection({
host: "******",
user: "******",
password: "******"
});
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
});
And I'm using Node to execute, While I execute the above program getting the below error message:
if (err) throw err;
^
Error: connect ECONNREFUSED XX.XXX.XX.XXX:3306
at Object.exports._errnoException (util.js:1018:11)
at exports._exceptionWithHostPort (util.js:1041:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1086:14)
Also I have pinged my ip address (ping XX.XXX.XX.XXX) and can able to get the response. Can help me to connect the DB.
I had the same issue and the error resolved by adding the socketPath parameter
var connection = mysql.createConnection({
user: 'user',
password: 'pass',
socketPath: '/var/run/mysqld/mysqld.sock',
database: 'dbname'
});
I highly suggest creating a connectionPool to save your resources. Here is how I did it:
//import settings.js
const db_config = {
hostname : "localhost",
user : settings.user, //username
password : settings.password, //password
database : settings.database //db
}
//create db connection pool
const con = mysql.createPool(db_config);
So the next step is to use that connection pool! Don't be scared about the async/bluebird nature of this code, it's just how I built it.
async function query(sql, params) {
const connection = await con.getConnectionAsync();
return connection.queryAsync(sql,params)
.then(rows => rows)
.finally(() => connection.release());
}
This is grabbing the connection getConnection method (Async is from bluebird promisifying the method), and using the query method (async'd), and then finally releasing the connection back into the pool. This helps save you from memory leaks caused by unclosed TCP connections.
Make sure that you also specify the port if you have changed it from the default MySQL port as well.
I can't get socket.io running on OpenShift. I googled for some hours now but nothing really helped me. Locally it works fine (with different ports and localhost as host of course).
This is my server.js file:
var port = process.env.OPENSHIFT_NODEJS_PORT || 8080;
var ipadr = process.env.OPENSHIFT_NODEJS_IP || "127.0.0.1";
var http = require('http').createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end();
}).listen(port,ipadr);
console.log(port+":"+ipadr);
var io = require('socket.io').listen(http),
fs = require('fs'),
request = require('request'),
mysql = require('mysql'),
moment = require('moment'),
connectionsArray = [],
connection = mysql.createConnection({
host: 'xxx',
user: 'xxx',
password: 'xxx',
database: 'xxx',
port: 3306
}),
POLLING_INTERVAL = 1000,
pollingTimer;
io.on('connection', function(socket){
console.log('a user connected');
});
var updateSockets = function(data) {
// adding the time of the last update
t = new Date();
t = moment().format('H:mm:ss');
console.log('(%s) Connections: %s', t, connectionsArray.length);
// sending new data to all the sockets connected
connectionsArray.forEach(function(tmpSocket) {
tmpSocket.volatile.emit('notification', data);
});
};
console.log('server.js executed\n');
When I run this on SSH OpenShift it just shows the first console.log with my port and ipadress of OpenShift and the last line of my server.js code:
server.js executed
and that's it. So I don't get the "a user connected" message like when I test it locally.
This is how I want to connect in my client-side .js-file:
var socket = io.connect('http://njs-uniqo.rhcloud.com:8080/');
Browser (Chrome) Console outputs:
> ?s=product&id=10:1 XMLHttpRequest cannot load http://xxx.rhcloud.com:8000/socket.io/?EIO=3&transport=polling&t=1430395459829-1.
> No 'Access-Control-Allow-Origin' header is present on the requested
> resource. Origin 'http://localhost' is therefore not allowed access.
> The response had HTTP status code 503.
If I change the port to 8080 on the client-side .js-file I get ERR_CONNECTION_TIMED_OUT:
GET http://xxx.rhcloud.com:8080/socket.io/?EIO=3&transport=polling&t=1430395346761-6 net::ERR_CONNECTION_TIMED_OUT
You need to use port 8000. It's what openshift forces for websockets.
var socket = io.connect('http://yourapp.rhcloud.com:8000/',{'forceNew':true });
Port 8000 is for http and 8443 is for https
Source
You must edit package.json. Add...
"socket.io": "~0.9.16"
...under dependencies. The server then automatically downloads socket.io which is not present by default.