forked from TryGhost/Ghost-CLI
/
index.js
126 lines (105 loc) · 4.23 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
'use strict';
const fs = require('fs-extra');
const url = require('url');
const path = require('path');
const execa = require('execa');
const validator = require('validator');
const Promise = require('bluebird');
const NginxConfFile = require('nginx-conf').NginxConfFile;
const BaseService = require('../base');
class NginxService extends BaseService {
init() {
this.on('setup', 'setup');
this.command('nginx-conf', 'setupConf');
this.command('nginx-ssl', 'setupSSL');
// TODO implement
// this.command('ssl-renew', 'renewSSL');
}
get parsedUrl() {
return url.parse(this.config.get('url'));
}
setup(context) {
// This is the result from the `ghost doctor setup` command - it will be false
// if nginx does not exist on the system
if (!context.nginx) {
return;
}
if (this.parsedUrl.port) {
this.ui.log('Your url contains a port. Skipping automatic nginx setup.', 'yellow');
return;
}
if (this.parsedUrl.pathname !== '/') {
this.ui.log('The Nginx service does not support subdirectory configurations yet. Skipping automatic nginx setup.', 'yellow');
return;
}
let prompts = [{
type: 'confirm',
name: 'ssl',
message: 'Do you want to set up your blog with SSL (using letsencrypt)?',
default: true
}, {
type: 'input',
name: 'email',
message: 'Enter your email (used for ssl registration)',
when: ans => ans.ssl,
validate: email => validator.isEmail(email) || 'Invalid email'
}];
if (this.config.environment === 'development') {
prompts.splice(1, 0, {
type: 'confirm',
name: 'staging',
message: 'You are running in development mode. Would you like to use letsencrypt\'s' +
' staging servers instead of the production servers?',
default: true,
when: ans => ans.ssl
});
}
let answers;
let ghostExec = process.argv.slice(0,2).join(' ');
return this.ui.prompt(prompts).then((_answers) => {
answers = _answers;
return this.ui.noSpin(execa.shell(`sudo ${ghostExec} service nginx-conf${!answers.ssl ? ' no-ssl' : ''}`, {stdio: 'inherit'}));
}).then(() => {
if (answers.ssl) {
return this.ui.noSpin(execa.shell(`sudo ${ghostExec} service nginx-ssl ${answers.email}${answers.staging ? ' staging' : ''}`, {
stdio: 'inherit'
}));
}
});
}
setupConf(ssl) {
let isSSL = (!ssl || ssl !== 'no-ssl');
let confFile = `${this.parsedUrl.hostname}.conf`;
let confFilePath = `/etc/nginx/sites-available/${confFile}`;
fs.ensureFileSync(confFilePath);
fs.ensureSymlinkSync(confFilePath, `/etc/nginx/sites-enabled/${confFile}`);
return Promise.fromNode((cb) => NginxConfFile.create(confFilePath, cb)).then((conf) => {
conf.nginx._add('server');
conf.nginx.server._add('listen', '80');
conf.nginx.server._add('listen', '[::]:80');
conf.nginx.server._add('server_name', this.parsedUrl.hostname);
let rootPath = path.resolve(process.cwd(), 'root');
fs.ensureDirSync(rootPath);
conf.nginx.server._add('root', rootPath);
conf.nginx.server._add('location', '/');
this._addProxyBlock(conf.nginx.server.location);
if (isSSL) {
conf.nginx.server._add('location', '~ /.well-known');
conf.nginx.server.location[1]._add('allow', 'all');
}
}).then(() => {
return execa.shell('service nginx restart', {stdio: 'inherit'});
});
}
setupSSL(/* email, staging */) {
}
_addProxyBlock(location) {
location._add('proxy_set_header', 'X-Real-IP $remote_addr');
location._add('proxy_set_header', 'Host $http_host');
location._add('proxy_pass', `http://127.0.0.1:${this.config.get('server.port')}`);
}
};
module.exports = {
name: 'nginx',
class: NginxService
};