---
title: Installation Troubleshooting
description: "When `install.sh` stops, it prints the stage that failed and the log file to read. This article lists every message the installer can produce, what it means, and what to do next — plus the problems that appear after a…"
url: "https://rackhelm.com/documentation/installation-troubleshooting/"
updated: "2026-09-24"
category: "Installation & Server Setup"
---

# Installation Troubleshooting

When `install.sh` stops, it prints the stage that failed and the log file to read. This article lists every message the installer can produce, what it means, and what to do next — plus the problems that appear after a technically successful install.

## Where the logs are

Each stage writes to its own file. All of them are set to mode `600` because they contain database passwords.

| Log file | Stage |
| --- | --- |
| `/var/log/rackhelm_install_sys.log` | OS packages, repositories, Composer, ionCube Loader |
| `/var/log/rackhelm_install_deploy.log` | Copying the application into `/var/www/rackhelm` |
| `/var/log/rackhelm_install_env.log` | Writing `.env` |
| `/var/log/rackhelm_install_composer.log` | `composer install` |
| `/var/log/rackhelm_install_npm.log` | `npm install` and `npm run build` |
| `/var/log/rackhelm_install_mysql_config.log` | Local database, user and root password |
| `/var/log/rackhelm_install_servers.log` | nginx, Supervisor, firewall, certbot |
| `/var/log/rackhelm_install_artisan.log` | Migrations, seeding, view cache, storage link (admin password redacted) |
| `/var/log/rackhelm_install_perms.log` | Final ownership and permissions |

Four of these stages run at the same time. When one of them fails the installer prints the names of the threads that broke, for example `Failed stage(s): npm servers`, followed by the exact log paths — so you do not have to work it out from timestamps.

![Terminal showing a Failed result with the failed stage names and their log file paths](/wp-content/uploads/rackhelm-docs/installation-failed-stage-output.png)
The failure output names the stage and the log; start there rather than reading all four.

## Pre-flight failures

| Message | Meaning and fix |
| --- | --- |
| `Please run this script as root (sudo ./install.sh)` | Run it with `sudo`. |
| `Warning: This script is designed for Debian/Ubuntu and RHEL-based distributions.` | Your `/etc/os-release` was not recognised. Answering `y` continues with Debian conventions; on a non-Debian system that will fail during package installation. |
| `This installer must be run from the extracted release directory.` | The installer looks for `artisan` and `.env.example` beside itself. You have copied `install.sh` out of the archive — change into the extracted directory and run it there. |

## System prerequisites stage

| Message | Meaning and fix |
| --- | --- |
| `npm is not available after installing Node.js…` | The `nodejs` package that won the apt or dnf resolution did not bundle npm, and the separate `npm` package could not be installed either. Install a Node.js 22.x distribution that provides npm, then re-run. |
| `Composer installer checksum mismatch; refusing to run it.` | The file downloaded from `getcomposer.org` did not match the published SHA-384 signature. Almost always a proxy or a truncated download; retry, and check any egress proxy is not rewriting responses. |
| `Unsupported architecture … for the ionCube Loader.` | Only `x86_64` and `aarch64` are supported. |
| `Failed to download the ionCube Loader from …` | No outbound access to `downloads.ioncube.com`. Open it, or mirror the tarball and re-run with `RACKHELM_IONCUBE_URL=https://mirror.example.com/… sudo -E ./install.sh`. |
| `ionCube Loader checksum mismatch; refusing to install it.` | You pinned `RACKHELM_IONCUBE_SHA256` and the tarball does not match. ionCube updates this file in place, so a pin can go stale — recompute the hash or drop the pin. |
| `ionCube did not ship ioncube_loader_lin_8.5.so …` | ionCube has no Loader for that PHP version on this architecture. Re-run against a version they do support, for example `RACKHELM_IONCUBE_PHP=8.4 sudo -E ./install.sh`. |
| `ionCube Loader installed but not active for PHP CLI.` | The `zend_extension` line was written but PHP did not load it. Check that the CLI is reading the configuration directory the installer wrote to, and that no other extension conflicts. Every Composer and Artisan step would fail cryptically otherwise, which is why the installer stops here. |

> **Tip:** The three `RACKHELM_IONCUBE_*` variables need `sudo -E` to survive into the root environment.

## Build and server stage

| Message | Meaning and fix |
| --- | --- |
| `Cannot authenticate to MySQL as an administrator. If a previous run already set a root password, pass it via ~/.my.cnf and retry.` | You are re-running the installer after it already secured MySQL root. The installer tries socket authentication and then Debian's maintenance account; if neither works, put the root password in `~/.my.cnf`. |
| `nginx configuration test or restart failed.` | Another site is already bound to port 80 or claims the same `server_name`. Run `nginx -t` for the specific error. |
| Failure in the `composer` thread | Usually the ionCube Loader not being active for CLI, or no outbound access to `packagist.org`. |
| Failure in the `npm` thread | Out of memory during the Vite build, or no outbound access to the npm registry. Note this thread runs after MySQL has already been reconfigured, so a re-run needs the MySQL note above. |

## Migration stage

| Symptom | Meaning and fix |
| --- | --- |
| `Database migration/seeding failed.` | Read `/var/log/rackhelm_install_artisan.log`. Common causes: wrong remote-database credentials, a database user without permission to create tables, or a database that is not empty. |
| No **Admin Panel Credentials** block at the end | The seeder only prints credentials the first time it creates the Super Admin. Re-running against an existing database leaves the account — and its existing password — alone. |

## Certificate and HTTPS

Certificate issuance is allowed to fail without aborting the install, because a domain that has not propagated yet is a normal situation. The installer prints:

```bash
WARNING: the Let's Encrypt certificate could NOT be issued. Check that
portal.example.com resolves to this server and port 80 is reachable, then retry:
  certbot --nginx -d portal.example.com --redirect
```

Take that seriously. Until a certificate is in place the portal serves plain HTTP, and **every login fails with a 419 error** because the session cookie is HTTPS-only. Fix DNS and firewalling, run the certbot command, then set `APP_URL` and `ASSET_URL` to the `https://` address. See [Web server, SSL and HTTPS](/docs/web-server-ssl-and-https/).

## Problems after a successful install

| Symptom | Meaning and fix |
| --- | --- |
| `400 Bad Request` on every URL, and nothing in `storage/logs/laravel.log` | The `Host` header does not match `APP_URL`. RackHelm trusts only that host, and the rejection happens before anything is logged. Correct `APP_URL` — and remember the **Company URL** setting overrides it once the database is readable. |
| Connections to the server IP hang or return nothing | Expected on Debian and Ubuntu: a catch-all nginx server returns `444` for any other hostname. Use the portal's own hostname. |
| `Licence validation error: …` on every page | See [Licensing and activation](/docs/licensing-and-activation/) for the failure codes, which are logged to `storage/logs/laravel.log` prefixed `[License]`. |
| Orders stay at pending provisioning | The queue worker is down. Check `supervisorctl status rackhelm-horizon` and `storage/logs/horizon.log`. |
| No invoices are ever generated | There is no `schedule:run` cron entry — the installer does not create one — or the seeded schedules are still disabled. See [Queue workers, Horizon and the scheduler](/docs/queue-workers-and-scheduler/). |
| Pages render without styling | The Vite build did not complete, or `public/build` is not readable by the web-server user. Check `/var/log/rackhelm_install_npm.log`. |
| Uploaded logos and page images 404 | The `public/storage` symlink is missing. Run `php artisan storage:link`. |
| Permission-denied errors writing logs or uploads | Ownership drifted. `storage` and `bootstrap/cache` must be owned by the web-server user; everything else `root:<web user>`. |
| No mail is delivered | The installer strips every `MAIL_` line from `.env`. Configure the relay under **Platform Settings → Mail Settings**. |

## Re-running the installer

The installer is written to survive a second run: it detects an existing database user and forces its password back into step with the newly generated one in `.env`, it skips the file copy when the archive was extracted straight into the install directory, and it clears stale compiled caches before rebuilding. The one thing it cannot recover on its own is the MySQL root password it set on the first pass — if socket authentication no longer works, put that password into `~/.my.cnf` first.

> **Warning:** Re-running against a populated production database re-runs `migrate --seed`. Back the database up first. See [Backing up and restoring](/docs/backup-and-restore/).

## What to send to support

- The exact stage name and message the installer printed.
- The tail of the matching `/var/log/rackhelm_install_*.log`, with any passwords removed.
- Your distribution and version, and the output of `php -v` (which should mention ionCube).
- The version shown in the admin sidebar footer, if the portal loads at all.
