Virtual servant for WordPress with Git

Last update: 26 of April of 2020

Table of contents

If sometimes you have considered to contribute to WordPress, many forms exist to do it. From we raised the first steps for it with the creation of a virtual machine here in which to synchronize WordPress with its Git, so that it always is.

This configuration is correct if you want to have a development version of WordPress that can be useful to develop and to prove your plugins or themes.


A first that we will need to mount development system is an account of Git and a machine where to install the version of development of WordPress.


We recommended to you to create an account in Github directly, where is repositorio main of WordPress. From this we will create our system of tests and development.


In principle the system in any type of machine, or a virtual one can be mounted, a Docker or a VPS. In this case, so that it is within reach of all and without minimum requirements, we will use a VPS of any supplier. If it interests to you, you can find some VPS for developer.

In this case we have used a machine with 1 CPU, 2 GB of RAM and 10 GB of disc SSD. With half of resources it would have to work without trouble. What we are going to show is based on an Ubuntu 18 LTS. We will use PHP 7,4, MariaDB 10,4 and other services.

To do fork of WordPress de Github

The first a to do is to enter the Github de WordPress and to beat in the Fork button that is in the right corner superior.

Virtual servant for WordPress with Git
We beat in the Fork button to create a copy in our account.

This ends up to you creating something of the style to

We create a machine

As it commented before, we can create a machine anywhere. It can be in a VPS of a company of hosting, or can be a Docker that we have in the premises. Also there are options to use the own system of Vagrant. In this case we will create the machine from zero with our moderately customized configuration.

As operating system of this example we are going to use Ubuntu 18 LTS.

Update of the system

First that we will do it is to bring up to date the system.

apt - and update && apt - and upgrade && apt - and dist-upgrade && apt - and autoremove

Once this, we will put in hour the system.

timedatectl UTC set-timezone timedatectl set-NTP on

In addition, we will install some basic tools.

apt - and install software-properties-common curl vim unzip

Basic servant of Data

For the data base we are going to use MariaDB 10.4; this version has a great change as far as the system of keys with respect to its version predecessor, reason why, to avoid problems, we are going to use this last version.

First it will be to unload and to install the basic servant of data.

curl - foll | I sweat bash - s -- --mariadb-server-version= " mariadb-10.4€ apt - and update apt - and install mariadb-server mariadb-client systemctl restart mysql.service

Now that we have the data base installed, we will execute the configuration system for the first time.


Here to some options and questions will occur us. It prepares your password of root of the data base and keeps it well.

For Enter current password root (to enter for none): Switch to unix_socket authentication [Y/n] n Change the root password? [Y/n] and Remove anonymous users? [Y/n] and Disallow root login remotely? [Y/n] and Remove test database and Access to it? [Y/n] and Reload privilege tables now? [Y/n] and

Once we have answered the questions, we will reinitiate the data base to leave working it.

systemctl restart mysql.service

Web server

For the Web server we are going to use nginx. This Web server works very or with WordPress at the time of developing or maintaining great sites, although he does not allow the use of the files .htaccess (he is had to form previously, without the users or plugins can change the configuration).

add-apt-repository ppa: ondrej/nginx apt - and update apt - and install nginx systemctl stop nginx.service systemctl inable nginx.service systemctl start nginx.service

Servant PHP

So that WordPress works we will need to install PHP, the interpreter of the code. In this case we will use the version of PHP 7.4. In addition, we will install the recommended extensions, which will suppose an extra work of configuration.

Installation PHP base

We will begin with the nucleus of PHP and PHP-FPM, in addition to the basic extensions that come pre-compiled.

add-apt-repository ppa: ondrej/php apt - and update apt - and install php7.4 php7.4-fpm php7.4-curl php7.4-gd php7.4-mbstring php7.4-XML php7.4-zip php7.4-mysql php7.4-mysqlnd php7.4-bcmath php7.4-gmp php7.4-tidy php7.4-dev to php-pear pkg-config imagemagick libmagickwand-dev pecl channel-update

Installation of ImageMagick

This extension allows the management of images improved on GD.

pecl install imagick I throw €˜€™ >> /etc/php/7.4/mods-available/imagick.ini ln - s /etc/php/7.4/mods-available/imagick.ini /etc/php/7.4/fpm/conf.d/30-imagick.ini

