I unpacked ViserHotel on Ubuntu — migrate --seed ran, Apache served a blank page

I unpacked ViserHotel on Ubuntu — migrate --seed ran, Apache served a blank page

I wanted a hotel booking front end on my VPS, not another SaaS reservation tab. ViserHotel is a Laravel CodeCanyon app. On Ubuntu, php artisan migrate --seed finished, then Apache served a blank page until APP_KEY existed and storage belonged to www-data.

· Updated · 9 min read #hotelbooking #laravel #serversetup

 ViserHotel booking system

Caption: ViserHotel Laravel hotel booking and reservation platform.

Introduction

I wanted rooms, rates, and a booking form on a server I control. ViserHotel (CodeCanyon) is a Laravel hotel booking app: public site, admin dashboard, payment gateways in the package. I installed it on Ubuntu 22.04 with Apache, PHP 8.1, MySQL, Composer, and Node for assets.

I do not have a cute story about a boutique hotel client. This is the same lab path as any CodeCanyon Laravel zip: unpack, .env, key:generate, migrate, npm run build, document root public/. On a fresh Ubuntu box this install is famous for a blank page when APP_KEY is still the placeholder, and a 500 when storage/ is not writable by the web user.

Where it broke

1. Blank page — APP_KEY never generated

On a fresh Ubuntu box this is the failure this install is famous for. You copied .env from the zip, left APP_KEY=base64:GENERATED_KEY, opened the domain, white screen.

No application encryption key has been specified.

Fix already in this post:

php artisan key:generate

Then reload. If you still see white, check storage/logs/laravel.log.

2. 500 — permissions on storage/ and .env

Zip extracted as root. Apache/PHP-FPM is www-data.

failed to open stream: Permission denied
sudo chown -R www-data:www-data /var/www/viserhotel
sudo chmod -R 755 /var/www/viserhotel

If logs still fail, tighten write bits on Laravel’s writable dirs the usual way: storage and bootstrap/cache need to be writable (775 is the pattern I use on other Laravel apps in this series). I am not inventing a ViserHotel-only flag.

Assets 404 after a “successful” install is usually npm run build never run, not a missing PHP extension.

Prerequisites

  • OS: Ubuntu 22.04 LTS (this write-up). Windows/IIS exists; I did not use it here.
  • Web server: Apache or Nginx. Apache vhost is below.
  • PHP: 8.1 or higher
  • Database: MySQL/MariaDB
  • Composer
  • Node.js and npm (front-end build)
  • Git if you track updates that way
  • Domain and SSL for anything public

Hardware: 2 CPU / 4 GB RAM / 20 GB disk minimum. 4 CPU / 8 GB / SSD is more comfortable if you generate PDFs or run reports.

The zip comes from your CodeCanyon download. I cannot wget a pirated copy; you upload viserhotel.zip yourself.

Step 1: Update the server

sudo apt update && sudo apt upgrade -y

Step 2: PHP and extensions

sudo apt install php8.1 php8.1-cli php8.1-mysql php8.1-xml php8.1-mbstring php8.1-curl php8.1-zip unzip curl git -y

Missing php-xml is the usual Laravel “Class DOMDocument not found” wall. This apt line already includes php8.1-xml. If the installer or artisan fatals on DOM/XML, reinstall that package and restart Apache/FPM.

You will also want a web SAPI. On Ubuntu that is typically libapache2-mod-php8.1 or PHP-FPM plus an Apache proxy. This post’s vhost assumes Apache can run PHP for public/index.php. Install the Apache PHP module if php CLI works but the browser downloads index.php:

sudo apt install apache2 libapache2-mod-php8.1 -y
sudo a2enmod rewrite

I am not adding extra PHP flags beyond what this app’s original steps listed.

Step 3: Composer

curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
composer --version

If the zip did not include vendor/, run composer install --no-dev --optimize-autoloader in the project root. If Composer OOMs on a 1 GB VPS, COMPOSER_MEMORY_LIMIT=-1 composer install is the documented Laravel workaround — same as Bagisto on a small box.

Step 4: MySQL

sudo apt install mysql-server -y
sudo mysql_secure_installation
CREATE DATABASE viserhotel;
CREATE USER 'viseruser'@'localhost' IDENTIFIED BY 'StrongPassword123!';
GRANT ALL PRIVILEGES ON viserhotel.* TO 'viseruser'@'localhost';
FLUSH PRIVILEGES;

Step 5: Unpack ViserHotel

Upload the CodeCanyon zip, then:

unzip viserhotel.zip -d /var/www/viserhotel

Some zips nest a folder. If you see /var/www/viserhotel/viserhotel/public, move up so public/ is directly under /var/www/viserhotel.

sudo chown -R www-data:www-data /var/www/viserhotel
sudo chmod -R 755 /var/www/viserhotel

Step 6: .env

APP_NAME="ViserHotel"
APP_ENV=production
APP_KEY=base64:GENERATED_KEY
APP_DEBUG=false
APP_URL=https://yourdomain.com

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=viserhotel
DB_USERNAME=viseruser
DB_PASSWORD=StrongPassword123!
php artisan key:generate

That command overwrites the placeholder. APP_URL must match the hostname you type in the browser (http vs https).

Step 7: Migrate and seed

php artisan migrate --seed

Run this as a user who can write storage/ — after chown, sudo -u www-data php artisan migrate --seed avoids root-owned cache files. I am not inventing extra artisan flags; --seed is what this post already used.

If migrate complains about missing tables or a lock, the zip’s README may want an import of an .sql dump instead. Follow the file you paid for. I will not invent a --force you do not have in that PDF.

