Sử dụng chung MongoDB database cho cả development và production
nodejs
82
mongodb
14
ssh
13
ssh-tunnel
3
White

Hùng Phong viết ngày 14/12/2018

Tất nhiên đây chỉ là một trick không hề được khuyến khích áp dụng vào bất cứ một dự án Company nào (vốn đòi hỏi yêu cầu bảo mật và an toàn dữ liệu cực kì lớn). App của mình cũng nhỏ thôi, và mình thì... lười. Giả sử như có một bảng user, tất nhiên, user phải vượt qua màn đăng nhập mới được phép truy cập vào app. Và một quãng thời gian đen đủi xảy ra, bạn phải vác chính cái app của mình đi deploy hết từ máy này cho đến máy nọ, vì mất lap, vì chó ỉa lên bàn phím hay sao sao đó chẳng hạn thì việc phải tạo ra một cái DB nữa cho development server nó khiến bạn muốn chán sống đúng không?

Mấy cái chuyện như thế này vốn có nhiều cách giải quyết mà. Dump sẵn một database demo phía client cũng được. Tái sử dụng mongoDB database phía server như mình cũng là một lựa chọn. Chả cái nào hơn cái nào, về phía mình, chỉ là... mình không có nhiều thời gian đi nghiên cứu những cái gì khiến chuyện mình phải focus vào cái app trở nên khó kiểm soát thôi. Mình chỉ là một frontend developer kiêm fullstack developer cho một startup cỡ nhỏ, và bản thân mình nghèo kiết xác k có tiền túi để thuê đứa khác làm giùm mấy cái backend này.

Public port 27017

Cảnh báo cực mạnh: trong mọi trường hợp, đây là cách làm nguy hiểm, trừ khi bạn đã thiết lập chặt chẽ việc bảo mật quá trình kết nối đến MongoDB bằng auth và SSL/TLS hoặc mấy thứ tương tự.

Nói đến chuyện SSL/TLS, chừng nào mình nghiên cứu xong vụ này mình sẽ có một bài viết, đây là trò mình khá thích. Thiết lập Nginx như là một stream reverse-proxy cho MongoDB phía sau hoặc public cổng 27017 rồi cài đặt để bắt buộc sử dụng SSL/TLS khi kết nối chẳng hạn.

Trò này thì đơn giản thôi không khó. Mở file mongod.conf lên (thường thì nằm ở /etc/mongod.conf vì server mình chạy CentOS), comment out dòng bind_ip đi hoặc khai báo rõ nó như dưới đây

# Listen to local interface only. Comment out to listen on all interfaces. 
# bind_ip=127.0.0.1
bind_ip=0.0.0.0

Rồi khởi động lại Mongo là xong. Dưới development, sửa lại localhost thành IP của server, ví dụ mongodb://user:password@aaa.bbb.ccc.ddd/database

SSH Tunnel

Về mặt hình thức thì trò này cũng tương tự như việc bạn sử dụng Robo3T hay mấy phần mềm MongoAdmin tương tự, cho phép kết nối đến mongo server thông qua SSH Tunnel. Kết nối từ máy local sẽ không đi thẳng đến mongo server mà thông qua SSH trước, bằng cách này, tất nhiên sẽ không cần phải public port 27017 nữa, vẫn đảm bảo tính an toàn cho dữ liệu bên trong MongoDB. Để giữ an toàn cho việc đọc/ghi dữ liệu, đừng quên thiết lập bảo mật cho SSH (ví dụ bắt buộc đăng nhập có mật khẩu hay sử dụng private key nhằm mã hoá kết nối SSH cũng như tránh việc bị thằng mấy dạy nào đó chôm được quyền đăng nhập vào server, nhất là tài khoản root, nói tới đây tự hiểu hậu quả nhe).

Bản thân NodeJS có một vài package cho phép hỗ trợ tunnel SSH kiểu này, mình thì ưa thích dùng package tunnel-ssh. Cách sử dụng tunnel-ssh để kết nối đến mongoDB phía server được demo chi tiết trong đoạn code dưới đây

// dev-tunnel.js
import tunnel from 'tunnel-ssh'
import fs from 'fs'

const devSSHTunnel = cb => {
  const sshConfig = {
    host: 'aaa.bbb.ccc.ddd',
    username: 'root',
    agent: process.env.SSH_AUTH_SOCK,
    privateKey: fs.readFileSync(process.env.DEV_SSH_PRIVATE_KEY, 'utf-8'),
    port: 22, // An toàn hơn nữa là đổi luôn cổng mặc định của SSH
    dstPort: 27017
  }

  tunnel(sshConfig, (err, server) => {
    if (err) {
      console.error(err.message)
      return
    }
    console.log('SSH connection successfully')
    cb()
  })
}

export default devSSHTunnel

// mongoose-connect.js
import mongoose from 'mongoose'
import devSSHTunnel from './dev-tunnel'

mongoose.Promise = global.Promise
const conf = {
  useNewUrlParser: true,
  // useMongoClient: true,
  poolSize: 2,
  promiseLibrary: global.Promise
}

function connectDevelopment() {
  return new Promise(resolve => {
    devSSHTunnel(() => {
      const connectPromise = mongoose.connect(
        'mongodb://user:pass@localhost/database',
        conf
      )
      var db = mongoose.connection
      db.on('error', console.error.bind(console, 'DB connection error:'))
      db.once('open', function() {
        console.log('DB connection successful')
      })
      resolve(connectPromise)
    })
  })
}

Mình chả biết viết linh tinh mấy cái này có giúp mình bớt gãy sau 14 tiếng liền ngủ vì cơ thể kiệt sức không chịu nổi. Nhưng thôi kệ, nevermind, anh em có cái để đọc để biết là được. Haha.

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Hùng Phong

4 bài viết.
28 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
26 12
Thương hiệu quen thuộc của mình mỗi khi bắt đầu một bài viết nghiêm túc nào luôn là một tràng dài dòng vớ vẩn tạm gọi là xả bớt nỗi lòng, tất nhiên...
Hùng Phong viết 8 tháng trước
26 12
White
12 6
Mình có đề trong CV là mình có kinh nghiệm ở mức tương đối vì UI/UX, dù không phải là một fulltime designer, đúng là có biết sử dụng Photoshop, Ske...
Hùng Phong viết 8 tháng trước
12 6
White
8 0
_Có mấy chia sẻ nhỏ, mình muốn đưa ra để mọi người cùng thảo luận góp ý. Thread này không tập trung vào Technical nữa mà discuss về Coding Style & ...
Hùng Phong viết 8 tháng trước
8 0
Bài viết liên quan
White
45 7
Giới thiệu MongoDB là một giải pháp nosql database. Data được lưu ở dạng các bson document. Hỗ trợ vertical scaling và horizontal scaling, dynamic...
manhdung viết 4 năm trước
45 7
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
4 bài viết.
28 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!