a lightweight image resizing proxy
Go to file
cupcakearmy 20d2c1b7a0
version bump
2022-10-18 13:58:53 +02:00
.github/workflows docker release 2021-12-02 18:15:21 +01:00
design logo 2022-05-29 10:42:02 +02:00
docker stuff 2022-05-29 11:31:18 +02:00
scripts stuff 2022-05-29 11:31:18 +02:00
src stuff 2022-10-18 13:58:37 +02:00
.dockerignore progress 2021-11-17 15:36:58 +01:00
.gitignore stuff 2022-10-18 13:58:37 +02:00
.npmrc strict engines 2022-05-29 00:09:09 +02:00
Dockerfile stuff 2022-05-29 11:31:18 +02:00
README.md stuff 2022-10-18 13:58:37 +02:00
docker-compose.yaml include in docker compose 2022-05-29 00:09:03 +02:00
package.json version bump 2022-10-18 13:58:53 +02:00
pnpm-lock.yaml stuff 2022-10-18 13:58:37 +02:00
tsconfig.json enable isolated modules 2022-02-05 23:21:49 +01:00

README.md

morphus




discord docker pulls Docker image size badge Latest version

A lightweight image resizing and effect proxy that caches image transformations. The heavy lifting is done by libvips and sharp

⚠️ Currently under development

🌈 Features

  • Config driven
  • Domain protection
  • Host verification
  • Multiple storage adapters (Local, Minio, S3, GCP)
  • Auto format based on Accept header
  • ETag caching
  • Presets and optional forcing of presets

🏗 Installation

The easies way to run is using docker.

# morphus.yaml
allowedDomains:
  - !regexp ^https?:\/\/images.unsplash.com
# docker-compose.yaml
version: '3.8'

services:
  app:
    image: cupcakearmy/morphus
    ports:
      - '80:80'
docker-compose up

For more realistic docker-compose files check the docker directory.

🎪 Examples

Simple resize: ?width=2000&resize=contain

https://my-morphus.org/api/image?width=2000&resize=contain&url=https://images.unsplash.com/photo-1636839270984-1f7cbc2b4c4b

Chose a format: ?format=webp

https://my-morphus.org/api/image?format=webp&width=2000&resize=contain&url=https://images.unsplash.com/photo-1636839270984-1f7cbc2b4c4b

Chose a format with a given quality: ?format=webp|quality:90

https://my-morphus.org/api/image?format=webp|quality:90&width=2000&resize=contain&url=https://images.unsplash.com/photo-1636839270984-1f7cbc2b4c4b

With some transformation operations: ?op=rotate|angle:90&op=sharpen|sigma:1,flat:2

This is transforming the image once by rotate with the argument angle: 90 and sharpen with the arguments of sigma: 1 and flat: 2.

https://my-morphus.org/api/image?width=2000&resize=contain&op=rotate|angle:90&op=sharpen|sigma:1,flat:2&url=https://images.unsplash.com/photo-1636839270984-1f7cbc2b4c4b

With custom presets: ?preset=thumbnail

# morphus.yaml
presets:
  thumbnail: ?width=300&height=150&resize=contain
https://my-morphus.org/api/image?preset=thumbnail&url=https://images.unsplash.com/photo-1636839270984-1f7cbc2b4c4b

💻 Usage

Parameter Syntax Example
url URL ?url=https://cdn.example.org/dog-full-res.png
format ComplexParameter ?format=webp ?format=webp|quality:90,progressive:true
resize sharp.fit ?resize=contain
width number ?width=500
height number ?width=500
op ComplexParameter[] ?op=rotate|angle:90&op=sharpen|sigma:1,flat:2

ComplexParameter

The syntax for the ComplexParameter is as follows:

Without options
?param=<name>
With two options
?param=<name>|optionA:1,optionB:true

⚙️ Configuration

Config files are searched in the current working directory under morphus.yaml.

Configuration can be done either thorough config files or env variables. The usage of a config file is recommended. Below is a table of available configuration options, for more details see below.

