T
Tenanto
Documentation / Installation

Installation

Installation Guide

This guide walks you through installing Tenanto on your server or local development environment.


Requirements

Server Requirements

Requirement Minimum Recommended
PHP 8.3 8.4
PostgreSQL 16 16
Redis 7 7
Node.js 20 22 LTS
Composer 2.x Latest

PHP Extensions

bcmath, ctype, curl, dom, fileinfo, hash, json,
mbstring, openssl, pcre, pdo, pdo_pgsql, session,
tokenizer, xml, redis, zip

Installation Methods

Docker provides the easiest setup with all services pre-configured.

Step 1: Extract the Package

unzip tenanto-v1.0.0.zip -d /path/to/your/projects/
cd /path/to/your/projects/tenanto

Step 2: Configure Environment

cp .env.example .env

Edit .env with your settings:

APP_NAME="Your SaaS Name"
APP_URL=https://yourdomain.com

# Database (Docker defaults work out of the box)
DB_CONNECTION=pgsql
DB_HOST=db
DB_PORT=5432
DB_DATABASE=tenanto
DB_USERNAME=tenanto
DB_PASSWORD=secret

# Redis
REDIS_HOST=redis
REDIS_PORT=6379

Step 3: Start Docker

docker compose up -d

This starts 8 services:

Step 4: Install Dependencies

docker compose exec app composer install

No npm install on the host. The vite service runs npm ci automatically in its own container on first start and serves frontend assets with hot module replacement at http://localhost:5273. Changes to .blade.php, resources/css/* and resources/js/* reload instantly. If port 5273 clashes with another project on your machine, set VITE_HOST_PORT=5274 (or any free port) in .env before docker compose up -d.

Step 5: Initialize Application

docker compose exec app php artisan key:generate
docker compose exec app php artisan migrate --seed

Step 6: Configure DNS (hosts file)

Tenanto uses tenanto.local and per-tenant subdomains by default (configured in .env.example via TENANCY_CENTRAL_DOMAINS=tenanto.local,admin.tenanto.local). Your local machine has to resolve those names to 127.0.0.1, which means adding entries to your operating system's hosts file.

Required entries:

127.0.0.1 tenanto.local
127.0.0.1 admin.tenanto.local
127.0.0.1 demo.tenanto.local

You can add more lines for any additional tenants you create, e.g. 127.0.0.1 acme.tenanto.local.

Linux / macOS — open a terminal and edit /etc/hosts with sudo:

sudo nano /etc/hosts
# or: sudo vi /etc/hosts

Append the three lines, save, exit. No restart needed.

Windows 10/11hosts file lives at C:\Windows\System32\drivers\etc\hosts. You must open your text editor as Administrator (right-click Notepad → "Run as administrator"), then File → Open → paste the path → change file filter to "All Files" → select hosts. Append the three lines, save. If Notepad refuses to save, your editor was not launched with elevated privileges.

WSL2 users — edit the Windows hosts file (the path above), not /etc/hosts inside WSL. WSL2 inherits DNS resolution from Windows for *.local names.

Verify the entries took effect:

# Linux/macOS/WSL2:
getent hosts tenanto.local admin.tenanto.local demo.tenanto.local

# Windows PowerShell:
Resolve-DnsName tenanto.local -Type A

All three names should resolve to 127.0.0.1.

Production note: When you deploy to a real domain, replace tenanto.local everywhere - in .env (APP_URL, TENANCY_CENTRAL_DOMAINS, TENANCY_SUBDOMAIN_SUFFIX) and in your DNS records. The hosts file step is only needed for local development.


Method 2: Traditional Server

Step 1: Clone/Upload Files

Upload the extracted files to your server's web root.

Step 2: Install Dependencies

composer install --optimize-autoloader --no-dev
npm ci && npm run build

Production builds only. Traditional (non-Docker) server deployments compile assets once with npm run build - the generated public/build/ directory is served by nginx. The Docker vite service is not used in production; see docker-compose.prod.yml.

Step 3: Configure Environment

cp .env.example .env
php artisan key:generate

Edit .env:

APP_ENV=production
APP_DEBUG=false
APP_URL=https://yourdomain.com

DB_CONNECTION=pgsql
DB_HOST=localhost
DB_PORT=5432
DB_DATABASE=tenanto
DB_USERNAME=your_db_user
DB_PASSWORD=your_db_password

REDIS_HOST=localhost

Step 4: Database Setup

php artisan migrate --seed

Step 5: Web Server Configuration

Nginx:

server {
    listen 80;
    server_name yourdomain.com *.yourdomain.com;
    root /var/www/tenanto/public;

    index index.php;

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

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

Step 6: Permissions

chmod -R 775 storage bootstrap/cache
chown -R www-data:www-data storage bootstrap/cache

Step 7: Queue Worker & Scheduler

Supervisor (queue):

[program:tenanto-queue]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/tenanto/artisan queue:work redis --sleep=3 --tries=3
autostart=true
autorestart=true
user=www-data
numprocs=2

Cron (scheduler):

* * * * * cd /var/www/tenanto && php artisan schedule:run >> /dev/null 2>&1

Post-Installation

1. Access the Application

After completing the install steps above, three local URLs are available:

Panel URL
Marketing landing http://tenanto.local
System Admin Panel http://admin.tenanto.local/admin
Tenant Panel (demo tenant) http://demo.tenanto.local/app
Mailhog (test inbox) http://localhost:8025

If any of these URLs returns "site cannot be reached", revisit Step 6 above - your hosts file is missing entries.

2. Default Login Credentials

The seeder creates four accounts using the password from the DEMO_DEFAULT_PASSWORD environment variable. With the unmodified .env.example, that value is ChangeMe-DemoPass!.

System Admin (use at http://admin.tenanto.local/admin):

Email Password
[email protected] ChangeMe-DemoPass!

Tenant Panel (use at http://demo.tenanto.local/app):

Email Role Password
[email protected] Owner ChangeMe-DemoPass!
[email protected] Admin ChangeMe-DemoPass!
[email protected] Member ChangeMe-DemoPass!

Important - rotate the password before going public. ChangeMe-DemoPass! is the same string for every fresh install of this package. Change it in two ways:

  1. Before first seed: edit DEMO_DEFAULT_PASSWORD in .env, then run php artisan migrate --seed. New users get the new password.
  2. After seeding: edit DEMO_DEFAULT_PASSWORD in .env, then run php artisan demo:reset-passwords. The command rotates the four demo accounts in place. Or manually change passwords through the admin panel.

Admin Login

3. Create Your First Tenant

Log into the admin panel, then go to TenantsNew tenant. Pick a slug like acme, save, then add 127.0.0.1 acme.tenanto.local to your hosts file (same place as Step 6 above) so the new subdomain resolves locally. The new tenant becomes accessible at http://acme.tenanto.local/app.

Admin Tenants

4. Configure Stripe (Optional)

See Billing Setup for Stripe configuration.


Troubleshooting

Docker containers won't start

# Check Docker is running
docker info

# Check for port conflicts
netstat -tulpn | grep -E '80|443|5432'

# View logs
docker compose logs -f

"Class not found" errors

composer dump-autoload
php artisan config:clear
php artisan cache:clear
php artisan view:clear

Database connection refused

Permissions errors

chmod -R 775 storage bootstrap/cache
# Docker:
docker compose exec app chmod -R 775 storage bootstrap/cache

Next Steps