Alex Ivaylov – a web developer http://www.alex.bg Alex BG Web Developer Blog Sat, 10 Aug 2024 13:17:17 +0000 en-US hourly 1 https://wordpress.org/?v=4.8.8 About Zend http://www.alex.bg/2018/12/about-zend/ Sun, 16 Dec 2018 14:16:57 +0000 http://www.alex.bg/?p=950 PHP was created in 1994 by Rasmus Lerdorf. He is still the lead of the PHP group today. It was a template layer for his software that was written in C. He open sourced it and people loved it. More and more functionality was added over the years and the language grew significantly from its original idea.

In the years 1997-1999 two students named Zeev Suraski and Andi Gutmans re-wrote the core of PHP and released it as version 4. This new core that they wrote was named the Zend Engine. “Zend” comes from their names. This is still the main engine that operates inside PHP today. In 1999 they founded the company Zend technologies. In the years between 2000 and 2010 Zend technologies receives a number of findings from various investors.

Over those years, they are the main contributor to PHP. They call themselves “the PHP company”. Their business model is offering paid PHP products and services to enterprise-class customers while helping and grow the open source PHP community.

They also created a number of products:

Zend Framework – a modular PHP MVC framework targeted towards the enterprise-class. It brings the Java enterprise patterns to PHP. It consists of professionally written packages. Those packages are (mostly) independent and managed by composer.

Zend Studio – a commercial PHP IDE based on Eclipse. Specially made for Zend Framework development. They also contribute the PHP developer tools (PDT) to Eclipse (IDE) foundation which is available for free. In my opinion Zend Studio still offers the best debugging capabilities today but not the best development capabilities (phpStorm is the market leader IDE today).

Zend Server – a custom PHP stack with a lot of extra goodies. Those goodies are Z-ray, better debugging, better event reporting, better monitoring, automatic deployment, etc. This is a fantastic product. When I discovered it I was wander how have I lived without it before.

Zend Guard – was a PHP obfuscator. Unfortunately it is now discontinued.

I have to say that I love their products. Zend Framework was the first framework I tried in 2011 and I was impressed how much easier it was than vanilla PHP. This must have been version 2 which had the Zend CLI tool for creating modules, controllers and other boilerplate code. At that time Zend Framework was the market leader.

In 2015 a company named Rogue Wave Software acquires Zend Technologies. Shortly after that Andi Gutmans leaves the company and gets a job at AWS.

This is now a tough time for Zend because more and more PHP frameworks are popping up from everywhere and they are stealing market share from Zend. At the same time NodeJS showed up which is also stealing market share from PHP.

The current market leader in PHP frameworks is Laravel. It stole the show because it is much easier to learn. It is SOLID based with a very good Inversion of Control (IoC) container that provides automatic constructor-based dependency injection. While the core component of ZF – the Zend Service Manager uses the service locator (anti)pattern. Laravel provides these facades that offer almost all of the functionality a modern web app would need and they are very easy to learn. However Laravel is not enterprise-grade. It doesn’t force modules on the user like Zend. Laravel is easier to get into and to learn. It has better documentation.

Zend Framework version 3 was released in 2016 but some aspects of it are still unfinished in 2018. It still doesn’t have a CLI tool and other things. If you look at a tutorial for ZF3 you will see you have to create like 10 folder structures manually in order to make a module. At the same time Zend Framework being an enterprise framework – they can’t break existing code so they have to stay backwards compatible. This means they can’t change much. For that reason, they decided to create a new framework to try to get some market share back from Laravel. They called the new framework Zend Expressive. This new framework takes all the good things from Laravel. But it does it the Zend way – everything is decoupled into separate composer packages. You also have modules. Expressive doesn’t force us to use their service manager or their routing component – we can use others. Expressive provides only the framework glue which holds those components in place along. It also provides the middleware which is something we see in Laravel. However in expressive almost everything is middleware while that’s not the case with Laravel.
At the same time I get the feeling that Rogue Wave are reducing the resources these guys get. There are 2 people that work on the Zend frameworks and another 2 people that work on the Zend engine. The Zend product portfolio becomes outdated. Zend studio doesn’t support version 3 of the framework or Expressive. Zend server doesn’t support them either. Documentation is poor. The CLI tool works for Expressive but doesn’t work for Zend Framework 3 (aka Zend MVC). At the same time Laravel and NodeJS keep on getting better.

