Improve environment variable stuff
This commit is contained in:
parent
760ee07a2e
commit
6ba174cff0
16 changed files with 66 additions and 64 deletions
24
.env.example
Normal file
24
.env.example
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
export DEBUG="hostr*"
|
||||||
|
|
||||||
|
export NODE_ENV=development
|
||||||
|
export PORT=4040
|
||||||
|
export WEB_BASE_URL=http://localhost:$PORT
|
||||||
|
export API_BASE_URL=http://localhost:$PORT/api
|
||||||
|
export UPLOAD_STORAGE_PATH=$HOME/.hostr/uploads
|
||||||
|
export COOKIE_KEY=INSECURE
|
||||||
|
export EMAIL_FROM=
|
||||||
|
export EMAIL_NAME=
|
||||||
|
|
||||||
|
export STATSD_HOST=localhost
|
||||||
|
export MONGO_URL=mongodb://localhost:27017/hostr
|
||||||
|
export REDIS_URL=redis://localhost:6379
|
||||||
|
export MANDRILL_KEY=
|
||||||
|
export STRIPE_SECRET_KEY=
|
||||||
|
export STRIPE_PUBLIC_KEY=
|
||||||
|
|
||||||
|
# optional, some functionality will be disabled
|
||||||
|
export AWS_ACCESS_KEY_ID=
|
||||||
|
export AWS_SECRET_ACCESS_KEY=
|
||||||
|
export AWS_BUCKET=
|
||||||
|
export VIRUSTOTAL_KEY=
|
||||||
|
export SENTRY_DSN=
|
40
README.md
40
README.md
|
@ -19,39 +19,11 @@ You'll need `graphicsmagick` for image thumbnailing, everything else is taken ca
|
||||||
|
|
||||||
### Enviroment Variable Configuration
|
### Enviroment Variable Configuration
|
||||||
|
|
||||||
`AWS_ACCESS_KEY_ID`
|
See [`.env.example`](.env.example). Copy it to `.env`, modify and `source .env` for development. [autoenv](https://github.com/kennethreitz/autoenv) is pretty nice for doing this automatically when you `cd` into your work directory.
|
||||||
|
|
||||||
`AWS_SECRET_ACCESS_KEY`
|
|
||||||
|
|
||||||
`AWS_BUCKET`
|
|
||||||
|
|
||||||
`MANDRILL_KEY`
|
|
||||||
|
|
||||||
`EMAIL_FROM` - defaults to `nobody@example.com`
|
|
||||||
|
|
||||||
`REDIS_URL` - defaults to `redis://localhost:6379`
|
|
||||||
|
|
||||||
`MONGO_URL` - defaults to `mongodb://localhost:27017/hostr`
|
|
||||||
|
|
||||||
`LOCAL_PATH` - defaults to `~/.hostr/uploads`.
|
|
||||||
|
|
||||||
`BASE_URL` - defaults to `https://localhost:4040`
|
|
||||||
|
|
||||||
`FILE_HOST` - used by API for absolute file urls, defaults to `$BASE_URL`
|
|
||||||
|
|
||||||
`API_URL` - defaults to `/api`
|
|
||||||
|
|
||||||
`PORT` - defaults to `4040`.
|
|
||||||
|
|
||||||
`VIRUSTOTAL` - API key enables Virustotal integration.
|
|
||||||
|
|
||||||
`SENTRY_DSN` - DSN enables Sentry integration.
|
|
||||||
|
|
||||||
Additionally, Hostr uses [debug](https://github.com/visionmedia/debug) so you can use the `DEBUG` environment variable something like `DEBUG=hostr*` to get debug output.
|
|
||||||
|
|
||||||
### Deploying to Heroku
|
### Deploying to Heroku
|
||||||
|
|
||||||
Because it uses iojs and graphicsmagick runtimes hostr needs an env variable for `BUILDPACK_URL` set to `https://github.com/ddollar/heroku-buildpack-multi.git`.
|
Because it uses iojs and graphicsmagick runtimes hostr needs an env variable for `BUILDPACK_URL` set to `https://github.com/ddollar/heroku-buildpack-multi.git` on Heroku.
|
||||||
|
|
||||||
You'll also need to add Heroku Redis and a MongoDB addon.
|
You'll also need to add Heroku Redis and a MongoDB addon.
|
||||||
|
|
||||||
|
@ -65,6 +37,14 @@ $ npm start
|
||||||
|
|
||||||
This will install and build the frontend too.
|
This will install and build the frontend too.
|
||||||
|
|
||||||
|
Alternatively
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm run watch
|
||||||
|
```
|
||||||
|
|
||||||
|
Will watch your JS and CSS for changes, rebuild them, and reload the server.
|
||||||
|
|
||||||
### Run the tests
|
### Run the tests
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -10,7 +10,7 @@ const debug = debugname('hostr-api');
|
||||||
|
|
||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
const statsdOpts = {prefix: 'hostr-api', host: process.env.STATSD_HOST || 'localhost'};
|
const statsdOpts = {prefix: 'hostr-api', host: process.env.STATSD_HOST};
|
||||||
router.use(stats(statsdOpts));
|
router.use(stats(statsdOpts));
|
||||||
const statsd = new StatsD(statsdOpts);
|
const statsd = new StatsD(statsdOpts);
|
||||||
router.use(function* statsMiddleware(next) {
|
router.use(function* statsMiddleware(next) {
|
||||||
|
|
|
@ -13,11 +13,11 @@ import { formatFile } from '../../lib/format';
|
||||||
import debugname from 'debug';
|
import debugname from 'debug';
|
||||||
const debug = debugname('hostr-api:file');
|
const debug = debugname('hostr-api:file');
|
||||||
|
|
||||||
const redisUrl = process.env.REDIS_URL || process.env.REDISTOGO_URL || 'redis://localhost:6379';
|
const redisUrl = process.env.REDIS_URL;
|
||||||
|
|
||||||
const fileHost = process.env.FILE_HOST || 'http://localhost:4040';
|
const baseURL = process.env.WEB_BASE_URL;
|
||||||
|
|
||||||
const storePath = process.env.STORE_PATH || path.join(process.env.HOME, '.hostr', 'uploads');
|
const storePath = process.env.UPLOAD_STORAGE_PATH;
|
||||||
|
|
||||||
export function* post(next) {
|
export function* post(next) {
|
||||||
if (!this.request.is('multipart/*')) {
|
if (!this.request.is('multipart/*')) {
|
||||||
|
@ -60,7 +60,7 @@ export function* post(next) {
|
||||||
const fileId = yield hostrId(Files);
|
const fileId = yield hostrId(Files);
|
||||||
|
|
||||||
// Fire an event to let the frontend map the GUID it sent to the real ID. Allows immediate linking to the file
|
// Fire an event to let the frontend map the GUID it sent to the real ID. Allows immediate linking to the file
|
||||||
const acceptedEvent = `{"type": "file-accepted", "data": {"id": "${fileId}", "guid": "${tempGuid}", "href": "${fileHost}/${fileId}"}}`;
|
const acceptedEvent = `{"type": "file-accepted", "data": {"id": "${fileId}", "guid": "${tempGuid}", "href": "${baseURL}/${fileId}"}}`;
|
||||||
this.redis.publish('/user/' + this.user.id, acceptedEvent);
|
this.redis.publish('/user/' + this.user.id, acceptedEvent);
|
||||||
this.statsd.incr('file.upload.accepted', 1);
|
this.statsd.incr('file.upload.accepted', 1);
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ export function* post(next) {
|
||||||
this.status = 201;
|
this.status = 201;
|
||||||
this.body = formattedFile;
|
this.body = formattedFile;
|
||||||
|
|
||||||
if (process.env.VIRUSTOTAL) {
|
if (process.env.VIRUSTOTAL_KEY) {
|
||||||
// Check in the background
|
// Check in the background
|
||||||
process.nextTick(function* malwareScan() {
|
process.nextTick(function* malwareScan() {
|
||||||
debug('Malware Scan');
|
debug('Malware Scan');
|
||||||
|
|
|
@ -6,7 +6,7 @@ import passwords from 'passwords';
|
||||||
import debugname from 'debug';
|
import debugname from 'debug';
|
||||||
const debug = debugname('hostr-api:user');
|
const debug = debugname('hostr-api:user');
|
||||||
|
|
||||||
const redisUrl = process.env.REDIS_URL || process.env.REDISTOGO_URL || 'redis://localhost:6379';
|
const redisUrl = process.env.REDIS_URL;
|
||||||
|
|
||||||
export function* get() {
|
export function* get() {
|
||||||
this.body = this.user;
|
this.body = this.user;
|
||||||
|
|
4
app.js
4
app.js
|
@ -17,8 +17,10 @@ import web from './web/app';
|
||||||
import debugname from 'debug';
|
import debugname from 'debug';
|
||||||
const debug = debugname('hostr');
|
const debug = debugname('hostr');
|
||||||
|
|
||||||
|
debug(process.env.COOKIE_KEY);
|
||||||
|
|
||||||
const app = websockify(koa());
|
const app = websockify(koa());
|
||||||
app.keys = [process.env.KEYS || 'INSECURE'];
|
app.keys = [process.env.COOKIE_KEY];
|
||||||
|
|
||||||
if (process.env.SENTRY_DSN) {
|
if (process.env.SENTRY_DSN) {
|
||||||
const ravenClient = new raven.Client(process.env.SENTRY_DSN);
|
const ravenClient = new raven.Client(process.env.SENTRY_DSN);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { sniff } from './type';
|
import { sniff } from './type';
|
||||||
|
|
||||||
const fileHost = process.env.FILE_HOST || 'http://localhost:4040';
|
const baseURL = process.env.WEB_BASE_URL;
|
||||||
|
|
||||||
export function formatDate(timestamp) {
|
export function formatDate(timestamp) {
|
||||||
return moment.unix(timestamp).format('D MMM YY [at] h:mm A');
|
return moment.unix(timestamp).format('D MMM YY [at] h:mm A');
|
||||||
|
@ -25,7 +25,7 @@ export function formatFile(file) {
|
||||||
added: moment.unix(file.time_added).format(),
|
added: moment.unix(file.time_added).format(),
|
||||||
readableAdded: formatDate(file.time_added),
|
readableAdded: formatDate(file.time_added),
|
||||||
downloads: file.downloads !== undefined ? file.downloads : 0,
|
downloads: file.downloads !== undefined ? file.downloads : 0,
|
||||||
href: fileHost + '/' + file._id, // eslint-disable-line no-underscore-dangle
|
href: baseURL + '/' + file._id, // eslint-disable-line no-underscore-dangle
|
||||||
id: file._id, // eslint-disable-line no-underscore-dangle
|
id: file._id, // eslint-disable-line no-underscore-dangle
|
||||||
name: file.file_name,
|
name: file.file_name,
|
||||||
size: file.file_size,
|
size: file.file_size,
|
||||||
|
@ -40,8 +40,8 @@ export function formatFile(file) {
|
||||||
formattedFile.width = file.width;
|
formattedFile.width = file.width;
|
||||||
const ext = (file.file_name.split('.').pop().toLowerCase() === 'psd' ? '.png' : '');
|
const ext = (file.file_name.split('.').pop().toLowerCase() === 'psd' ? '.png' : '');
|
||||||
formattedFile.direct = {
|
formattedFile.direct = {
|
||||||
'150x': fileHost + '/file/150/' + file._id + '/' + file.file_name + ext, // eslint-disable-line no-underscore-dangle
|
'150x': baseURL + '/file/150/' + file._id + '/' + file.file_name + ext, // eslint-disable-line no-underscore-dangle
|
||||||
'970x': fileHost + '/file/970/' + file._id + '/' + file.file_name + ext, // eslint-disable-line no-underscore-dangle
|
'970x': baseURL + '/file/970/' + file._id + '/' + file.file_name + ext, // eslint-disable-line no-underscore-dangle
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return formattedFile;
|
return formattedFile;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import virustotal from 'virustotal.js';
|
import virustotal from 'virustotal.js';
|
||||||
|
|
||||||
virustotal.setKey(process.env.VIRUSTOTAL);
|
virustotal.setKey(process.env.VIRUSTOTAL_KEY);
|
||||||
|
|
||||||
const extensions = ['EXE', 'PIF', 'APPLICATION', 'GADGET', 'MSI', 'MSP', 'COM', 'SCR', 'HTA', 'CPL', 'MSC',
|
const extensions = ['EXE', 'PIF', 'APPLICATION', 'GADGET', 'MSI', 'MSP', 'COM', 'SCR', 'HTA', 'CPL', 'MSC',
|
||||||
'JAR', 'BAT', 'CMD', 'VB', 'VBS', 'VBE', 'JS', 'JSE', 'WS', 'WSF', 'WSC', 'WSH', 'PS1', 'PS1XML', 'PS2',
|
'JAR', 'BAT', 'CMD', 'VB', 'VBS', 'VBE', 'JS', 'JSE', 'WS', 'WSF', 'WSC', 'WSH', 'PS1', 'PS1XML', 'PS2',
|
||||||
|
|
|
@ -3,11 +3,9 @@ const MongoClient = mongodb().MongoClient;
|
||||||
import debugname from 'debug';
|
import debugname from 'debug';
|
||||||
const debug = debugname('hostr:mongo');
|
const debug = debugname('hostr:mongo');
|
||||||
|
|
||||||
const uristring = process.env.MONGO_URL || process.env.MONGOLAB_URI || 'mongodb://localhost:27017/hostr';
|
|
||||||
|
|
||||||
const configuredClient = new Promise((resolve, reject) => {
|
const configuredClient = new Promise((resolve, reject) => {
|
||||||
debug('Connecting to Mongodb');
|
debug('Connecting to Mongodb');
|
||||||
return MongoClient.connect(uristring).then((client) => {
|
return MongoClient.connect(process.env.MONGO_URL).then((client) => {
|
||||||
debug('Successfully connected to Mongodb');
|
debug('Successfully connected to Mongodb');
|
||||||
client.Users = client.collection('users');
|
client.Users = client.collection('users');
|
||||||
client.Files = client.collection('files');
|
client.Files = client.collection('files');
|
||||||
|
|
|
@ -5,7 +5,7 @@ import session from 'koa-generic-session';
|
||||||
import debugname from 'debug';
|
import debugname from 'debug';
|
||||||
const debug = debugname('hostr:redis');
|
const debug = debugname('hostr:redis');
|
||||||
|
|
||||||
const redisUrl = process.env.REDIS_URL || process.env.REDISTOGO_URL || 'redis://localhost:6379';
|
const redisUrl = process.env.REDIS_URL;
|
||||||
|
|
||||||
const connection = new Promise((resolve, reject) => {
|
const connection = new Promise((resolve, reject) => {
|
||||||
debug('Connecting to Redis');
|
debug('Connecting to Redis');
|
||||||
|
|
10
lib/s3.js
10
lib/s3.js
|
@ -3,17 +3,15 @@ import s3UploadStream from 's3-upload-stream';
|
||||||
import debugname from 'debug';
|
import debugname from 'debug';
|
||||||
const debug = debugname('hostr:s3');
|
const debug = debugname('hostr:s3');
|
||||||
|
|
||||||
const bucket = process.env.AWS_BUCKET || 'hostrdotcodev';
|
|
||||||
|
|
||||||
const s3 = new aws.S3();
|
const s3 = new aws.S3();
|
||||||
const s3Stream = s3UploadStream(s3);
|
const s3Stream = s3UploadStream(s3);
|
||||||
|
|
||||||
export function get(key) {
|
export function get(key) {
|
||||||
debug('fetching file: %s', 'hostr_files/' + key);
|
debug('fetching from s3: %s', 'hostr_files/' + key);
|
||||||
return s3.getObject({Bucket: bucket, Key: 'hostr_files/' + key}).createReadStream();
|
return s3.getObject({Bucket: process.env.AWS_BUCKET, Key: 'hostr_files/' + key}).createReadStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function upload(key) {
|
export function upload(key) {
|
||||||
debug('Uploading file: %s', 'hostr_files/' + key);
|
debug('sending to s3: %s', 'hostr_files/' + key);
|
||||||
return s3Stream.upload({Bucket: bucket, Key: 'hostr_files/' + key});
|
return s3Stream.upload({Bucket: process.env.AWS_BUCKET, Key: 'hostr_files/' + key});
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ function range(start, stop) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const storePath = process.env.FILE_PATH || path.join(process.env.HOME, '.hostr', 'uploads');
|
const storePath = process.env.UPLOAD_STORAGE_PATH;
|
||||||
|
|
||||||
const directories = range('A', 'Z').concat(range('a', 'z'), range('0', '9'));
|
const directories = range('A', 'Z').concat(range('a', 'z'), range('0', '9'));
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ const router = new Router();
|
||||||
|
|
||||||
router.use(errors({template: path.join(__dirname, 'public', 'error.html')}));
|
router.use(errors({template: path.join(__dirname, 'public', 'error.html')}));
|
||||||
|
|
||||||
const statsdOpts = {prefix: 'hostr-web', host: process.env.STATSD_HOST || 'localhost'};
|
const statsdOpts = {prefix: 'hostr-web', host: process.env.STATSD_HOST};
|
||||||
router.use(stats(statsdOpts));
|
router.use(stats(statsdOpts));
|
||||||
const statsd = new StatsD(statsdOpts);
|
const statsd = new StatsD(statsdOpts);
|
||||||
router.use(function* statsMiddleware(next) {
|
router.use(function* statsMiddleware(next) {
|
||||||
|
@ -29,8 +29,8 @@ router.use(redis.sessionStore());
|
||||||
router.use(function* stateMiddleware(next) {
|
router.use(function* stateMiddleware(next) {
|
||||||
this.state = {
|
this.state = {
|
||||||
session: this.session,
|
session: this.session,
|
||||||
apiURL: process.env.API_URL,
|
baseURL: process.env.WEB_BASE_URL,
|
||||||
baseURL: process.env.BASE_URL,
|
apiURL: process.env.API_BASE_URL,
|
||||||
stripePublic: process.env.STRIPE_PUBLIC_KEY,
|
stripePublic: process.env.STRIPE_PUBLIC_KEY,
|
||||||
};
|
};
|
||||||
yield next;
|
yield next;
|
||||||
|
|
|
@ -94,11 +94,11 @@ export function* signup(email, password, ip) {
|
||||||
};
|
};
|
||||||
Users.insertOne(user);
|
Users.insertOne(user);
|
||||||
|
|
||||||
const html = yield render('email/inlined/activate', {activationUrl: process.env.BASE_URL + '/activate/' + user.activationCode});
|
const html = yield render('email/inlined/activate', {activationUrl: process.env.WEB_BASE_URL + '/activate/' + user.activationCode});
|
||||||
const text = `Thanks for signing up to Hostr!
|
const text = `Thanks for signing up to Hostr!
|
||||||
Please confirm your email address by clicking the link below.
|
Please confirm your email address by clicking the link below.
|
||||||
|
|
||||||
${process.env.BASE_URL + '/activate/' + user.activationCode}
|
${process.env.WEB_BASE_URL + '/activate/' + user.activationCode}
|
||||||
|
|
||||||
— Jonathan Cremin, Hostr Founder
|
— Jonathan Cremin, Hostr Founder
|
||||||
`;
|
`;
|
||||||
|
@ -130,9 +130,9 @@ export function* sendResetToken(email) {
|
||||||
'token': token,
|
'token': token,
|
||||||
'created': Math.round(new Date().getTime() / 1000),
|
'created': Math.round(new Date().getTime() / 1000),
|
||||||
});
|
});
|
||||||
const html = yield render('email/inlined/forgot', {forgotUrl: process.env.BASE_URL + '/forgot/' + token});
|
const html = yield render('email/inlined/forgot', {forgotUrl: process.env.WEB_BASE_URL + '/forgot/' + token});
|
||||||
const text = `It seems you've forgotten your password :(
|
const text = `It seems you've forgotten your password :(
|
||||||
Visit ${process.env.BASE_URL + '/forgot/' + token} to set a new one.
|
Visit ${process.env.WEB_BASE_URL + '/forgot/' + token} to set a new one.
|
||||||
`;
|
`;
|
||||||
mandrill.messages.send({message: {
|
mandrill.messages.send({message: {
|
||||||
html: html,
|
html: html,
|
||||||
|
|
|
@ -3,7 +3,7 @@ import mime from 'mime-types';
|
||||||
import hostrFileStream from '../../lib/hostr-file-stream';
|
import hostrFileStream from '../../lib/hostr-file-stream';
|
||||||
import { formatFile } from '../../lib/format';
|
import { formatFile } from '../../lib/format';
|
||||||
|
|
||||||
const storePath = process.env.STORE_PATH || path.join(process.env.HOME, '.hostr', 'uploads');
|
const storePath = process.env.UPLOAD_STORAGE_PATH;
|
||||||
|
|
||||||
function userAgentCheck(userAgent) {
|
function userAgentCheck(userAgent) {
|
||||||
if (!userAgent) {
|
if (!userAgent) {
|
||||||
|
|
|
@ -6,8 +6,8 @@ const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
|
||||||
import { Mandrill } from 'mandrill-api/mandrill';
|
import { Mandrill } from 'mandrill-api/mandrill';
|
||||||
const mandrill = new Mandrill(process.env.MANDRILL_KEY);
|
const mandrill = new Mandrill(process.env.MANDRILL_KEY);
|
||||||
|
|
||||||
const fromEmail = process.env.EMAIL_FROM || 'nobody@example.com';
|
const fromEmail = process.env.EMAIL_FROM;
|
||||||
const fromName = process.env.EMAIL_NAME || 'Nobody';
|
const fromName = process.env.EMAIL_NAME;
|
||||||
|
|
||||||
export function* create() {
|
export function* create() {
|
||||||
const Users = this.db.Users;
|
const Users = this.db.Users;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue