Skip to content

Commit

Permalink
Relocate persistent data files.
Browse files Browse the repository at this point in the history
These need to be moved out of the gateway tree to better handle
upgrades and for data persistence when using Docker.
  • Loading branch information
Mike Stegeman committed Feb 12, 2018
1 parent f673aed commit 68cf5a1
Show file tree
Hide file tree
Showing 18 changed files with 113 additions and 55 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Expand Up @@ -5,9 +5,10 @@
.nyc_output/
/build
OZW_Log.txt
config/local.js
db.sqlite3
node_modules/
static/js/lib/stm_web.min.js
static/uploads/floorplan.svg
static/uploads
zwcfg_0x*.xml
zwscene.xml
9 changes: 5 additions & 4 deletions README.md
Expand Up @@ -121,10 +121,11 @@ $ yarn
The HTTPS server looks for privatekey.pem and certificate.pem. You can use a real certificate or generate a self-signed one by following the steps below.

```
$ mkdir -p ssl
$ openssl genrsa -out ssl/privatekey.pem 2048
$ openssl req -new -sha256 -key ssl/privatekey.pem -out ssl/csr.pem
$ openssl x509 -req -in ssl/csr.pem -signkey ssl/privatekey.pem -out ssl/certificate.pem
$ export SSL_DIR="$HOME/mozilla-iot/data/ssl"
$ [ ! -d "${SSL_DIR}" ] && mkdir -p "${SSL_DIR}"
$ openssl genrsa -out "${SSL_DIR}/privatekey.pem" 2048
$ openssl req -new -sha256 -key "${SSL_DIR}/privatekey.pem" -out "${SSL_DIR}/csr.pem"
$ openssl x509 -req -in "${SSL_DIR}/csr.pem" -signkey "${SSL_DIR}/privatekey.pem" -out "${SSL_DIR}/certificate.pem"
```

Start the web server:
Expand Down
16 changes: 11 additions & 5 deletions config/default.js
Expand Up @@ -8,13 +8,18 @@

'use strict';

const os = require('os');
const home = os.homedir();