The reason why I am writing this is because in October, Zeev and the other 3 people that work fulltime on those Zend products announced that Rogue Wave has decided to move resources away from all the Zend products apart from Zend Server. These are very bad news for PHP…

Although we did see PHP 7.3 recently, we are not likely to see PHP 8 any time soon if this is true. We are expecting JIT in PHP and JS-style asynchronous support in Zend Frameworks (via Swoole).

Rogue Wave were quick to assure us they will continue their support for PHP but their actions speak otherwise. If they do this – PHP is left without a commercial backer. It will be an entirely community-run project. Which means things will happen a lot slower (if they happen at all).

It’s now December and I have been watching these guys – they have been committing as usual and I really hope things won’t change..

So what should Rogue Wave do?

I think that they have the classic problem of business people and developer people being disconnected and not understating each other.

They shouldn’t look at the numbers directly – now they see “Zend Server sells best so lets kill everything else”. However, what they forget is that Zend server is tightly coupled to everything else. It links to Zend Studio, PHP (Zend Engine) and the Zend Framework. Without all of these – there will be no Zend Server.

They should invest into updating and finishing those great Zend products.

After that invest in making them more accessible. Laravel offer video lessons (known as Laracasts) that cost $9 per month. Zend offer live training that costs $1000 per session. May be look into a cheaper option considering the market has changed? How difficult would it be to record those live training sessions and offer them cheaper?

Back in the day, Zend tried to do an alternative to AWS and Google Cloud Platform. I am not sure why they failed. It probably wasn’t finished. However, both AWS and GCP lack good PHP support. Zend would have been perfect for this service. And with 80% of the web running on PHP – why would anyone go to GCP where they only support PHP 5?

I can’t believe they hold the keys to a technology that runs 80% of the web and they want to kill it because they don’t know how to profit from it.

I have worked with Zend consultants in the past. The first time I approached them they just didn’t understand the requirements. In the end they said they can’t deliver and redirected me to another company. At the same time they sold me Zend Server. And when I went to their website and I tried to buy it – I couldn’t. I had to contact the help desk of Rogue Wave where they eventually took my money.

That’s the other problem – make those products more accessible. I am sure “the PHP company” can put a “buy now” button instead of forms where they take my details and then some sales representative contacts you (or doesn’t contact you like in my case).

If anyone at Rogue Wave or Zend is reading this and wants to talk to me – feel free to click the “Contact me” button above.

]]>
Show PHP server2server connections in Fiddler (part 2) http://www.alex.bg/2018/12/show-php-server2server-connections-in-fiddler-part-2/ Sat, 15 Dec 2018 01:39:59 +0000 http://www.alex.bg/?p=944 This is the second part of my original article “Show IIS PHP server2server connections in Fiddler”. Here I will be talking about the PHP’s CURL extension.

However there are differences in this scenario:

We are not using IIS – we are using Zend Server on my local MacOS machine (Zend’s custom LAMP stack with extra goodies). However standard PHP installation should be the same. If you are using docker there will be differences with your network stack (the IP address below should be different) but you probably already know that.

We are not using Fiddler on Windows – we are using Charles on MacOS. However this is irrelevant because both Charles and Fiddler are very, very similar. I prefer Fiddler but since I am on a Mac – I am using Charles. Both proxies listen on port 8888 and show you the contents of the http requests that go through.

As mentioned in part 1 there is no universal way to tell PHP “use this proxy server for everything”. There is no universal proxy setting in php.ini. For the curl component we can set these runtime options:

curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1');
curl_setopt($ch, CURLOPT_PROXYPORT, 8888);

This will work fine with plain http but. But it would give you SSL handshake failures for HTTPS. This is expected as the http proxies use their own Certificate Authorities (CAs) to cheat the system that the certificate they present is valid. However on MacOS libcurl and php-curl don’t use the system CAs so we need to tell them to use the CA root certificate we want.

To get the Charles CA root certificate, click Help > SSL proxying > Save Charles root certificate. Save the new pem file somewhere on your system. After this we set the .pem file as the CURLOPT_CAINFO option:

curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, '1L');
curl_setopt($ch, CURLOPT_SSL_VERIFYSTATUS, 0);
curl_setopt($ch, CURLOPT_CAINFO,'/usr/local/zend/bin/charles.pem');

