SaaS Kit
Turn any single-tenant PHP app into a multi-tenant SaaS, with its own database per tenant.
For builders who host one PHP app for many customers.
Single license $79 · Extended license $179 · paid once, yours for good
What it does
SQLite gives each tenant its own file; MySQL gives each its own database. There is no shared schema with a tenant_id column.
A forged Host header, an unknown subdomain or a suffix spoof reaches no tenant database. A shipped isolation test proves it on your server.
Sign-up creates the tenant and its database, then runs the app's own installer. No schema code is duplicated.
Stripe or Lemon Squeezy, with your own keys. Signed, replay-protected webhooks move each tenant from trial through active, past due and suspended to canceled.
Each tenant has its own database and its own copy of the app. Its files folder, sessions and static files are separate too.
Upload storage is capped, as is any limit your adapter declares, such as staff or clients. The plane enforces them before the app runs.
A tenant can answer on its own domain once DNS points there. TLS is issued only for verified domains.
The menu, footer, landing page and emails come from one config block. Nothing names the kit's maker unless you choose to.
A KPI dashboard, a filterable tenant list with CSV export, and tenant detail with provisioning state. An append-only log records every tenant change with the billing event behind it.
Your apps in the job groups you name: icon, one line, monthly price. Every plan's inclusions said once. Off until you set design.default to v2.
48 Ownware apps come with an adapter, each one config line from being a SaaS. Your own app needs a shim of about six lines and a copied adapter.
An agent with an owner-minted key can list tenants, plans and statuses and search the audit trail. It cannot create or suspend a tenant.
Also: two-factor sign-in, one free trial per email, your own terms pages with an agree box, crawlable public pages, labeled sign-up fields, and an installable phone app.
What SaaS Kit deliberately doesn’t do.
- Not for $3 shared hosting — per-tenant databases need CREATE DATABASE privileges, so a VPS or a host where you control MySQL is required
- You need wildcard DNS (*.yourapp.com) pointed at your server — no wildcard record, no tenant subdomains
- Billing runs on your own Stripe or Lemon Squeezy keys; the kit is not a payment processor and takes no cut
- Isolation is at the PHP/database level, not container level — not Docker/VM-per-tenant infrastructure isolation
- Not the end business — if you're one company wanting one instance, buy the underlying product itself, not this kit
Release history
For the SaaS Kit, 4.0 means updates from inside the console: the Updates page checks for a new release with your license key, verifies Ownware's signature, takes a… What’s new in 4.0 →
For the SaaS Kit, 3.4 meant a second face for your platform's public pages: your apps grouped by job, off until you set design.default to v2. What’s new in 3.4 →
The 3.1 wave gave the catalog a way to reach the other side of the transaction: counterparty email through your own SMTP server, calendar feeds your own calendar… What’s new in 3.1 →
The control plane gains an append-only audit trail: every tenant lifecycle change with the billing event that caused it, 2FA-aware operator logins, settings saves and…
SaaS Kit 2.0 adds the 2.0 owner layer.
What’s in the zip
The tree as the zip ships it — the working leftovers the packager deletes are not listed
- .htaccess
- API.md
- Dockerfile
- assets/
- bin/
- config.sample.php
- controllers/
- index.php
- install/
- manifest.json
- offline.html
- products/
- router.php
- src/
- sw.js
- tests/
- views/
src/Control.php: a real module, the first 24 of 513 lines
Chosen as the largest module in src/ that is not one of the shared cores — this product's own logic, not a file every product carries.
<?php
/**
* Control.php — the CONTROL database layer. This DB is separate from every tenant DB and holds
* only the registry: owners (super-admins), plans, tenants, subscriptions, and a webhook-event
* ledger for replay protection. It NEVER holds tenant business data. Named `Control` (not
* `Database`) so a wrapped product's own `Database` class can load in the same process untouched.
*
* Works on MySQL (production) or SQLite (zero-config demo/dev) through one PDO handle.
*/
declare(strict_types=1);
final class Control
{
private static ?PDO $pdo = null;
private static string $driver = 'sqlite';
public static function boot(array $db): PDO
{
if (self::$pdo instanceof PDO) return self::$pdo;
$driver = $db['driver'] ?? 'sqlite';
self::$driver = $driver;
if ($driver === 'mysql') {
$dsn = "mysql:host={$db['host']};port=" . ($db['port'] ?? 3306) . ";dbname={$db['name']};charset=utf8mb4";Runs on: 2-minute web installer (MySQL or SQLite for the control DB); PHP 8.1+ with PDO, requires a VPS with wildcard DNS for tenant subdomains. Tested on PHP 8.3. Or run it in Docker: the Dockerfile is in the zip.
Nothing is obfuscated or encoded; what you read is what runs. · API · the test run
Which license do I need?
It comes down to how many installations you need. Running your own business on one site is the Single license. A second domain of your own, or sites you build or run for other people, is the Extended license.
- Install it on one domain you own or operate
- Run it as a hosted, multi-tenant service your own customers sign up for and pay you for
- Change the source however you like for that installation
- Re-download the current build any time from your buyer portal
- A second domain, or an installation you hand to a client as theirs, needs the Extended license
- No reselling, redistributing or sublicensing the source: your customers use the service you run and never receive this code
- Everything the Single license grants
- Install it on as many domains as you own or operate — no cap on the number
- Build and hand over one installation per client project
- Still no reselling or redistributing the source itself
Every download carries the full terms as LICENSE.txt. The complete wording is on the terms page.
After you buy
The app’s Updates page installs a new release with your license key, with the release’s signature checked and a backup taken first. Your download link always serves the current build. Download again any time from your order page or the buyer portal; there is no renewal fee.
Email support for installation and for defects in the code as delivered: a person reads and answers every message. It does not cover custom development or server administration. What support covers
Refunds are handled by Lemon Squeezy as merchant of record, case by case. EU consumers keep the statutory 14-day right until delivery starts. Refund terms
It keeps running: your server, the full PHP source, no license check that can fail. If no stable release is published for 365 days, the domain limit lifts; after three such years your copy becomes MIT-licensed. The terms have the exact wording: continuity.
Questions
Will it run on my host?
Is the isolation claim marketing?
What if the seller disappears?
Does it take a cut of my billing?
Can I wire my own (non-Ownware) app?
Does the price change as I add tenants?
Is the kit a merchant of record?
Can an AI agent create or suspend a tenant?
Does every tenant share one database with a tenant_id column?
Covered in these guides
- What's new in Own It 4.0
- What's new in Own It 3.4
- What SaaS in PHP actually means, and the two people searching for it
- Merchant of record, seller of record: who is actually selling you the software
- What's new in Own It 3.1
- Rent the hosting, own the software — how Ownware Cloud actually works
Also covered in: Ownware OS — the anti-ERP, completed.
More about SaaS Kit
Turn any single-tenant PHP app into a multi-tenant SaaS with its own database per tenant.
The problem it solves
You have a solid single-tenant PHP app — a booking system, an invoicing tool, a membership manager — and ten customers want it. So you either install it ten times and babysit ten servers, or you rewrite it "multi-tenant" by threading a tenant_id through every query and praying you never forget a WHERE clause.
- One missed scope and Customer A is reading Customer B's data
- A separate database per tenant makes cross-tenant leaks structurally impossible instead of a hoped-for discipline
- The alternative today is ten servers to babysit, or a rewrite you have to get perfectly right
Every feature
- Fail-closed subdomain routing. A forged Host header, an unknown subdomain, or a suffix-spoof reaches no tenant database at all — proven by a shipped isolation test, not claimed.
- Separate database per tenant. SQLite means one file per tenant; MySQL means one database per tenant — not a shared schema with a tenant_id column.
- Self-serve signup & provisioning. Signup creates the tenant, creates its database, and runs the product's own installer headlessly, with no duplicated schema code.
- Billing on your own Stripe or Lemon Squeezy keys. Signature-verified, replay-protected webhooks drive the lifecycle from trial through active, past_due, suspended, to canceled, which is terminal.
- Operator console. A KPI dashboard, a filterable tenant list with CSV export, tenant detail with provisioning state, and product-registry health in one place.
- An adapter for every business app. Each of the 48 business apps Ownware sells ships with an adapter and is one config line away from being a SaaS (Own Your AI runs on your own machine, so it has none); a documented reference adapter shows how to wire your own.
- Installable mobile app (PWA). Add it to a phone or tablet home screen straight from the browser — a full-screen app served from your own server, with no app store involved. Business data is not stored offline on the device; what you see is read live.
- Your platform, your name. The menu, footer, landing page and emails are set in one config block, and nothing names the kit's maker unless you choose to.
- Custom domains per tenant. A tenant can answer on its own domain once DNS points it there, with TLS issued only for verified domains.
- Plan limits that bite. Storage caps on uploads, and any limit your adapter declares (staff, clients…) is enforced by the plane before the app runs, with no change to the app.
- Every tenant stands alone. Its own database, its own copy of the app with its own files folder, its own sessions and its own static files.
- Updates from inside the console. The console's Updates page installs a new release with your license key: Ownware's signature is checked, a backup is taken first, and it puts the previous version back by itself if the update is interrupted or the database step or start-up check of the new version fails. Where the console is hosted for you, the page says why updates are off.
- Own It 4.0.1 — the updater stops cleanly. For the SaaS Kit, 3.5.1 fixes a command-line update that ended in an error after putting the previous version back: it now stops there and says what happened. Its LICENSE.txt also uses US spelling now. Your license covers it: press Check for updates on the console's Updates page, or download it from your order page.
- Own It 4.0.2 — affiliate referrals reach the checkout. For the SaaS Kit, 3.5.2 carries an affiliate's referral through to the checkout your console creates at sign-up, so the affiliate who sent the buyer is credited. Before, a referred buyer lost the referral on the way to the payment page. The console reads Lemon Squeezy's own tracking cookie, or the click on the link that brought the buyer in, and loads no tracking script of its own. Your license covers it: press Check for updates on the console's Updates page, or download it from your order page.
Release notes in full
- Own It 4.0: the console updates itself. For the SaaS Kit, 4.0 means updates from inside the console: the Updates page checks for a new release with your license key, verifies Ownware's signature, takes a backup and puts the previous version back by itself if the update is interrupted or the database step or start-up check of the new version fails. A restore now also brings back rows that point at other rows.
- Own It 3.4: a second face, and your terms at sign-up. For the SaaS Kit, 3.4 meant a second face for your platform's public pages: your apps grouped by job, off until you set design.default to v2. It also brought your own terms, agreed at sign-up, request logs kept at most 30 days, and public pages that search engines and screen readers can use.
- Own It 3.1: it writes to the people you serve. The 3.1 wave gave the catalog a way to reach the other side of the transaction: counterparty email through your own SMTP server, calendar feeds your own calendar subscribes to, attachments filed where the paperwork belongs, and export presets other people's software imports. Each outbound feature ships switched off and runs on your own credentials; a failed send is recorded, and the action that triggered it stands. This app gained no new outbound path in 3.1 — its pass rewrote the honest-limitations list against the shipped code instead, which is the more useful change when the product was already complete.
- Own It 3.0: works for your AI, not just for you. The control plane gains an append-only audit trail: every tenant lifecycle change with the billing event that caused it, 2FA-aware operator logins, settings saves and backup downloads — when a customer asks why an instance is suspended, the answer is one filtered page. Backup exports are hardened with wider secret redaction. And every app you provision with it carries its own full Own It 3.0 layer.
- Own It 2.0: signed webhooks, an MCP door, 2FA. SaaS Kit 2.0 adds the 2.0 owner layer. Upgrade by replacing the files — the database migrates itself, and it is still the same one-time purchase.
Browse self-hosted: Software for builders & product teams · Software for builders & agencies