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
- 8.2
- 8.3 (default)
- 8.4
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.3. 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.
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;
}