Problem uploading images

I’ve done a lot of reading, none of it useful to the point of resolution.

*** ENV

  • OS: FreeBSD 13.1 (VM)
  • Web Service: NGINX v1.22.1_5,3

*** Packages

  • node16-16.20.0 V8 JavaScript for client and server
  • npm-node16-9.5.0 Node package manager

*** Ghost
Ghost-CLI version: 1.24.0
Ghost version: 5.46.1

Node and NPM were installed as root; Ghost was installed as user huiboo.

» After login as the first user (admin), I am not able to upload any images, such as an avatar or an image in a test post. I’ve attempted .gif, .jpg and .webp < 500K each in size. Oddly I was able to install additional themes!

Error: “Internal server error, cannot upload image.”

As I’m writing this, did find more detail after reading <>

$ ghost log -f

NAME: InternalServerError
MESSAGE: Sharp wasn’t installed

level: critical

Error: Cannot find module ‘sharp’
<//> - ghost is supposed to fallback to omit image optimization in the event of sharp not being installed.

I’ve already attempted to install “sharp” but that turns in a dependency clusterfuk with vulnerable modules and/or a deeper can of worms with custom compilation of ‘vips’. This is a show-stopper unless there’s a better alternative.

Difficult to post a question when I cannot include more than 3 legitimate links!

Problem description continued:

Since I run FreeBSD, ‘ghost setup nginx’ comes back with response ‘skipped’. Then researched whether it’s possible to specify a path for the nginx parameter but don’t see any syntax for it —assuming ghost will write a config provided it can find nginx in a presumed path. I would like the installer to at least dump an nginx.conf/site.conf file for me to look at —I’ll modify paths and other details relative to my environment. Searching online did not turn up any config files that work either. Plus I’m still getting used to nginx syntax.

Octal permissions for Ghost directories are 755 and for files 644. 775/664 makes no difference. Files are owned by user/group ‘huiboo’ who is also member of group ‘wheel’ (appropriate for FreeBSD as opposed to root on Linux) as per installation instructions for Ubuntu.

Does Ghost have a problem with IPv6? It is the preferred protocol on my servers. Everytime I replaced with [::1] ({PATH}/ghost/config.production.json) ghost barfs. LOL

No local firewall.
Logfiles prove inconclusive.

2023/05/03 19:59:48 [error] 71327#100967: 1 kevent() reported that connect() failed (61: Connection refused) while connecting to upstream, client: { non-routable IPv6 }, server: { }, request: “GET /ghost/assets/img/user-cover-e8f42b12b5fcba292a8b5dfa81e13dd2.png HTTP/2.0”, upstream: “http://[::1]:2368/ghost/assets/img/user-cover-e8f42b12b5fcba292a8b5dfa81e13dd2.png”, host: “{ }:{ CUSTOM }”, referrer: “https://{ }:{ CUSTOM }/ghost/”

*Ex: fc00::/7 net

The self-hosted Ghost site is running on FreeBSD with NGINX and nodejs16 with npm-node16. The web service is running on a custom port since I am not ready to share it with the world AND I have Apache running on the same server on standard ports 80/443.

