Install

Install Cypht

Cypht has four differents installation ways:


1. Manual installation

Requirements

Cypht 1.4.x requires PHP 5.6 to 7.4. For PHP 8.1+, please use Cypht 2.x+, Composer 2, and at minimum the OpenSSL, mbstring and cURL extensions. Cypht can also leverage several other extensions as defined in composer.json. Testing is done on Debian and Ubuntu platforms with Nginx and Apache.

Before proceeding please make sure your system meets minimal requirements

Steps

1. Check minimum requirements

        #!/bin/bash
        # You need to check php version. For Cypht version 1.4.x, ensure PHP version is between 5.6 and 7.4, while for version 2.x.x, PHP 8.1 or higher is required.
        php --version
        # Next you need to check composer version which should be >=2.0.0
        composer --version
    

2. Download and prepare the code

It's important to consider where you place the Cypht source. The web server will need read-only access to it, and moving it from one place to another requires re-running the configuration script. Do not put the source in the document root as it could create a security risk. On Debian systems, it's common to place the source in the "/usr/local/share/" sub-directory for such cases. The provided bash script downloads(installs or upgrades) the specified version of Cypht, prepares the necessary directories, sets up correct permissions and ownership, and places the Cypht source in "/usr/local/share/cypht/cypht-version". It also ensures that the required configuration files are created, such as .env or hm3.ini (depending on the version). The script requires sudo access to perform these actions:


                #!/bin/bash

                bold_green() {
                echo -e "\033[1m\033[32m✓ $1\033[0m"
                }

                bold_red() {
                echo -e "\033[1m\033[31m$1\033[0m"
                }

                bold_blue() {
                echo -e "\033[1m\033[34m$1\033[0m"
                }

                bold_yellow() {
                echo -e "\033[1m\033[33m$1\033[0m"
                }

                # Function to check prerequisites
                check_prerequisites() {
                    echo "Checking prerequisites..."

                    # Check if PHP is installed
                    if ! command -v php &>/dev/null; then
                        bold_red "Error: PHP is not installed or not in the system PATH."
                        bold_red "Please install PHP before proceeding."
                        exit 1
                    fi

                    # Print the PHP version
                    bold_green "PHP is installed."

                    # List installed PHP extensions
                    required_extensions=("openssl" "mbstring" "curl")
                    missing_extensions=()

                    for ext in "${required_extensions[@]}"; do
                        if ! php -m | grep -iq "$ext"; then
                            missing_extensions+=("$ext")
                        fi
                    done

                    if [ ${#missing_extensions[@]} -gt 0 ]; then
                        bold_red "Error: The following required PHP extensions are missing: ${missing_extensions[*]}"
                        bold_red "Please install the missing extensions before proceeding."
                        exit 1
                    else
                        bold_green "All required PHP extensions (OpenSSL, mbstring, cURL) are installed."
                    fi

                    # Check if Composer is installed
                    if ! command -v composer &>/dev/null; then
                        bold_red "Error: Composer is not installed or not in the system PATH."
                        bold_red "Please install Composer before proceeding: https://getcomposer.org/download/"
                        exit 1
                    fi

                    # Print the Composer version
                    bold_green "Composer is installed.\n"

                }

                # Function to fetch the list of valid tags from the GitHub repository
                fetch_tags() {
                    echo "Fetching latest versions from GitHub..." >&2  # Print to stderr to avoid mixing with output
                    curl -s https://api.github.com/repos/cypht-org/cypht/releases | \
                    jq -r '.[] | select(.created_at > "2018-11-13T03:58:48Z") | .tag_name' | sort -V | \
                    awk -F. '
                    {
                        major = substr($1, 2)  # Extract major version number (e.g., "1" from "v1.x.y")
                        latest[major] = $0     # Always update the latest version for this major version
                    }
                    END {
                        # Print the latest version for each major version
                        for (major in latest) {
                            print latest[major]
                        }
                    }' | sort -V  # Sort the final output by version
                }

                # Function to install Cypht for a given version
                install_cypht() {
                    local version=$1
                    local destination="$BASE_DIR/cypht-$version"

                    # Check if the destination directory already exists
                    if [ -d "$destination" ]; then
                        bold_yellow "Cypht version $version already exists at $destination."
                        read -p "Do you want to overwrite it? (yes/no) [yes]: " overwrite
                        overwrite="${overwrite:-yes}"  # Default to 'yes' if no input is provided
                        if [[ "$overwrite" != "yes" ]]; then
                            bold_red "Installation aborted."
                            exit 0
                        else
                            bold_blue "Overwriting existing installation..."
                            sudo rm -rf "$destination"
                        fi
                    fi

                    # Create destination directory
                    bold_blue "Creating directory for version $version: $destination\n\n"
                    sudo mkdir -p "$destination"

                    # Create temporary working directory
                    temp_dir=$(mktemp -d)
                    cd "$temp_dir" || exit 1

                    # Download the selected version of Cypht
                    if [ "$version" == "master" ]; then
                        bold_blue "Downloading the latest development version (master branch)..."
                        wget "https://github.com/cypht-org/cypht/archive/refs/heads/master.zip" -O "master.zip"
                        archive_name="master.zip"
                        extracted_folder="cypht-master"
                    else
                        bold_blue "Downloading version $version..."
                        wget "https://github.com/cypht-org/cypht/archive/refs/tags/$version.zip" -O "$version.zip"
                        archive_name="$version.zip"
                        extracted_folder="cypht-${version#v}"
                    fi

                    if [ $? -ne 0 ]; then
                        bold_red "Error downloading version $version."
                        exit 1
                    fi

                    # Unpack the archive
                    bold_blue "Unpacking the archive...\n"
                    unzip "$archive_name"

                    if [ $? -ne 0 ]; then
                        bold_red "Error unpacking the archive."
                        exit 1
                    fi

                    # Run composer
                    cd "$extracted_folder" || exit 1
                    bold_blue "Installing dependencies with composer...\n"
                    composer install

                    # Handle configuration file creation

                    if [[ "$selected_version" =~ ^v1 ]]; then
                        bold_blue "Creating hm3.ini from hm3.sample.ini\n"
                        cp hm3.sample.ini hm3.ini
                    else
                        bold_blue "Creating .env from .env.example....\n"
                        cp .env.example .env
                    fi

                    # Fix permissions and ownership
                    bold_blue "Fixing permissions...\n"
                    find . -type d -exec chmod 755 {} \;
                    find . -type f -exec chmod 644 {} \;

                    # Ask for group (root is default for other systems, or user for macOS)
                    read -p "Enter the group to own the files [root]: " group
                    group="${group:-root}"

                    sudo chown -R root:"$group" .

                    # Move files to the destination folder
                    bold_blue "Copying files to $destination...\n"
                    sudo mv ./* ./.[!.]* "$destination"

                    # Clean up temporary directory
                    cd ..
                    sudo rm -rf "$temp_dir"

                    if [ $? -ne 0 ]; then
                        echo "Error moving files to $destination."
                        exit 1
                    fi
                    bold_green "Cypht $version installed successfully to $destination"
                }

                # Main script execution

                # Check prerequisites
                check_prerequisites

                # Fetch available version tags
                available_versions=$(fetch_tags)
                available_versions=$(echo -e "$available_versions\nmaster")  # Add master branch to the list

                # Display available versions
                echo "$available_versions" | nl -s '. '

                # Prompt user to select a version
                read -p "Enter the version number (e.g. 1 for $(echo "$available_versions" | head -n 1)) [master]: " version_choice
                version_choice="${version_choice:-$(echo "$available_versions" | grep -n "master" | cut -d: -f1)}"

                # Get the version based on the user’s choice
                selected_version=$(echo "$available_versions" | sed -n "${version_choice}p")

                if [ -z "$selected_version" ]; then
                    bold_red "Error: Invalid version choice. Please select a valid number from the list."
                    exit 1
                fi

                # Prompt user for BASE_DIR
                read -p "Enter the base directory for Cypht installation [/usr/local/share/cypht]: " BASE_DIR
                BASE_DIR="${BASE_DIR:-/usr/local/share/cypht}"

                bold_blue "Installation of version: $selected_version"
                install_cypht "$selected_version"

            
                @echo off
                setlocal enabledelayedexpansion

                :: Enabling ANSI Support and UTF-8 Encoding
                chcp 65001 >nul
                reg add HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1 /f >nul 2>&1

                :: Définition des codes couleur et symboles
                for /F "tokens=2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
                    set "ESC=%%a"
                )
                set "GREEN=%ESC%[32m"
                set "RED=%ESC%[31m"
                set "RESET=%ESC%[0m"

                :: Minimalist version and functional guarantee
                echo
                echo Checking prerequisites...
                echo.
                ::1. PHP Verification...
                where php >nul 2>&1
                if %errorlevel% neq 0 (
                echo %RED%Error: PHP is not installed or not in the system PATH.%RESET%
                echo %RED%Please install PHP before proceeding.%RESET%
                pause
                exit /b 1
                )
                echo %GREEN%   [✓] PHP is installed.%RESET%

                set "required_extensions=openssl mbstring curl "
                set "missing_extensions="

                for %%e in (%required_extensions%) do (
                    php -m | find /i "%%e" >nul 2>&1
                    if errorlevel 1 (
                        set "missing_extensions=!missing_extensions! %%e"
                        echo %RED%   [X] Extension PHP %%e missing%RESET%
                    )
                )

                if defined missing_extensions (
                    echo.
                    echo  %RED%   [X] Missing extension :%missing_extensions% %RESET%
                    echo %RED%Install these extensions before proceeding%RESET%
                    pause
                    exit /b 1
                ) else (
                    echo.
                    echo %GREEN%   [✓] All required PHP extensions [OpenSSL, mbstring, cURL] are installed.%RESET%
                )
                echo.

                :: 2. Composer Verification
                where composer >nul 2>&1
                if %errorlevel% neq 0 (
                echo %RED%   Error: Composer is not installed or not in the system PATH.%RESET%
                echo %RED%   Please install Composer before proceeding: https://getcomposer.org/download/%RESET%
                pause
                exit /b 1
                )
                echo %GREEN%   [✓] Composer is installed.%RESET%
                echo.
                :: fetch list of valid tags from the GitHub repository

                :: Create a temporary file
                set "temp_file=%temp%\cypht_versions.txt"

                :: fetch list
                powershell -command "$releases = Invoke-RestMethod -Uri 'https://api.github.com/repos/cypht-org/cypht/releases' -UseBasicParsing; $versions = $releases | Where-Object { $_.created_at -gt [datetime]'2018-11-13T03:58:48Z' } | Select-Object -ExpandProperty tag_name; $latest = $versions | Where-Object { $_ -match '^v\d+\.\d+\.\d+$' } | Group-Object { ($_ -split '\.')[0] } | ForEach-Object { $_.Group | Sort-Object -Descending | Select-Object -First 1 }; if ($versions -contains 'master') { $latest += 'master' }; $latest | Sort-Object" > "%temp_file%"

                :: Check if we have recovered any versions
                set "count=0"
                for /f "delims=" %%v in (%temp_file%) do (
                    set /a "count+=1"
                    set "version[!count!]=%%v"
                )

                :: Displaying Numbered Versions
                if !count! equ 0 (
                    echo %RED%No version found!%RESET%
                    goto cleanup
                )

                echo Fetching latest versions from GitHub...
                for /l %%i in (1,1,!count!) do (
                    echo    %%i. !version[%%i]!
                )

                :: Also offer the master version
                set /a "count+=1"
                set "version[!count!]=master"
                echo    !count!. master
                echo.

                :cleanup
                del "%temp_file%" 2>nul

                :: 3. Request version
                echo.
                :input_version_number
                set /p "VERSION=Enter the version number (e.g. 1 for v1.4.5) [master]:"
                if "!VERSION!"=="" set "VERSION=!count!"
                if not defined version[%VERSION%] (
                    echo %RED%   Error: Invalid version choice. Please select a valid number from the list..%RESET%
                    goto input_version_number
                )
                :: 4. Request directory
                set /p "INSTALL_DIR=Enter the base directory for Cypht installation [C:\cypht]:"
                if "!INSTALL_DIR!"=="" set "INSTALL_DIR=C:\cypht"
                :: 5. Confirmation
                echo.

                echo Installation in progress... 
                set "version=!version[%VERSION%]!"
                set "destination=%INSTALL_DIR%\cypht-%version%"
                echo.

                :: Check if the folder already exists
                if exist "%destination%" (
                    echo %RED%[X] Version %version% already exists in %destination%.%RESET%
                    set /p "overwrite=Do you want to crush it? (yes/no) [yes]:"
                    if "!overwrite!"=="" set "overwrite=yes"
                    if /i "!overwrite!"=="no" (
                        echo Installation canceled.
                        exit /b 0
                    )
                    echo Overwriting of the existing installation...
                    rmdir /s /q "%destination%"
                )

                :: Create destination folder
                echo Creating the folder for the release %version%: %destination%
                mkdir "%destination%" 2>nul
                if not exist "%destination%" (
                    echo %RED%Failed to create the folder.%RESET%
                    exit /b 1
                )

                :: Create a temporary folder
                set "temp_dir=%temp%\cypht_install"
                mkdir "%temp_dir%" 2>nul

                :: Download Cypht
                if "%version%"=="master" (
                    echo Download the development version [master]...
                    powershell -command "Invoke-WebRequest -Uri 'https://github.com/cypht-org/cypht/archive/refs/heads/master.zip' -OutFile '%temp_dir%\master.zip'"
                    set "archive_name=master.zip"
                    set "extracted_folder=cypht-master"
                ) else (
                    echo Download the development version %version%...
                    powershell -command "Invoke-WebRequest -Uri 'https://github.com/cypht-org/cypht/archive/refs/tags/%version%.zip' -OutFile '%temp_dir%\%version%.zip'"
                    set "archive_name=%version%.zip"
                    set "extracted_folder=cypht-!version:v=!"
                )

                if not exist "%temp_dir%\%archive_name%" (
                    echo %RED%Error downloading.%RESET%
                    exit /b 1
                )

                echo Extracting the archive...
                powershell -command "Expand-Archive -Path '%temp_dir%\%archive_name%' -DestinationPath '%destination%'; $extracted = Get-ChildItem '%destination%' -Directory | Where-Object {$_.Name -like 'cypht-*'} | Select-Object -First 1; if ($extracted) { Get-ChildItem $extracted.FullName | Move-Item -Destination '%destination%' -Force; Remove-Item $extracted.FullName -Recurse -Force }"
                if not exist "%destination%" (
                    echo %RED%Error during extraction.%RESET%
                    exit /b 1
                )

                ::Cleaning
                rd /s /q "%temp_dir%"

                cd /d "%destination%"

                :: Create the configuration file
                if "!version:~0,2!"=="v1" (
                    echo Creating hm3.ini from hm3.sample.ini
                    copy "%destination%\hm3.sample.ini" "%destination%\hm3.ini"
                ) else (
                    echo Creating .env from .env.example
                    copy "%destination%\.env.example" "%destination%\.env"
                )

                echo.
                echo Installing dependencies with Composer...
                powershell -command "composer install"

                echo.
                echo Copying files to %destination%
                echo.
                echo  %GREEN% ✓ Cypht %version%  installed successfully to %destination% %RESET%
                pause
            

3. Configure the program

To configure Cypht for your environment, you must first edit the "hm3.ini" (for Cypht 1.4.x) or ".env" (for Cypht 2.x.x) file to your liking, .env content can be generated using the Cypht Config Generator, then run the "config_gen.php" script to generate the optimized configuration file and assets used at run-time.

For Cypht 1.4.x, begin by editing the "hm3.ini" file to configure Cypht for your environment. If you choose to use a database for any of the three available purposes (authentication, sessions, or user settings), you will need to complete the "DB support" section and create the required tables. SQL to do so can be found in the "hm3.sample.ini" file. The "hm3.ini" file contains many comments explaining each configuration option and how to set it up for your environment.

        sudo mkdir -p /var/lib/hm3/{attachments,users,app_data}
        sudo chown -R www-data /var/lib/hm3/
    

The "/var/lib/hm3/users" directory is only required if you are using the file-system and not a database to store user settings (user_config_type = file in the "hm3.ini" or ".env"). You can put these directories anywhere, just make sure the values in the ini file point to the right place.

4. Generate the run-time configuration

Cypht uses a build process to create an optimized configuration, and to combine and minimize page assets.Once you have edited your "hm3.ini" or ".env" file, generate the configuration with:

        cd /usr/local/share/cypht  (or wherever you put the code in section 1)
        sudo php ./scripts/config_gen.php
    

Now going to https://your-server/mail/ should load the Cypht login page. Note that If you use a symlink, your web-server must be configured to follow symlinks.

5. Enable the program in your web-server

The easiest way to serve Cypht is to symlink it to the web-server document root. You can also copy the generated files to your web-server location, but then you will need to re-copy them anytime the config_gen script is run. If the source is located at /usr/local/share/cypht, and the web-server document root is at /var/www/html, the following command will make Cypht available under the "mail" path of the web-server:

        sudo ln -s /usr/local/share/cypht/site /var/www/html/mail
    

Now going to https://your-server/mail/ should load the Cypht login page. Note that If you use a symlink, your web-server must be configured to follow symlinks.

6. Users

Setting up users depends on what type of authentication you configure in the hm3.ini file. If you are using the local database configuration for users, there are scripts in the scripts/ directory to help manage them:

        # create an account
        php ./scripts/create_account.php username password

        # delete an account
        php ./scripts/delete_account.php username

        # change an account password
        php ./scripts/update_password.php username password
    

7. Debug mode

Cypht has a debug or developer mode that can be used to troubleshoot problems or enable faster development of modules. To enable the debug version of Cypht, just sym-link the entire source directory instead of the site sub-directory:

sudo ln -s /usr/local/share/cypht /var/www/html/mail-debug

Debug mode is not as efficient as the normal version, and it is NOT designed to be secure. DO NOT RUN DEBUG MODE IN PRODUCTION. You have been warned! Debug mode outputs lots of information to the PHP error log that can be useful for trouble-shooting problems. The location of the error log varies based on your php.ini settings and web-server software.

8. Other INI files

Some Cypht modules require additional ini files to be configured. These should NOT be inside the web-server document root. Cypht will look for them in the location defined by "app_data_dir" in the hm3.ini file. A sample ini file for each module set that requires one is included in the source for that module. To configure them you must copy the sample ini file to the "app_data_dir" and edit it for your setup. Some of these require configuring your service with a provider, specifically ones related to Oauth2 client setup (Github, WordPress, Oauth2 over IMAP for Gmail and Outlook). Re-run the config_gen script after configuring an ini file and it will be merged into the main configuration settings.

2. Install cypht using Docker

Using Docker is one of the easiest way to install cypht as the cypht docker image comes with all the steps required in the manual instalation done for you. But the bad news is that this installation way requiresdocker knowledge.
Here is the cypht docker repository: https://hub.docker.com/r/sailfrog/cypht-docker
To run containers required by cypht, please, first make sure you have docker and docker-compose installed on your system, then take a look on the section "example docker-compose" of repository overview, then do the following:

NOTE: Please change usernames and passwords before using the given docker-compose code in your production environment.

3. Install Cypht on a YunoHost server

This is an other easy way of installing and use Cypht.
YunoHost is an operating system that aims to simplify server administration as much as possible to democratize self-hosting while remaining reliable, secure, ethical and lightweight. It is a free software project owned exclusively by volunteers. Technically, it can be seen as a distribution based on Debian GNU/Linux and can be installed on many types of hardware.
To learn more about YunoHost, visit https://yunohost.org/en/whatsyunohost

To install Cypht on YunoHost, please follow these steps:

4. Install Cypht within Tiki

If you have tiki installed, you can use Cypht within tiki. This is an easy way of installing Cypht.
Please follow the following link for a complete guide of how to install and use cypht within Tiki. https://doc.tiki.org/Webmail

Having problems?

We are happy to help trouble-shoot any installation issues you run into. Chat with us at Gitter Cypht at Gitter and We'll get back to you as soon as we can.