# Deploying Housa Studio

## Hosting layout

Upload the project to a private application directory and configure the website document root as its **public** subdirectory:

```text
/var/www/housa-cms/public
```

Only `public/` belongs on the web. `app/`, `storage/`, `data/`, `template/`, `templates/`, `bin/`, and `tests/` must remain outside the document root. Do not upload the entire project directly into a publicly served folder.

For cPanel/shared hosting, use a domain or subdomain whose document root can be set to the project’s `public/` folder. If your host fixes the primary domain to `public_html`, ask the host to configure the application’s document root or use a suitable subdomain. The application assumes installation at the domain root, not under a URL subdirectory.

## PHP configuration

Use PHP 8.2+ with PDO SQLite, mbstring, fileinfo, and sessions enabled. Recommended upload settings:

```ini
upload_max_filesize = 10M
post_max_size = 12M
memory_limit = 256M
display_errors = Off
log_errors = On
```

The application itself enforces an 8 MB image limit. Configure your host to retain PHP error logs outside the public directory.

Give the PHP process read access to the application source and write access to `storage/` and `public/uploads/`. Use the host’s normal ownership/group arrangement. Do not use world-writable permissions.

## First administrator

Run the setup command using the same account that owns the application’s writable directories:

```bash
php bin/setup.php
```

On a Linux server where PHP runs as `www-data`, your server administrator can instead run the setup command as that user after setting ownership appropriately:

```bash
sudo -u www-data php bin/setup.php
```

The command validates the environment, initializes the database and starter content, and prints a single-use setup key. Visit `https://your-domain.example/admin/`, enter that key, and create the first administrator. The key is not available through the public API and is removed after setup.

No database, administrator credentials, or setup key from development is included in the delivery archive.

## Apache

Enable `mod_rewrite` and allow the included `public/.htaccess` to run. Example virtual-host configuration:

```apache
<VirtualHost *:80>
    ServerName your-domain.example
    DocumentRoot /var/www/housa-cms/public
    <Directory /var/www/housa-cms/public>
        AllowOverride All
        Require all granted
        Options -Indexes
    </Directory>
</VirtualHost>
```

Configure the host’s HTTPS virtual host/certificate and redirect HTTP to HTTPS using its normal tooling. Production administration should use HTTPS.

## Nginx and PHP-FPM

Example routing; adapt the server name, root, and PHP-FPM socket to your server:

```nginx
server {
    listen 80;
    server_name your-domain.example;
    root /var/www/housa-cms/public;
    index index.php index.html;
    client_max_body_size 12m;

    location ~ /\. {
        deny all;
    }

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

    location ~ ^/(index|router)\.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }

    location ~ \.(php[0-9]?|phtml|phar)$ {
        return 404;
    }
}
```

Add your host’s HTTPS configuration. If TLS terminates at a trusted reverse proxy, set `CMS_TRUST_PROXY=1` in the server process environment only when that proxy controls and sanitizes `X-Forwarded-Proto`. Without that configuration, the application uses the web server’s direct HTTPS state for secure session cookies.

## Persistent storage

The database defaults to `storage/cms.sqlite`. The application enables SQLite WAL and a busy timeout. The directory must be a persistent, local filesystem writable by the PHP process.

Set `CMS_STORAGE_PATH` in the server environment if the private storage folder must be located elsewhere. Keep it outside the public document root. The same environment setting must apply to web requests and CLI setup/recovery commands.

Do not place the SQLite database on an ephemeral deployment filesystem. This package is a single-host PHP application. Horizontally scaled hosting requires a separate database/storage adaptation.

## Before opening the site

1. Open `/admin/` and create the owner account.
2. Replace logos, contact details, starter copy, properties, and legal-page content.
3. Choose the homepage and check the menu destinations.
4. Publish only the pages and collection items you intend to expose; hide unused template variations.
5. Submit a test inquiry and confirm that it appears in the dashboard inbox.
6. Confirm the host’s backup covers the private database and uploaded media.

The dashboard’s JSON export is a content backup. It does not contain uploaded file bytes, user accounts, or inquiries.

## Troubleshooting

| Symptom | Check |
| --- | --- |
| “Finish the server setup” | PHP version and required extensions in the web-server PHP configuration, which can differ from CLI PHP. |
| “Run php bin/setup.php” | Run the CLI command, then use its one-time key. |
| Blank page or HTTP 500 | Private PHP error log, source readability, and `storage/` ownership. |
| Routes such as `/api/session` return 404 | Document root and Apache/Nginx rewrite/front-controller configuration. |
| Media cannot upload | `public/uploads/` permissions, PHP/proxy upload limits, supported type, image 8 MB/40 MP limits, video 100 MB application limit. |
| Draft changes are not visible publicly | Save and publish the page. Draft preview is authenticated. |
| Another editor’s save causes a conflict | Reload the current page data and apply your edits to that version. |
| Password forgotten | Run `php bin/reset-password.php` with server access. |
| Footer uses the original logo | Set Main logo or Footer / alternate logo in Appearance and save. |
| Template-only promotional block is unchanged | Edit that block’s fields in Pages; it is separate from a shared collection card. |

