I'm running Drupal 8.4.3 on PHP 7.0.22 atop Ubuntu 16.04LTS, Nginx 1.10.3 and MySQL 5.7.20, using the OpenSocial distribution. Whenever I try to add an inline image into a basic page using CKeditor, I get broken image displayed. The image i'm trying to load appears in Chrome Developer Tools as being collected from <img alt="Angela Luker" data-entity-type="file" data-entity-uuid="f6af8f2e-3450-440d-a154-f45d4a552a7f" src="/system/files/inline-images/Angela-Luker-Then.JPG".

This file is appearing in the file system (not the database) as /var/www/html/private:/inline-images/Angela-Luker-Then.JPG.

So I'm guessing I have an issue with my Nginx rewrites. I've based the Nginx configuration on the suggested Nginx settings for Drupal 8, and several enhancements down the years suggested as workarounds, but still no joy.

The public file base URL is http://www.software-enabled.eu/sites/default/files; the private file system path is /var/www/html/sites/default/files/private; the temporary directory is /tmp.

The above directories are present, owned by www-data:www-data with file permissions set to 770. The default download method is set to Public local files served by the webserver.

Is there a rewrite in the Apache versions for Drupal 8 that I'm missing in my Nginx setup?

server {
  listen 80;
  listen 443 ssl http2;

  server_name software-enabled.eu www.software-enabled.eu;

  root /var/www/html;

  # Redirect to https if user has come in on http

  # if ( $scheme = "http") {
  #    return 301 https://$server_name$request_uri;
  # }

  # Add index.php to the list if you are using PHP

  index index.php index.html index.htm index.nginx-debian.html;

  location = /favicon.ico {
    log_not_found off;
    access_log off;

  location = /robots.txt {
    allow all;
    log_not_found off;
    access_log off;

  # Very rarely should these ever be accessed outside of your lan
  location ~* \.(txt|log)$ {
    deny all;

  location ~ \..*/.*\.php$ {
    return 403;

  # location ~ ^/sites/.*/private/ {
  #   return 403;
  # }

  # Allow "Well-Known URIs" as per RFC 5785
  location ~* ^/.well-known/ {
    allow all;

  # Block access to "hidden" files and directories whose names begin with a
  # period. This includes directories used by version control systems such
  # as Subversion or Git to store control files.
  location ~ (^|/)\. {
    return 403;

  location / {
    root /var/www/html;
    index index.php;
    error_page 404 = @drupal;
    # First attempt to serve request as file, then
    # as directory, then fall back to displaying a 404.
    # try_files $uri /index.php?query_string; # For Drupal >= 7

  location @drupal {
    rewrite ^(.*)$ /index.php?q=$1;

  # Don't allow direct access to PHP files in the vendor directory.
  location ~ /vendor/.*\.php$ {
    deny all;
    return 404;

  # Pass the PHP scripts to FastCGI server listening on
  # In Drupal 8, we must also match new paths where the '.php' appears in
  # the middle, such as update.php/selection. The rule we use is strict,
  # and only allows this pattern with the update.php front controller.
  # This allows legacy path aliases in the form of
  # blog/index.php/legacy-path to continue to route to Drupal nodes. If
  # you do not have any paths like that, then you might prefer to use a
  # laxer rule, such as:
  #   location ~ \.php(/|$) {
  # The laxer rule will continue to work if Drupal uses this new URL
  # pattern with front controllers other than update.php in a future
  # release. (Note: $ removed as .php extension may not be at end of
  # URL in Drupal 8.
  location ~ '\.php|^/update.php' {
    include snippets/fastcgi-php.conf;
    # With php7.0-cgi alone:
    # fastcgi_pass;
    # With php7.0-fpm:
    fastcgi_split_path_info ^(.+?\.php)(|/.*)$;

    # Security note: If you're running a version of PHP older than the
    # latest 5.3, you should have "cgi.fix_pathinfo = 0;" in php.ini.
    # See http://serverfault.com/q/627903/94922 for details.
    include fastcgi_params;

    # Block httpoxy attacks. See https://httpoxy.org/.
    fastcgi_param HTTP_PROXY "";
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param QUERY_STRING $query_string;
    fastcgi_intercept_errors on;

    # PHP 5 socket location.
    #fastcgi_pass unix:/var/run/php5-fpm.sock;

    # PHP 7 socket location.
    fastcgi_pass unix:/run/php/php7.0-fpm.sock;

  # Fighting with Styles? This little gem is amazing.
  # location ~ ^/sites/.*/files/imagecache/ { # For Drupal <= 6
  location ~ ^/sites/.*/files/styles/ { # For Drupal >= 7
    try_files $uri @rewrite;

  # Handle private files through Drupal. Private file's path can come
  # with a language prefix.
  location ~ ^/sites/default/files/private/ {
    rewrite ^/sites/default/files/private/(.*) /system/files/$1 last;

  location ~ ^(/[a-z\-]+)?/system/files/ { # For Drupal >= 7
    try_files $uri /index.php?$query_string;

  location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
    try_files $uri @rewrite;
    expires max;
    log_not_found off;

  # Deny access to .htaccess files, if Apache's document root
  # concurs with nginx's one
  location ~ /\.ht {
    deny all;

  ssl_certificate /etc/letsencrypt/live/software-enabled.eu/fullchain.pem; # managed by Certbot
  ssl_certificate_key /etc/letsencrypt/live/software-enabled.eu/privkey.pem; # managed by Certbot
  • Coming to the conclusion that inline-images in CKeditor on Basic pages on Drupal 8.4.3 is fundamentally broken. Anyone have it working?
    – Ian Waring
    Commented Dec 31, 2017 at 14:15

1 Answer 1


I've fixed my inline image load issues, albeit in the most draconian way. I zeroed out the site completely and rather than using Nginx and the Open Social distribution, I installed raw Drupal 8.4.3 on top of Apache instead - and did the web based install. Everything is working perfectly now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.