Installation of XDiff

This extension allows the application of patch that includes differences of files.

CD /usr/src wget to tar - xzf libxdiff-0.23.tar.gz rm - RF libxdiff-0.23.tar.gz CD libxdiff-0.23 ./configure make make install pecl install xdiff I throw €˜€™ >> /etc/php/7.4/mods-available/xdiff.ini ln - s /etc/php/7.4/mods-available/xdiff.ini /etc/php/7.4/fpm/conf.d/30-xdiff.ini

Installation of APCu

This extension improves the system of cache of code PHP.

CD pecl install apcu I throw €˜€™ >> /etc/php/7.4/mods-available/apcu.ini ln - s /etc/php/7.4/mods-available/apcu.ini /etc/php/7.4/fpm/conf.d/30-apcu.ini

Installation of Redis

Also we will install the extension of the servant of Redis cache.

pecl install redis I throw €˜€™ >> /etc/php/7.4/mods-available/redis.ini ln - s /etc/php/7.4/mods-available/redis.ini /etc/php/7.4/fpm/conf.d/30-redis.ini

Configuration of PHP

For the development, we will make some changes in the file of PHP configuration, mainly to give more manoeuvre margin to the memory and the visualization of errors by screen and at the time of testing.

First that we will do it will be to open the configuration file.

vim /etc/php/7.4/fpm/php.ini

And there we will make some changes in the configuration.

max_execution_time = 60 memory_limit = 256M error_reporting = E_ALL display_errors = On post_max_size = 32M upload_max_filesize = 32M date.timezone = UTC

NOTE: The one is formed that is errors since it occurs by fact that this machine is for development.

Once this, we will form PHP-FPM so that one activates automatically with the system.

systemctl stop php7.4-fpm.service systemctl inable php7.4-fpm.service systemctl start php7.4-fpm.service

Servant of Redis cache

We will install the Redis servant and we will give some changes him to the configuration so that it is not saturated.

First we will install it and we will synchronize it with PHP.

apt - and install redis-server php-redis

We will open the configuration file.

vim /etc/redis/redis.conf

And we will make some changes in the configuration.

maxmemory 256megabyte maxmemory-policy allkeys-lru

Finally we will reinitiate it, next to PHP so that its extension is applied.

systemctl stop redis-server.service systemctl inable redis-server.service systemctl start redis-server.service systemctl restart php7.4-fpm.service

Servant TLS certificate

Nowadays all the sites would have to work under HTTPS, reason why to make more real and similar the surroundings of development we will use a certificate of Let's Encrypt. For this we will need that the site has a hostname/public domain. Normally the VPS suppliers usually put a hostname to him to the machines, reason why we can use that.

We will generate one nails only in addition to installing the system of Certbot for nginx.

openssl dhparam - out /etc/ssl/certs/dhparam.pem 2048 add-apt-repository ppa: certbot/certbot apt - and update apt - and install python-certbot-nginx

And so that one does not forget to us, we will form a programmed task that updates the certificate automatically. For it we will open the publisher of crones.

crontab - e

And there we will add the execution, every day to the 06:45.

45 6 * * * certbot renew

Conclusion of the configuration

In principle or we have everything what we needed installed, reason why, before following, we are going to make a complete update of the system (again) to eliminate old or incompatible software yet the one that we have installed.

apt - and update && apt - and upgrade && apt - and dist-upgrade && apt - and autoremove

Configuration of the site

Now that already we have all ready at system level and tools, which we will do will be to form software so that we can work with him as if of a normal website and current one treated, although with that version of development.

First that we will do it will be to eliminate the website by defect that brings the system and we will replace it by which of little information.

rm /var/www/html/index. * vim /var/www/html/index.html

Here we will add following code HTML by defect.

<! DOCTYPE html> <p>Hello World! </p>

The same we will do with the file robots.txt

vim /var/www/html/robots.txt

In that we will block its tracking.

User-Agent: * Disallow: /

Now that we have the site by corrected defect, we are going to alter the configuration of nginx to be able to work of more suitable form with our site of development. First we will eliminate the configuration by defect and we will replace it by one altered.

CD /etc/nginx/sites-enabled/ rm default nginx.conf.original CD /etc/nginx/ cp nginx.conf vim nginx.conf