This should show you the server2server connections in Fiddler/Charles. Use this on dev environments only.

PS: Obviously there is no way to intercept pinned SSL sockets.

]]>
Installing imagick on Windows http://www.alex.bg/2017/08/installing-imagick-on-windows/ Wed, 30 Aug 2017 19:24:42 +0000 http://www.alex.bg/?p=885 A few years ago i wrote a post moaning about how difficult it is to install imagick on Centos. Well i have to say that was a breeze compared to installing it on Windows..

As we know it is a PECL extension. On the page we see this “This extension requires ImageMagick version 6.5.3-10+ and PHP 5.4.0+.”.

But what they are not saying there is that you should not use the official windows binaries that you get from imagemagick.org. In fact they are saying the opposite.


When I installed the official binaries together with the PECL extension I got low level crashes of php-cgi.exe. There wasn’t much information on to why.

After that I noticed that on the bottom of the download page of imagemagick that they require Visual C++ 2013 while the php PECL extension and PHP itself require Visual C++ 2015 (VC14). So that explained the crashes.

Just as I was thinking about compiling it myself – I found this great article. The guy has went through the same pain as me.

In that article there is a link to PECL dependencies folder. The link is http://windows.php.net/downloads/PECL/deps# in there there is a different build of the imagick runtime. So I downloaded that and uninstalled the official imagick binaries.

I then added the environmental variables as explained in that article and boom – it started working.

]]>
Show IIS PHP server2server connections in Fiddler http://www.alex.bg/2017/04/show-iis-php-server2server-connections-in-fiddler/ Mon, 24 Apr 2017 19:56:02 +0000 http://www.alex.bg/?p=872 So I am running PHP on Microsoft IIS web server. I have to open some sort of a socket to a remote host. I would like to inspect that socket because I would like to see the data being exchanged between PHP and the remote web service. In our case you could call this a server to server connection. But remember that as far as the remote web service is concerned PHP is acting as a client. Fiddler is an irreplaceable tool. I have been using it for years and I really can’t imagine my life without it.

Fiddler itself is a web debugging proxy. When it is started, it creates a proxy service (by default on port 8888). It also configures Windows and the browsers to automatically route the traffic through that proxy but only for the current user. After that you see a list of all http(s) requests that have went through the proxy and you can click on one to view all its of its parameters. As a bonus it can render XML, JSON or HTML. This is priceless.

However, if you are on a Windows Server box with PHP running on IIS. It is highly likely that IIS is running under a different user so server2server connections will not show in fiddler. Do not try to configure the IIS settings via the IIS console or web.config as that will not work as those are specific for .NET apps and do not affect PHP. Remember PHP is running in FastCGI mode.

What we need to do is we need to tell PHP to use the proxy server. I was surprised that there are no Proxy settings in php.ini. The recommended way to do this is using the stream_context_set_default() function.

$stream_default_opts = array(
'http'=>array(
'proxy'=>"tcp://127.0.0.1:8888",
'request_fulluri' => true,
)
);

stream_context_set_default($stream_default_opts);

As with most of the other PHP environment setters – this needs to be at the start of the PHP file. If you would like this to be global server setting, you can save the above snippet in a .php file on your server and then you could specify it to be prepended (i.e put in the start) of every other PHP file automatically in php.ini like this:

auto_prepend_file = "/path/to/proxySetter.php"

To make things more complicated, this method does not apply to all connections. If this doesn’t work – you will need to research how to set proxy for whatever objects you are using. In my case where I am using the SoapClient class, I have to explicitly specify the proxy host and port:

$wsdl = 'https://example.com/path/myWebService.wsdl';
$options=array(
'trace' => 1,
'exceptions' => 1,

'proxy_host'=>'127.0.0.1',
'proxy_port'=>'8888',

);

try
{
$client = new SoapClient($wsdl, $options);
}
catch (Exception $e)
{
echo 'The web service call failed with error "';
echo $e->getMessage();
echo '"';
exit();

}

If all of these fail (or you are too lazy) you could try a program called Proxifier but I can’t guarantee it will work.

