<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>debian wordpress — LowEndSpirit</title>
        <link>https://lowendspirit.com/index.php?p=/</link>
        <pubDate>Thu, 04 Jun 2026 07:00:35 +0000</pubDate>
        <language>en</language>
            <description>debian wordpress — LowEndSpirit</description>
    <atom:link href="https://lowendspirit.com/index.php?p=/discussions/tagged/debian-wordpress/feed.rss" rel="self" type="application/rss+xml"/>
    <item>
        <title>Debian 13, minimum ram and disk, 38mb - Guide - Part 2 (running wordpress)</title>
        <link>https://lowendspirit.com/index.php?p=/discussion/10687/debian-13-minimum-ram-and-disk-38mb-guide-part-2-running-wordpress</link>
        <pubDate>Tue, 24 Mar 2026 15:24:12 +0000</pubDate>
        <category>WordPress</category>
        <dc:creator>AnthonySmith</dc:creator>
        <guid isPermaLink="false">10687@/index.php?p=/discussions</guid>
        <description><![CDATA[<h1>WordPress on Debian 13: Minimal VPS</h1>

<p>This guide installs a tuned WordPress stack on a minimised Debian 13 VPS, picking up from the end of the <a href="https://lowendspirit.com/discussion/10684/debian-13-minimum-ram-and-disk-38mb-guide-part-1-running-nothing#latest" rel="nofollow">https://lowendspirit.com/discussion/10684/debian-13-minimum-ram-and-disk-38mb-guide-part-1-running-nothing#latest</a> guide. Every command has been run on a real instance and the results recorded.</p>

<p>AI USE Declaration: md formatting, spelling, grammar done with Claude, the work and methods are my own.</p>

<p>The stack is Nginx with FastCGI caching, MariaDB 10.11 LTS, and PHP 8.4-FPM. The target is the lowest practical idle RAM footprint on a 256MB VPS without sacrificing WordPress compatibility.</p>

<hr />

<h2>Before</h2>

<p>End state of the Debian 13 minimisation guide.</p>

<pre><code>               total        used        free      shared  buff/cache   available
Mem:             213          38         141           0          41         174
Swap:              0           0           0
</code></pre>

<pre><code>Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1       2.8G  275M  2.4G  11% /
</code></pre>

<p>Even if you did not follow that guide, this should give you some ideas on reducing the footprint for your small WordPress setup.</p>

<hr />

<h2>Stage 1: Install MariaDB 10.11 LTS</h2>

<p>Debian 13 (trixie) ships MariaDB 11.8. This guide uses MariaDB 10.11 LTS from the MariaDB Foundation repository. On this configuration, 10.11 uses 57MB RSS at idle versus 68MB for 11.8.</p>

<p>Installing 10.11 on Debian 13 requires three steps before the main package install: a compatibility shim for <code>libaio1</code> (renamed in Debian 13's library transition), the MariaDB Foundation repository, and an apt preference to pin the packages.</p>

<p><strong>libaio1 compatibility shim.</strong> Debian 13 renamed <code>libaio1</code> to <code>libaio1t64</code>. The MariaDB 10.11 bookworm packages declare a dependency on the old name. Create a symlink so the library is found at runtime, then build a dummy package to satisfy the dependency declaration:</p>

<pre><code>apt-get update
apt-get install -y gnupg equivs libaio1t64

ln -s /usr/lib/x86_64-linux-gnu/libaio.so.1t64 /usr/lib/x86_64-linux-gnu/libaio.so.1
ldconfig

cat &gt; /tmp/libaio1-compat &lt;&lt; 'EOF'
Section: libs
Priority: optional
Standards-Version: 3.9.2
Package: libaio1
Version: 0.3.113-8+b1
Provides: libaio1
Depends: libaio1t64
Architecture: amd64
Description: libaio1 compatibility shim for Debian 13
EOF

cd /tmp &amp;&amp; equivs-build libaio1-compat
dpkg -i /tmp/libaio1_0.3.113-8+b1_amd64.deb
</code></pre>

<p><strong>MariaDB Foundation repository and apt pin:</strong></p>

<pre><code>curl -LsS https://mariadb.org/mariadb_release_signing_key.asc \
    | gpg --dearmor &gt; /etc/apt/trusted.gpg.d/mariadb.gpg

cat &gt; /etc/apt/sources.list.d/mariadb.list &lt;&lt; 'EOF'
deb [arch=amd64,arm64] https://dlm.mariadb.com/repo/mariadb-server/10.11/repo/debian bookworm main
EOF

cat &gt; /etc/apt/preferences.d/mariadb &lt;&lt; 'EOF'
Package: mariadb-* libmariadb*
Pin: release n=trixie
Pin-Priority: -1
EOF

apt-get update
</code></pre>

<p>The pin sets the priority of Debian's trixie mariadb packages to -1, which prevents apt from ever selecting them, including during <code>apt full-upgrade</code>.</p>

<p><strong>Remove build tools.</strong> <code>equivs</code> pulls in the full compiler and build toolchain as dependencies. <code>gnupg</code> is no longer needed once the signing key is imported. Remove them now before the main install to keep the disk footprint clean:</p>

<pre><code>apt-get purge -y equivs gnupg dpkg-dev build-essential &amp;&amp; apt-get autoremove -y --purge
</code></pre>

<p><strong>Install the stack:</strong></p>

<pre><code>DEBIAN_FRONTEND=noninteractive apt-get install -y \
    nginx mariadb-server-core mariadb-client-core \
    php8.4-fpm php8.4-mysql php8.4-curl php8.4-gd \
    php8.4-mbstring php8.4-xml php8.4-zip \
    curl
</code></pre>

<p><code>mariadb-server-core</code> is the server binary package. <code>mariadb-server</code> is a meta-package that additionally depends on <code>galera-4</code>, <code>perl</code>, <code>rsync</code>, and <code>socat</code>, which are Galera cluster tools that a single-site server does not need. Installing <code>mariadb-server-core</code> directly avoids all of them.</p>

<p>The <code>php8.4-opcache</code> and <code>php8.4-readline</code> packages are pulled in as dependencies. Both are disabled from the FPM process in Stage 3.</p>

<p><strong>Post-install cleanup.</strong> Nginx's post-install script attempts to start the service, which fails because IPv6 is disabled at the kernel and the default configuration includes <code>listen [::]:80</code>. Fix the default configuration and complete the package setup, then remove <code>man-db</code> which the install brought back as a trigger dependency:</p>

<pre><code>sed -i "s/listen \[::\]:80 default_server;//" /etc/nginx/sites-available/default
dpkg --configure -a

apt-get purge -y man-db &amp;&amp; apt-get autoremove -y --purge &amp;&amp; apt-get clean
</code></pre>

<hr />

<h2>Stage 2: Configure MariaDB 10.11</h2>

<p>The default MariaDB configuration reserves memory as if the server has gigabytes available. Three settings must be addressed:</p>

<ul>
<li><code>innodb_buffer_pool_size</code> defaults to <strong>128MB</strong>. For a single low-traffic WordPress site this can be set to the minimum: 6MB, which is the smallest value the InnoDB engine accepts for the default 16KB page size.</li>
<li><code>aria_pagecache_buffer_size</code> defaults to <strong>128MB</strong>. The Aria engine is used only by MariaDB's internal <code>mysql</code> schema tables. 4MB is sufficient.</li>
<li><code>key_buffer_size</code> defaults to <strong>128MB</strong>. This is the MyISAM key cache. WordPress has zero MyISAM tables. It can be set to zero.</li>
</ul>

<pre><code>cat &gt; /etc/mysql/mariadb.conf.d/99-minvps.cnf &lt;&lt; 'EOF'
[mysqld]
# Disable performance schema
performance_schema             = OFF

# InnoDB -- default is 128MB, 6M is minimum for 16KB page size
innodb_buffer_pool_size        = 6M
innodb_log_buffer_size         = 2M
innodb_flush_log_at_trx_commit = 2
innodb_buffer_pool_dump_at_shutdown = OFF
innodb_buffer_pool_load_at_startup  = OFF

# InnoDB threads -- write minimum is 2, read and purge can be 1
innodb_read_io_threads         = 1
innodb_write_io_threads        = 2
innodb_purge_threads           = 1

# InnoDB open files -- we have 16 WordPress tables
innodb_open_files              = 32

# Aria -- used by mysql schema internally; all WordPress tables are InnoDB
# Default 128MB; mysql schema Aria data totals ~3MB
aria_pagecache_buffer_size     = 4M

# MyISAM key cache -- zero MyISAM tables in WordPress
key_buffer_size                = 0

# Per-session sort/join buffers -- only allocated during queries, not at idle
sort_buffer_size               = 256K
join_buffer_size               = 128K
read_rnd_buffer_size           = 128K

# No DNS lookups -- DB only accepts localhost connections
skip_name_resolve              = ON
host_cache_size                = 0

# Connection and table limits
max_connections                = 10
max_allowed_packet             = 16M
table_open_cache               = 64
table_definition_cache         = 400
thread_cache_size              = 2

# Temp tables
tmp_table_size                 = 8M
max_heap_table_size            = 8M

# No binary logging on a single server
skip_log_bin

# Unix socket only
bind-address                   = 127.0.0.1

[client]
default-character-set = utf8mb4
EOF
</code></pre>

<ul>
<li><code>innodb_buffer_pool_dump_at_shutdown = OFF</code> and <code>innodb_buffer_pool_load_at_startup = OFF</code> disable the buffer pool state file. With a 6MB pool, saving and reloading it on every restart is pointless I/O. <code>innodb_write_io_threads</code> has a hard minimum of 2 in MariaDB 10.11. Read and purge threads can be reduced to 1.</li>
<li><code>skip_log_bin</code> disables binary logging. Binary logs are used for replication and point-in-time recovery. A single-server WordPress instance has no replicas, and recovery is handled by scheduled backups.</li>
<li><code>performance_schema = OFF</code> disables the performance monitoring tables. They serve no purpose on a production single-site server.</li>
</ul>

<p><code>mariadb-server-core</code> does not include a systemd service file, nor does it create the <code>mysql</code> system user or the data directory. Do all three before starting the service:</p>

<pre><code>groupadd -r mysql
useradd -r -g mysql -d /var/lib/mysql -s /usr/sbin/nologin mysql
mkdir -p /var/lib/mysql
chown mysql:mysql /var/lib/mysql
mariadb-install-db --user=mysql --datadir=/var/lib/mysql

cat &gt; /etc/systemd/system/mariadb.service &lt;&lt; 'EOF'
[Unit]
Description=MariaDB 10.11 LTS Database Server
After=network.target

[Service]
Type=notify
User=mysql
Group=mysql
ExecStart=/usr/sbin/mariadbd --defaults-file=/etc/mysql/mariadb.conf.d/99-minvps.cnf
Restart=on-failure
RuntimeDirectory=mysqld
RuntimeDirectoryMode=0755
TimeoutSec=300

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable mariadb
</code></pre>

<p>Start MariaDB and create the WordPress database:</p>

<pre><code>systemctl restart mariadb

DB_PASS=$(openssl rand -base64 18)
echo "DB password: $DB_PASS"

mysql -e "CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -e "CREATE USER 'wordpress'@'localhost' IDENTIFIED BY '$DB_PASS';"
mysql -e "GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'localhost';"
mysql -e "FLUSH PRIVILEGES;"
</code></pre>

<p>Save the generated password. It is needed in Stage 5.</p>

<hr />

<h2>Stage 3: Configure PHP-FPM</h2>

<p><strong>Pool configuration.</strong> The default FPM pool uses <code>pm = dynamic</code>, which pre-forks worker processes at startup. For a low-traffic site, <code>pm = ondemand</code> is better: it spawns a worker only when a request arrives and kills it after 10 seconds of inactivity. At idle, only the master process remains.</p>

<p>Edit <code>/etc/php/8.4/fpm/pool.d/www.conf</code> and set:</p>

<pre><code>pm = ondemand
pm.max_children = 1
pm.process_idle_timeout = 10s
pm.max_requests = 500
</code></pre>

<p><strong>Timezone.</strong> PHP 8.4 rejects the bare string <code>UTC</code> as a timezone identifier. Use the canonical name:</p>

<pre><code>sed -i "s|;date.timezone =|date.timezone = Etc/UTC|" \
    /etc/php/8.4/fpm/php.ini \
    /etc/php/8.4/cli/php.ini
</code></pre>

<p><strong>Disable unused extensions from FPM.</strong> The default PHP install loads 32 extensions in the FPM process. WordPress needs 18 of them. The <code>-s fpm</code> flag disables extensions only in FPM, leaving the CLI unaffected:</p>

<pre><code>phpdismod -s fpm \
    ffi shmop sysvmsg sysvsem sysvshm \
    sockets calendar xsl gettext readline \
    phar ftp tokenizer
</code></pre>

<p>Opcache is a Zend extension and is not handled by <code>phpdismod</code>. Remove its FPM configuration file directly:</p>

<pre><code>rm /etc/php/8.4/fpm/conf.d/10-opcache.ini
</code></pre>

<p>The 18 extensions remaining in FPM: <code>ctype</code>, <code>curl</code>, <code>dom</code>, <code>exif</code>, <code>fileinfo</code>, <code>gd</code>, <code>iconv</code>, <code>mbstring</code>, <code>mysqli</code>, <code>mysqlnd</code>, <code>pdo</code>, <code>pdo_mysql</code>, <code>posix</code>, <code>simplexml</code>, <code>xml</code>, <code>xmlreader</code>, <code>xmlwriter</code>, <code>zip</code>. This is the minimum set for a fully functional WordPress install including image uploads and resize.</p>

<p>Restart PHP-FPM:</p>

<pre><code>systemctl restart php8.4-fpm
</code></pre>

<hr />

<h2>Stage 4: Configure Nginx</h2>

<p>Debian 13's default Nginx configuration tries to listen on <code>[::]:80</code>. IPv6 was disabled at the kernel in the minimisation guide. Replace the configuration entirely:</p>

<pre><code>cat &gt; /etc/nginx/nginx.conf &lt;&lt; 'EOF'
user www-data;
worker_processes 1;
pid /run/nginx.pid;

events {
    worker_connections 512;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    sendfile on; tcp_nopush on; tcp_nodelay on;
    keepalive_timeout 15;
    server_tokens off;
    access_log off;
    error_log /var/log/nginx/error.log warn;
    gzip on;
    gzip_types text/plain text/css application/javascript application/json text/xml application/xml application/rss+xml;
    gzip_min_length 1000;
    fastcgi_cache_path /tmp/nginx-cache levels=1:2 keys_zone=WORDPRESS:10m inactive=60m max_size=50m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    include /etc/nginx/conf.d/*.conf;
}
EOF
</code></pre>

<p>The FastCGI cache lives in <code>/tmp/nginx-cache</code> on tmpfs. This directory disappears at reboot. Create a tmpfiles rule to recreate it on boot:</p>

<pre><code>echo "d /tmp/nginx-cache 0755 www-data www-data -" &gt; /etc/tmpfiles.d/nginx-cache.conf
mkdir -p /tmp/nginx-cache
chown www-data:www-data /tmp/nginx-cache
</code></pre>

<p>Create the site configuration. Replace <code>YOUR_DOMAIN</code> with your domain name and <code>YOUR_IP</code> with the IP address you will administer wp-admin from:</p>

<pre><code>cat &gt; /etc/nginx/conf.d/YOUR_DOMAIN.conf &lt;&lt; 'EOF'
set_real_ip_from 10.X.X.X/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

server {
    listen 80;
    server_name YOUR_DOMAIN;
    root /var/www/YOUR_DOMAIN;
    index index.php;

    location = /xmlrpc.php { deny all; }

    location ~ ^/(wp-admin|wp-login\.php) {
        allow YOUR_IP_HERE;
        deny all;
        try_files $uri $uri/ /index.php?$args;
        location ~ \.php$ {
            include fastcgi_params;
            fastcgi_pass unix:/run/php/php8.4-fpm.sock;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_cache_bypass 1;
            fastcgi_no_cache 1;
        }
    }

    set $skip_cache 0;
    if ($request_method = POST)        { set $skip_cache 1; }
    if ($query_string != "")           { set $skip_cache 1; }
    if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") { set $skip_cache 1; }

    location / { try_files $uri $uri/ /index.php?$args; }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_cache WORDPRESS;
        fastcgi_cache_valid 200 60m;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
        fastcgi_cache_use_stale error timeout updating http_500 http_503;
        add_header X-Cache $upstream_cache_status;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
        log_not_found off;
    }
}
EOF
</code></pre>

<p>The <code>set_real_ip_from</code> and <code>real_ip_header</code> directives are for TierHive instances where all external traffic arrives through HAProxy from the <code>10.0.0.0/8</code> range. They replace the HAProxy-internal source IP with the real client IP before the <code>allow</code>/<code>deny</code> rules are evaluated. On a server with a direct public IP, remove those three lines.</p>

<p>The <code>wp-admin</code> and <code>wp-login.php</code> location block restricts access to a single IP before any PHP executes. The <code>X-Cache</code> header exposes cache status to the client (<code>HIT</code> or <code>MISS</code>). Remove it if you do not want this visible in response headers.</p>

<p>Remove the default Nginx site configuration and test:</p>

<pre><code>rm -f /etc/nginx/sites-enabled/default /etc/nginx/conf.d/default.conf
nginx -t &amp;&amp; systemctl reload nginx
</code></pre>

<hr />

<h2>Stage 5: Install WordPress</h2>

<p><strong>Create the web root:</strong></p>

<pre><code>mkdir -p /var/www/YOUR_DOMAIN
chown www-data:www-data /var/www/YOUR_DOMAIN
</code></pre>

<p><strong>Install WP-CLI.</strong> WP-CLI is the WordPress command-line management tool. Dropbear does not support SFTP, so download directly to the VPS:</p>

<pre><code>curl -sL https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar \
    -o /usr/local/bin/wp &amp;&amp; chmod +x /usr/local/bin/wp
</code></pre>

<p><strong>Download WordPress and create wp-config.php.</strong> Run as <code>www-data</code> so that all files are owned by the web server user. This causes WordPress to detect <code>FS_METHOD = direct</code>, meaning it can update itself and install plugins without FTP credentials. <code>sudo</code> was removed so either add it back or stick with su; use <code>su</code> to switch user from root:</p>

<pre><code>su -s /bin/bash -c "wp core download --path=/var/www/YOUR_DOMAIN" www-data

su -s /bin/bash -c "wp config create --path=/var/www/YOUR_DOMAIN --dbname=wordpress --dbuser=wordpress --dbpass=YOUR_DB_PASSWORD --dbhost=localhost --extra-php" www-data &lt;&lt; 'PHPEOF'
define( 'DISABLE_WP_CRON', true );
define( 'DISALLOW_FILE_EDIT', true );
define( 'WP_POST_REVISIONS', 3 );

if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) &amp;&amp; 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ) {
    $_SERVER['HTTPS'] = 'on';
}
PHPEOF
</code></pre>

<ul>
<li><code>DISABLE_WP_CRON</code> stops WordPress from triggering cron jobs on page load. A system cron job replaces it below.</li>
<li><code>DISALLOW_FILE_EDIT</code> removes the theme and plugin editor from wp-admin, reducing the attack surface if credentials are compromised.</li>
<li><code>WP_POST_REVISIONS = 3</code> caps the revision history stored per post, keeping the database smaller.</li>
<li>The <code>HTTP_X_FORWARDED_PROTO</code> block tells WordPress it is being served over HTTPS even though Nginx receives plain HTTP from the upstream proxy. Without it, WordPress generates <code>http://</code> URLs and the browser enters an infinite redirect loop. This applies when SSL terminates upstream: HAProxy, Cloudflare, or a load balancer. Remove it if Nginx handles TLS directly.</li>
</ul>

<p><strong>Install WordPress:</strong></p>

<pre><code>su -s /bin/bash -c 'wp core install --path=/var/www/YOUR_DOMAIN --url=https://YOUR_DOMAIN --title="YOUR_SITE_TITLE" --admin_user=YOUR_ADMIN_USER --admin_password=YOUR_ADMIN_PASSWORD --admin_email=YOUR_EMAIL --skip-email' www-data
</code></pre>

<p><strong>Replace WP-Cron with a system cron job.</strong> WordPress's built-in cron fires on page load, which adds latency and fails entirely if the site has no traffic. A system job runs on a fixed schedule regardless:</p>

<pre><code>cat &gt; /etc/cron.d/wordpress &lt;&lt; 'EOF'
*/5 * * * * www-data php /usr/local/bin/wp cron event run --due-now --path=/var/www/YOUR_DOMAIN --quiet 2&gt;/dev/null
EOF
</code></pre>

<hr />

<h2>Reboot</h2>

<pre><code>reboot
</code></pre>

<hr />

<h2>After</h2>

<pre><code>               total        used        free      shared  buff/cache   available
Mem:             213          84          32           0         104         128
Swap:              0           0           0
</code></pre>

<pre><code>Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1       2.8G  800M  1.9G  31% /
</code></pre>

<p>RAM up from 38MB to 84MB. Disk up from 275MB to 800MB.</p>

<hr />

<h2>What Is Still Running</h2>

<p>At idle with no active requests, the FPM pool has no workers. Workers spawn on demand and exit after 10 seconds of inactivity.</p>

<table>
<thead>
<tr>
  <th>Process</th>
  <th>RSS</th>
  <th>PSS</th>
</tr>
</thead>
<tbody>
<tr>
  <td>mariadbd</td>
  <td>57MB</td>
  <td>52MB</td>
</tr>
<tr>
  <td>php-fpm master (no workers)</td>
  <td>30MB</td>
  <td>25MB</td>
</tr>
<tr>
  <td>nginx (master + worker + cache_mgr)</td>
  <td>11MB</td>
  <td>--</td>
</tr>
<tr>
  <td>systemd</td>
  <td>14MB</td>
  <td>--</td>
</tr>
<tr>
  <td>systemd-udevd</td>
  <td>9MB</td>
  <td>--</td>
</tr>
<tr>
  <td>dbus, dropbear, busybox syslogd, getty</td>
  <td>12MB</td>
  <td>--</td>
</tr>
</tbody>
</table>

<p>RSS is the process's resident set. PSS (proportional set size) credits each process only its share of shared library mappings and is the more accurate measure of unique memory use.</p>

<p>Under load with one active PHP worker, total used RAM is approximately 112MB. Cached requests are served by Nginx without spawning a worker.</p>

<p>MariaDB's 57MB RSS is close to the practical minimum for 10.11 with InnoDB. <code>innodb_buffer_pool_size = 6M</code> is the smallest value the engine accepts for the default 16KB page size.</p>

<hr />

<h2>What the tuning saves</h2>

<p>The three MariaDB buffer defaults (<code>innodb_buffer_pool_size</code>, <code>aria_pagecache_buffer_size</code>, and <code>key_buffer_size</code>) reserve 384MB of buffer space in a default install. None of it is used by a single WordPress site. The full set of changes applied:</p>

<table>
<thead>
<tr>
  <th>Change</th>
  <th>Saving</th>
</tr>
</thead>
<tbody>
<tr>
  <td>MariaDB 10.11 LTS instead of Debian's 11.8</td>
  <td>~13MB</td>
</tr>
<tr>
  <td><code>innodb_buffer_pool_size</code> 128MB → 6MB</td>
  <td>~30MB</td>
</tr>
<tr>
  <td><code>aria_pagecache_buffer_size</code> 128MB → 4MB</td>
  <td>~15MB</td>
</tr>
<tr>
  <td><code>key_buffer_size</code> 128MB → 0</td>
  <td>~5MB</td>
</tr>
<tr>
  <td>InnoDB IO threads 4 → 2 (write), 1 (read/purge)</td>
  <td>~2MB</td>
</tr>
<tr>
  <td><code>innodb_buffer_pool_load_at_startup = OFF</code></td>
  <td>marginal</td>
</tr>
<tr>
  <td>Removed opcache shared memory</td>
  <td>~12MB</td>
</tr>
<tr>
  <td>Disabled 13 FPM extensions via phpdismod</td>
  <td>~2MB</td>
</tr>
</tbody>
</table>

<p>I did run this on 128mb ram for a few days, it ran ok, but if you build aritifical load it soon starts to fall over, so on that basis I recommend 256mb.</p>

<p>I am also aware you can run this on sqlite and then probably 128mb is fine, i decided against that, apart from the concurrency issues with sqlite, there are also lots of reported plugin issues, so its not technically supported as a "standard full WordPress install" but you can probably save about 40 - 45mb ram if you decide to use SQLite instead then 128mb is fine.</p>

<p>Example site running this: <a href="https://pop2.me" rel="nofollow">https://pop2.me</a></p>

<p>Thats the end of the guides for a while, might do some micro howto's but these full fat ones take to long for me right now and I tend to get obsessed with trying ot shave KB's of ram off.</p>
]]>
        </description>
    </item>
   </channel>
</rss>
