Skip to content
Sign in

Getting started

Install and run the WBengine skeleton locally, or deploy a clean instance to an Ubuntu VPS with Docker and HTTPS.

Requirements

  • PHP 8.3 or newer with the extensions mysqli, json and mbstring.
  • MySQL 8 or MariaDB 10.6 or newer.
  • Apache with mod_rewrite, or Nginx with PHP-FPM.
  • Composer 2. Docker is optional.

The application requires the Composer package wbengine/wbengine. The framework has no further Composer dependencies; its template engine and Markdown parser are included. Check the package metadata for the exact PHP requirements.

Docker quick start

git clone https://github.com/rrsoftcz/wbengine-skeleton-app
cd wbengine-skeleton-app
docker compose up --build

Open http://localhost:8080. On startup, the web container runs bin/wbe install: it creates and validates Settings.json, prepares the compiled-template directory and installs locked dependencies. The demo login is admin@example.com with password changeme. Change it before exposing the site.

Manual setup

Run php bin/wbe install to create and validate settings, prepare src/View/Compiled, and install dependencies from composer.lock. The command reports invalid JSON, unreadable settings, unwritable compiled cache and Composer failures. Never use chmod 777; grant write access to the PHP web-server user. For local debugging only, set debug to true or WBENGINE_DEBUG=1. Remove debug mode before going live.

php bin/wbe install

Create a database, import schemas/wbengine_skeletone_app_mysql_template.sql and then schemas/wbengine_skeletone_app_mysql_template_content.sql. Configure src/Config/Settings.json and point the web root to public/.

Installation and exception troubleshooting

In development, set debug to true in Settings.json to show the WBengine exception template with the exception type, message, file, line and stack trace. If settings are missing or malformed, use WBENGINE_DEBUG=1 only in a private development environment. Never expose debug output publicly. The production error page shows a safe explanation and reference code; find the full exception in the PHP or container error log under that code.

For upgrades, back up the database and apply pending scripts in schemas/migrations/ in order. Docker imports the schema and seed files only when it initializes a new database volume. Rebuilding the web image does not update an existing database.

Clean VPS deployment with Docker

This procedure is for a new, empty Ubuntu server. It creates a new database from the schema and content committed to this repository. It does not copy a database from a development or existing website. Do not run the clean-install script against an existing database. For an existing site, first back it up and follow the upgrade procedure instead.

The PHP application and MySQL run in Docker. Nginx and Certbot run on the Ubuntu host. The application port is bound to 127.0.0.1:8080, and MySQL is not published on a host port. The optional WBengine Admin is a separate SvelteKit application and is not installed by this procedure; it can remain on a development computer and connect through a separately configured API v2 integration.

1. Prepare DNS and firewall

Point www.wbengine.org to the VPS IPv4 address. Allow inbound SSH on port 22 and web traffic on ports 80 and 443 in the VPS firewall. The apex domain wbengine.org may continue to redirect to www from its current DNS host. The sample Nginx configuration serves www.wbengine.org.

2. Install Docker

Install Docker Engine and the Docker Compose plugin using the official Ubuntu instructions. The host does not need PHP or Composer. PHP, Composer and MySQL are provided by the application containers.

3. Create the clean application and database

Install Git, OpenSSL, Nginx and Certbot, then clone the repository and run the production installer:

apt-get update
apt-get install -y git openssl nginx certbot
git clone https://github.com/rrsoftcz/wbengine-skeleton-app.git /opt/wbengine-skeleton-app
cd /opt/wbengine-skeleton-app
./bin/setup-production.sh https://www.your-domain.tld

The installer takes the public HTTPS address of the site as its argument, trusts the Docker network gateway as the proxy that forwards the HTTPS headers from host Nginx, generates private database passwords on the server, builds the production PHP image, initializes a new MySQL volume from the tracked schema and content seed, creates the API and analytics tables, and replaces the documented demo password with a random unusable password. Keep .env and src/Config/Settings.json private. The script leaves analytics collection disabled. It does not import data from another database.

4. Configure HTTPS in Nginx

Create the ACME webroot and enable the temporary HTTP-only configuration so Let's Encrypt can verify the hostname:

install -d -m 755 /var/www/letsencrypt
ln -sfn /opt/wbengine-skeleton-app/deploy/nginx/www.wbengine.org-http.conf /etc/nginx/sites-enabled/www.wbengine.org.conf
rm -f /etc/nginx/sites-enabled/default
nginx -t && systemctl reload nginx
certbot certonly --webroot -w /var/www/letsencrypt -d www.wbengine.org

After the certificate is issued, switch to the TLS reverse-proxy configuration and verify renewal:

ln -sfn /opt/wbengine-skeleton-app/deploy/nginx/www.wbengine.org.conf /etc/nginx/sites-enabled/www.wbengine.org.conf
nginx -t && systemctl reload nginx
certbot renew --dry-run --no-random-sleep-on-renew

5. Verify and update

Check the public site and both container health states:

curl -I https://www.wbengine.org/
docker compose -f docker-compose.production.yml ps
docker compose -f docker-compose.production.yml logs --tail=100 web db

For a later application update, fetch the reviewed commit and rebuild the web image:

git pull --ff-only
docker compose -f docker-compose.production.yml up -d --build --wait

The database volume persists across image rebuilds. Database updates of a newer version must be applied once, after a backup (see the Deployment page). Never expose MySQL port 3306 publicly. The complete procedure is also in the repository deployment guide.

Users and the first login

Every WBengine site keeps its accounts in the cms_users table. A user has one of three roles: user (signs in and uses the profile), editor and admin. The role is read from the database on every privileged request, so changing or deleting an account takes effect immediately. There is no public registration: accounts are managed with the bin/wbe command line tool.

What a fresh install contains

  • Local Docker (docker compose up): the seed contains the demo account admin@example.com with the published password changeme. Use it only on your own computer.
  • Production (bin/setup-production.sh): the installer replaces the demo password with a random one that nobody knows. Nobody can sign in until you create an administrator.

Create the first administrator

Run the command inside the web container (use docker compose exec web ... for the local stack, docker compose -f docker-compose.production.yml exec web ... in production, or plain php bin/wbe ... without Docker):

docker compose -f docker-compose.production.yml exec web php bin/wbe user:create --email=you@your-domain.tld --role=admin

The command asks for the password twice and does not show it. The password is never accepted as an argument or an environment variable, so it does not end up in the shell history or in the process list. For automation, send one line on standard input (without a terminal, so use exec -T):

printf '%s\n' "$PASSWORD" | docker compose -f docker-compose.production.yml exec -T web php bin/wbe user:create --email=you@your-domain.tld --role=admin

Then sign in at /login/ with the e-mail address and the password you chose.

Remove the demo account

bin/wbe user:delete --example --dry-run
bin/wbe user:delete --example

The first command only lists the accounts. The second deletes every account whose e-mail address is in a reserved example domain (example.com, example.org, example.net and their subdomains, and the .example, .test, .invalid and .localhost top-level domains). It refuses to run when no other administrator would remain, so create your own administrator first.

List users, change a password, delete a user

bin/wbe user:list
bin/wbe user:password --email=you@your-domain.tld
bin/wbe user:delete --email=someone@your-domain.tld

A forgotten password is reset with user:password, which also ends the user's web sessions. The last administrator cannot be deleted. None of these commands prints a password or a password hash.

Next step

To manage this site from the central WBengine Admin, see the page Central administration, section Connecting a site step by step. It needs an account with the role admin. Installing and running the administration itself is described on the same page, in the section Installing and configuring.