How to Create a Custom Transport Script for Backups in WHM

This guide explains how to build a custom transport script for cPanel & WHM’s backup system. Custom transport scripts allow advanced users to send backups to destinations not supported by WHM’s built‑in options.

WHM custom backup scriptcPanel backup transportcustom backup destination

~5 min read • Updated Feb 15, 2026

1. Overview


cPanel & WHM allows advanced users to create custom transport scripts for sending backups to destinations that are not supported by default. These scripts integrate with WHM’s Backup Configuration interface:


WHM » Home » Backups » Backup Configuration


Warning: Custom transport scripts are intended only for advanced users. If you prefer simpler options, WHM already supports:

  • Local directory
  • Amazon S3™
  • Backblaze B2
  • FTP
  • Google Drive™
  • Rsync
  • S3 Compatible
  • SFTP
  • WebDAV

2. What Is a Custom Transport Script?


A custom transport script is a user‑created script that handles file transfers for a custom backup destination. You provide the script’s absolute path in the Script field when selecting the Custom destination type in WHM’s Additional Destinations section.


3. Script Operation Rules


Your script must follow these rules:

  • The script runs once per command.
  • li>The script cannot store state between commands.
  • Connections are not reused; each command triggers a new connection.
  • The system passes arguments to the script in this order:
1. Command name
2. Current directory
3. Command-specific parameters
4. Host
5. Username

Password is passed through the environment variable PASSWORD.


4. Required Script Commands


Your script must implement the following commands:

CommandDescriptionParameters
chdir Changes directory on the remote destination. $path
delete Deletes a file on the remote destination. $path
get Downloads a remote file to the local server. $dest_root_dir, $dest_file, $local_file
ls Lists files (same as ls -l). $path
mkdir Creates a directory on the remote destination. $path
put Uploads a local file to the remote destination. $dest_root_dir, $dest_file, $local_file
rmdir Deletes a directory recursively. $path

Warning: Always verify paths before deleting. Passing / will cause severe system damage.


5. Script Structure


5.1 Required Perl Modules

use strict;
use warnings;
use Cwd qw(getcwd abs_path);
use File::Spec;
use File::Copy;
use File::Path qw(make_path remove_tree);
use autodie qw(:all copy);

5.2 Command Hash

The script must define a hash that maps commands to subroutines:

my %commands = (
    put    => \&my_put,
    get    => \&my_get,
    ls     => \&my_ls,
    mkdir  => \&my_mkdir,
    chdir  => \&my_chdir,
    rmdir  => \&my_rmdir,
    delete => \&my_delete,
);

5.3 Argument Handling

my ( $cmd, $local_dir, @args, $host, $user ) = @ARGV;
my $password = $ENV{'PASSWORD'};

usage() unless exists $commands{$cmd};

6. Command Implementations


6.1 put — Upload a File


sub my_put {
    my ( $local, $remote, $host, $user ) = @_;
    my $password = $ENV{'PASSWORD'};

    $remote = convert_path($remote);

    my ( undef, $dir, undef ) = File::Spec->splitpath($remote);
    make_path($dir) unless ( $dir and -d $dir );

    copy( $local, $remote );
    return;
}

6.2 get — Download a File


sub my_get {
    my ( $remote, $local, $host, $user ) = @_;
    my $password = $ENV{'PASSWORD'};

    $remote = convert_path($remote);
    copy( $remote, $local );
    return;
}

6.3 ls — List Files


sub my_ls {
    my ( $path, $host, $user ) = @_;
    my $password = $ENV{'PASSWORD'};

    $path = convert_path($path);
    my $ls = `ls -al $path`;
    $ls =~ s|^total[^\n]*\n||;

    print $ls;
    return;
}

6.4 mkdir — Create Directory


sub my_mkdir {
    my ( $path, $recurse, $host, $user ) = @_;
    my $password = $ENV{'PASSWORD'};

    $path = convert_path($path);
    make_path($path);

    die "Failed to create $path" unless -d $path;
    return;
}

6.5 chdir — Change Directory


sub my_chdir {
    my ( $path, $host, $user ) = @_;
    my $password = $ENV{'PASSWORD'};

    $path = convert_path($path);
    chdir $path;

    print get_sub_directory( getcwd() ) . "\n";
    return;
}

6.6 rmdir — Remove Directory


sub my_rmdir {
    my ( $path, $host, $user ) = @_;
    my $password = $ENV{'PASSWORD'};

    $path = convert_path($path);
    remove_tree($path);

    die "$path still exists" if -d $path;
    return;
}

6.7 delete — Delete File


sub my_delete {
    my ( $path, $host, $user ) = @_;
    my $password = $ENV{'PASSWORD'};

    $path = convert_path($path);
    unlink $path;
    return;
}

7. Basic Error Checking



usage() if ( @ARGV < 2 );

sub usage {
    my @cmds = sort keys %commands;
    print STDERR "This script implements a custom backup destination.\n";
    print STDERR "Required arguments: cmd, local_dir, cmd_args\n";
    print STDERR "Valid commands: @cmds\n";
    exit 1;
}

8. Execute the Command


$commands{$cmd}->(@args);

Conclusion


Custom transport scripts give advanced users full control over how backups are transferred to remote destinations. By following the required structure and implementing all mandatory commands, you can integrate any custom storage system with WHM’s backup framework.


Written & researched by Dr. Shahin Siami