Hope this will help someone out there 🙂

]]>
Copy Mac OS X installation from physical to virtual machine http://www.alex.bg/2016/04/copy-mac-os-x-installation-from-physical-to-virtual-machine/ Sun, 10 Apr 2016 14:11:07 +0000 http://www.alex.bg/?p=861 I am writing this guide because I couldn’t find a working solution to the problem where you might want to clone a complete installation of Mac OS X on a physical hardware Mac to a Parallels virtual machine. In order to do that you would need to take full DMG image of the whole hard drive. Most solutions out there suggest that Parallels should automatically prompt you to conver the DMG file to its .HDD format when you add it to the VM, so you should try that first. However, that method did not work for me.

Before trying this method, you should also try to take a complete Time Machine backup and then try to restore it on to the VM. If time machine backup / restore method doesn’t work, follow this guide. Unfortunately it didn’t work for me either. Before trying this method you would need an external hard drive that is bigger in size than the disk space you have used. This guide was written assuming that you will be taking the installation of an old Mac and putting it inside a VM on your new mac. However, it should also work if you want to reinstall OS X on the same box (but I haven’t tested it this way).

1) Plug the external hard drive into the old mac
2) Turn on the old Mac while pressing multiple times Cmd + R during start up, in order to enter the start up recovery options
3) Choose Disk Utility
2) Take an image of the whole hard drive and save it as a .DMG file on the external hard drive
3) Once you have your DMG on the external hard drive, unplug the hard drive, restart the old mac and plug in the hard drive into your new mac.
4) Copy the DMG file into a folder somewhere on to your new mac (For example in “Documents”)
5) Mount it (by double clicking the copied DMG file). Let the system verify if it can open the image before it mounts it (dont skip verification – it might take some time depending on the size of your drive)
6) Optimal: Browse the files to make sure you are happy all your files are there
7) Unmount it
5) On your old mac: open parallels (If both your old mac and new mac have the exact same version of Mac OS X, you should use your new mac instead)
6) Create a new VM installing Mac OS from the recovery partition
7) You should now have a virtual machine which has a clean, working version of Mac OS that is exactly the same as the OS X version on your old mac.
8) If you used your old mac, copy the VM to your new mac (Documents/Parallels). On the new mac choose “add existing VM” and add the clean Mac OS from the old mac
10) Open the settings of the VM
12) Click the Add (“+”) sign and choose hard drive.
13) Create a new blank hard drive which is bigger in size than the disk space used in the the DMG file and make sure it is expandable (dont worry if your old hard drive is bigger than your new one – just make sure you have enough space to cover the used disk space)
14) Turn on the VM and go into the clean Mac OS installation
14) Open the Disk Utility app
17) Click File, Open Disk Image
18) Go to the Parallels shared folders
19) Find your copied DMG file and open it
20) You should now have your old hard drive mounted into your clean installation VM
21) Unfortunately, doing a recovery to the empty disk from the disk utility did not work for me here. For that reason I went out and looked for a 3rd party solution. I used Carbon Disk Cloner. You can get a free trial from their official website bombich.com
22) Install Carbon Disk Cloner inside your VM and open it. Choose the source to be your mounted disk image and destination to be you blank hard drive
23) Click “Clone”
24) Once the clone completes, turn off your VM
25) Go into the VM settings and delete the clean installation hard drive without moving files to trash (by clicking the “-” sign). Make sure you leave only what was the blank HDD
26) Boot up the machine – you should now have your old installation working
27) Install parallels tools (from the Parallels Action menu on the top)
28) Optimal: If you are happy that everything is working you should backup up your VM (you can delete the copy you made in step 8)
29) Optimal: After you have backed up your VM you can delete the clean install OS hard drive to free up disk space (go to Documents/Parallels/ and right click on the VM, select “Show Package contents”)
30) Optimal: Delete the DMG file to free up space

]]>
dynamically manipulate a jQuery Mobile Control Group http://www.alex.bg/2015/05/jquery-mobile-control-group-populate-and-change-dynamically/ Mon, 18 May 2015 18:26:28 +0000 http://www.alex.bg/?p=821 I could not find a working answer to the question How to dynamically populate a control group in jQuery Mobile and programatically change its selected value in the search engines, so I though I would write this quick article.

Now, lets say your HTML looks like this:


