use environment variables for configuration

This commit is contained in:
jomo 2020-03-28 23:47:23 +01:00
parent d81e2777d2
commit d967db3ad4
10 changed files with 97 additions and 78 deletions

6
.gitignore vendored
View File

@ -1,9 +1,3 @@
images/*/*.png images/*/*.png
node_modules/ node_modules/
coverage/ coverage/
.DS_Store
*.log
*.rdb
*.sublime-*
config.js
lib/public/images/sponsor.png

View File

@ -1,8 +1,29 @@
FROM node:12-alpine FROM node:12-alpine
ARG REDIS_URL ARG AVATAR_MIN
ARG DEBUG ARG AVATAR_MAX
ARG AVATAR_DEFAULT
ARG RENDER_MIN
ARG RENDER_MAX
ARG RENDER_DEFAULT
ARG FACE_DIR
ARG HELM_DIR
ARG SKIN_DIR
ARG RENDER_DIR
ARG CAPE_DIR
ARG CACHE_LOCAL
ARG CACHE_BROWSER
ARG EPHEMERAL_STORAGE ARG EPHEMERAL_STORAGE
ARG REDIS_URL
ARG PORT
ARG BIND
ARG EXTERNAL_HTTP_TIMEOUT
ARG DEBUG
ARG LOG_TIME
ARG SPONSOR_SIDE
ARG TOP_RIGHT
ENV NODE_ENV production
RUN apk --no-cache --virtual .build-deps add git python build-base RUN apk --no-cache --virtual .build-deps add git python build-base
RUN apk --no-cache --virtual .canvas-deps add cairo-dev pango-dev jpeg-dev giflib-dev RUN apk --no-cache --virtual .canvas-deps add cairo-dev pango-dev jpeg-dev giflib-dev
@ -15,8 +36,7 @@ RUN mkdir -p /crafatar/images/capes
VOLUME /crafatar/images VOLUME /crafatar/images
COPY package.json www.js crafatar/ COPY package.json www.js config.js crafatar/
COPY config.example.js crafatar/config.js
COPY lib/ crafatar/lib/ COPY lib/ crafatar/lib/
WORKDIR /crafatar WORKDIR /crafatar

View File

@ -53,17 +53,9 @@ docker run --net crafatar -d --name redis redis
docker run --net crafatar -v crafatar-images:/crafatar/images -e REDIS_URL=redis://redis -p 3000:3000 crafatar/crafatar docker run --net crafatar -v crafatar-images:/crafatar/images -e REDIS_URL=redis://redis -p 3000:3000 crafatar/crafatar
``` ```
## Environment variables ## Configration / Environment variables
| Variable | Default | Description | See the `config.js` file.
| :- | :- | :- |
| `BIND` | `0.0.0.0` | Hostname to listen on |
| `PORT` | `3000` | Port to listen on |
| `DEBUG` | `false` | Enable verbose debug logging |
| `REDIS_URL` | `redis://127.0.0.1:6379` | URI of the redis server |
| `EPHEMERAL_STORAGE` | | If set, redis is flushed on start* |
\* Use this to avoid issues when you have a persistent redis database but an ephemeral storage
# Operational notes # Operational notes

View File