*** Ghost Config

  • cat /usr/local/www/ghost/config.production.json

  "url": "https://{ PRIVATE }:{ CUSTOM }",
  "server": {
    "port": 2368,
    "host": ""
  "database": {
    "client": "mysql",
    "connection": {
      "host": "localhost",
      "user": "{ PRIVATE }",
      "password": "{ PRIVATE }",
      "database": "{ PRIVATE }"
  "mail": {
    "transport": "Direct"
  "logging": {
    "transports": [
  "process": "local",
  "paths": {
    "contentPath": "/usr/local/www/ghost/content"

NOTE: The installer gets confused at some point (it replaced ghost port with my custom port in the conf) if a custom port is specified during installation, so I simply chose a standard “https :// { }” syntax, later updated the config file and added my custom port for the URL.

*** NGINX Configs

  • (1) # cat nginx.conf
user  huiboo;
worker_processes  1;

events {
    use kqueue;
    worker_connections  1024;

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile       on;
    tcp_nopush     on;
    keepalive_timeout  65;
    gzip  off;

    include conf.d/*.conf;
  • (2) # cat ghost.conf
server {
	listen [::]:{ CUSTOM } ssl http2;
	listen { CUSTOM } ssl http2;
	server_name { PRIVATE };
	root /usr/local/www/ghost;

	ssl_certificate { PRIVATE }.pem;
	ssl_certificate_key { PRIVATE }.pem;

	location / {
		proxy_set_header X-Forwarded-For $remote_addr;
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header Host $http_host;

	# Supposed to bypass caching - upload fails regardless of syntax presence
	location ~* ^/(assets/|fonts/|images/|robots.txt|sitemap.xml)$ {
		root /usr/local/www/ghost;
	client_max_body_size 50m;


*** Package Details

  • Node 16

pkg info node16 ## Command Line

Name : node16
Version : 16.20.0
Installed on : Thu Apr 27 16:28:31 2023 EDT
Origin : www/node16
Architecture : FreeBSD:13:amd64
Prefix : /usr/local
Categories : www
Licenses : MIT
Maintainer :
Comment : V8 JavaScript for client and server
Options :
DOCS : on
NLS : on
Shared Libs required:
Annotations :
FreeBSD_version: 1301000
repo_type : binary
repository : FreeBSD
Flat size : 41.0MiB
Description :
Node.js is a JavaScript runtime built on Chrome’s V8 JavaScript
engine. Node.js uses an event-driven, non-blocking I/O model that
makes it lightweight and efficient. Node.js’ package ecosystem,
npm, is the largest ecosystem of open source libraries in the world.



  • NPM Node 16

pkg info npm-node16 ## Command Line

Name : npm-node16
Version : 9.5.0
Installed on : Thu Apr 27 16:29:00 2023 EDT
Origin : www/npm-node16
Architecture : FreeBSD:13:*
Prefix : /usr/local
Categories : www
Licenses : ART20
Maintainer :
Comment : Node package manager
Annotations :
cpe : cpe:2.3:a:npmjs:npm:9.5.0:::::freebsd13:x64
repo_type : binary
repository : FreeBSD
Flat size : 11.3MiB
Description :
npm is a package manager for node. You can use it to install and publish your
node programs. It manages dependencies and does other cool stuff.

Created symlink …

/etc/nginx → /usr/local/etc/nginx

but that didn´t seem to help when running

$ ghost doctor

│Warning: MySQL 8 will be the required database in the next major release of Ghost.│
│ Make sure your database is up to date to ensure forwards compatibility. │

:heavy_check_mark: Checking system Node.js version - found v16.20.0
:heavy_check_mark: Checking current folder permissions
:heavy_check_mark: Checking for a MySQL installation
Instance is currently running
:information_source: Validating config [skipped]
:heavy_check_mark: Checking memory availability
:heavy_check_mark: Checking binary dependencies
:heavy_check_mark: Checking free space

in hopes of the doctor analyzing and correcting my existing nginx configs.

This was a mess to upgrade.
so… I have the same setup FreeBSD (VM) running ghost
and after last upgrade (from 44 to 47) I coudn’t get images to work.

problem: it requires “sharp”
problem 2: “sharp” requires a later vips version than you get from stable release.

so my solution was:
1: change pkg repo to “latest”
To do that: create the file /usr/local/etc/pkg/repos/FreeBSD.conf
Enter the following text inside:

FreeBSD: {
  url: "pkg+${ABI}/latest"
3: pkg update
4: pkg install vips
5: npm add sharp
4: ghost update --force

and hopefully I remeber all the steps.  if it doesn't work after this, send me a message and I'll see if I can help
1 Like

Thanks so much for writing, Ken! :face_with_monocle:
After banging my head against the wall :triumph: :exploding_head: :crazy_face: for many more hrs I found that by simply adding the following syntax right before the closing " } " of the config.production.json config file, I can sidestep the sharp requirement:

  "imageOptimization": {
    "resize": false

There is one last challenge:
I will not be doing mass mailings. My use case only needs email functionality to invite users. Do you happen to make use of your server’s local mail service? Do you have the syntax to make that happen? I’ve tested the Invitate People feature, but no email goes out. Using Google’s email is another option since I pay for their most basic workspace … so far have not come across config file syntax for email that works. Mailgun is a deal-breaker as I’m simply not going to go through setting up another service provider when I already have everything I need

Thanks again!

I only use ghost for a personal blog as of now, so I haven’t looked at any mail functionality.
thanks for sharing your solution. good to know that it is possible to bypass sharp if needed.

No worries, glad I could help :slightly_smiling_face:
… going to look into your solution of updating my repo but need to research and understand that a little better before mangling with the default repo.
Enjoy blogging!

… bit the bullet and updated my FBSD repo, installed sharp, removed ‘imageOptimization’ exclusion in config, updated Ghost … works like a charm! :+1:

On to the next challenge ~

1 Like

glad it worked out.
I would recommend that you change the topic to “solved: Problem uploading images” so it’s easier for future people to search for possible solutions :)

1 Like

I totally forgot that detail esp. since I’m not on forums that often. Thanks for the reminder :innocent:

For the life of me, I cannot find where to mark a message thread as SOLVED!?
With all these buttons and bells and whistles everywhere, one would think the solved option should be at the bottom of each message … I just don’t see it.

Thought to give you an update. As of

FreeBSD localhost 13.2-RELEASE-p1 FreeBSD 13.2-RELEASE-p1 GENERIC amd64

Just install vips and then do your npm add sharp and c’est tout!

… no repo changes are necessary anymore :star_struck:


Thank you,It worked!

1 Like

You’re welcome.
Be sure to look at my latest post … RE FBSD v13.2