Installation
Upload the files, create an empty database, and answer five screens. No shell access is needed.
Before you start, have three things ready: the folder your site is served from, a new empty MySQL database with a user that has full rights on it, and the SMTP details of a mailbox on your own domain. The email step can be skipped and completed later.
1. Upload the files
If your download contains Main-Files/, first unzip the application
ZIP inside that folder. The other top-level folders contain documentation, licensing
guidance and samples for local use. For an application-only download, unzip it directly.
Upload everything inside the extracted application
folder into your web root. The result should look like this, with app/,
public/ and vendor/ at the top level:
public_html/
app/ bin/ bootstrap/ config/ cron/ database/ lang/
public/ resources/ storage/ vendor/
.env.example .htaccess .user.ini composer.json composer.lock
LICENSE.txt README.txt SECURITY.md THIRD-PARTY-LICENSES.md VERSION
Documentation/ Licensing/ Sample-Files/
In cPanel, the File Manager can upload the ZIP and extract it in place, which is much
faster than uploading thousands of files over FTP. If you upload by FTP, use binary mode
and check afterwards that vendor/ arrived complete.
Documentation/, Licensing/ and Sample-Files/ are
for you rather than for visitors. Nothing serves them, and you may delete them from the
server once you have a copy.
Where the document root should point
Point the document root at public/ if your hosting lets you. Everything else
then sits outside the served folder, which is the safest arrangement.
If you cannot change the document root, leave it at the folder you uploaded into. The
included .htaccess forwards every request into public/ and denies
direct access to the configuration and documentation files. This is the normal case on
shared hosting and it works.
2. Make the storage folder writable
The application writes generated PDFs, logs, exports and uploaded images under
storage/. Set that folder and everything in it to 0755, or
0775 if your host runs PHP under a different user than the file owner. The
installer checks each folder it needs and names any that is not writable.
3. Create the database
- In cPanel, open MySQL Databases and create a new database.
- Create a new database user with a strong password.
- Add that user to that database with All Privileges.
- Write down the database name, user name and password. Shared hosting usually prefixes the first two with your account name.
The database must be empty. The installer creates the tables itself.
4. Run the installer
Open https://your-domain/install. The wizard has five steps.
| Step | What it asks | What it does |
|---|---|---|
| 1. Requirements | Nothing | Runs every check on the requirements page and refuses to continue while a hard requirement fails. |
| 2. Database | Host, port, name, user, password | Connects before accepting the values, so a typo is caught here rather than three screens later. |
| 3. Application | Name, address, host names, timezone, language | The address is what verification links and QR codes are built from. Get it right, including https. |
| 4. Email | SMTP host, port, encryption, user, password, sender | Can be skipped. You can set it later on the email settings screen. |
| 5. Administrator | Name, email address, password | Writes .env, creates the tables, seeds the roles, creates your account and closes the installer. |
The installer closes behind itself. When step 5 finishes, a file called
storage/installed.lock is written and every installer address answers 404 from
then on. If a step fails part way through, fix the cause and open /install
again: an installation that never reached an administrator account reopens the wizard, and
running it again is safe.
5. First sign-in
Open /login and sign in with the account you just created. Two-factor
authentication is required for it, and no authenticator is paired yet, so the next screen
shows a QR code.
- Scan the QR code with an authenticator application, or type the secret it shows.
- Enter the six-digit code the application generates.
- Save the recovery codes. They are shown once. Each one works once, and they are the only way back into the account if you lose the authenticator.
6. Finish the setup
- Add the scheduled jobs. The email job is the one the product needs to function.
- Install an HTTPS certificate, then set
FORCE_HTTPS=trueandSESSION_SECURE_COOKIE=truein.env. - Set your logo, colours and browser title.
- Check
/admin/diagnosticsonce, so you know what a healthy report looks like.
Apache
The package includes the rewrite rules it needs. If you manage the virtual host yourself, this is the arrangement to aim for.
<VirtualHost *:443>
ServerName certificates.example.com
DocumentRoot /var/www/certiflow/public
<Directory /var/www/certiflow/public>
AllowOverride All
Require all granted
</Directory>
ErrorLog /var/log/apache2/certiflow-error.log
CustomLog /var/log/apache2/certiflow-access.log combined
</VirtualHost>
mod_rewrite must be enabled. If AllowOverride is
None, the .htaccess files are ignored and every address except the
home page returns 404.
Nginx
Nginx does not read .htaccess, so the rules have to be in the server block.
Adjust the PHP socket to the version you run.
server {
listen 443 ssl;
server_name certificates.example.com;
root /var/www/certiflow/public;
index index.php;
client_max_body_size 12m;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~ /\. { deny all; }
}
With the root at public/ nothing outside it is reachable. If you must point
the root at the package folder instead, add a deny rule for the application directories:
location ~ ^/(app|bin|bootstrap|config|cron|database|lang|resources|routes|storage|vendor)/ {
deny all;
}
Keep client_max_body_size at or above REQUEST_MAX_MB, or large
imports fail with an Nginx error page rather than a message from the product.
Installing from the command line instead
If you do have shell access, the same installation can be done without the browser. Copy
.env.example to .env, fill in the database and application values,
generate a key, then run:
php bin/migrate.php # create the tables
php bin/seed.php # roles, permissions and default settings
php bin/create-admin.php # create the first administrator
Write storage/installed.lock afterwards, or the wizard will still be open.
The browser installer does all of this in one pass and is the supported route.