@ -1,40 +0,0 @@
var config = {
avatars: {
min_size: 1, // for avatars
max_size: 512, // for avatars; too big values might lead to slow response time or DoS
default_size: 160 // for avatars; size to be used when no size given
},
renders: {
min_scale: 1, // for 3D rendered skins
max_scale: 10, // for 3D rendered skins; too big values might lead to slow response time or DoS
default_scale: 6 // for 3D rendered skins; scale to be used when no scale given
},
cleaner: {
interval: 600, // interval seconds to check limits
disk_limit: 524288, // min allowed free KB on disk to trigger image deletion
redis_limit: 24576, // max allowed used KB on redis to trigger redis flush
amount: 50000 // amount of skins for which all image types are deleted
},
directories: {
faces: "./images/faces/", // directory where faces are kept. must have trailing "/"
helms: "./images/helms/", // directory where helms are kept. must have trailing "/"
skins: "./images/skins/", // directory where skins are kept. must have trailing "/"
renders: "./images/renders/", // directory where rendered skins are kept. must have trailing "/"
capes: "./images/capes/" // directory where capes are kept. must have trailing "/"
},
caching: {
local: 1200, // seconds until we will check if user's skin changed. should be > 60 to comply with Mojang's rate limit
browser: 3600 // seconds until browser will request image again
},
server: {
http_timeout: 2000, // ms until connection to Mojang is dropped
debug_enabled: false, // enables logging.debug & editing index page
log_time: true // set to false if you use an external logger that provides timestamps
},
sponsor: {
sidebar: '<hr><div class="list-group"><a class="list-group-item sponsor-item" href="https://akliz.net/crafatar" target="_blank" title="Applies to all modpacks and plans for the first billing cycle only.">Save 20% on a Minecraft server with Akliz.</a></div>',
top_right: '<a href="https://akliz.net/crafatar" target="_blank" title="Crafatar is sponsored by Akliz" class="sponsor"><img src="/images/sponsor.png" alt="Akliz"></a>'
},
};
module.exports = config;

60
config.js Normal file
View File

@ -0,0 +1,60 @@
var config = {
avatars: {
// for avatars
min_size: parseInt(process.env.AVATAR_MIN) || 1,
// for avatars; large values might lead to slow response time or DoS
max_size: parseInt(process.env.AVATAR_MAX) || 512,
// for avatars; size to be used when no size given
default_size: parseInt(process.env.AVATAR_DEFAULT) || 160
},
renders: {
// for 3D rendered skins
min_scale: parseInt(process.env.RENDER_MIN) || 1,
// for 3D rendered skins; large values might lead to slow response time or DoS
max_scale: parseInt(process.env.RENDER_MAX) || 10,
// for 3D rendered skins; scale to be used when no scale given
default_scale: parseInt(process.env.RENDER_DEFAULT) || 6
},
directories: {
// directory where faces are kept. must have trailing "/"
faces: process.env.FACE_DIR || "./images/faces/",
// directory where helms are kept. must have trailing "/"
helms: process.env.HELM_DIR || "./images/helms/",
// directory where skins are kept. must have trailing "/"
skins: process.env.SKIN_DIR || "./images/skins/",
// directory where rendered skins are kept. must have trailing "/"
renders: process.env.RENDER_DIR || "./images/renders/",
// directory where capes are kept. must have trailing "/"
capes: process.env.CAPE_DIR || "./images/capes/"
},
caching: {
// seconds until we will check if user's skin changed.
// Should be > 60 to comply with Mojang's rate limit
local: parseInt(process.env.CACHE_LOCAL) || 1200,
// seconds until browser will request image again
browser: parseInt(process.env.CACHE_BROWSER) || 3600,
// If true, redis is flushed on start.
// Use this to avoid issues when you have a persistent redis database but an ephemeral storage
ephemeral: process.env.EPHEMERAL_STORAGE === "true" || false,
},
// URL of your redis server
redis: process.env.REDIS_URL || 'redis://localhost:6379',
server: {
// port to listen on
port: parseInt(process.env.PORT) || 3000,
// IP address to listen on
bind: process.env.BIND || "0.0.0.0",
// ms until connection to Mojang is dropped
http_timeout: parseInt(process.env.EXTERNAL_HTTP_TIMEOUT) || 2000,
// enables logging.debug & editing index page
debug_enabled: process.env.DEBUG === "true" || false,
// set to false if you use an external logger that provides timestamps,
log_time: process.env.LOG_TIME === "true" || true,
},
sponsor: {
sidebar: process.env.SPONSOR_SIDE,
top_right: process.env.SPONSOR_TOP_RIGHT
},
};
module.exports = config;

View File