<fieldset data-role="controlgroup" data-type="horizontal" id="myContrGrp">
<input name="favFruit" id="favFruit-f1" value="apples" type="radio" />
<label for="favFruit-f1">Apples</label>
<input name="favFruit" id="favFruit-f2" value="bananas" type="radio" />
<label for="favFruit-f2">Bananas</label>
<input name="favFruit" id="favFruit-f3" value="strawberries" type="radio" />
<label for="favFruit-f3">Strawberries</label>
</fieldset>

The first thing I am gonna do with this is I am going to bring in a relation between the VALUE and the ID of the inputs. So something like this is better:


<fieldset data-role="controlgroup" data-type="horizontal" id="myContrGrp">
<input name="favFruit" id="favFruit-apples" value="apples" type="radio" />
<label for="favFruit-apples">Apples</label>
<input name="favFruit" id="favFruit-bananas" value="bananas" type="radio" />
<label for="favFruit-bananas">Bananas</label>
<input name="favFruit" id="favFruit-strawberries" value="strawberries" type="radio" />
<label for="favFruit-strawberries">Strawberries</label>
</fieldset>

Now that there is a link between the ID and the VALUE attributes, we can do something like this:

 


//the value we want to set the control Group to
var favFrt = 'strawberries';
var favFrtSelector = '#favFruit-' + favFrt;
//add the checked="checked" attribute to the appropriate INPUT
$(favFrtSelector).attr('checked', 'checked');
//refresh the control group
$("#myContrGrp").enhanceWithin().controlgroup("refresh");

 

The above concludes how to change the selected option of control group that already exists and has all its HTML pre-set.
If you need to dynamically populate a jQuery mobile group before you change it, follow these steps.

Create an empty fieldset:


<fieldset data-role="controlgroup" data-type="horizontal" id="myContrGrp"></fieldset>

And use something like the following:


//create an array with all your options:
var cgOpts = ['apples', 'bananas', 'strawberries'];
//create your innerHTML container var:
var innerHTML = '';
//iterate through your array:
for (var i=0;i<cgOpts.length;i++)
{
//current fruit is cgOpts[i]
innerHTML += '<input name="favFruit" id="favFruit-'+ cgOpts[i] + '" value="'+ cgOpts[i] + '" type="radio" /><label for="favFruit-'+ cgOpts[i] +'">'+ cgOpts[i] + '</label>';
}
//now that you have your innerHTML - append it to the jQuery Mobile control group like this:
$("#myContrGrp").controlgroup("container").append(innerHTML);
//and refresh the jQuery Mobile control group like this:
$("#myContrGrp").enhanceWithin().controlgroup("refresh");

 

Also, I couldn’t find out how to disable a jQuery mobile control group programatically. The native plugin has a “disable” method as well as a disable option but unfortunately they both don’t work.

What I found did work was adding the disabled=”disabled” attribute to the inputs:


$("#myContrGrp input").attr('disabled', 'disabled');

Remember to refresh after this.


So there you have it. Feel free to copy/paste whatever you like.
Note this was done with jQuery Mobile version 1.4. It might change in future versions.

]]>
Enabling PHP in a single directory http://www.alex.bg/2015/03/enabling-php-in-a-single-directory/ Tue, 10 Mar 2015 18:05:44 +0000 http://www.alex.bg/?p=808 I am writing this because I couldn’t find any information on how to enable PHP for a single directory.

Let’s say we have a website example.com, whose documentRoot is in /var/www/vhosts/example.com. I want PHP disabled for the entire website apart from the directory /myApp.

Let’s say the configuration of the vhost is something like this:


<VirtualHost *:80>
ServerAdmin me@example.com
ServerName example.com

DocumentRoot /var/www/vhosts/example.com

<Directory /var/www/vhost/example.com>
Options -Indexes
AllowOverride All
Order allow,deny
allow from all

#disable PHP:
php_admin_value engine Off
</Directory>
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined

As you can see we have turned off PHP globally for the whole website.

One thing I found by trail and error is that if you change engine Off to engine On in the above example, PHP will still not work.

That is the case in the current Ubuntu (Debian) Apache 2 with mod_php 5. I dont know if this is a feature or a bug.

If you want to switch on the PHP engine, try 1 instead of On.

This works:

php_admin_value engine 1

So now we need to figure out how to override the flag just for the /myApp directory.

Overriding with <Directory> does not work. What I found is that overriding with <Location> does work. That’s probably because <Location> is called last (after <Directory> and .htaccess).

