Skip to content

Lamp App

About

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 File Manager 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.

  • Questions? Ask in the Cloudron Forum - LAMP

Supported PHP Versions

The LAMP app supports the following PHP versions:

  • 7.4
  • 8.0
  • 8.1 (default)
  • 8.2

To switch the PHP version, edit /app/data/PHP_VERSION using the file manager and restart the app.

See supported versions for PHP support status.

PHP CLI

The php binary is hardcoded to use PHP 8.1. In scripts, use php8.0, phar8.0 and so on explicitly.

Uploading Files

The LAMP app can be uploaded using the File Manager or SFTP.

SFTP

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

You can find the SFTP login details by clicking the Documentation drop down.

SFTP Access

SFTP access for non-admin users can be granted using the operator role.

PHP settings

Custom PHP settings can be added in two ways:

  • App's apache configuration - /app/data/apache/app.conf
  • Via htaccess - /app/data/public/.htaccess

The files above can be edited using the File Manager. Note that settings with a mode of PHP_INI_SYSTEM cannot be set in htaccess files.

Example htaccess configuration:

#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

Custom Apache settings can be added in two ways:

  • App's apache configuration - /app/data/apache/app.conf
  • Via htaccess - /app/data/public/.htaccess

The files above can be edited using the File Manager. Be sure to restart the app after making changes.

Example htaccess configuration:

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):

zend_extension=/app/data/ioncube/ioncube_loader_lin_7.2.so

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.

Step 5: Verifying installation

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

Configuring MySQL

Database credentials can be found in /app/data/credentials.txt using the File manager.

On a technical note, 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:

CLOUDRON_MYSQL_URL=            # the mysql url (only set when using a single database, see below)
CLOUDRON_MYSQL_USERNAME=       # username
CLOUDRON_MYSQL_PASSWORD=       # password
CLOUDRON_MYSQL_HOST=           # server IP/hostname
CLOUDRON_MYSQL_PORT=           # server port
CLOUDRON_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("CLOUDRON_MYSQL_HOST"),
    'username' => getenv("CLOUDRON_MYSQL_USERNAME"),
    'password' => getenv("CLOUDRON_MYSQL_PASSWORD"),
    'database' => getenv("CLOUDRON_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 using the File Manager inside the file /app/data/credentials.txt.

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 SQL_MODE = 'TRADITIONAL'");
mysql_query("SET SESSION UNIQUE_CHECKS = false");
mysql_query("SET SESSION FOREIGN_KEY_CHECKS=0");

phpMyAdmin

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.

Disabling phpMyAdmin

It is good security practice to disable phpMyAdmin once you have finished using it. To disable it, edit /app/data/apache/app.conf using the File Manager and comment out the following line:

    # This line can be commented out, if you do no require PHPMyAdmin Access
    # Include "/app/code/apache/phpmyadmin.conf"

Be sure to restart the app after making the above change.

Email

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

The exposed environment variables are:

CLOUDRON_MAIL_SMTP_SERVER   # SMTP server
CLOUDRON_MAIL_SMTP_PORT         # SMTP server port
CLOUDRON_MAIL_SMTPS_PORT    # SMTPS server port. This is mostly for legacy apps
CLOUDRON_MAIL_SMTP_USERNAME     # Username
CLOUDRON_MAIL_SMTP_PASSWORD     # Password
CLOUDRON_MAIL_FROM          # The MAIL FROM. If you want to change this, see [this](/apps/#mail-from-address)
CLOUDRON_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 using the File Manager inside the file /app/data/credentials.txt.

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

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

You can use PHPMailer to send emails (installed using composer require phpmailer/phpmailer):

<?php
//Import PHPMailer classes into the global namespace
//These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;

//Load Composer's autoloader
require 'vendor/autoload.php';

//Create an instance; passing `true` enables exceptions
$mail = new PHPMailer(true);

try {
    //Server settings
    $mail->SMTPDebug = SMTP::DEBUG_SERVER;                      //Enable verbose debug output
    $mail->isSMTP();                                            //Send using SMTP
    $mail->Host       = getenv('CLOUDRON_MAIL_SMTP_SERVER');    //Set the SMTP server to send through
    $mail->SMTPAuth   = true;                                   //Enable SMTP authentication
    $mail->Username   = getenv('CLOUDRON_MAIL_SMTP_USERNAME');  //SMTP username
    $mail->Password   = getenv('CLOUDRON_MAIL_SMTP_PASSWORD');  //SMTP password
    $mail->SMTPSecure = '';
    $mail->Port       = getenv('CLOUDRON_MAIL_SMTP_PORT');

    //Recipients
    $mail->setFrom(getenv('CLOUDRON_MAIL_FROM'), 'Mailer');
    $mail->addAddress('test@cloudron.io', 'Cloudron Test');     //Add a recipient

    //Content
    $mail->isHTML(true);                                  //Set email format to HTML
    $mail->Subject = 'Here is the subject';
    $mail->Body    = 'This is the HTML message body <b>in bold!</b>';
    $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';

    $mail->send();
    echo 'Message has been sent';
} catch (Exception $e) {
    echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}

Redis

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

The exposed environment variables are:

CLOUDRON_REDIS_URL          # redis URL of the form redis://username:password@host:port
CLOUDRON_REDIS_HOST             # redis hostname
CLOUDRON_REDIS_PORT     6379    # redis port
CLOUDRON_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 using the File Manager inside the file /app/data/credentials.txt

LDAP

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

The exposed environment variables are:

CLOUDRON_LDAP_SERVER=                                # ldap server IP
CLOUDRON_LDAP_HOST=                                  # ldap server IP (same as above)
CLOUDRON_LDAP_PORT=                                  # ldap server port
CLOUDRON_LDAP_URL=                                   # ldap url of the form ldap://ip:port
CLOUDRON_LDAP_USERS_BASE_DN=                         # ldap users base dn of the form ou=users,dc=cloudron
CLOUDRON_LDAP_GROUPS_BASE_DN=                        # ldap groups base dn of the form ou=groups,dc=cloudron
CLOUDRON_LDAP_BIND_DN=                               # DN to perform LDAP requests
CLOUDRON_LDAP_BIND_PASSWORD=                         # Password to perform LDAP requests

To protect the site with basic authentication via LDAP, use the following for apache config:

    <Directory /app/data/public>
        Options +FollowSymLinks

        AllowOverride None
        Require valid-user
        AuthName "Cloudron LDAP Authentication"
        AuthBasicProvider ldap
        AuthType Basic
        AuthLDAPURL ${CLOUDRON_LDAP_URL}/${CLOUDRON_LDAP_USERS_BASE_DN}?username?sub?(username=*)
        AuthLDAPBindDN ${CLOUDRON_LDAP_BIND_DN}
        AuthLDAPBindPassword ${CLOUDRON_LDAP_BIND_PASSWORD}
    </Directory>

Custom Startup Script

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

#!/bin/bash

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

Composer

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 /app/data/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.

Laravel

To run Laravel apps, see this article.

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:

/*
 http://cmanios.wordpress.com/2014/04/12/nginx-https-reverse-proxy-to-wordpress-with-apache-http-and-different-port/
 http://wordpress.org/support/topic/compatibility-with-wordpress-behind-a-reverse-proxy
 https://wordpress.org/support/topic/wp_home-and-wp_siteurl
 */
// If WordPress is behind reverse proxy which proxies https to http
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];

    if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
        $_SERVER['HTTPS']='on';
}

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"] == '172.18.0.1') {
    echo "Cloudron healthcheck reponse";
    exit;
}