@ -1,7 +1,6 @@
var logging = require("./logging"); var logging = require("./logging");
var node_redis = require("redis"); var node_redis = require("redis");
var config = require("../config"); var config = require("../config");
var url = require("url");
var redis = null; var redis = null;
@ -9,19 +8,10 @@ var redis = null;
// flushes redis when using ephemeral storage (e.g. Heroku) // flushes redis when using ephemeral storage (e.g. Heroku)
function connect_redis() { function connect_redis() {
logging.log("connecting to redis..."); logging.log("connecting to redis...");
// parse redis env redis = node_redis.createClient(config.redis);
var redis_env = process.env.REDISCLOUD_URL || process.env.REDIS_URL;
var redis_url = redis_env ? url.parse(redis_env) : {};
redis_url.port = redis_url.port || 6379;
redis_url.hostname = redis_url.hostname || "localhost";
// connect to redis
redis = node_redis.createClient(redis_url.port, redis_url.hostname);
if (redis_url.auth) {
redis.auth(redis_url.auth.split(":")[1]);
}
redis.on("ready", function() { redis.on("ready", function() {
logging.log("Redis connection established."); logging.log("Redis connection established.");
if (process.env.EPHEMERAL_STORAGE) { if (config.caching.ephemeral) {
logging.log("Storage is ephemeral, flushing redis"); logging.log("Storage is ephemeral, flushing redis");
redis.flushall(); redis.flushall();
} }

View File

@ -32,7 +32,7 @@ exp.warn = function() {
exp.error = function() { exp.error = function() {
log("ERROR", arguments, console.error); log("ERROR", arguments, console.error);
}; };
if (config.server.debug_enabled || process.env.DEBUG === "true") { if (config.server.debug_enabled) {
exp.debug = function() { exp.debug = function() {
log("DEBUG", arguments); log("DEBUG", arguments);
}; };

View File

@ -35,7 +35,6 @@ a.forkme:hover {
a.sponsor { a.sponsor {
position: fixed; position: fixed;
z-index: 1041;
width: 48px; width: 48px;
height: 48px; height: 48px;
right: 0px; right: 0px;
@ -43,6 +42,11 @@ a.sponsor {
margin: 5px; margin: 5px;
} }
.sponsor img {
width: 100%;
height: 100%;
}
a.sponsor-item { a.sponsor-item {
color: #aa7100 !important; color: #aa7100 !important;
font-weight: initial; font-weight: initial;

View File

@ -136,8 +136,8 @@ function requestHandler(req, res) {
var exp = {}; var exp = {};
exp.boot = function(callback) { exp.boot = function(callback) {
var port = process.env.PORT || 3000; var port = config.server.port;
var bind_ip = process.env.BIND || "0.0.0.0"; var bind_ip = config.server.bind;
server = http.createServer(requestHandler).listen(port, bind_ip, function() { server = http.createServer(requestHandler).listen(port, bind_ip, function() {
logging.log("Server running on http://" + bind_ip + ":" + port + "/"); logging.log("Server running on http://" + bind_ip + ":" + port + "/");
if (callback) { if (callback) {
@ -149,7 +149,7 @@ exp.boot = function(callback) {
// wait for established connections to finish (30s max), // wait for established connections to finish (30s max),
// then exit // then exit
process.on("SIGTERM", function() { process.on("SIGTERM", function() {
logging.warn("Got SIGTERM, no longer accepting connections!"); logging.warn("Got SIGTERM, no longer accepting new connections!");
setTimeout(function() { setTimeout(function() {
logging.error("Dropping connections after 30s. Force quit."); logging.error("Dropping connections after 30s. Force quit.");

View File

@ -25,7 +25,6 @@
"avatar" "avatar"
], ],
"scripts": { "scripts": {
"postinstall": "cp 'config.example.js' 'config.js'",
"start": "node www.js", "start": "node www.js",
"test": "mocha", "test": "mocha",
"test-travis": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage" "test-travis": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage"