# Installation

## 1. Upload

Unpack the package on the server, e.g. to `/home/user/billing/`. Best: point the web root of the billing
domain to the `public/` folder, so only `public/` is reachable from the web.

If the web root cannot be changed (shared hosting), point it to the package folder: the included
`.htaccess` serves `public/` and blocks everything else (Apache with mod_rewrite).

The web server user must be able to write `config/` (only during installation), `storage/` and `public/themes/`.

On CWP, cPanel or any server with suPHP / suexec, unpack as the account user and keep folders 755 and files
644 (the package comes like this). Group- or world-writable PHP files are refused with HTTP 500 ("writeable by
group"); fix with `find /home/user/billing -perm /022 -exec chmod go-w {} +`. On CWP the account's `public_html`
must stay `user:nobody` with mode 750, otherwise Apache cannot read `.htaccess` (HTTP 403).

## 2. Database

Create an empty MySQL/MariaDB database (utf8mb4) and a user with all privileges on it.

## 3. Installer

Open the domain in a browser. The installer checks the server, then asks for:

* the license key (bound to this domain), or nothing for the **free trial**: the billing then works fully
  for the trial days (15 at the time of writing) on this domain; the domain and the admin e-mail are sent to
  the license provider for it. Buy a license any time and enter its key under **Settings → License**;
  your data stays as it is,
* the billing address (URL), company name, time zone and a secret admin path,
* the database,
* the first administrator (two-factor authentication is set up at the first login).

It creates the tables and writes `config/config.php`. After that the installer is gone. Make `config/`
read-only for the web server user if you like (`chmod 750 config; chmod 600 config/config.php`).

Without a browser: `php bin/console install --url=https://billing.example.com --db-name=… --db-user=… --db-pass=… --admin-email=… [--license=…]` (no `--license`: free trial)

## 4. Cron (required)

```
*/5 * * * * php /home/user/billing/bin/console cron
* * * * *   php /home/user/billing/bin/console massmail:send
```

Use the same PHP version as the web server (`php -v`). The daily run (renewal invoices, reminders,
suspensions) happens once a day at the hour set under Billing settings.

## 5. Web server

Apache: nothing to do (`public/.htaccess`). nginx:

```
root /home/user/billing/public;
index index.php;
location / { try_files $uri /index.php$is_args$args; }
location ~ ^/index\.php$ {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root/index.php;
    fastcgi_param HTTP_AUTHORIZATION $http_authorization;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
location ~ \.php$ { return 404; }
```

Attachments up to 20 MB: `upload_max_filesize = 20M` and `post_max_size = 25M` (public/.user.ini does this for PHP-FPM).

## 6. First steps in the admin area

1. Settings → General: outgoing e-mail (SMTP) and a test mail.
2. Billing settings: company details for invoices, currency, taxes, automation days.
3. Payment gateways (Stripe, PayPal, Skrill, bank transfer): keys and webhook URLs are shown there.
4. Servers (cPanel, DirectAdmin, CWP, Proxmox) and products.
5. Ticket departments and their e-mail addresses.

## E-mail piping (tickets by e-mail)

Forward each department address to `pipe.php`. Postfix example (`/etc/postfix/master.cf`, one line per
address via a transport, or an alias):

```
support: "|php -q /home/user/billing/pipe.php"
```

The department is chosen by the recipient address (Departments → e-mail). Replies are matched by
"[Ticket ID: …]" in the subject. Log: `storage/logs/pipe-YYYY-MM.log`.

## Themes and languages

* Client-area look: copy any file from `views/` into `themes/<name>/views/` (same path) and change it;
  colours and images go to `themes/<name>/assets/`. Set `'theme' => '<name>'` in config.php and run
  `php bin/console theme:publish`. See themes/README.md.
* Languages: the client area and the client e-mails come in English, German, Spanish, French, Croatian, Italian,
  Portuguese (Brazil), Russian and Turkish, all enabled by the installer (`languages` in config.php). The client
  picks one in the footer, otherwise the browser language is used. Add or adjust a language in `lang/<code>.php`
  (the English text is the key) and `lang/emails/<code>.php`; e-mail texts can also be edited under Settings → E-mails.

## Security notes

* Keep `config/config.php` private: it holds the database password and `app_key`. The app key encrypts
  gateway keys, server passwords and the vault — never change or lose it (back it up with the database).
* The admin path is secret; staff log in with password + authenticator app. Optional IP allowlist under Staff.
* Behind a proxy / CDN, add its addresses to `trusted_proxies` so client IPs are logged correctly.
