...
How to install itflow on debian vps
Learn how to install itflow on debian vps!

This article provides a guide demonstrating how to install ITFlow on Debian VPS.

Table of Contents

What is ITFlow?

ITFlow is a free, open-source professional services automation platform designed primarily for managed service providers and IT departments. It combines client documentation, asset tracking, password management, ticketing, invoicing, accounting, domain and SSL monitoring, and a client portal in one application.

The ITFlow developers currently recommend installing the application on a clean Debian 13 server using their official installation script. The script configures Apache, PHP, MariaDB, TLS, scheduled tasks, and the ITFlow application itself.

This guide covers:

  • VPS and DNS preparation
  • Server hardening
  • The recommended automated installation
  • Verification and troubleshooting
  • Email and cron configuration
  • Backups
  • Updates
  • A manual installation alternative

Launch 100% ssd debian vps from $3. 19/mo!


Compare Debian VPS Plans

KVM-SSD-1
KVM-SSD-8
KVM-SSD-16
KVM-SSD-32
CPU
1 Core
2 Cores
4 Cores
8 Cores
Memory
1 GB
8 GB
16 GB
32 GB
Storage
16 GB NVMe
128 GB NVMe
256 GB NVMe
512 GB NVMe
Bandwidth
1 TB
4 TB
8 TB
16 TB
Network
1 Gbps
1 Gbps
1 Gbps
1 Gbps
Delivery Time
⏱️ Instant
⏱️ Instant
⏱️ Instant
⏱️ Instant
Location
US/EU/APAC
US/EU/APAC
US/EU/APAC
US/EU/APAC
Price
$7.58*
$39.50*
$79.40*
$151.22*
KVM-SSD-1
$7.58*
CPU 1 Core
Memory 1 GB
Storage 16 GB NVMe
Bandwidth 1 TB
Network 1 Gbps
Delivery Time ⏱️ Instant
Location US/EU/APAC
KVM-SSD-8
$39.50*
CPU 2 Cores
Memory 8 GB
Storage 128 GB NVMe
Bandwidth 4 TB
Network 1 Gbps
Delivery Time ⏱️ Instant
Location US/EU/APAC
KVM-SSD-16
$79.40*
CPU 4 Cores
Memory 16 GB
Storage 256 GB NVMe
Bandwidth 8 TB
Network 1 Gbps
Delivery Time ⏱️ Instant
Location US/EU/APAC
KVM-SSD-32
$151.22*
CPU 8 Cores
Memory 32 GB
Storage 512 GB NVMe
Bandwidth 16 TB
Network 1 Gbps
Delivery Time ⏱️ Instant
Location US/EU/APAC

How to Install ITFlow on Debian VPS