So here is how to override the PHP engine flag directive for one single directory:


<VirtualHost *:80>
ServerAdmin me@example.com
ServerName example.com

DocumentRoot /var/www/vhosts/example.com

<Directory /var/www/vhost/example.com>
Options -Indexes
AllowOverride None
Order allow,deny
allow from all

#disable PHP:
php_admin_value engine Off
</Directory>
<Location /myApp>
php_admin_value engine 1
</Location>
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined

I haven’t tried it with .htaccess because I don’t use it any more.

]]>
Upgrading PHP? http://www.alex.bg/2014/01/upgrading-php/ Mon, 27 Jan 2014 21:17:56 +0000 http://www.alex.bg/?p=794 If you think that by upgrading to the latest version of PHP you will be more secure than before you might be wrong. Some security features such as magic quotes GPC and safe mode have been removed as of 5.4.

In HTTP all of the communication coming into a web app from the outside world happens via one of the 3 channels (Get, Post and Cookie). The magic quotes GPC feature automatically escapes the input.

In the newer versions of PHP it has been removed and now it is up to the developer to escape the user input accordingly. Problem is that newbie developers might not know that they have to do that. Other problem is with old legacy code which makes use of magic quotes. Businesses simply can not afford to re-code web applications according to the new standards. Other problem is that the resources available those learning PHP in many cases are out of date and contain code snippets and examples which are potentially vulnerable. That is why it is very important that only seasoned developers who code php the right way are hired for business critical web applications. Of course that will not be the low-tariff developers who cant even speak English.

The other removed feature “Safe Mode” was a handy setting which lets sys admins disable potentially dangerous PHP functionality used by exploits and rootkits (such as the functions which let php run custom code on the system shell (system(), shell_exec(), “, etc). Safe mode also prevents PHP from writing files to the file system. I would actually recommend that safe mode is kept on by default and only disabled if really needed.

The good news is that even though 5.3 is end of life – it still receives critical security updates. So for now you can secretly continue to run 5.3 on your server (which is recommended if you provide shared web hosting and you don’t need the new features). However, we don’t know how long that will continue to be the case. Also remember that there’s the option of running multiple versions of PHP on the same server (as FastCGI) if you are dying for traits or the new password hashing.

]]>
Kitchens Website http://www.alex.bg/2013/11/kitchens-website/ Sat, 23 Nov 2013 20:17:05 +0000 http://www.alex.bg/?p=785 I’ve just finished working on this website for my uncle in Bulgaria who has a kitchens company. Check it out:

http://kitchens.bg/en/

]]>
Copying a LAMP web application http://www.alex.bg/2013/06/copying-a-lamp-web-application/ Wed, 12 Jun 2013 23:29:47 +0000 http://www.alex.bg/?p=769 One of the most common things a web professional does is copying a website from one web server to another. Whatever the reason – deploying, debugging, upgrading – it doesn’t matter. A few years ago when I started working with the web – I was using FTP. The more I was digging into the Linux Command Line the less I was using things like FTP until the point I completely stopped using it. You will see how quicker it is doing a copying via SSH compared to downloading all files via FTP and then uploading them again. The 5 main steps you need to take when copying a website are described below:

1. Prepare the new server

If you are using a control panel such as CPanel, Plesk, Kloxo, etc – it is most likely that your environment is automatically prepared when you create the website from the control panel interface because it uses pre-defined templates to create all websites so you don’t need to do any of the preparation here.

Before you can copy a website from server A to server B – you need to ensure that server B is ready. That means that the virtual host is configured properly in Apache, you have a document root folder for the website and Apache is serving it correctly. An easy way to test this is to edit the hosts file on your system and make it point to the IP address of server B. Search google on how to do that. To ensure that Apache is serving the right document root – you could create a test.html file and then try to request it from your browser http://example.com/test.html

Also make sure that server B is matching the system requirements of the web application. Popular CMSes such as WordPress, Joomla, etc have their system requirements on their websites.

Some web systems might require specific Apache options to be set in a specific way and/or specific modules to be enabled – for example if the system uses mod_rewrite – you will need to enable it and if the system also uses .htaccess to specify the rewriting rules – you will need to set the vhost config to have the directory’s AllowOverride to either ‘options’ or ‘all’ (but not ‘none’).

