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: '
', - top_right: '' - }, -}; - -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"