To install ITFlow on Debian VPS, follow the steps below:

  1. Deployment architecture

    The finished deployment will use:

    Component Purpose
    Debian 13 Server operating system
    Apache Web server
    PHP ITFlow application runtime
    MariaDB ITFlow database
    Let’s Encrypt HTTPS certificate
    Cron Background maintenance and mail processing
    UFW Host firewall
    Fail2ban Protection against repeated login attacks

    The official documentation recommends Apache with MariaDB. It specifically recommends MariaDB over MySQL because some ITFlow pages may not function correctly with MySQL.

  2. VPS requirements

    For a small ITFlow deployment, a reasonable starting configuration is:

    The official installation-script requirements are:

    For example:

    itflow.example.com
    

    Because ITFlow can contain passwords, network diagrams, client records, billing information, and infrastructure documentation, it should not be deployed on an unsecured or shared hosting account.

  3. Configure DNS

    Create an A record for the ITFlow hostname.

    Example:

    Type Name Value TTL
    A itflow 203.0.113.25 300

    This produces:

    itflow.example.com
    

    Replace 203.0.113.25 with the VPS public IPv4 address.

    If the server has IPv6, you may also create an AAAA record:

    Type Name Value
    AAAA itflow Server IPv6 address

    Verify the record from your workstation:

    dig +short itflow.example.com
    

    Or:

    nslookup itflow.example.com
    

    The result should show the VPS IP address.

    Do not begin certificate issuance until the domain resolves correctly. Let’s Encrypt must be able to reach the server over port 80 or 443.

  4. Connect to the server

    Connect over SSH:

    ssh root@203.0.113.25
    

    Alternatively, connect as a sudo-enabled user:

    ssh administrator@203.0.113.25
    

    Then obtain a root shell:

    sudo -i
    

    Confirm the operating system:

    cat /etc/os-release
    

    You should see output identifying Debian 13.

    Check the hostname:

    hostnamectl
    

    Set a meaningful hostname when necessary:

    hostnamectl set-hostname itflow.example.com
    

    Add the hostname to /etc/hosts:

    nano /etc/hosts
    

    Use an entry similar to:

    127.0.0.1       localhost
    203.0.113.25    itflow.example.com itflow
    

    Do not remove the standard IPv6 entries.

  5. Update Debian

    Update the package indexes and install available upgrades:

    apt update
    apt full-upgrade -y
    

    Install basic administration utilities:

    apt install -y \
        ca-certificates \
        curl \
        wget \
        git \
        unzip \
        nano \
        sudo \
        ufw \
        fail2ban \
        dnsutils
    

    Reboot if the kernel or core system packages were updated:

    reboot
    

    Reconnect after the server returns online.

  6. Create an administrative user

    Although the official script is run as root, routine server administration should use a non-root account.

    Create an administrator:

    adduser itflowadmin
    

    Grant sudo privileges:

    usermod -aG sudo itflowadmin
    

    Confirm membership:

    id itflowadmin
    

    The output should include the sudo group.

    Copy the existing root SSH authorization when appropriate:

    install -d -m 700 -o itflowadmin -g itflowadmin /home/itflowadmin/.ssh
    cp /root/.ssh/authorized_keys /home/itflowadmin/.ssh/
    chown itflowadmin:itflowadmin /home/itflowadmin/.ssh/authorized_keys
    chmod 600 /home/itflowadmin/.ssh/authorized_keys
    

    Open a second terminal and verify that you can sign in:

    ssh itflowadmin@203.0.113.25
    

    Do not disable root or password authentication until key-based access has been tested successfully.

  7. Configure the firewall

    Allow SSH before enabling the firewall:

    ufw allow OpenSSH
    

    Allow web traffic:

    ufw allow 80/tcp
    ufw allow 443/tcp
    

    Enable the firewall:

    ufw enable
    

    Review the rules:

    ufw status verbose
    

    Expected rules include:

    22/tcp                     ALLOW
    80/tcp                     ALLOW
    443/tcp                    ALLOW
    

    When SSH runs on a custom port, allow that port before enabling UFW:

    ufw allow 2222/tcp
    

    Recommended installation method

  8. Download the official installer

    The official project recommends its installation script as the preferred self-hosting method for Debian and Ubuntu.

    Move to a safe working directory:

    cd /root
    

    Download the installer:

    wget -O itflow_install.sh \
    https://github.com/itflow-org/itflow-install-script/raw/main/itflow_install.sh
    

    Confirm that the file exists:

    ls -lh itflow_install.sh
    

    Before running a remotely downloaded script as root, inspect it:

    less itflow_install.sh
    

    You can also check its syntax:

    bash -n itflow_install.sh
    

    No output from bash -n normally means no shell syntax errors were found.

    Optionally calculate and retain a checksum:

    sha256sum itflow_install.sh
    

    This does not establish trust by itself, but it records exactly which script was executed.

  9. Run the installer

    Run the official script:

    bash itflow_install.sh
    

    Follow the interactive prompts.

    Depending on the current installer version, it may ask for information such as:

    • Domain name
    • Stable or development branch
    • SSL configuration
    • Certificate email address
    • Database password
    • Application administrator details

    Use the production hostname:

    itflow.example.com
    

    Choose the stable release or production branch unless you are intentionally building a testing server.

    Use a valid email address for Let’s Encrypt expiration and security notifications.

    Generate a strong database password with:

    openssl rand -base64 36
    

    Store that password in a secure password manager.

    The official installer currently clones ITFlow into a domain-specific directory under /var/www, creates an itflow MariaDB database and user, creates Apache configuration, and installs ITFlow cron jobs.

  10. Monitor the installation

    The installer writes a log to:

    /var/log/itflow_install.log
    

    Watch the log from another SSH session:

    tail -f /var/log/itflow_install.log
    

    After installation, review it for errors:

    less /var/log/itflow_install.log
    

    Search for common failure indicators:

    grep -Ei "error|failed|failure|denied" /var/log/itflow_install.log
    

    Not every line containing “error” indicates installation failure, so review the surrounding context.

  11. Verify services

    Check Apache:

    systemctl status apache2 --no-pager
    

    Check MariaDB:

    systemctl status mariadb --no-pager
    

    Check cron:

    systemctl status cron --no-pager
    

    Enable all three services at boot:

    systemctl enable apache2 mariadb cron
    

    Confirm that ports 80 and 443 are listening:

    ss -lntp | grep -E ':80|:443'
    

    Expected output should reference Apache.

    Test Apache configuration:

    apachectl configtest
    

    Expected result:

    Syntax OK
    
  12. Open ITFlow

    Visit:

    https://itflow.example.com
    
    Itflow login
    Itflow login

    If the installer completed the initial application configuration, you should see either:

    • The ITFlow login page
    • The initial account setup screen
    • A final installation/configuration page

    Complete the web-based setup when prompted.

    You will generally need to provide:

    • Company name
    • Administrator name
    • Administrator email address
    • A strong administrator password
    • Locale and currency
    • Database details, if they were not created automatically

    Use a unique administrator password. Do not reuse the server root password or database password.

  13. Confirm HTTPS

    Inspect the site from the command line:

    curl -I https://itflow.example.com
    

    A successful response will normally include an HTTP status such as:

    HTTP/2 200
    

    or:

    HTTP/1.1 200 OK
    

    Check the certificate:

    openssl s_client \
        -connect itflow.example.com:443 \
        -servername itflow.example.com </dev/null 2>/dev/null |
    openssl x509 -noout -issuer -subject -dates
    

    Test automatic renewal:

    certbot renew --dry-run
    

    List installed certificates:

    certbot certificates
    

    Check the Certbot timer:

    systemctl status certbot.timer --no-pager
    

    If the installer used a different ACME client, identify it with:

    systemctl list-timers --all | grep -Ei 'certbot|acme|letsencrypt'
    

    Understanding the deployed components

  14. Locate the application directory

    The current official installer clones ITFlow into:

    /var/www/DOMAIN
    

    For this example:

    /var/www/itflow.example.com
    

    Confirm it:

    ls -la /var/www/itflow.example.com
    

    Store the path in a shell variable for convenience:

    ITFLOW_ROOT="/var/www/itflow.example.com"
    

    Check repository status:

    sudo -u www-data git -C "$ITFLOW_ROOT" status
    

    Check the active branch:

    sudo -u www-data git -C "$ITFLOW_ROOT" branch --show-current
    

    Do not run arbitrary Git commands or force resets on a production instance without taking a database and file backup first.

  15. Review file ownership

    The Apache user on Debian is normally:

    www-data
    

    Check ownership:

    stat -c '%U:%G %a %n' "$ITFLOW_ROOT"
    

    Inspect the main configuration file:

    stat -c '%U:%G %a %n' "$ITFLOW_ROOT/config.php"
    

    The application directory normally needs to remain writable by www-data because ITFlow supports Git-based self-updates. The official manual documentation sets the application ownership to www-data:www-data, uses directory permissions of 775, and restricts config.php to 640.

    A typical configuration is:

    chown -R www-data:www-data "$ITFLOW_ROOT"
    find "$ITFLOW_ROOT" -type d -exec chmod 775 {} \;
    find "$ITFLOW_ROOT" -type f -exec chmod 664 {} \;
    chmod 640 "$ITFLOW_ROOT/config.php"
    

    Only run those commands if permissions are demonstrably incorrect. Avoid repeatedly changing permissions without understanding the application’s update requirements.

  16. Review Apache configuration

    List the enabled sites:

    apache2ctl -S
    

    Look for files associated with the hostname:

    ls -l /etc/apache2/sites-available/
    ls -l /etc/apache2/sites-enabled/
    

    View the virtual host:

    cat /etc/apache2/sites-available/itflow.example.com.conf
    

    The filename may differ.

    A production HTTP virtual host should redirect to HTTPS:

        ServerName itflow.example.com
        Redirect permanent / https://itflow.example.com/
    

    The HTTPS host should resemble:

        ServerName itflow.example.com
        DocumentRoot /var/www/itflow.example.com
    
        
            Options FollowSymLinks
            AllowOverride All
            Require all granted
        
    
        SSLEngine on
        SSLCertificateFile /etc/letsencrypt/live/itflow.example.com/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/itflow.example.com/privkey.pem
    
        ErrorLog ${APACHE_LOG_DIR}/itflow-error.log
        CustomLog ${APACHE_LOG_DIR}/itflow-access.log combined
    

    Test and reload after any change:

    apachectl configtest && systemctl reload apache2
    

    PHP configuration

  17. Verify PHP and extensions

    Check the PHP version:

    php -v
    

    List the extensions:

    php -m
    

    Confirm the modules ITFlow commonly requires:

    php -m | grep -Ei \
    'curl|gd|intl|mbstring|mysqli|xml|zip'
    

    The official manual installation currently lists:

    • PHP
    • php-intl
    • php-mysqli
    • php-curl
    • php-gd
    • php-mbstring
    • php-zip
    • php-xml
    • libapache2-mod-php

    Install any missing modules:

    apt install -y \
        php \
        php-intl \
        php-mysql \
        php-curl \
        php-gd \
        php-mbstring \
        php-zip \
        php-xml \
        libapache2-mod-php
    

    Restart Apache:

    systemctl restart apache2
    
  18. Adjust PHP upload limits

    ITFlow may be used to store documentation and attachments. The official manual guide suggests:

    upload_max_filesize = 500M
    post_max_size = 500M
    max_execution_time = 300
    

    Find the active Apache PHP configuration:

    php --ini
    

    Determine the installed version:

    php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION.PHP_EOL;'
    

    For example:

    nano /etc/php/8.4/apache2/php.ini
    

    Search for and change:

    upload_max_filesize = 500M
    post_max_size = 500M
    max_execution_time = 300
    memory_limit = 512M
    

    Also update the CLI configuration so cron tasks receive appropriate limits:

    nano /etc/php/8.4/cli/php.ini
    

    Set at least:

    memory_limit = 512M
    max_execution_time = 300
    

    Restart Apache:

    systemctl restart apache2
    

    Verify the CLI values:

    php -i | grep -E \
    'memory_limit|upload_max_filesize|post_max_size|max_execution_time'
    

    To verify Apache’s PHP configuration, create a temporary file:

    echo '<?php phpinfo();' > "$ITFLOW_ROOT/phpinfo.php"
    chown www-data:www-data "$ITFLOW_ROOT/phpinfo.php"
    

    Visit:

    https://itflow.example.com/phpinfo.php
    

    Delete it immediately after testing:

    rm -f "$ITFLOW_ROOT/phpinfo.php"
    

    A public phpinfo() page exposes sensitive server configuration and should never remain accessible.

    MariaDB configuration

  19. Verify the database

    Check MariaDB:

    mysqladmin ping
    

    Expected result:

    mysqld is alive
    

    Open the database console:

    mariadb
    

    List databases:

    SHOW DATABASES;
    

    Confirm the ITFlow database:

    USE itflow;
    SHOW TABLES;
    

    Exit:

    EXIT;
    

    The current installer creates the database using utf8mb4 with utf8mb4_unicode_ci, creates an itflow user limited to localhost, and grants that user access only to the ITFlow database.

    Verify the character set:

    mariadb -N -e \
    "SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
     FROM information_schema.SCHEMATA
     WHERE SCHEMA_NAME='itflow';"
    

    Expected output:

    utf8mb4    utf8mb4_unicode_ci
    
  20. Secure MariaDB

    Run:

    mariadb-secure-installation
    

    Depending on Debian’s authentication configuration, answer the prompts to:

    • Remove anonymous users
    • Disable remote root login
    • Remove the test database
    • Reload privilege tables

    Do not expose port 3306 publicly.

    Check listening database sockets:

    ss -lntp | grep 3306
    

    MariaDB should normally listen only on localhost or not expose an external TCP socket.

    Check UFW:

    ufw status numbered
    

    There should be no public MariaDB rule.

    Cron and background processing

  21. Verify ITFlow cron jobs

    ITFlow relies on cron for maintenance, ticket email processing, outbound mail queues, domain checks, and certificate checks.

    The official installer currently creates:

    /etc/cron.d/itflow
    

    Display it:

    cat /etc/cron.d/itflow
    

    The current installer defines tasks similar to:

    0 2 * * * www-data /usr/bin/php /var/www/itflow.example.com/cron/cron.php
    * * * * * www-data /usr/bin/php /var/www/itflow.example.com/cron/ticket_email_parser.php
    * * * * * www-data /usr/bin/php /var/www/itflow.example.com/cron/mail_queue.php
    0 3 * * * www-data /usr/bin/php /var/www/itflow.example.com/cron/domain_refresher.php
    0 4 * * * www-data /usr/bin/php /var/www/itflow.example.com/cron/certificate_refresher.php
    

    These schedules come from the current official installer and could change in later releases.

    Check file ownership and mode:

    stat -c '%U:%G %a %n' /etc/cron.d/itflow
    

    Expected values are normally:

    root:root 644
    

    Correct them if necessary:

    chown root:root /etc/cron.d/itflow
    chmod 644 /etc/cron.d/itflow
    

    Restart cron:

    systemctl restart cron
    

    Check recent cron activity:

    journalctl -u cron --since "1 hour ago"
    
  22. Test a cron task manually

    Run the general maintenance task as the Apache user:

    sudo -u www-data php "$ITFLOW_ROOT/cron/cron.php"
    

    Check the exit status:

    echo $?
    

    A status of 0 usually indicates success.

    Test the outbound queue processor:

    sudo -u www-data php "$ITFLOW_ROOT/cron/mail_queue.php"
    

    Test the domain refresher:

    sudo -u www-data php "$ITFLOW_ROOT/cron/domain_refresher.php"
    

    Do not run email parsers repeatedly on a production system unless inbound email configuration is complete.

    Email configuration

  23. Configure outbound email

    ITFlow uses outbound email for functions including:

    • Ticket notifications
    • Password-reset emails
    • Invoice delivery
    • Quote delivery
    • Client portal notifications
    • System alerts

    Sign in as an administrator and locate the email or mail settings under the ITFlow administrative settings.

    Enter the SMTP information supplied by your email provider.

    Typical settings:

    SMTP host: smtp.example.com
    SMTP port: 587
    Encryption: STARTTLS
    Authentication: Enabled
    Username: itflow@example.com
    Password: Application-specific password
    From address: itflow@example.com
    From name: Company IT Support
    

    Prefer authenticated SMTP submission over installing a public mail server directly on the VPS.

    Send a test message from the ITFlow interface.

    Follow the mail queue log while testing:

    journalctl -u cron -f
    

    Also inspect Apache errors:

    tail -f /var/log/apache2/error.log
    

    Depending on the virtual-host configuration, ITFlow may have a separate log file under /var/log/apache2/.

  24. Configure email-to-ticket

    ITFlow can retrieve messages from a mailbox and create or update tickets. The official installation documentation considers outbound email and email-to-ticket essential post-installation housekeeping.

    Create a dedicated support mailbox, for example:

    support@example.com
    

    Use a separate mailbox rather than a personal account.

    Typical inbound settings:

    Protocol: IMAP
    Host: imap.example.com
    Port: 993
    Encryption: SSL/TLS
    Username: support@example.com
    Password: Application-specific password
    

    Ensure the email parser cron task is present:

    grep ticket_email_parser /etc/cron.d/itflow
    

    Test it manually after configuring the mailbox:

    sudo -u www-data php \
    "$ITFLOW_ROOT/cron/ticket_email_parser.php"
    

    Send a test message from an external address and verify that a ticket appears.

    Initial ITFlow configuration

  25. Complete the organization settings

    After the first login, configure:

    • Organization name
    • Address and contact information
    • Logo and branding
    • Default locale
    • Time zone
    • Date format
    • Default currency
    • Tax rates
    • Invoice numbering
    • Quote numbering
    • Ticket numbering
    • Payment terms
    • Client portal branding

    Make sure the application and Debian use the same time zone.

    Check Debian:

    timedatectl
    

    List time zones:

    timedatectl list-timezones
    

    Set one, for example:

    timedatectl set-timezone America/Chicago
    

    Confirm:

    timedatectl
    
  26. Create individual administrator accounts

    Do not share a single global administrator login.

    Create separate accounts for each team member and assign only the permissions required for their role.

    Recommended role separation:

    • System administrator
    • Help-desk technician
    • Billing staff
    • Read-only auditor
    • Client portal user

    Enable multifactor authentication wherever supported.

    Remove or disable unused accounts promptly.

  27. Protect sensitive ITFlow data

    ITFlow may hold:

    • Administrative passwords
    • API credentials
    • Device login details
    • Network diagrams
    • Client contact data
    • Financial records
    • Internal notes
    • Domain and certificate details

    Apply these minimum controls:

    1. Require HTTPS.
    2. Use unique administrator accounts.
    3. Use long, randomly generated passwords.
    4. Enable multifactor authentication.
    5. Restrict access through a VPN or IP allowlist when practical.
    6. Back up the master encryption key separately.
    7. Encrypt backup storage.
    8. Test restorations regularly.
    9. Review account and application logs.
    10. Keep Debian and ITFlow updated.

    The ITFlow documentation explicitly warns that no system is risk-free and recommends careful judgment before storing highly confidential information.

    Backups

  28. Identify what must be backed up

    A complete ITFlow backup should include:

    • MariaDB database
    • Application files
    • Uploaded documents and attachments
    • config.php
    • The ITFlow master encryption key
    • Apache virtual-host configuration
    • Let’s Encrypt configuration, when useful
    • Cron configuration
    • A record of the installed branch/version

    The master encryption key is particularly important. Losing it may make encrypted credentials or other protected data unrecoverable. The official post-installation checklist specifically calls out backups, especially of the master encryption key.

    Do not keep the only backup on the ITFlow server.

  29. Create a local backup script

    Create a protected backup directory:

    install -d -m 700 /var/backups/itflow
    

    Create the script:

    nano /usr/local/sbin/backup-itflow
    

    Add:

    #!/bin/bash
    
    set -Eeuo pipefail
    umask 077
    
    DOMAIN="itflow.example.com"
    APP_DIR="/var/www/${DOMAIN}"
    BACKUP_ROOT="/var/backups/itflow"
    STAMP="$(date +'%Y-%m-%d_%H-%M-%S')"
    DEST="${BACKUP_ROOT}/${STAMP}"
    DB_NAME="itflow"
    
    mkdir -p "$DEST"
    
    echo "Backing up MariaDB..."
    mariadb-dump \
        --single-transaction \
        --quick \
        --routines \
        --triggers \
        --events \
        "$DB_NAME" |
    gzip > "${DEST}/itflow-database.sql.gz"
    
    echo "Backing up application files..."
    tar \
        --acls \
        --xattrs \
        -czf "${DEST}/itflow-files.tar.gz" \
        -C /var/www \
        "$DOMAIN"
    
    echo "Backing up server configuration..."
    tar \
        -czf "${DEST}/server-config.tar.gz" \
        /etc/apache2 \
        /etc/cron.d/itflow \
        /etc/letsencrypt 2>/dev/null || true
    
    echo "Recording application information..."
    git -C "$APP_DIR" rev-parse HEAD \
        > "${DEST}/git-commit.txt" 2>/dev/null || true
    
    git -C "$APP_DIR" branch --show-current \
        > "${DEST}/git-branch.txt" 2>/dev/null || true
    
    php -v > "${DEST}/php-version.txt"
    mariadb --version > "${DEST}/mariadb-version.txt"
    
    echo "Creating checksums..."
    (
        cd "$DEST"
        sha256sum \
            itflow-database.sql.gz \
            itflow-files.tar.gz \
            server-config.tar.gz \
            > SHA256SUMS
    )
    
    echo "Removing local backups older than 14 days..."
    find "$BACKUP_ROOT" \
        -mindepth 1 \
        -maxdepth 1 \
        -type d \
        -mtime +14 \
        -exec rm -rf {} +
    
    echo "Backup complete: $DEST"
    

    Make it executable:

    chmod 700 /usr/local/sbin/backup-itflow
    

    Run it:

    /usr/local/sbin/backup-itflow
    

    List the results:

    find /var/backups/itflow -maxdepth 2 -type f -ls
    

    Verify checksums:

    cd /var/backups/itflow/$(ls -1 /var/backups/itflow | tail -1)
    sha256sum -c SHA256SUMS
    

    Transfer the backup to encrypted remote storage using a suitable backup platform, object-storage client, or off-server synchronization tool.

  30. Schedule backups

    Create:

    nano /etc/cron.d/itflow-backup
    

    Add:

    30 1 * * * root /usr/local/sbin/backup-itflow >> /var/log/itflow-backup.log 2>&1
    

    Set permissions:

    chown root:root /etc/cron.d/itflow-backup
    chmod 644 /etc/cron.d/itflow-backup
    

    Restart cron:

    systemctl restart cron
    

    Inspect the log:

    tail -n 100 /var/log/itflow-backup.log
    

    A backup is not reliable until you have restored it successfully on a separate test server.

    Updates and maintenance

  31. Update Debian safely

    Install security and package updates regularly:

    apt update
    apt upgrade -y
    

    Review packages that require a reboot:

    test -f /var/run/reboot-required && cat /var/run/reboot-required
    

    Reboot during an appropriate maintenance window:

    reboot
    

    After rebooting, verify:

    systemctl --failed
    systemctl status apache2 mariadb cron --no-pager
    curl -I https://itflow.example.com
    
  32. Update ITFlow

    ITFlow is designed to update through Git, and its web interface may offer an application update function.

    Before every application update:

    1. Read the release notes.
    2. Take a database backup.
    3. Take an application-file backup.
    4. Record the current Git commit.
    5. Confirm sufficient disk space.
    6. Perform the update during a maintenance window.
    7. Test login, ticketing, billing, and cron afterward.

    Record the current commit:

    sudo -u www-data git -C "$ITFLOW_ROOT" rev-parse HEAD
    

    Check repository status:

    sudo -u www-data git -C "$ITFLOW_ROOT" status
    

    The working tree should normally be clean before updating.

    Check for remote changes:

    sudo -u www-data git -C "$ITFLOW_ROOT" fetch --prune
    

    Review the active branch:

    sudo -u www-data git -C "$ITFLOW_ROOT" branch --show-current
    

    Use ITFlow’s built-in updater when available and recommended by the project. Avoid blindly running git pull when the application reports local modifications or requires database migrations.

    After updating:

    apachectl configtest
    systemctl restart apache2
    sudo -u www-data php "$ITFLOW_ROOT/cron/cron.php"
    

    Test:

    • Administrator login
    • Client portal login
    • Ticket creation
    • Outbound email
    • Attachments
    • Invoice display
    • Domain monitoring
    • Certificate monitoring
  33. Monitor available storage

    Check storage:

    df -h
    

    Check inode usage:

    df -i
    

    Find large directories:

    du -xhd1 /var | sort -h
    

    Check ITFlow storage use:

    du -sh "$ITFLOW_ROOT"
    

    Check database size:

    mariadb -N -e "
    SELECT
        table_schema,
        ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb
    FROM information_schema.tables
    WHERE table_schema='itflow'
    GROUP BY table_schema;
    "
    

    Ensure backups, Apache logs, attachments, and database growth cannot exhaust the root filesystem.

  34. Configure log rotation

    Debian already rotates Apache and MariaDB logs, but your custom backup log should also be rotated.

    Create:

    nano /etc/logrotate.d/itflow-backup
    

    Add:

    /var/log/itflow-backup.log {
        weekly
        rotate 12
        compress
        delaycompress
        missingok
        notifempty
        create 0640 root adm
    }
    

    Test the configuration:

    logrotate -d /etc/logrotate.d/itflow-backup
    

    Additional security hardening

  35. Configure Fail2ban

    Enable and start Fail2ban:

    systemctl enable --now fail2ban
    

    Create a local SSH jail:

    nano /etc/fail2ban/jail.d/sshd.local
    

    Add:

    [sshd]
    enabled = true
    port = ssh
    backend = systemd
    maxretry = 5
    findtime = 10m
    bantime = 1h
    

    Restart:

    systemctl restart fail2ban
    

    Check status:

    fail2ban-client status
    fail2ban-client status sshd
    

    If SSH uses a custom port, replace port = ssh with that port number.

  36. Harden SSH

    Edit:

    nano /etc/ssh/sshd_config
    

    Once key-based access has been tested, consider:

    PermitRootLogin no
    PasswordAuthentication no
    PubkeyAuthentication yes
    PermitEmptyPasswords no
    MaxAuthTries 4
    X11Forwarding no
    

    Validate the configuration:

    sshd -t
    

    Reload SSH:

    systemctl reload ssh
    

    Keep the current SSH session open while testing a second login. A configuration mistake could otherwise lock you out of the server.

  37. Add HTTP security headers

    Enable the headers module:

    a2enmod headers
    

    Inside the HTTPS virtual host, add:

    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    

    Be careful with HSTS. Only enable includeSubDomains when every subdomain is served securely over HTTPS.

    Test and reload:

    apachectl configtest && systemctl reload apache2
    

    Check the headers:

    curl -I https://itflow.example.com
    

    Do not add a restrictive Content Security Policy without testing ITFlow thoroughly, because it may interfere with scripts, styles, editors, or embedded content.

  38. Restrict access by IP when appropriate

    For an internal-only deployment, restrict Apache to trusted addresses:

        AllowOverride All
        Require ip 198.51.100.10
        Require ip 192.0.2.0/24
    

    This may interfere with client portal access, email webhooks, payment integrations, remote staff, and API access.

    A VPN such as WireGuard or a properly configured identity-aware proxy is often more flexible than a fixed IP allowlist.

    Troubleshooting

  39. Website does not load

    Check DNS:

    dig +short itflow.example.com
    

    Check services:

    systemctl status apache2 mariadb --no-pager
    

    Check listening ports:

    ss -lntp | grep -E ':80|:443'
    

    Check the firewall:

    ufw status verbose
    

    Check Apache syntax:

    apachectl configtest
    

    Review errors:

    tail -n 100 /var/log/apache2/error.log
    journalctl -u apache2 -n 100 --no-pager
    
  40. Apache shows the default page

    Inspect virtual-host selection:

    apache2ctl -S
    

    Disable the Debian default sites when they conflict:

    a2dissite 000-default.conf
    a2dissite default-ssl.conf
    

    Enable the ITFlow sites:

    a2ensite itflow.example.com.conf
    a2ensite itflow.example.com-ssl.conf
    

    The exact filenames may differ.

    Reload:

    apachectl configtest && systemctl reload apache2
    
  41. HTTP 403 Forbidden

    Check ownership:

    namei -l "$ITFLOW_ROOT"
    

    Check Apache directory permissions:

    grep -R -n \
    "/var/www/itflow.example.com" \
    /etc/apache2/sites-available/
    

    The relevant directory block should include:

    Require all granted
    

    Correct application ownership when necessary:

    chown -R www-data:www-data "$ITFLOW_ROOT"
    

    Then:

    systemctl reload apache2
    
  42. HTTP 500 Internal Server Error

    Review:

    tail -f /var/log/apache2/error.log
    

    Check PHP:

    php -v
    php -m
    

    Check configuration syntax:

    php -l "$ITFLOW_ROOT/config.php"
    

    Check Apache modules:

    apache2ctl -M | grep -E 'php|rewrite|ssl|headers'
    

    Enable commonly required modules:

    a2enmod rewrite ssl headers
    systemctl restart apache2
    
  43. Database connection failed

    Verify MariaDB:

    systemctl status mariadb --no-pager
    mysqladmin ping
    

    Test the ITFlow database user:

    mariadb -u itflow -p itflow
    

    Review application settings without publicly displaying the password:

    sudo -u www-data grep -n \
    'db_host\|db_name\|db_user' \
    "$ITFLOW_ROOT/config.php"
    

    Check grants from a root database session:

    SHOW GRANTS FOR 'itflow'@'localhost';
    

    Expected privileges should be limited to:

    itflow.*
    
  44. SSL certificate issuance fails

    Confirm DNS:

    dig +short A itflow.example.com
    dig +short AAAA itflow.example.com
    

    An incorrect AAAA record can cause validation failure even when the IPv4 record is correct.

    Confirm port 80 is accessible:

    ss -lntp | grep ':80'
    ufw status
    

    Review Certbot logs:

    journalctl -u certbot --no-pager
    tail -n 100 /var/log/letsencrypt/letsencrypt.log
    

    Retry after resolving DNS and firewall problems:

    certbot --apache -d itflow.example.com
    
  45. Cron tasks are not running

    Check cron:

    systemctl status cron --no-pager
    

    Inspect the file:

    cat -A /etc/cron.d/itflow
    

    Check permissions:

    stat /etc/cron.d/itflow
    

    Verify the PHP path:

    command -v php
    

    Verify referenced scripts:

    ls -l "$ITFLOW_ROOT/cron/"
    

    Run a task manually:

    sudo -u www-data php "$ITFLOW_ROOT/cron/cron.php"
    

    Review cron logs:

    journalctl -u cron --since today
    
  46. Outbound mail is stuck

    Confirm the mail queue task exists:

    grep mail_queue /etc/cron.d/itflow
    

    Run it manually:

    sudo -u www-data php "$ITFLOW_ROOT/cron/mail_queue.php"
    

    Test the SMTP endpoint:

    openssl s_client \
        -starttls smtp \
        -connect smtp.example.com:587 \
        -servername smtp.example.com
    

    Common causes include:

    • Incorrect SMTP password
    • Wrong encryption mode
    • Provider requiring an application password
    • Outbound port 25 blocked by the VPS provider (Hint: Use Rad Web Hosting VPS to avoid)
    • Incorrect port 465 versus 587
    • Sender address not authorized
    • Expired OAuth or SMTP credentials

    Use port 587 with STARTTLS unless the mail provider specifies otherwise.

    Manual installation alternative

    The automated script is the recommended method. The following condensed procedure is useful when you require a custom Apache virtual host or need to understand the underlying deployment.

  47. Install the LAMP components

    apt update
    apt install -y \
        apache2 \
        mariadb-server \
        php \
        php-intl \
        php-mysql \
        php-curl \
        php-gd \
        php-mbstring \
        php-zip \
        php-xml \
        libapache2-mod-php \
        git \
        whois \
        certbot \
        python3-certbot-apache
    

    Enable modules:

    a2enmod rewrite ssl headers
    systemctl restart apache2
    

    These packages reflect the current official manual installation requirements.

  48. Create the database

    Generate a password:

    DB_PASSWORD="$(openssl rand -base64 36)"
    printf '%s\n' "$DB_PASSWORD"
    

    Store it securely, then open MariaDB:

    mariadb
    

    Run:

    CREATE DATABASE itflow
        CHARACTER SET utf8mb4
        COLLATE utf8mb4_unicode_ci;
    
    CREATE USER 'itflow'@'localhost'
        IDENTIFIED BY 'REPLACE_WITH_STRONG_PASSWORD';
    
    GRANT ALL PRIVILEGES
        ON itflow.*
        TO 'itflow'@'localhost';
    
    FLUSH PRIVILEGES;
    EXIT;
    
  49. Clone ITFlow

    Create the document root:

    mkdir -p /var/www/itflow.example.com
    

    Clone the application:

    git clone \
        https://github.com/itflow-org/itflow.git \
        /var/www/itflow.example.com
    

    Set ownership:

    chown -R www-data:www-data /var/www/itflow.example.com
    

    Set permissions:

    find /var/www/itflow.example.com \
        -type d \
        -exec chmod 775 {} \;
    
    find /var/www/itflow.example.com \
        -type f \
        -exec chmod 664 {} \;
    

    The official manual documentation clones the repository directly into the web root and grants ownership to www-data.

  50. Create the Apache virtual host

    Create:

    nano /etc/apache2/sites-available/itflow.example.com.conf
    

    Add:

        ServerName itflow.example.com
        DocumentRoot /var/www/itflow.example.com
    
        
            Options FollowSymLinks
            AllowOverride All
            Require all granted
        
    
        ErrorLog ${APACHE_LOG_DIR}/itflow-error.log
        CustomLog ${APACHE_LOG_DIR}/itflow-access.log combined
    
    

    Enable it:

    a2ensite itflow.example.com.conf
    a2dissite 000-default.conf
    apachectl configtest
    systemctl reload apache2
    
  51. Obtain the TLS certificate

    Run:

    certbot --apache \
        -d itflow.example.com \
        --redirect
    

    Enter a valid email address and accept the terms when prompted.

    Test renewal:

    certbot renew --dry-run
    
  52. Complete the browser installer

    Open:

    https://itflow.example.com
    

    Provide:

    Database host: localhost
    Database name: itflow
    Database username: itflow
    Database password: the generated password
    

    Create the primary administrator account.

    After setup, protect the configuration:

    chown www-data:www-data /var/www/itflow.example.com/config.php
    chmod 640 /var/www/itflow.example.com/config.php
    
  53. Create the cron file manually

    Create:

    nano /etc/cron.d/itflow
    

    Add:

    0 2 * * * www-data /usr/bin/php /var/www/itflow.example.com/cron/cron.php
    * * * * * www-data /usr/bin/php /var/www/itflow.example.com/cron/ticket_email_parser.php
    * * * * * www-data /usr/bin/php /var/www/itflow.example.com/cron/mail_queue.php
    0 3 * * * www-data /usr/bin/php /var/www/itflow.example.com/cron/domain_refresher.php
    0 4 * * * www-data /usr/bin/php /var/www/itflow.example.com/cron/certificate_refresher.php
    

    Set permissions:

    chown root:root /etc/cron.d/itflow
    chmod 644 /etc/cron.d/itflow
    systemctl restart cron
    

    This matches the task schedule generated by the current official installer.

Final verification checklist

Run:

systemctl is-active apache2
systemctl is-active mariadb
systemctl is-active cron
apachectl configtest
ufw status
curl -I https://itflow.example.com
certbot renew --dry-run
sudo -u www-data php /var/www/itflow.example.com/cron/cron.php

Then verify through the browser:

  • HTTPS is valid.
  • Administrator login works.
  • Multifactor authentication is enabled.
  • A test client can be created.
  • A test ticket can be opened.
  • Outbound email works.
  • Email-to-ticket works, when enabled.
  • Attachments upload successfully.
  • The client portal loads.
  • Domain and SSL checks run.
  • Database and file backups complete.
  • A backup has been copied off the VPS.
  • The master encryption key is stored securely off-server.
  • A restoration procedure has been tested.

Once those checks pass, the ITFlow server is ready for production onboarding.
Launch 100% ssd debian vps from $3. 19/mo!

Conclusion

You now know how to install ITFlow on Debian VPS.

Avatar of editorial staff

Editorial Staff

Rad Web Hosting is a leading provider of web hosting, Cloud VPS, and Dedicated Servers in Dallas, TX.
lg