This page covers installing KingCMS X1.0.0-alpha, the first visit, online updates, backups and scheduled tasks. The web root must point to the public/ directory of the package. The database is created automatically on first visit; there is no step-by-step installer.

1. Requirements

  • PHP 8.2 or later. The examples use PHP 8.4 from Debian 13.
  • PHP extensions: pdo_sqlite, sqlite3, sodium, mbstring, intl, curl, gd, xml, ctype, json, openssl. Image handling needs gd, online backups need sqlite3, and backups including uploads need the zip extension.
  • SQLite 3 (the sqlite3 command line is used for manual backups).
  • nginx (shown here) or Apache, with PHP running through PHP-FPM.
  • A writable data/ directory. The SQLite database, app.key, cache and uploads live there.

app/ and data/ must stay outside the web root and must not be reachable from the browser. Only public/ is the web root.

2. Download and verify

Download page: https://download.kingcms.com/. Current version X1.0.0-alpha (released 2026-10-20), about 16.4 MB, signed.

wget https://update.kingcms.com/stable/kingcms-x1-X1.0.0-alpha.zip
sha256sum kingcms-x1-X1.0.0-alpha.zip

The checksum must be:

278bdb5d4a1cb1ca480b7e0802cc8773d69664f58194eb72ee59546a29490767

If it does not match, do not deploy; download again.

3. Install packages

sudo apt update
sudo apt install -y \
  nginx \
  php8.4-fpm php8.4-cli php8.4-sqlite3 php8.4-mbstring \
  php8.4-intl php8.4-curl php8.4-gd php8.4-xml \
  sqlite3

sodium is provided by the PHP 8.4 common package.

Check PHP extensions

for ext in pdo_sqlite sqlite3 sodium mbstring intl curl gd xml ctype json openssl; do
  php -r 'exit(extension_loaded($argv[1]) ? 0 : 1);' "$ext" \
    || echo "missing extension: $ext"
done

No output means all extensions are present. If you installed extensions later, restart PHP-FPM:

sudo systemctl restart php8.4-fpm

4. Upload and unzip

sudo mkdir -p /var/www/kingcms
sudo unzip kingcms-x1-X1.0.0-alpha.zip -d /var/www/kingcms

The package contains app/, bin/, modules/, public/, resources/, themes/ and vendor/. Dependencies are bundled, so no composer install is needed.

Point the web root to /var/www/kingcms/public, not to /var/www/kingcms or app/.

Enabling OPcache is recommended:

opcache.enable=1
opcache.memory_consumption=128
opcache.validate_timestamps=1

5. Directory permissions

cd /var/www/kingcms
sudo mkdir -p data/uploads data/cache
sudo chown -R www-data:www-data data
sudo find data -type d -exec chmod 750 {} \;
sudo find data -type f -exec chmod 640 {} \;

On first visit the program creates data/app.key and sets it to 0600. Confirm:

sudo chmod 600 /var/www/kingcms/data/app.key
sudo ls -l /var/www/kingcms/data/app.key

app.key encrypts secret settings. Never delete or replace it; encrypted values cannot be recovered without it.

6. nginx

Put the rate-limit zone in /etc/nginx/conf.d/kingcms-limit.conf (limit_req_zone is only valid in the http context):

limit_req_zone $binary_remote_addr zone=kingcms:10m rate=10r/s;

Site config /etc/nginx/sites-available/kingcms:

server {
    listen 80;
    server_name cms.example.com;

    root /var/www/kingcms/public;
    index index.php;

    client_max_body_size 20m;

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

    location /media/ {
        alias /var/www/kingcms/data/uploads/;
        add_header Cache-Control "public, max-age=2592000";

        location ~ \.php$ {
            return 404;
        }

        location ~ /\. {
            deny all;
        }
    }

    location ~ /\.(?!well-known) {
        deny all;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.4-fpm.sock;
        limit_req zone=kingcms burst=20 nodelay;
    }
}
sudo ln -s /etc/nginx/sites-available/kingcms /etc/nginx/sites-enabled/kingcms
sudo nginx -t
sudo systemctl reload nginx

