diff --git a/.gitignore b/.gitignore index 5990e30..c33eaad 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,3 @@ images/*/*.png node_modules/ coverage/ -.DS_Store -*.log -*.rdb -*.sublime-* -config.js -lib/public/images/sponsor.png diff --git a/Dockerfile b/Dockerfile index 7bd382b..d3688d7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,29 @@ FROM node:12-alpine -ARG REDIS_URL -ARG DEBUG +ARG AVATAR_MIN +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 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 .canvas-deps add cairo-dev pango-dev jpeg-dev giflib-dev @@ -15,8 +36,7 @@ RUN mkdir -p /crafatar/images/capes VOLUME /crafatar/images -COPY package.json www.js crafatar/ -COPY config.example.js crafatar/config.js +COPY package.json www.js config.js crafatar/ COPY lib/ crafatar/lib/ WORKDIR /crafatar diff --git a/README.md b/README.md index 14ebf03..1fd6e22 100644 --- a/README.md +++ b/README.md @@ -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 ``` -## Environment variables +## Configration / Environment variables -| Variable | Default | Description | -| :- | :- | :- | -| `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 +See the `config.js` file. # Operational notes diff --git a/config.example.js b/config.example.js deleted file mode 100644 index 09061e7..0000000 --- a/config.example.js +++ /dev/null @@ -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: '
'
- },
-};
-
-module.exports = config;
\ No newline at end of file
diff --git a/config.js b/config.js
new file mode 100644
index 0000000..7c5baec
--- /dev/null
+++ b/config.js
@@ -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;
\ No newline at end of file
diff --git a/lib/cache.js b/lib/cache.js
index 80a7a61..5223581 100644
--- a/lib/cache.js
+++ b/lib/cache.js
@@ -1,7 +1,6 @@
var logging = require("./logging");
var node_redis = require("redis");
var config = require("../config");
-var url = require("url");
var redis = null;
@@ -9,19 +8,10 @@ var redis = null;
// flushes redis when using ephemeral storage (e.g. Heroku)
function connect_redis() {
logging.log("connecting to redis...");
- // parse redis env
- 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 = node_redis.createClient(config.redis);
redis.on("ready", function() {
logging.log("Redis connection established.");
- if (process.env.EPHEMERAL_STORAGE) {
+ if (config.caching.ephemeral) {
logging.log("Storage is ephemeral, flushing redis");
redis.flushall();
}
diff --git a/lib/logging.js b/lib/logging.js
index 668bd89..c517930 100644
--- a/lib/logging.js
+++ b/lib/logging.js
@@ -32,7 +32,7 @@ exp.warn = function() {
exp.error = function() {
log("ERROR", arguments, console.error);
};
-if (config.server.debug_enabled || process.env.DEBUG === "true") {
+if (config.server.debug_enabled) {
exp.debug = function() {
log("DEBUG", arguments);
};
diff --git a/lib/public/stylesheets/style.css b/lib/public/stylesheets/style.css
index 784a66e..2aba08f 100644
--- a/lib/public/stylesheets/style.css
+++ b/lib/public/stylesheets/style.css
@@ -35,7 +35,6 @@ a.forkme:hover {
a.sponsor {
position: fixed;
- z-index: 1041;
width: 48px;
height: 48px;
right: 0px;
@@ -43,6 +42,11 @@ a.sponsor {
margin: 5px;
}
+.sponsor img {
+ width: 100%;
+ height: 100%;
+}
+
a.sponsor-item {
color: #aa7100 !important;
font-weight: initial;
diff --git a/lib/server.js b/lib/server.js
index f38e063..5507daa 100644
--- a/lib/server.js
+++ b/lib/server.js
@@ -136,8 +136,8 @@ function requestHandler(req, res) {
var exp = {};
exp.boot = function(callback) {
- var port = process.env.PORT || 3000;
- var bind_ip = process.env.BIND || "0.0.0.0";
+ var port = config.server.port;
+ var bind_ip = config.server.bind;
server = http.createServer(requestHandler).listen(port, bind_ip, function() {
logging.log("Server running on http://" + bind_ip + ":" + port + "/");
if (callback) {
@@ -149,7 +149,7 @@ exp.boot = function(callback) {
// wait for established connections to finish (30s max),
// then exit
process.on("SIGTERM", function() {
- logging.warn("Got SIGTERM, no longer accepting connections!");
+ logging.warn("Got SIGTERM, no longer accepting new connections!");
setTimeout(function() {
logging.error("Dropping connections after 30s. Force quit.");
diff --git a/package.json b/package.json
index b4115e2..aa3a17b 100644
--- a/package.json
+++ b/package.json
@@ -25,7 +25,6 @@
"avatar"
],
"scripts": {
- "postinstall": "cp 'config.example.js' 'config.js'",
"start": "node www.js",
"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"