And we will replace the configuration by the following one.

to user www-dates; pid /run/; worker_processes car; worker_rlimit_nofile 65535; include /etc/nginx/modules-enabled/ *.conf; events \ {multi_accept on; worker_connections 65535; it uses epoll; } HTTP \ {charset utf-8; sendfile on; tcp_nopush on; tcp_nodelay on; server_tokens in off; log_not_found in off; types_hash_max_size 2048; client_max_body_size 64m; keepalive_timeout 65; server_names_hash_bucket_size 128; server_names_hash_max_size 1024; # PAMPERS include /etc/nginx/mime.types; default_type application/octet-stream; # logging access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; # SSL ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; # gzip gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 9; gzip_disable €œmsie6€; gzip_buffers 16 8k; gzip_min_length 1100; gzip_types application/atom+xml application/Javascript application/json application/x-Javascript application/xml application/xml+rss image/svg+xml text/css text/Javascript text/plain text/xml; # dwells include /etc/nginx/conf.d/ *.conf; include /etc/nginx/sites-enabled/ *; }

In addition, we will add a configuration to work with PHP and WordPress.

vim wordpress_fastcgi.conf

That it will contain the following thing.

fastcgi_pass UNIX: /var/run/php/php7.4-fpm.sock; fastcgi_index index.php; fastcgi_buffers 256 16k; fastcgi_buffer_size 128k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; fastcgi_intercept_errors in off; fastcgi_split_path_info ^ (. +.php) (/.+) $; try_files $fastcgi_script_name =404; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PHP_ADMIN_VALUE open_basedir=$document_root/: /usr/lib/php/: /tmp/; fastcgi_param PATH_INFO $path_info; set $path_info $fastcgi_path_info; include fastcgi.conf;

Once we have this, we would have to be able to reinitiate nginx without trouble and to leave it in march.

nginx - t nginx - s reload

From we are going here to make a copy of the software of WordPress following the account of Git that we have created previously. In this case we are going to mount all the system in the /webs/ folder from the root of the system, but it is possible to be done on anyone.

to mkdir /webs/ CD /webs/ git clones CD /webs/WordPress/

Now that we have cloned software, we are going to cause that it is navigable as any website were.

CD /etc/nginx/sites-available/ vim WordPress.conf

Where we will create a minimum configuration.

server \ {lists 80; they list [::]: 80; server_tokens in off; server_name; root /webs/WordPress; index index.php index.html; location = /favicon.ico \ {log_not_found in off; access_log in off; } location = /robots.txt \ {allow all; log_not_found in off; access_log in off; } location ~ /.well-known \ {allow all; } location ~/\ .ht \ {deny all; }}

And we will reinitiate nginx so that the changes are applied.

ln - s /etc/nginx/sites-available/WordPress.conf /etc/nginx/sites-enabled/ nginx - t nginx - s reload

Now we have to create and to install the TLS certificate to have a site with HTTPS.

certbot email --agree-cough --authenticator webroot --to installer nginx

When it asks us for tura of our software, we will tell him that it is in the corresponding folder.


Now we have to create the data base for our website. We will need the password root that we formed previously.

mysql - or root - p

You will need a password for this exclusive data base for our WordPress development. Please, it creates your own password that is something safe.

Wordpress CHARACTER CREATES DATABASE to YOU SET = utf8mb4 COLLATE = utf8mb4_bin; GRANT ALL ON wordpress.* TO €˜wordpress'@'localhost€™ IDENTIFIED BY €˜__PASSWORD€™; GRANT ALL ON wordpress.* TO €˜wordpress'@'€™ IDENTIFIED BY €˜__PASSWORD€™; FLUSH PRIVILEGES; quit

Now that we have the TLS certificate and the data base, we are going to create our site with all the safe configuration, in addition to certain specific configuration for WordPress.

CD /etc/nginx/sites-available/ vim WordPress.conf

Here we will be able to replace basic the initial configuration by more an outpost.

# All HTTP traffic will sees sent to HTTPS server \ {list 80; they list [::]: 80; server_name; return 301$request_uri; access_log in off; } # REAL SITE server \ {lists 443 SSL http2; they list [::]: 443 SSL http2; # SSL ssl_dhparam /etc/ssl/certs/dhparam.pem; ssl_certificate /etc/letsencrypt/live/; ssl_certificate_key /etc/letsencrypt/live/; ssl_trusted_certificate /etc/letsencrypt/live/; ssl_session_timeout 1d; ssl_session_cache shared: SSL: 128m; ssl_session_tickets in off; # SSL modern configuration ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384: ECDHE-RSA-AES256-GCM-SHA384: ECDHE-ECDSA-CHACHA20-POLY1305: ECDHE-RSA-CHACHA20-POLY1305: ECDHE-ECDSA-AES128-GCM-SHA256: ECDHE-RSA-AES128-GCM-SHA256: ECDHE-ECDSA-AES256-SHA384: ECDHE-RSA-AES256-SHA384: ECDHE-ECDSA-AES128-SHA256: ECDHE-RSA-AES128-SHA256; # SSL OCSP Stapling ssl_stapling on; ssl_stapling_verify on; to solve valid=300s; resolver_timeout 2s; # Security headers to add_header Referrer-Policy €œstrict-origin-when-cross-origin€ always; to add_header Strict-Transport-Security €œmax-age=31536000; includeSubDomains; preload€ always; #logs access_log /var/log/nginx/WordPress-access.log combined buffer=64k flush=5m; error_log /var/log/nginx/WordPress-error.log; #CONFIG server_name; root /webs/WordPress; index index.php; # try_files ROOT location/\ {$uri $uri//index.php; } # ROOT PHP location ~ \ .php$ \ {include wordpress_fastcgi.conf; } location ~ wp-config \ {deny all; } # HIDDEN YOU CASE OUT location ~/\ .well-known \ {allow all; } location ~/\ .ht \ {deny all; } # WEB YOU CASE OUT location ~ /favicon. (ICO|png) \ {log_not_found in off; access_log in off; } location = /robots.txt \ {allow all; log_not_found in off; access_log in off; } # STATIC YOU BREAK location ~* \. (aac|avi|bmp|bz2|cur|docx? |eot|exe|flv|GIF|gz|heic|htc|ICO|jpe? g|m4a|midi? |mov|mp3|mp4|MEP? g|ogg|ogv|otf|pdf|png|pptx? |to rar|rtf|svgz? |to tar|tgz|tiff? |ttc|ttf|txt|wav|webm|webp|wmv|woff|woff2|xlsx? |zip) $ \ {you expire max; to add_header Break-Control €œpublic€; log_not_found in off; access_log in off; } location ~* \. (atom|css|js|rss) $ \ {you expire 7d; to add_header Break-Control €œpublic€; log_not_found in off; access_log in off; } location ~* \. (: eot|otf|ttf|woff|woff2) $ \ {to add_header Access-Control €œ*€; } location ~* \ /wp-admin \ /load- (: scripts|styles) \ .php \ {if ($query_string ~* €œ^. \ {512,} $€) \ {return 444; }}}

We will reinitiate nginx and accede to the folder of our new WordPress.

nginx - t nginx - s reload CD /webs/WordPress/

Installation of WordPress

Now that already we have all ready one concerning systems to have a WordPress ready to moestrar errors and problems, we will begin the installation as any WordPress one is. For it simply we will accede to the direction Web of our hostname/domain that we have formed previously.

We form Git with stream for WordPress

Now we have to form our software so that can be maintained to the day with the development source code of WordPress. It is necessary to remember that this version of software usually is one alpha or beta, reason why the probabilities that there are errors are great, and therefore of they seben to report in the Trac de WordPress.

We will begin seeing what remote data we have.

CD /webs/WordPress/ git remote - v

Us it would have to appear something similar to this:

origin (fetch) origin (push)

We will add another source, the one of Git main.

git remote add wordpress git remote - v

This will give back to us that we have several sources, like thus.

origin (fetch) origin (push) wordpress (fetch) wordpress (push)

From this momeno, we can be updating and synchronizing our code, executing an update of Git and, of step, all the system.

apt - and update && apt - and upgrade && apt - and dist-upgrade && apt - and autoremove CD /webs/WordPress/ git pull wordpress master

And up to here we have an installation from zero of the Git main of development of WordPress, where we can analyze or verify our developments for future versions.

If you enter direction URL, it will ask to you to fill up the data as any normal installation. another option is to create your own file wp-config.php and that the installation begins to work.