Configure HTTPS before going live. WeChat/Alipay callbacks and Secure cookies require it.

PHP upload limits

upload_max_filesize = 20M
post_max_size = 20M

Keep these equal to or larger than nginx client_max_body_size, then restart PHP-FPM.

7. Apache rewriting

Enable mod_rewrite (a2enmod rewrite, then restart Apache) and allow .htaccess overrides (AllowOverride All).

<VirtualHost *:80>
    ServerName cms.example.com
    DocumentRoot /var/www/kingcms/public

    <Directory /var/www/kingcms/public>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

The bundled .htaccess in public/ sends missing files and directories to index.php, keeping the query string:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]

8. Database created on first visit

Open the site in a browser. If data/kingcms.sqlite does not exist, the program creates the SQLite database, runs core and module migrations, writes default settings and generates data/app.key. No SQL import is needed.

9. Create the administrator

Until an administrator exists, every page redirects to /admin/setup (except /assets/ and /healthz). The one-time form asks for:

  • username (required, up to 64 characters);
  • password (at least 8 characters);
  • password confirmation;
  • optionally, create sample content;
  • acceptance of the license agreement.

After creation you are logged in and redirected to /admin; /admin/setup then returns 404 permanently. Login is at /admin/login. To reset a forgotten password:

cd /var/www/kingcms
sudo -u www-data php bin/kingcms admin:reset-password

10. Online updates

Online updates are available. The update page in the admin reads https://update.kingcms.com/stable/latest.json, compares it with the installed version and shows release notes and checksums.

  • Back up the database and app.key first.
  • Updates replace program files and keep data/ (database, app.key, uploads, cache).
  • With OPcache and validate_timestamps=0, reload PHP-FPM afterwards.
  • You can also download the new package, verify it as in section 2 and overwrite the program files, keeping data/.

11. Backups

Back up the SQLite database and app.key together.

sudo install -d -m 700 /var/backups/kingcms
sudo sqlite3 /var/www/kingcms/data/kingcms.sqlite \
  ".backup '/var/backups/kingcms/kingcms-$(date +%F).sqlite'"
sudo install -m 600 /var/www/kingcms/data/app.key \
  /var/backups/kingcms/app.key

Use sqlite3 .backup rather than copying a live .sqlite file. The admin backup page can also back up, download, delete and restore, and schedule daily or weekly backups.

Note: to back up a running site, use the admin's backup feature or sqlite3 .backup rather than copying the live database file; back up the database together with app.key.

12. cron

php bin/kingcms cron:run runs per-minute hooks of enabled modules and due background jobs (releasing stock reservations, ntfy pushes, statistics rollups). Add to /etc/cron.d/kingcms:

SHELL=/bin/sh
PATH=/usr/local/bin:/usr/bin:/bin
* * * * * www-data /usr/bin/php /var/www/kingcms/bin/kingcms cron:run >/dev/null 2>&1

13. Quick local trial

php -S 127.0.0.1:8080 -t public public/index.php

Open http://127.0.0.1:8080. The first visit creates data/, data/kingcms.sqlite and data/app.key, then redirects to /admin/setup. The built-in server is for local trials only, not production.

14. FAQ

Home page works, inner pages return 404. Rewriting is not active. On nginx check try_files ... /index.php?$query_string; on Apache check mod_rewrite and AllowOverride All.

Home page also returns 404. Check that the web root points to public/ and that public/index.php exists.

Uploaded images do not load. They live in data/uploads/, outside the web root; configure the /media/ alias as shown and disable PHP execution there.

Old URLs break after renaming. The program stores 301 redirects automatically.

15. License

Removing the front-end Powered by KingCMS link requires a license; see Pricing & licensing.