Step 8: Node assets

sudo apt install nodejs npm -y
npm install
npm run build

If CSS/JS 404, run npm run build again from the project root, and confirm Apache’s document root is public/, not the folder that contains package.json.

Step 9: Apache

<VirtualHost *:80>
    ServerName yourdomain.com
    DocumentRoot /var/www/viserhotel/public

    <Directory /var/www/viserhotel/public>
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/viserhotel_error.log
    CustomLog ${APACHE_LOG_DIR}/viserhotel_access.log combined
</VirtualHost>

AllowOverride All so Laravel’s public/.htaccess can rewrite to index.php. Without mod_rewrite, you get 404 on every booking URL.

sudo a2ensite viserhotel.conf
sudo systemctl reload apache2

Put the vhost in /etc/apache2/sites-available/viserhotel.conf before a2ensite.

Step 10: TLS

sudo apt install certbot python3-certbot-apache -y
sudo certbot --apache -d yourdomain.com

Then set APP_URL=https://yourdomain.com and php artisan config:clear.

Step 11: Open the app

https://yourdomain.com

Admin is usually:

https://yourdomain.com/admin

If the vendor shipped different admin credentials in the documentation, use those and change them immediately. I will not invent a default password.

Extra tips

ViserHotel is Laravel. The CodeCanyon “install” PDF often stops at unzip and URL. Operators still need:

  • Laravel.env, APP_KEY, artisan migrate, storage/ + bootstrap/cache ownership, public/ as the web root. Blank page and 500 are this layer.
  • Composer vendor — if the zip is source-style, composer install is required. If vendor is bundled, skip it.
  • Node buildnpm install / npm run build for the theme. Missing mix/vite output looks like “the template is broken.”
  • Scheduler / queues — many CodeCanyon Laravel apps send mail and reminders via schedule:run or queue:work. If the vendor README mentions cron, add:
* * * * * cd /var/www/viserhotel && php artisan schedule:run >> /dev/null 2>&1

I only add a queue worker if their .env has QUEUE_CONNECTION other than sync. I am not inventing Horizon or Spatie for this product.

Troubleshooting

  • 500: permissions and .env. storage/logs/laravel.log.
  • Database connection: user/password/host in .env, then php artisan config:clear.
  • Assets not loading: npm run build again; document root public/.
  • Blank page: php artisan key:generate.
  • XML/DOM errors: php8.1-xml installed and Apache restarted.
  • Rewrite 404: a2enmod rewrite, AllowOverride All.

Screenshots and images

Cover image is the product visual I already had for this post. I did not scrape extra admin screenshots from the vendor demo.

A feature I would not have found from the homepage

The CodeCanyon zip is a Laravel app with a vendor PDF. The PDF often says “upload and visit /install.” This write-up used artisan migrate --seed because that is what the original post documented. If your zip still has a web installer, use that and still set APP_KEY, APP_URL, and public/ as the vhost root. Do not run both and hope.

Admin URL and seed users live in the vendor docs, not in a blog post I will invent. Change whatever default admin they shipped before the hostname is public. APP_DEBUG=false.

Payment gateways are .env plus admin settings, not a Composer package I would guess at. I would get a room type and a test booking with “offline/cash” (or whatever they ship) working before Stripe keys go in. Mail for booking confirmations is the same Laravel mail/QUEUE_CONNECTION story as Invoice Ninja: if they queued it, you need a worker or cron.

cPanel vs VPS: on cPanel the document root still has to be public/, or you fight index.php in a subdirectory. I deploy these on cPanel often enough that I check that first when someone pastes a screenshot of a directory listing.

Day two on the VPS

CodeCanyon Laravel apps age like any other Laravel app:

  • Vendor updates come as a new zip. I would diff .env, keep storage/, and read their upgrade notes. I would not composer update blindly and assume the theme still compiles.
  • Cron: if booking reminders exist, add schedule:run for www-data. Confirm with a log line, not hope.
  • Mail: a booking with no email is a support ticket. Test SMTP after APP_KEY and permissions, not before.
  • Backups: viserhotel database plus storage/ (uploads, generated invoices if they store files).
  • PHP 8.1 vs 8.3: this post used 8.1 because that is what the original install listed. If the vendor now wants 8.2+, I would follow their current PDF, not invent flags. Same extensions: xml, mbstring, curl, zip, mysql.
  • UFW and TLS before the first real guest. Admin at /admin is a brute-force target.

I would add rooms and a test booking on HTTPS, then payment keys. Kubernetes is not a day-two task for a 20-room property.

References

Conclusion

ViserHotel is unpacked on my Ubuntu box: MySQL database, .env with a real APP_KEY, migrate --seed, npm run build, Apache to public/. The front end loads; /admin is next. I would then set room types and rates, plug in the payment gateway the vendor documented, turn on TLS, and add a mysqldump cron. I would not talk about Kubernetes until a real booking has hit the database.

Did you hit the same wall?

I got stuck on a blank page after php artisan migrate --seed because APP_KEY was still the placeholder and storage/ was not writable by the web user. Did you hit the same thing, or a different one — Composer memory, storage permissions, PHP extensions, a queue worker that never started? Tell me in the comments. I read them.

Need this done on your server?

I deploy and harden Laravel/CodeCanyon apps on cPanel or VPS, and offer monthly Server Watch retainers. Hire for deploy · Care plan

Share:

Get new posts in your inbox

No spam. One short email per new article — practical PHP, Laravel, devops, and AI-assisted workflows.

Comments

Powered by GitHub Discussions via Giscus. A free GitHub account is required.