Skip to content

Lamp App

LAMP App on Cloudron

Running LAMP apps on the Cloudron is no different than what is available on many hosting providers. You can upload your PHP code using SFTP or the Web terminal and then modify the .htaccess and php.ini files as required. Most commonly used PHP extensions are pre-installed and you don't have to worry about keeping them up-to-date.

The main advantage of using the Cloudron to host LAMP apps are:

  • DNS configuration, Let's Encrypt (SSL) certificate installation and renewal are automated.
  • Can use MySQL, redis and send email out of the box.
  • Don't have to worry about app and server backups, restore and updates since the Cloudron takes care of it.
  • Run multiple LAMP apps, isolated from one another, on same server easily.

Uploading LAMP app

The LAMP app can be upload using the Web terminal or SFTP.

Using SFTP

The app can be uploaded using an SFTP client like FileZilla.

You can find the SFTP login details when clicking on the i icon in the app grid.

SFTP Access

SFTP access for non-admin users can be granted using the access control UI.

Web terminal

  • Open a web terminal for the app.

  • Upload the app .zip or .tar.gz to /tmp using the upload button

  • Use the terminal to extract the code to /app/data/public

# unzip /tmp/ -d /app/data/public       # for zip files

# tar zxvf /tmp/app.tar.gz -C /app/data/public # for tarballs

PHP settings

You can add custom PHP settings in /app/data/public/.htaccess using the Web terminal. Note that settings with a mode of PHP_INI_SYSTEM cannot be set in htaccess files.

For example:

php_value post_max_size 600M
php_value upload_max_filesize 600M
php_value memory_limit 128M
php_value max_execution_time 300
php_value max_input_time 300
php_value session.gc_maxlifetime 1200

Apache settings

You can add custom Apache settings in /app/data/public/.htaccess using the Web terminal.

For example:

ServerSignature Off

Custom HTTP headers

Custom HTTP headers can be set in /app/data/public/.htaccess. apache mod_headers is already enabled. See this article for more information.

PHP extensions

The LAMP app already includes most of the popular PHP extensions including the following:

  • php-apcu
  • php-cli
  • php-curl
  • php-fpm
  • php-gd
  • php-gmp
  • php-imap
  • php-intl
  • php-json
  • php-mbstring
  • php-mcrypt
  • php-mysql
  • php-mysqlnd
  • php-pgsql
  • php-redis
  • php-sqlite
  • php-xml
  • php-xmlrpc
  • php-zip

You can check the complete list of pre-installed extensions by visiting the default index.php of the app that prints out phpInfo().

Installing custom PHP extensions

The LAMP app supports installing custom PHP extensions. As an example, we will install ionCube Loader, which is often required to install commercial PHP apps.

ionCube is already installed

The LAMP app has built-in support for ionCube. The installation steps for ionCube here are just an example.

Step 1: Download extension

Download and extract the tar.gz or zip Linux 64-bit ionCube packages to your PC/Mac from the ionCube website or use the direct link.

Step 2: Upload using SFTP

Upload the extracted directory to the SFTP root directory (/app/data) of the Cloudron app (i.e one level above public/).

Step 3: Enable extension

In the top level directory of the Cloudron app (in /app/data), you will find a php.ini.

Add the following line to enable the extension (just add it before the many ;extension lines):


The LAMP app has thread safety disabled, so we choose the extension without the ts extension.

Step 4: Restart app

Lastly, restart the app for the extension to be enabled. You can do this using the Restart button in the web terminal.

Step 5: Verifying installation

Visit the LAMP app's default page to verify that the extension is enabled.

Configuring MySQL

On the Cloudron, MySQL credentials are exposed as environment variables to the app. These variables can change over time. This approach makes it possible for Cloudron to transparently rotate the MySQL password periodically as a security measure and also makes app easily migratable across Cloudrons.

The exposed environment variables are:

MYSQL_URL=            # the mysql url (only set when using a single database, see below)
MYSQL_USERNAME=       # username
MYSQL_PASSWORD=       # password
MYSQL_HOST=           # server IP/hostname
MYSQL_PORT=           # server port
MYSQL_DATABASE=       # database name (only set when using a single database, see below)

If the PHP app has a config.php that requires the MySQL credentials to be set, they can set as below:

'db' => array (
    'hostname' => getenv("MYSQL_HOST"),
    'username' => getenv("MYSQL_USERNAME"),
    'password' => getenv("MYSQL_PASSWORD"),
    'database' => getenv("MYSQL_DATABASE")
  ), // Database configuration

Some apps show a setup screen and will require the raw MySQL credentials. For such apps, the MySQL credentials can be obtained from the Web terminal by executing the following command:

# env | grep MYSQL_

IMPORTANT: Once the installation is completed, be sure to switch the config file of the app to use the environment variables using getenv() instead of the raw credentials. Otherwise, future updates might break the app.

Customizing MySQL

On Cloudron, the MySQL server is shared across all apps. Each app gets non-root credentials to the database that helps isolate them from one another. This means one cannot configure mysql for one app specifically.

However, many MySQL variables like sql_mode can be set per session by modifying your code as follows:

// connect to mysql and call the first query
mysql_query("SET SESSION UNIQUE_CHECKS = false");


phpMyAdmin can be accessed at the /phpmyadmin path of the app. It uses basic auth through a htpasswd file and is pre-setup with an admin account and a generated password. The password can be found in the phpmyadmin_login.txt file, alongside with details how to managed more users.

