Gyaaniguy_
self-made · nerd
hosting 5 min read July 2024

Forge alternative. Host a Laravel website on any VPS with ease using dokku

A complete guide. Dealing with Vite, ssl etc

For an introduction to dokku: https://gyaaniguy.top/blog/dokku/

In Brief: dokku is an application to manage hosting websites easily on your own server. It does so by using docker. Automating the tasks of installing servers/databases, configuring various services, running, building, handling ssl etc.

General steps:
First install dokku on your server. Then create a dokku project on the server. Setup ssl, some options, environment variables for laravel.

Next we configure our laravel project - PHP's composer.json file. Dokku uses it to install PHP extensions
- add dokku configurations files in our laravel project.

Then we configure sqlite. Which is default database in laravel v11
Finally we have a workaround to deal with vite's quirk.

Create dokku application

Run on your server.

!! Set the 2 variables below !!

 APP_NAME="p2" ;  DOMAIN="p2.gyaaniguy.top" ;

# Create the app
dokku apps:create "$APP_NAME"
# Set the domain
dokku domains:set "$APP_NAME" "$DOMAIN"
# Enable Let's Encrypt for SSL
dokku letsencrypt:enable "$APP_NAME"

# Setup Environment Variables
dokku config:set   "$APP_NAME" APP_NAME="$APP_NAME" APP_ENV="production"  APP_DEBUG="false"

Note: environment variables, to configure laravel are passed via dokku config:set KEY_NAME=value . These are typically stored in .env file

Setup composer.json

We'll need to explicitly tell dokku to install php extensions, like ext-pdo_sqlite.

Add the extensions to the require section in composer.json. Adjust the PHP version to match your server. Note the pdo_sqlite line for sqlite. MariaDB / postgres will require different extensions.

 "require": {
        "ext-ctype": "*",
        "ext-curl": "*",
        "ext-exif": "*",
        "ext-fileinfo": "*",
        "ext-gd": "*",
        "ext-json": "*",
        "ext-mbstring": "*",
        "ext-pdo": "*",
        "ext-openssl": "*",
        "ext-tokenizer": "*",
        "ext-xml": "*",
        "ext-zip": "*",
        "ext-pdo_sqlite": "*"
    },

Now Run composer update on local

Local dokku settings

We will add a few more files to your laravel app.

.buildpacks file in the root of your laravel project:

https://github.com/heroku/heroku-buildpack-php
https://github.com/heroku/heroku-buildpack-nodejs

!!! Order is important !!

These instruct dokku to run commands like composer install. The nodejs buildpack runs the frontend vite / laravel_mix build. It's optional, but laravel uses @vite by default. If you are not using vite, you can drop the nodejs buildpack.

Create a Procfile file in the root of your laravel project, to run migrations:

release: php artisan migrate --force
web: vendor/bin/heroku-php-apache2 public/

Now push your project to the server. See the Intro article for instructions

Set APP_Key

This is an encryption used by laravel. There should be a better way of generating it. But I can't quite figure it out !

dokku run "$APP_NAME" php artisan key:generate --show

Copy the output - base64:Ng9mTA83j+Y7FZJSj22oSa6zw6r260Y9VRot01xG80U=

Then paste here


dokku config:set "$APP_NAME" APP_KEY="PASTE_HERE"
# dokku config:set "$APP_NAME" APP_KEY="base64:Ng9mTA83j+Y7FZJSj22oSa6zw6r260Y9VRot01xG80U="

Setup Database (sqlite)

Dokku runs in containers, which get destroyed every time the website is deployed. So it's important to keep database files outside the container. We do this by creating a directory on the server, then mounting it in the container. Dokku makes this easy.

# Create a directory for storage
dokku storage:ensure-directory "$APP_NAME"
# Mount it on the app container
dokku storage:mount "$APP_NAME" "/var/lib/dokku/data/storage/$APP_NAME:/app/databasedir"
# Set environment variable for laravel
dokku config:set "$APP_NAME" DB_DATABASE=/app/databasedir/database.sqlite DB_CONNECTION=sqlite

PS: Don't forget the sqlite extension (ext-pdo_sqlite) in composer.json, as shown earlier.

Fix https error with vite

If you are using Vite, you may get https issues with css/js files. Why? Because your dokku app is behind a reverse proxy.

Mixed Content: The page at 'domain.com' was loaded over HTTPS, but requested an insecure ...

Normal: User -> Apache -> site Dokku: User -> Nginx -> [forwards to] -> Docker container (apache or nginx) -> site

Some headers sent by the user get lost along the way. Nginx then re-sends some of them to apache, but apache doesn't know who is sending them, since the user could be spoofing them. The fix: tell apache to trust the proxy headers, since they come from a known proxy.


use Symfony\Component\HttpFoundation\Request;


  ->withMiddleware(function (Middleware $middleware) {
        $middleware->trustProxies(headers: 
            Request::HEADER_X_FORWARDED_FOR |
            Request::HEADER_X_FORWARDED_HOST |
            Request::HEADER_X_FORWARDED_PORT |
            Request::HEADER_X_FORWARDED_PROTO |
            Request::HEADER_X_FORWARDED_AWS_ELB
        );
        $middleware->trustProxies(at: '*');
    })

Ideally laravel should handle this automatically....

Troubleshooting

  • dokku logs "$APP_NAME"
  • Run composer update after modifying composer.json
  • Enable and set logs. They will log important errors !
# Set the environment variables to enable log. 
# set LOG_LEVEL=info to see more entries. Check laravel docs for more.   
dokku config:set "$APP_NAME" APP_DEBUG=true

# enter the docker container
docker exec -it  $(docker ps | grep "$APP_NAME" | awk 'NR==1 {print $1}') bash
# watch logs 
tail -f /app/storage/log/logging.txt
  • Check if vite is being used. @vite()
  • .buildpacks and Procfile file names are case-sensitive.
  • Order of .buildpacks file
  • Is sqlite being installed properly ? Check the git push log. It contains a lot of useful info

If log is empty. Then add some logging Log::debug('manual debug message');


References:

https://dev.to/vdsmartin/deploying-a-laravel-app-using-dokku-5bi3 https://laracasts.com/discuss/channels/vite/laravel-vite-assets-blockedmixed-content-issues-in-production-environment