Config Environment Default Description
port PORT 80 The port to bind.
address ADDRESS 127.0.0.1 The address to bind.
logLevel LOG_LEVEL info The log level to use. Possible values: trace, debug, info, warn, error, fatal, silent.
presets not available null Predefined presets. See below for an example.
onlyAllowPresets ONLY_ALLOW_PRESETS false Whether to allow only presets. This can prevent unfair usage.
allowedDomains unsupported for now as ENV null The domains that are allowed to be used as image sources.
allowedHosts unsupported for now as ENV null The hosts that are allowed to access the images.
cleanUrls CLEAN_URL Fragment Whether source URLs are cleaned.
maxAge MAX_AGE 1d How long the served images are marked as cached, after that ETag is used to revalidate.
storage STORAGE local The storage driver to use. Possible values: local, minio, s3, gcs.

Storage Drivers

Local

Config Environment Default Description
local.assets LOCAL_ASSETS ./assets The path to the assets folder

Minio

Config Environment Default Description
minio.accessKey MINIO_ACCESS_KEY The access key for Minio
minio.secretKey MINIO_SECRET_KEY The secret key for Minio
minio.endpoint MINIO_ENDPOINT The endpoint for Minio
minio.bucket MINIO_BUCKET The bucket to use for Minio
minio.region MINIO_REGION The region for Minio
Example
# morphus.yaml

storage: minio
minio:
  accessKey: minioadmin
  secretKey: minioadmin
  bucket: morphus
  endpoint: http://localhost:9000

AWS S3

Config Environment Default Description
s3.bucket S3_BUCKET The S3 bucket to use
s3.region S3_REGION The S3 region to use
s3.accessKey S3_ACCESS_KEY_ID The S3 access key id to use
s3.secretKey S3_SECRET_ACCESS_KEY The S3 secret access key to use
Example
# morphus.yaml

storage: s3

s3:
  accessKey: abc
  secretKey: def
  bucket: morphus

Google Cloud Storage

Config Environment Default Description
gcs.bucket GCS_BUCKET The GCS bucket to use
gcs.keyFilename GCS_KEY_FILENAME The GCS key file to use

Due to Google Cloud requiring a keyfile, that keyfile needs to be available to morphus. In docker this means passing it into the volume for example.

Example
# morphus.yaml

storage: gcs
gcs:
  bucket: morphus
  keyFilename: keyfile.json

Presets

With the help of presets you can give predefined sets of operations and transformations. Clients then can use the presets without specifying the exact parameters.

The syntax is an object that maps a preset name to a value. The value is a valid url query.

presets:
  sm: ?format=webp|quality:90&width=500&resize=contain
  md: ?format=webp|quality:90&width=1000&resize=contain
  lg: ?format=webp|quality:90&width=2000&resize=contain

A client can the request an image with the following url

https://my-morphus.org/api/image?preset=sm&url=https://images.unsplash.com/photo-1636839270984-1f7cbc2b4c4b

Only allow presets

This feature can help reduce abuse of the server by only allowing. When onlyAllowPresets is set no other parameter is allowed besides url and preset. If possible it's recommended to turn this on.

onlyAllowPresets: true

Allowed Domains

Allowed domains are a way to secure the service by only allowing certain remote domains as possible sources of images.

You can provide a string which will match as prefix or RegExp that allow for more powerful control.

If omitted every domain is allowed.

allowedDomains:
  # This will match any URL that starts with the string.
  - https://my.cloud.org

  # For regexp you need to add the !regexp tag in from of it.
  - !regexp ^https?:\/\/images.unsplash.com

Allowed Hosts

Same syntax as for allowed domains.

Allowed hosts enables you to whitelist a number of origins.

If ommtted any origin is allowed.

allowedHosts:
  - https://my.cloud.org
Note

When using the url in an <img> tag you need to add the <img crossorigin="anonymous"> attribute to enable sending the origin header to the server. Read more here

Clean URLs

This option allows cleaning the source URLs to remove duplicates. allowed options are off, fragment, query.

Example
Type URL
Original https://images.unsplash.com/photo-1636839270984-1f7cbc2b4c4b?lang=en#chapter1
off https://images.unsplash.com/photo-1636839270984-1f7cbc2b4c4b?lang=en#chapter1
fragment https://images.unsplash.com/photo-1636839270984-1f7cbc2b4c4b?lang=en
query https://images.unsplash.com/photo-1636839270984-1f7cbc2b4c4b