Serve images directly through Nginx
See original GitHub issueThis issue is a
- Bug Report
- Feature Request
Summary
Ghost’s image handling is currently pretty basic. Even in “private mode” there is no node.js level gateway, all images are served as static assets. However, in the default Nginx config we still push all static image data through the node.js/express layer which adds overhead.
A default Ghost install has images files in a known directory so we can configure those files to be served directly via Nginx rather than passing it through the Ghost server.
Template changes
Example nginx config for serving image files directly:
location ^~ /content/images/ {
root /var/www/ghost;
add_header Cache-Control "public, no-transform";
add_header Vary "Accept-Encoding";
expires max;
}
In this case we would need the /var/www/ghost
value to be interpolated. The validity of the no-transform
header should also be discussed, details are here:
no-transform No transformations or conversions should be made to the resource. The Content-Encoding, Content-Range, Content-Type headers must not be modified by a proxy. A non- transparent proxy might, for example, convert between image formats in order to save cache space or to reduce the amount of traffic on a slow link. The no-transform directive disallows this.
It may be that we want to allow CDNs or other proxies in front of a default Ghost install to perform additional compression.
Benchmarks
I performed a local benchmark on a DigitalOcean 1-click instance serving a 2.1MB image, SSL was used to replicate the typical stack:
siege -q -b -c25 -r50 https://ghost-test.lookingsideways.co.uk/content/images/2018/06/Cosmos01.jpg
As can be seen below, throughput doubled, response time is halved and there is much smaller deviation in overall transaction time.
Default config
Transactions: 1250 hits
Availability: 100.00 %
Elapsed time: 43.17 secs
Data transferred: 2486.66 MB
Response time: 0.86 secs
Transaction rate: 28.96 trans/sec
Throughput: 57.60 MB/sec
Concurrency: 24.86
Successful transactions: 1250
Failed transactions: 0
Longest transaction: 1.22
Shortest transaction: 0.25
Nginx serving image
Transactions: 1250 hits
Availability: 100.00 %
Elapsed time: 20.68 secs
Data transferred: 2486.66 MB
Response time: 0.41 secs
Transaction rate: 60.44 trans/sec
Throughput: 120.24 MB/sec
Concurrency: 24.70
Successful transactions: 1250
Failed transactions: 0
Longest transaction: 0.47
Shortest transaction: 0.07
Issue Analytics
- State:
- Created 5 years ago
- Reactions:1
- Comments:6 (5 by maintainers)
Top GitHub Comments
@jloh the problem with that approach is that it requires changes in Ghost itself and ties Ghost to Nginx. With the above approach we’re only changing config in the default Ghost-CLI Nginx configuration, users of Ghost are still free to use a different web server, not use Ghost-CLI, or re-configure in a way they want.
If you want to use
X-Accel-Redirect
it would certainly be possible to create a custom storage engine that responds with the necessary headers for static content requests and then configure Nginx appropriately to respond to them.Our bot has automatically marked this issue as stale because there has not been any activity here in some time. The issue will be closed soon if there are no further updates, however we ask that you do not post comments to keep the issue open if you are not actively working on a PR. We keep the issue list minimal so we can keep focus on the most pressing issues. Closed issues can always be reopened if a new contributor is found. Thank you for understanding 🙂