Fix It 'Til It's Broke

A poorly designed WP blog


The whole secret lies in confusing the enemy, so that he cannot fathom our real intent

Who thought that Sun Tzu would be helping me maintain a blog?

Since the beginning, I haven’t been able to upload any media to this site in excess of 1MB. I literally learned how to use ffmpeg to convert a .mp4 from my phone into a .webp earlier today instead of an animated .gif because it’s supposed to be more efficient at packing pixels onto a disk.

For reference, I have one VM that handles most of my overall administrative functions for the home lab. Nginx is one of those services. I have tried to run nginx inside a docker container in the past and only gotten frustrated as it fought with the rest of the docker network stack. So now it runs on “bare metal” as a service on a Debian VM. I would rather have one nginx.conf file that is slightly convoluted than try to deal with reverse proxy inception.

A separate LXC container runs websites. One docker compose file for each. WordPress, mariadb, and phpmyadmin in each compose file. Then we just have to manage the ports for wordpress in each docker network stack, and point nginx at the IP and port of each of those instances.

The Problem:
I will demonstrate my problem in the draft of this post itself. Let’s try and upload a file larger than 1MB.

The file on the disk
The JSON error, circled in red, is the problem, and shows up nowhere in the logs for mariadb, wordpress, or phpmyadmin. This is immediately after selecting the file, the dialog on the screen is prompting for a new (acceptable) file that apparently is never coming.

And a sub-1MB file works just fine.

A screenshot from my other post that was small enough.
And here it is inside of this post working just fine.

my docker-compose.yaml file for the site in question.

services:
  mariadb:
    image: mariadb:latest
    container_name: mariadb
    hostname: mariadb
    restart: unless-stopped
    volumes:
      - ./mysql:/var/lib/mysql
      - ./etc/mysql:/etc/mysql
    environment:
     - TZ=America/Chicago
     - MYSQL_ROOT_PASSWORD=_secret_
     - MYSQL_DATABASE=_secret_
     - MYSQL_USER=_secret_
     - MYSQL_PASSWORD=_secret_
    networks:
      - wordpress
  phpmyadmin:
    image: phpmyadmin:latest
    container_name: phpmyadmin
    hostname: phpmyadmin
    restart: unless-stopped
    depends_on:
      - mariadb
      - wordpress
    environment:
     - TZ=America/Chicago
     - PMA_HOST=_secret_
     - MYSQL_ROOT_PASSWORD=_secret_
     - UPLOAD_LIMIT=64M
    networks:
      - wordpress
  wordpress:
    image: wordpress:latest
    container_name: wordpress
    hostname: wordpress
    restart: unless-stopped
    depends_on: 
     - mariadb
    ports:
      - _port_:80
      - _port_:443
    environment:
      - TZ=America/Chicago
      - WORDPRESS_DB_HOST=mariadb:_port_
      - MYSQL_DATABASE=_secret_    
      - WORDPRESS_DB_USER=_secret_
      - WORDPRESS_DB_PASSWORD=_secret_
      - PHP_UPLOAD_MAX_FILESIZE=64M
    volumes:
      - ./html:/var/www/fitib.us
      - ./etc/letsencrypt:/etc/letsencrypt
      - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
    networks:
      - wordpress
networks:
  wordpress:
    driver: bridge

And here’s the uploads.ini file with additional settings. That *should* have done the trick as well.

_name_@_lxccontainer_:~/docker/wordpress# cat uploads.ini 
file_uploads = On
memory_limit = 64M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 600

It turns out none of that worked! Still the json error on the page when uploading anything larger than 1024kB. I don’t even remember where I found it, but some kind soul out there told me that nginx by default will truncate inbound traffic greater than 1MB or something for security.

This was the missing piece, and it was not well documented anywhere else. So I’m documenting it here for anyone that might need it. We need to get into the host running our nginx service and modify a config file there.

Adding the last line, the magic bullet[?], to /etc/nginx/nginx.conf. Everything prior to the client_max_body_size variable was already existing in my .conf file. I have no idea what’s in yours, but it’s probably similar since I’m not doing any groundbreaking work here.

http {
        ##
        # Basic Settings
        ##
        sendfile on;
        tcp_nopush on;
        types_hash_max_size 2048;
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        client_max_body_size 64M;
...

Then reload nginx.conf settings. Don’t be an ignoramus (like I should talk, especially given the topic of this post) and restart the entire service. Just reload with

sudo nginx -s reload

Now we upload a nice large video file from my earlier car post to test it out, and it works just fine. I spent months trying to tweak the settings, realizing it wasn’t working, then compressing my files in creative ways as a workaround.

So now what?

  1. Upgrade the small grainy videos from my latest car post.
  2. Finish up some drafts that I have stashed away for some 3D printing projects. Namely .stl that you will be able to download, and the solidworks part/assembly files in case anyone needs to modify them. Because we don’t trust thingiverse anymore
  3. Find old photos from my kiln purchase, and upload the calculator I made for winding your own heating elements. Because they’re $60/ea from the manufacturer, but only $10 for 100ft of 22AWG kanthal wire. And everyone with a kiln deserves to save money.