If access does not work anymore, simply remove the file .phpmyadminauth and restart the app. This will generate new phpMyAdmin credentials.


On Cloudron, Email credentials are exposed as environment variables to the app.

The exposed environment variables are:

MAIL_SMTP_PORT      # SMTP server port
MAIL_SMTPS_PORT     # SMTPS server port. This is mostly for legacy apps
MAIL_FROM           # The MAIL FROM. If you want to change this, see [this](
MAIL_DOMAIN         # The mail domain

You can use getenv() to get the values of the above environment variables in code. The raw values can be obtained from the Web terminal by executing the following command:

# env | grep MAIL_

The built-in PHP mail() function does not work

It uses the local sendmail binary, which is not configured on Cloudron.

Use the following code instead, which has the same arguments and will pickup the correct environment variables:

function cloudronmail($to, $subject, $body, $headers)
    $smtp = stream_socket_client('tcp://' . getenv('MAIL_SMTP_SERVER') . ':' . getenv('MAIL_SMTP_PORT'), $eno, $estr, 30);

    $B = 8192;
    $c = "\r\n";
    $s = getenv('MAIL_FROM');

    fwrite($smtp, 'helo ' . getenv('HOSTNAME') . $c);
        $junk = fgets($smtp, $B);

    // Envelope
    fwrite($smtp, 'mail from: ' . $s . $c);
        $junk = fgets($smtp, $B);
    fwrite($smtp, 'rcpt to: ' . $to . $c);
        $junk = fgets($smtp, $B);
    fwrite($smtp, 'data' . $c);

        $junk = fgets($smtp, $B);

    // Header
    fwrite($smtp, 'To: ' . $to . $c);
    if(strlen($subject)) fwrite($smtp, 'Subject: ' . $subject . $c);
    if(strlen($headers)) fwrite($smtp, $headers); // Must be \r\n (delimited)
    fwrite($smtp, $headers . $c);

    // Body
    if(strlen($body)) fwrite($smtp, $body . $c);
    fwrite($smtp, $c . '.' . $c);
        $junk = fgets($smtp, $B);

    // Close
    fwrite($smtp, 'quit' . $c);
        $junk = fgets($smtp, $B);


On Cloudron, Redis credentials are exposed as environment variables to the app.

The exposed environment variables are:

REDIS_URL           # redis URL of the form redis://username:password@host:port
REDIS_HOST          # redis hostname
REDIS_PORT  6379    # redis port
REDIS_PASSWORD      # redis password

You can use getenv() to get the values of the above environment variables in code. The raw values can be obtained from the Web terminal by executing the following command:

# env | grep REDIS_

Custom Startup Script

A custom startup script can be placed at /app/data/ For example,


echo "This script is called before the app starts"

# create symlinks
rm -rf /app/data/var/cache
mkdir -p /run/cache
ln -sf /run/cache /app/data/var/cache

Cron support

For cron support, add a file named /app/data/crontab support.

The file can be edited using the Web terminal or FileZilla.

The crontab contains a line like:

0 * * * * php /app/code/update.php --feeds

The app must be restarted after making any changes to the crontab file. You can do this by pressing the 'Restart' button in the web terminal.

Running composer, npm, bundler, ...

composer, npm and other common tools are installed in from the Cloudron base app image. To run these tools, first switch to the www-data user (most of them should not be run as root).

su - www-data
cd public           # this is where PHP code resides
composer require drush/drush

npm install

Memory limit

The LAMP app runs with 256MB ram by default which is not enough for Composer and possibly others. If you see a Killed error message after a run, increase the memory limit of the app to 1GB.


To init a laravel app, you can use the CLI tool to shell into the app and run composer commands. If you have an existing Laravel app, you can skip this step and simply SFTP the app.

Memory limit

The LAMP app runs with 256MB ram by default which is not enough for Composer. We recommend increasing the memory limit of the app to 1GB.

Switch to the www-user because the web server runs as that user.

root@869b2f2e-dccc-4e06-a22a-8aa0e9265c00:/app/data# su - www-data

We can now create a Laravel app, following the Larabel Quickstart:

www-data@869b2f2e-dccc-4e06-a22a-8aa0e9265c00:~$ composer create-project laravel/laravel my-project
Installing laravel/laravel (v6.4.0)
  - Installing laravel/laravel (v6.4.0): Loading from cache
Created project in my-project

The LAMP app has public as the document root. Let's move the project into the public directory:

www-data@869b2f2e-dccc-4e06-a22a-8aa0e9265c00:~$ cp -r my-project/. public
www-data@869b2f2e-dccc-4e06-a22a-8aa0e9265c00:~$ rm -rf my-project

Next, adjust the /app/data/public/.htaccess to serve lavarel's public directory:

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/public/
RewriteRule ^(.*)$ /public/$1 [L,QSA]

That's it! Your app should load on the browser now.

Reverse proxy setup

If you want to run for example a custom WordPress within this app, please note that the code will run behind a nginx proxy. Apps like WordPress require some code in wp-config.php to handle such a setup:

// If WordPress is behind reverse proxy which proxies https to http
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {

    if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')

Health check

The LAMP app expects a 2xx response from the '/' path. If your app is completely protected, then the healthcheck logic will mark your app as not responding instead of running.

You can work around this by adding the following in /app/data/public/.htaccess:

RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} CloudronHealth
RewriteRule ^ - [R=200]

Alternately, add something like below in the app's config.php or index.php:

if ($_SERVER["REMOTE_ADDR"] == '') {
    echo "Cloudron healthcheck reponse";