module.exports = {
// Expose CLI
cli: true,

userConfigDir: `${home}/mozilla-iot/data/config`,

ports: {
https: 4443,
http: 8080
http: 8080,
},
// Whether the gateway is behind port forwarding and should use simplified
// port-free urls
Expand All @@ -25,7 +30,7 @@ module.exports = {
listUrl: 'https://raw.githubusercontent.com/mozilla-iot/addon-list/master/list.json',
},
database: {
filename: './db.sqlite3',
filename: `${home}/mozilla-iot/data/config/db.sqlite3`,
removeBeforeOpen: false,
},
ipc: {
Expand All @@ -44,7 +49,7 @@ module.exports = {
},
},
uploads: {
directory: '../static/uploads/' // Directory to store uploads in
directory: `${home}/mozilla-iot/data/static/uploads/`, // Directory to store uploads in
},
authentication: {
defaultUser: null,
Expand All @@ -55,7 +60,8 @@ module.exports = {
domain: 'mozilla-iot.org',
pagekite_cmd: './pagekite.py',
port: 443,
certemail: 'certificate@mozilla-iot.org'
certemail: 'certificate@mozilla-iot.org',
directory: `${home}/mozilla-iot/data/ssl`,
},
bcryptRounds: 2
bcryptRounds: 2,
};
11 changes: 0 additions & 11 deletions config/test.js
Expand Up @@ -26,15 +26,4 @@ module.exports = {
ipc: {
protocol: 'inproc',
},
settings: {
defaults: {
},
},
uploads: {
directory: '../../static/uploads/' // Directory to store uploads in
},
authentication: {
defaultUser: null,
},
bcryptRounds: 2
};
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -38,6 +38,7 @@
"greenlock": "^2.1.15",
"jsonwebtoken": "^8.1.0",
"le-challenge-dns": "https://github.com/mozilla-iot/le-challenge-dns",
"mkdirp": "^0.5.1",
"mustache-express": "^1.2.5",
"nanomsg": "^3.3.0",
"nocache": "^2.0.0",
Expand Down
2 changes: 1 addition & 1 deletion run-app.sh
Expand Up @@ -16,4 +16,4 @@ run_app() {
npm start
}

run_app > ${HOME}/mozilla-iot/gateway/run-app.log 2>&1
run_app > ${HOME}/mozilla-iot/data/log/run-app.log 2>&1
75 changes: 66 additions & 9 deletions src/app.js
Expand Up @@ -19,6 +19,7 @@ const GetOpt = require('node-getopt');
const config = require('config');
const path = require('path');
const mustacheExpress = require('mustache-express');
const mkdirp = require('mkdirp');
const addonManager = require('./addon-manager');
const db = require('./db');
const Router = require('./router');
Expand All @@ -34,6 +35,17 @@ require('./log-timestamps');
// This is then used in other places (like src/addons/plugin/ipc.js)
require('./app-instance');

// Relocate the database before opening it, if necessary.
const dbPath = config.get('database.filename');
const dbDir = path.dirname(dbPath);
if (!fs.existsSync(dbPath)) {
mkdirp.sync(dbDir);
}

if (fs.existsSync('db.sqlite3')) {
fs.renameSync('db.sqlite3', dbPath);
}

// Open the database
db.open();

Expand All @@ -57,20 +69,65 @@ if (fs.existsSync('notunnel')) {
}

// Move certificates, if necessary. If this throws an error, let it bubble up.
if (!fs.existsSync('ssl')) {
fs.mkdirSync('ssl');
const sslDir = config.get('ssltunnel.directory');
if (!fs.existsSync(sslDir)) {
mkdirp.sync(sslDir);
}

if (fs.existsSync('privatekey.pem')) {
fs.renameSync('privatekey.pem', path.join('ssl', 'privatekey.pem'));
fs.renameSync('privatekey.pem', path.join(sslDir, 'privatekey.pem'));
} else if (fs.existsSync('ssl/privatekey.pem')) {
fs.renameSync('ssl/privatekey.pem', path.join(sslDir, 'privatekey.pem'));
}

if (fs.existsSync('certificate.pem')) {
fs.renameSync('certificate.pem', path.join('ssl', 'certificate.pem'));
fs.renamesync('certificate.pem', path.join(sslDir, 'certificate.pem'));
} else if (fs.existsSync('ssl/certificate.pem')) {
fs.renameSync('ssl/certificate.pem', path.join(sslDir, 'certificate.pem'));
}

if (fs.existsSync('chain.pem')) {
fs.renameSync('chain.pem', path.join('ssl', 'chain.pem'));
fs.renameSync('chain.pem', path.join(sslDir, 'chain.pem'));
} else if (fs.existsSync('ssl/chain.pem')) {
fs.renameSync('ssl/chain.pem', path.join(sslDir, 'chain.pem'));
}

if (fs.existsSync('ssl')) {
fs.rmdirSync('ssl');
}

// Move old uploads, if necessary.
const uploadDir = config.get('uploads.directory');
if (!fs.existsSync(uploadDir)) {
mkdirp.sync(uploadDir);
}

const oldUploadDir = `${__dirname}/../static/uploads`;
if (fs.existsSync(oldUploadDir) && fs.lstatSync(oldUploadDir).isDirectory()) {
const fnames = fs.readdirSync(oldUploadDir);
for (const fname of fnames) {
fs.renameSync(path.join(oldUploadDir, fname), path.join(uploadDir, fname));
}

fs.rmdirSync(oldUploadDir);
fs.symlinkSync(uploadDir, oldUploadDir);
}

// Create a user config if one doesn't exist.
const userConfig = config.get('userConfigDir');
if (!fs.existsSync(userConfig)) {
mkdirp.sync(userConfig);
}

const userConfigPath = path.join(userConfig, 'local.js');
if (!fs.existsSync(userConfigPath)) {
fs.writeFileSync(
userConfigPath, '\'use strict\';\n\nmodule.exports = {\n};');
}

const localConfigPath = `${__dirname}/../config/local.js`;
if (!fs.existsSync(localConfigPath)) {
fs.symlinkSync(userConfigPath, localConfigPath);
}

let httpServer = http.createServer();
Expand All @@ -86,11 +143,11 @@ function createHttpsServer() {

// HTTPS server configuration
const options = {
key: fs.readFileSync(path.join('ssl', 'privatekey.pem')),
cert: fs.readFileSync(path.join('ssl', 'certificate.pem'))
key: fs.readFileSync(path.join(sslDir, 'privatekey.pem')),
cert: fs.readFileSync(path.join(sslDir, 'certificate.pem'))
};
if (fs.existsSync(path.join('ssl', 'chain.pem'))) {
options.ca = fs.readFileSync(path.join('ssl', 'chain.pem'));
if (fs.existsSync(path.join(sslDir, 'chain.pem'))) {
options.ca = fs.readFileSync(path.join(sslDir, 'chain.pem'));
}
return https.createServer(options);
}
Expand Down
7 changes: 4 additions & 3 deletions src/controllers/settings_controller.js
Expand Up @@ -180,9 +180,10 @@ SettingsController.post('/subscribe', async (request, response) => {
console.log('success', results);

// ok. we got the certificates. let's save them
fs.writeFileSync(path.join('ssl', 'certificate.pem'), results.cert);
fs.writeFileSync(path.join('ssl', 'privatekey.pem'), results.privkey);
fs.writeFileSync(path.join('ssl', 'chain.pem'), results.chain);
const sslDir = config.get('ssltunnel.directory');
fs.writeFileSync(path.join(sslDir, 'certificate.pem'), results.cert);
fs.writeFileSync(path.join(sslDir, 'privatekey.pem'), results.privkey);
fs.writeFileSync(path.join(sslDir, 'chain.pem'), results.chain);

// now we associate user's emails with the subdomain, unless it was
// reclaimed.
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/uploads_controller.js
Expand Up @@ -16,7 +16,7 @@ const path = require('path');
const config = require('config');
const Constants = require('../constants');

const UPLOADS_PATH = path.join(__dirname, config.get('uploads.directory'));
const UPLOADS_PATH = config.get('uploads.directory');
const FLOORPLAN_PATH = path.join(UPLOADS_PATH, 'floorplan.svg');
const FALLBACK_FLOORPLAN_PATH = path.join(Constants.STATIC_PATH,
'images',
Expand Down
5 changes: 3 additions & 2 deletions src/ssltunnel.js
Expand Up @@ -95,8 +95,9 @@ var TunnelService = {

// method to check if the box has certificates
hasCertificates: function() {
return fs.existsSync(path.join('ssl', 'certificate.pem')) &&
fs.existsSync(path.join('ssl', 'privatekey.pem'));
const sslDir = config.get('ssltunnel.directory');
return fs.existsSync(path.join(sslDir, 'certificate.pem')) &&
fs.existsSync(path.join(sslDir, 'privatekey.pem'));
},

// method to check if the box has a registered tunnel
Expand Down
2 changes: 1 addition & 1 deletion src/test/run-tests.sh
Expand Up @@ -2,7 +2,7 @@

SCRIPTDIR="$(dirname ""$0"")"

if [ ! -f "ssl/certificate.pem" ]; then
if [ ! -f "$HOME/mozilla-iot/data/ssl/certificate.pem" ]; then
${SCRIPTDIR}/../../tools/make-self-signed-cert.sh
fi

Expand Down
5 changes: 3 additions & 2 deletions src/tunnel_setup.js
Expand Up @@ -33,8 +33,9 @@ var TunnelSetup = {
}

// then we check if we have certificates installed
if ((fs.existsSync(path.join('ssl', 'certificate.pem'))
&& fs.existsSync(path.join('ssl', 'privatekey.pem')))
const sslDir = config.get('ssltunnel.directory');
if ((fs.existsSync(path.join(sslDir, 'certificate.pem'))
&& fs.existsSync(path.join(sslDir, 'privatekey.pem')))
|| notunnel) {
// if certs are installed,
// then we don't need to do anything and return
Expand Down
Empty file removed ssl/.gitkeep
Empty file.
1 change: 0 additions & 1 deletion static/uploads/README.md

This file was deleted.

2 changes: 1 addition & 1 deletion tools/config-editor.py
Expand Up @@ -9,7 +9,7 @@
import tempfile


_DEFAULT_DATABASE = '/home/pi/mozilla-iot/gateway/db.sqlite3'
_DEFAULT_DATABASE = '/home/pi/mozilla-iot/data/db.sqlite3'
_DEFAULT_EDITOR = 'nano'


Expand Down
10 changes: 5 additions & 5 deletions tools/deploy-certificates.sh
@@ -1,15 +1,15 @@
#!/bin/bash

gateway_dir="/home/pi/mozilla-iot/gateway"
ssl_dir="/home/pi/mozilla-iot/data/ssl"

# Make sure the certificate and private key files are never world readable.
umask 077

# Copy in the new certs.
mkdir -p "${gateway_dir}/ssl"
cp "${RENEWED_LINEAGE}/chain.pem" "${gateway_dir}/ssl/chain.pem"
cp "${RENEWED_LINEAGE}/cert.pem" "${gateway_dir}/ssl/certificate.pem"
cp "${RENEWED_LINEAGE}/privkey.pem" "${gateway_dir}/ssl/privatekey.pem"
[ ! -d "${ssl_dir}" ] && mkdir -p "${ssl_dir}"
cp "${RENEWED_LINEAGE}/chain.pem" "${ssl_dir}/chain.pem"
cp "${RENEWED_LINEAGE}/cert.pem" "${ssl_dir}/certificate.pem"
cp "${RENEWED_LINEAGE}/privkey.pem" "${ssl_dir}/privatekey.pem"

# Restart the gateway.
systemctl restart mozilla-iot-gateway.service
9 changes: 5 additions & 4 deletions tools/make-self-signed-cert.sh
Expand Up @@ -2,7 +2,8 @@

set -x

mkdir -p ssl
openssl genrsa -out ssl/privatekey.pem 2048
openssl req -new -sha256 -key ssl/privatekey.pem -out ssl/csr.pem -subj '/CN=www.toizom.com/O=MozillaIoT Gateway/C=US'
openssl x509 -req -in ssl/csr.pem -signkey ssl/privatekey.pem -out ssl/certificate.pem
export SSL_DIR="${HOME}/mozilla-iot/data/ssl"
[ ! -d "${SSL_DIR}" ] && mkdir -p "${SSL_DIR}"
openssl genrsa -out "${SSL_DIR}/privatekey.pem" 2048
openssl req -new -sha256 -key "${SSL_DIR}/privatekey.pem" -out "${SSL_DIR}/csr.pem" -subj '/CN=www.toizom.com/O=MozillaIoT Gateway/C=US'
openssl x509 -req -in "${SSL_DIR}/csr.pem" -signkey "${SSL_DIR}/privatekey.pem" -out "${SSL_DIR}/certificate.pem"
8 changes: 4 additions & 4 deletions tools/manual-renew-certs.sh
Expand Up @@ -120,13 +120,13 @@ kill -15 $(<"${pagekite_pidfile}") >/dev/null 2>&1
rm -f "${pagekite_pidfile}"

echo "Copying in new certificates."
mkdir -p "${moziot_dir}/gateway/ssl"
mkdir -p "${moziot_dir}/data/ssl"
cp "${moziot_dir}/etc/live/${domain}/cert.pem" \
"${moziot_dir}/gateway/ssl/certificate.pem"
"${moziot_dir}/data/ssl/certificate.pem"
cp "${moziot_dir}/etc/live/${domain}/privkey.pem" \
"${moziot_dir}/gateway/ssl/privatekey.pem"
"${moziot_dir}/data/ssl/privatekey.pem"
cp "${moziot_dir}/etc/live/${domain}/chain.pem" \
"${moziot_dir}/gateway/ssl/chain.pem"
"${moziot_dir}/data/ssl/chain.pem"

echo "Registering domain with server."
curl "http://api.mozilla-iot.org/setemail" \
Expand Down

0 comments on commit 68cf5a1

Please sign in to comment.