On the PHP side of things – you need to make sure that all the required PHP extensions are installed (that should be specified in the system requirements document).

2. Copy files

Once you are happy that the environment on server B is ready for the website to be copied you can continue.

2.1 The first step before you start copying the website is to suspend it. So if the CMS or the Shopping Cart has an option to close the site – you need to do it now. The reason for that is because you don’t want orders placed (or users registered) on your website between the times DNS has switched to the new server to be lost.
2.2. First you need to change the current directory the directory of your website:

cd /var/www/vhosts/alex.bg/httpdocs/

2.3.Then you need to use the tar utility to create the archive:


tar cfz mywebsite.tar.gz .

When you type the command – it might take some time to create the archive – so be patient.
Once the command has finished – you should see the root@serverA… place to type again.
Make sure that no errors are displayed.
2.4. Open a new SSH window to server B.
2.6. cd to the directory of where the new website will be hosted:

cd /var/www/vhosts/alex.bg/httpdocs/

If you have any files which are not needed by the website in there (like a test.html file) – delete them(using “rm ” command).
2.7. Download the archive from Server A:

wget http://example.com/mywebsite.tar.gz

You should see a file download.
Again – wait for it to finish and make sure no errors are displayed.
2.8. Once the download is complete – extract the files:

tar xf mywebsite.tar.gz

2.9. Once the extract is complete – delete the archive(do this on both servers A and B):

rm mywebsite.tar.gz

Congrats – you have copied all the files from your old server to the new one.

3. Copy database
3.1 The database information is stored into a configuration php file. In most cases it is something like config.php, configuration.php(in Joomla), wp-config.php (in wordpress), etc.
3.2. FTP into your new server and find the config file in there (or use “ls” to view the files).
3.3. After that open the configuration file and look for Database Name, Database User and Database Password variables (constants in WordPress).
3.4 On server A – login to your database manager (phpmyadmin) via the control panel or via the PMA url if you have installed it yourself (using the username/password from above step).
3.5 On the top left click on “Databases”, then click the database name.
3.6. Click “Export” on the top
3.7. Leave it as “quick” and click the “export” button
3.8. A .sql file should download – save the file to your computer
3.9. Logout of phpMyAdmin on Server A and login to phpMyAdmin on server B (preferably using a root account)
3.10. Again, click on “databases” on the top left
3.11. In the “Create new database” section enter the name of the database exactly as the way you had it in 3.3.
3.12. After your database has been created – click on it’s name
3.13. Click import
3.14. Click “browse” and find the .sql file you just downloaded from the other server
3.15. Click the “Import” button and wait for the file to import. Your browser might look like frozen but wait for it (it might take hours depending on your network speed and size of the .sql file).
After it completes – you should see a list of all the tables in the database on the left.
Again – make sure no errors are displayed.
3.16. After the import is complete – create a new user for this database
3.17. Click “users” (or “Privileges” in the old phpMyAdmin) on the top of the screen
3.18. Click add new
3.19. Now you could either specify the old user/password you have from step 3.3. or enter a completely different user/password combination. Make sure that host is set as “localhost” and you have not assigned any global server rights to the user. I would recommend using a new user/pass combination because it is always good to change credentials.
3.20. If you created a new user/password – update the config file with them, save it and then upload it to the server B. If you used the old user/pass – skip this step.
3.21 Go into the “users” section of the database again and go into the “edit user” screen for the user you just created.
3.22 From the drop down with database names find the one you just created and submit the form
3.23. Assign only the privileges needed for the web system to work (if you are no sure – you could have a look at Server A to see what privileges the user has to the database there).

4. Test

At this stage your old website should be working on your new server.

Make sure the hosts file is pointing to the new server and load the website. If you closed the web system – open it again. Do not open the website on Server A – only the one on server B.

Test everything – if you see any errors – search Google.

5. Change DNS
Once you are happy that your website works on the new server as intended – change the DNS of the domain name. Look for A records. Where you see the IP address of Server A, change it to the IP of Server B (note this might effect services different than web such as Email, so make sure those are set up on the new server properly too).

After DNS switches your visitors should be served by the new server. If you are intending to close your old server’s hosting account make sure you cancel it properly (using the system of the host provider) because some hosts do auto-renew and charge your card without any notice (bad practice in my opinion).

]]>