eexit / ghost-storage-cloudinary Goto Github PK
View Code? Open in Web Editor NEW:rocket: A fully-featured and deeply tested Cloudinary Ghost storage adapter
Home Page: https://ghost.org/integrations/cloudinary/
:rocket: A fully-featured and deeply tested Cloudinary Ghost storage adapter
Home Page: https://ghost.org/integrations/cloudinary/
Hello @eexit!
I found out a little problem while uploading images using ghost-cloudinary-storage
. Every time I upload a new image from Ghost, it appears uploaded twice on the Cloudinary dashboard.
I've been looking at the Console to see if the request was made twice but seems that is firing only once 🤔
This is my configuration file:
"storage": {
"active": "ghost-storage-cloudinary",
"ghost-storage-cloudinary": {
"cloud_name": "removed",
"api_key": "removed",
"api_secret": "removed",
"configuration": {
"image": {
"secure": true
},
"file": {}
}
}
},
Thanks!
I was trying to setup responsive image transformations following the official Cloudinary Node.js documentation.
I changed my configuration file as follows:
"fetch": {
"fetch_format": "auto",
"responsive": true,
"width": "auto",
"crop": "scale",
"quality": "auto",
"secure": false,
"cdn_subdomain": true
}
The default Ghost Image Optimisation has been disabled as required.
"imageOptimisation": {
"resize": false
}
However, there seems to be no change in the widths on Pagespeed Insights.
While the image URL shows the parameters:
https://res-4.cloudinary.com/da9mvldpq/image/upload/c_scale,f_auto,q_auto,w_auto/v1/blog-images/2--Resource.jpg
The attribute for the image has the original width and height
<img src="https://res-4.cloudinary.com/da9mvldpq/image/upload/c_scale,f_auto,q_auto,…" class="kg-image" alt="" loading="lazy" width="1500" height="741">
I do not know if the problem is in my configuration or if the adapter does not support these functions.
Any help is much appreciated!
Adding both options for format and quality is resulting in wrong URL of https://res-2.cloudinary.com/NAME/image/upload/q_auto/v1/blog/2021/02/Testing.png.auto instead of https://res-2.cloudinary.com/NAME/image/upload/q_auto,f_auto/v1/blog/2021/02/Testing.png
Below is the configuration used for Fetch section.
"fetch": {
"format": "auto",
"quality": "auto",
"secure": true,
"cdn_subdomain": true
}
Hello,
I appreciate your report and I am very pleased to see that this plugin is used. However, please be patient as I need more time to test it against the latest versions of Ghost.
Thanks a lot for your support ❤️
On a brand new Ghost 4 install using the same config.production.json
that I'd used previously with 2.* and 3.0.3 I get the following error message:
Debug Information:
OS: Fedora, v34
Node Version: v14.17.0
Ghost Version: 4.8.4
Ghost-CLI Version: 1.17.3
Environment: production
Command: 'ghost start'
Message: Ghost was able to start, but errored during boot with: Unable to find storage adapter ghost-storage-cloudinary in ,/var/www/myurl.com/ghost/content/adapters/,/var/www/myurl.com/ghost/versions/4.8.4/core/server/adapters/.
Stack: Error: Ghost was able to start, but errored during boot with: Unable to find storage adapter ghost-storage-cloudinary in ,/var/www/myurl.com/ghost/content/adapters/,/var/www/myurl.com/ghost/versions/4.8.4/core/server/adapters/.
at ChildProcess.<anonymous> (/home/kevin/ghost-cli/node_modules/ghost-cli/lib/utils/local-process.js:75:35)
at ChildProcess.emit (events.js:376:20)
at emit (internal/child_process.js:910:12)
at processTicksAndRejections (internal/process/task_queues.js:83:21)
I've tried putting the adapter in both /var/www/myurl.com/ghost/content/adapters/
and /var/www/myurl.com/ghost/versions/4.8.4/core/server/adapters/
, directly in that path as well as the storage/
subdirectory, I've triple-checked the permissions of all files, but I simply can't get the storage adapter to load.
In the Ghost forum I found this suggestion https://forum.ghost.org/t/updating-from-3-20-3-to-latest-cloudinary-content-store/16699/2 that it might have to do with the adapter crashing because it uses internal API/exports that have become unavailable with Ghost 4?
So following KINGMJ/qn-store@bde0b56 I tried removing all usage of the require('ghost-ignition').debug('adapter')
as well as GhostError
instances from the code but it still produces the same error message.
All help/hints would be appreciated. I'm also curious/confused about how @adikari apparently managed to get the adapter to start in #123?
Hello!
I've been using the default Ghost storage adapter for a while, and have got a few year's worth of images in my content/images/
folder.
Recently though I've switched to using Cloudinary for my image storage, and I've activated this adapter.
However all my old images no longer work. Let's say I'm requesting image 2022/05/Untitled.png
. This is what happens:
{domain}/content/images/2022/05/Untitled.png
, redirecting to {domain}/content/images/2022/05/untitled.png
.{domain}/content/images/2022/05/untitled.png
(makes sense, the image doesn't exist)What I'm not sure about is why the original 301 response!
Deactivating this storage adapter and going back to the default one fixes the problem. No more 301s, and therefore no more 404s.
Looking through the code, I can't see anywhere in this storage adapter that would fall back to the filesystem (but also I don't know much about the code).
Should it fall back to the filesystem if the image is not found in Cloudinary? Or are we expected to migrate all our in-post images to Cloudinary before switching the adapter?
Looking at previous issues and PRs I found #90 which was closed without merging, seems like it adds this missing functionality.
ghost:3-alpine has NODE_VERSION=12.15.0 and your package only supports 8.10.0 || ^10.13.0
So can you bump the Node version or should I use ghost:2.38.0?
How can I integrate into an existing project? I'm currently running Ghost using the following docker-compose.yml
:
version: '3.1'
services:
ghost:
image: arm64v8/ghost
restart: unless-stopped
environment:
url: http://localhost:3001
volumes:
- ./ghost-data:/var/lib/ghost/content
ports:
- 3001:2368
I've tried creating a new Dockerfile based on your example on the readme, and then modifying docker-compose.yml
to the following:
FROM arm64v8/ghost as cloudinary
WORKDIR $GHOST_INSTALL/current
RUN su-exec node yarn add ghost-storage-cloudinary@2
FROM arm64v8/ghost
COPY --chown=node:node --from=cloudinary $GHOST_INSTALL/current/node_modules $GHOST_INSTALL/current/node_modules
COPY --chown=node:node --from=cloudinary $GHOST_INSTALL/current/node_modules/ghost-storage-cloudinary $GHOST_INSTALL/current/core/server/adapters/storage/ghost-storage-cloudinary
RUN set -ex; \
su-exec node ghost config storage.active ghost-storage-cloudinary; \
su-exec node ghost config storage.ghost-storage-cloudinary.upload.use_filename true; \
su-exec node ghost config storage.ghost-storage-cloudinary.upload.unique_filename false; \
su-exec node ghost config storage.ghost-storage-cloudinary.upload.overwrite false; \
su-exec node ghost config storage.ghost-storage-cloudinary.fetch.quality auto; \
su-exec node ghost config storage.ghost-storage-cloudinary.fetch.cdn_subdomain true;
version: '3.1'
services:
ghost:
build:
context: ./
dockerfile: Dockerfile
image: ghost
restart: unless-stopped
environment:
url: http://localhost:3001
volumes:
- ./ghost-data:/var/lib/ghost/content
ports:
- 3001:2368
However, this causes a generic error with NextJS and GraphQL: Error: Index creation failed.
Any ideas? I'm using the latest version of Ghost (v4).
More an idea for an enhancement rather than a bug: I started off using the recommended fetch.secure: false
but ended up having to change to secure: true
because our site is served over https and most browsers didn't like us dynamically requesting content from a non-secured site. I assumed that the storage adapter would just change all picture URLs from http://
to https://
but to my surprise all previously uploaded pictures were still requested over http, only those uploaded after the config change got a https://
path by default.
I understand that this probably has to do with how storage adapters fit into the Ghost architecture (storing a fixed path to the image at the time of upload) but especially given the name of the config setting I found it deeply unintuitive that previously uploaded images were unaffected. I wonder if there is a safe way for the storage adapter to check all the URLs in the Ghost storage and update any cloudinary URLs which have the wrong protocol? It seems like the storage adapter isn't actually queried when Ghost generates the <img>
tags, so this might have to happen during the adapter initialisation...
I think this is a problem if you want to be able to be to upload images with the same name and still have them uniquely named - using the unique_filename
option. Because the public_id
is always set, Cloudinary will use that and never generate the unique filename.
I've solved this locally by modifying the source code (commenting out index.js:72
, but I believe this might affect more people. Would public_id
need to be set anyway? The upload options should be able to solve all of this automagically, right?
I'm getting the following error on installation:
[email protected]: The engine "node" is incompatible with this module. Expected version "^12.22.1 || ^14.17.0 || ^16.13.0". Got "18.19.1"
Dockerfile looks like:
FROM amd64/node:18 as builder
WORKDIR /scratch
COPY ./theme/ ./
RUN yarn add ghost-storage-cloudinary
Hello,
I'm setting up Ghost on Heroku via the awesome ghost-on-heroku. This provisions the Cloudinary resource and sets up ghost-storage-cloudinary
by default.
My problem is that I have already migrated a lot of my blog posts to a Ghost(Pro) instance before I decided to host my own instance on Heroku. I was able to export all of my posts from Ghost(Pro) as JSON, and I downloaded all of the images by scraping the blog using wget --recursive
. So I copied all of these historical images into content/images/
. If I disable Cloudinary by unsetting the CLOUDINARY_URL
, then everything is working great and all the images load properly.
However, when the ghost-storage-cloudinary
storage is configured in this code, the server can no longer serve any of my images in the content/images/
folder.
I was wondering if it would be possible to support a hybrid approach where any new images are uploaded to Cloudinary, but this library also checks for any hard-coded images inside the content/images/
folder?
You have the option to enable fetch.quality = "auto"
would be awesome if you also could use
fetch.format = "auto"
for the webp functionality.
6.9.1
to 6.9.2
.This version is covered by your current version range and after updating it in your project the build failed.
npm is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.
The new version differs by 2 commits.
31718e7
6.9.2
21eef31
doc: update changelog for [email protected]
See the full diff
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
Hi, I am serving my ghost site in https mode,
But during create new post, upload an image in right hand side panel ( as know as post banner)
It's successful to upload, and show correctly in panel.
After publish the post, image wont show in post, in chrome developer tools, it show the error as below:
Mixed Content: The page at 'https://<mydomain>/' was loaded over HTTPS, but requested an insecure image 'http://<cloudinary url link>'. This request has been blocked; the content must be served over HTTPS.
Addon details:
Normal image upload in content is work fine.
Any idea on this?
Thank you for help!
Hi,
I'm using digitalocean to host my ghost blog site. I've successfully installed this adapter, How do I configure this? As I checked configuration.json.dist file it is already configured and I've set cloude-name, api-key and secret key, It would be great if you could guide me as what to do next?
As seen in the README's installation instructions it's recommended to install the package with @2
. It's a bit unconventional comparing to most packages, so was wondering why the package should be installed this way?
Mixed Content: The page at 'https://gubuktekno.info/artikel/' was loaded over HTTPS, but requested an insecure image 'http://res-3.cloudinary.com/xxxx/image/upload/q_auto/v1/blog-images/ghost-cms.jpg'. This request has been blocked; the content must be served over HTTPS.
I'm serving my Ghost blog on a subdirectory on my root domain, so I proxy all the requests through my application server. I also route all the traffic on my root domain through Cloudflare, and set it to cache every request.
I can see that this Ghost plugin is loading the images directly from the cloudinary domain, so this bypasses all of my proxies and caches, and it means I have to be more careful about bandwidth for my image requests. I would prefer to send everything through CloudFlare if possible so that I can cache and serve everything for free.
How difficult would it be to proxy all the image requests through the Node.js server, instead of serving directly from Cloudinary?
I'm thinking that I could return a simple path from the uploader
function, e.g. /cloudinary/{image_id}
. Then I could set up a handler in serve
to respond to the /cloudinary/{image_id}
requests.
Would anyone else be interested in a proxyImages
option?
@eexit I am using this plugin with ghost self-hosted sever. I noticed that this plugin only manage images with cloudinary. Ghost also provide facility of uploading video, audio etc. to sever. When I upload other file it get uploaded to local file storage of my server. But in order to make my app state less I have to store all the uploaded files to cloudinary. I thinks its best add support for it to the library.
Thanks!
ghost-storage-cloudinary
cannot be installed with Node.js v18 due to the following error:
error [email protected]: The engine "node" is incompatible with this module. Expected version "^14.17.0 || ^16.13.0". Got "18.16.1"
Would it be possible to add support for Node.js v18?
Hi,
I've recently set up a blog with Ghost Version 3.1.1, just wondering if this plugin is compatible with this ghost blog version.
To see what happens to your code in Node.js 10, Greenkeeper has created a branch with the following changes:
.travis.yml
If you’re interested in upgrading this repo to Node.js 10, you can open a PR with these changes. Please note that this issue is just intended as a friendly reminder and the PR as a possible starting point for getting your code running on Node.js 10.
Greenkeeper has checked the engines
key in any package.json
file, the .nvmrc
file, and the .travis.yml
file, if present.
engines
was only updated if it defined a single version, not a range..nvmrc
was updated to Node.js 10.travis.yml
was only changed if there was a root-level node_js
that didn’t already include Node.js 10, such as node
or lts/*
. In this case, the new version was appended to the list. We didn’t touch job or matrix configurations because these tend to be quite specific and complex, and it’s difficult to infer what the intentions were.For many simpler .travis.yml
configurations, this PR should suffice as-is, but depending on what you’re doing it may require additional work or may not be applicable at all. We’re also aware that you may have good reasons to not update to Node.js 10, which is why this was sent as an issue and not a pull request. Feel free to delete it without comment, I’m a humble robot and won’t feel rejected 🤖
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
Hi,
I'm curious if there is a way to specify the fetch flags once the images are uploaded and a post is saved. It currently saves the fetch
options that just generates ULR which cannot be changed unless the image is re-added again.
I am building a custom theme and using for rather smaller feature images to display a grid on the index, and when in the post is rendered then you can click on the smaller thumb and get a full screen image. Ideally I'd like to upload a full-quality asset to Cloudinary (via Ghost) and in my theme somehow specify the requested size (Cloudinary will do the rest).
It needs to happen in the theme - in HBS - in order to serve small image where it needs to be. I know this is more of a role for CMS and Ghost is not really excelling here.
I was thinking -- if this storage provider registered a Handlebars helper like cloudinary <<Cloudinary params here>> imgUrl
then as someone creating a custom theme on your Ghost with this storage adapter you could use that to actually have HTML with for example resized (smaller) images if you wanted to.
Hello,
When using ghost-storage-cloudinary as default storage adapter, the image url automatic use "http" instead of "https" and that create warning in Firefox and Chrome about the security of pages.
Is there anyway that we can config the link will be "https" automatically?
I am trying to use this in Ghost 4 and seems like when I upload the image, it crashes the entire ghost instance.
I am running this in the dockerized version. I can't really see the logs to figure out what the actual problem is.
Would be cool if this worked with Ghost 4.
I tried to install ghost-storage-cloudinary on my ghost blog in fly.io but after restarting my app I get this error:
chown: cannot dereference ‘/var/lib/ghost/content/adapters/storage/ghost-storage-cloudinary/node_modules/.bin/image-size’: No such file or directory
and my app crashed and needs restore,
how to fix this?
Follow the guide: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
Hello,
I tried to change the config.production.json, but adding the fetch format as .webp didn't work. Is there any workaround to this?
Thanks in advance!
"ghost-storage-cloudinary": { "useDatedFolder": false, "auth": { "cloud_name": "...", "api_key": "...", "api_secret": "..." }, "upload": { "use_filename": true, "unique_filename": false, "overwrite": false, "folder": "blog-images", "tags": [ "blog" ] }, "fetch": { "quality": "auto", "secure": true, "cdn_subdomain": true, "format": "webp" }, "plugins": {} }
You cannot use 'v' followed by numeric characters as the name of a folder
https://cloudinary.com/documentation/upload_images#uploading_images_to_the_cloud
I tried to follow the example of Dockerfile for the newest version and this message appears when I try to start it.
Not sure if your project isn't 2.0 compatible or where is the issue.
ghost | module.js:550
ghost | throw err;
ghost | ^
ghost |
ghost | Error: Cannot find module 'ghost-ignition'
ghost | at Function.Module._resolveFilename (module.js:548:15)
ghost | at Function.Module._load (module.js:475:25)
ghost | at Module.require (module.js:597:17)
ghost | at require (internal/module.js:11:18)
ghost | at Object.<anonymous> (/var/lib/ghost/versions/2.4.0/index.js:5:13)
ghost | at Module._compile (module.js:653:30)
ghost | at Object.Module._extensions..js (module.js:664:10)
ghost | at Module.load (module.js:566:32)
ghost | at tryModuleLoad (module.js:506:12)
ghost | at Function.Module._load (module.js:498:3)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.