How to Install Virtualmin on CentOS 7 With PHP 7 and NGINX
I have a couple of sites that I am keeping on a VPS with the above configuration. In this article, I will present you all the steps and the configurations you need to make to have
Virtualmin is a great tool and is offering all you need from DNS, email, FTP, and server administration. It has a GUI interface from where you can manage everything easily and is very stable.
Do you need help with your projects?
A. Steps to Install Virtualmin and Have Everything Configured.
1. Create The VPS
The first thing to do is to have your VPS ready and installed. I am using DigitalOcean for my sites as it has exactly what I need. You can check the review here: DigitalOcean Review
For a more affordable option to DigitalOcean, you can check this Hetzner Review.
To do this you login into
The size of the VPS is up to you but to have a couple of small sites hosted the 5$ plan can be enough ( without a lot of email processing) Also you can increase your size in the future if you need more.
2. Add a swap file, to do this you do:
After the creation process finishes you should receive an email with your VPS IP with the user name and password. The next thing you need to download Putty so you can connect to the VPS and run the commands.
sudo fallocate -l 1G /swapfile
sudo dd if=/dev/zero of=/swapfile bs=1024 count=1048576
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab
After you add the swap you can upgrade your machine to the latest version. to do that you just run:
yum update
yum upgrade
After you finish with the above you just reboot the machine and you are set to install Virtualmin
3. Install Virtualmin With NGINX
The install is very easy, you just need to install wget first so you can take the package and after just run the install with /root/install.sh -b LEMP
yum install wget
wget http://software.virtualmin.com/gpl/scripts/install.sh
sh /root/install.sh -b LEMP
▣▣▣ Phase 3 of 3: Configuration
[1/23] Configuring AWStats [ ✔ ]
[2/23] Configuring Bind [ ✔ ]
[3/23] Configuring ClamAV [ ✔ ]
[4/23] Configuring Dovecot [ ✔ ]
[5/23] Configuring Firewalld [ ✔ ]
[6/23] Configuring MySQL [ ✔ ]
[7/23] Configuring NTP [ ✔ ]
[8/23] Configuring Net [ ✔ ]
[9/23] Configuring Nginx [ ✔ ]
[10/23] Configuring ProFTPd [ ✔ ]
[11/23] Configuring Procmail [ ✔ ]
[12/23] Configuring Quotas
The filesystem / could not be remounted with quotas enabled.
You may need to reboot your system, and/or enable quotas in the Disk
Quotas module. [ ⚠ ]
[13/23] Configuring SASL [ ✔ ]
[14/23] Configuring Shells [ ✔ ]
[15/23] Configuring SpamAssassin [ ✔ ]
[16/23] Configuring Status [ ✔ ]
[17/23] Configuring Upgrade [ ✔ ]
[18/23] Configuring Usermin [ ✔ ]
[19/23] Configuring Webalizer [ ✔ ]
[20/23] Configuring Webmin [ ✔ ]
[21/23] Configuring Fail2banFirewalld [ ✔ ]
[22/23] Configuring Postfix [ ✔ ]
[23/23] Configuring Virtualmin [ ✔ ]
▣▣▣ Cleaning up
[SUCCESS] Installation Complete!
[SUCCESS] If there were no errors above, Virtualmin should be ready
[SUCCESS] to configure at https://ns1.wpdoze.site:10000 (or https://159.65.108.159
10.46.0.5:10000).
After 10 minutes or so all the packages will be installed and you are ready to configure the installation.
4. Connect to the GUI and make final changes
https://159.65.108.159:10000/
After you need to access the UI with the server public
- Preload Virtualmin libraries? – No (less RAM used, slower UI and more CPU load)
- Run email domain lookup server? – No (less RAM used, slower mail and more CPU load)
- Run ClamAV server scanner? – No (less RAM used, slower mail processing)
- Run SpamAssassin server filter? – No (less RAM used, slower mail processing)
- Run MariaDB/MySQL database server? – Yes (more RAM used, needed for most non-static websites)
- Run PostgreSQL database server? – No (less RAM used)
- MariaDB/MySQL configuration size -Medium system (512M) with regular MariaDB/MySQL use
- DNS set up: Primary nameserver: ns1.domain.com check the box Skip check for resolvability
add a secondary DNS like:
ns2.domain.com - Password storage mode – Store plain-text passwords
After all this, you are set you just need to point your domain name to the DNS and create the custom DNS records.
5. Set UP the custom DNS Names and point the domain to the server
Now Virtualmin is installed and ready to host sites 🙂 as next actions, you need to go where you host your domain and create the custom DNS names pointing to the server IP. I am using NameCheap for this. And you need to go under the domain name and hit Manage -> Advanced DNS and add the ns1 and ns2 with the IP as below:
Now you have your custom nameserver set up and you just need to point your domain to use them from Domain Tab like below:
Video For Installing Virtualmin with Part A steps:
B. Some Extra Configurations:
In this area, we will do some extra configurations for multiple PHP versions, create a custom server template that will deploy WordPress automatically, and do some Nginx configurations for advanced performance.
1. Install Multiple PHP versions
Now as we have everything set up we can do some extra configs to have multiple PHP versions on our site, by default Virtualmin is installing PHP 5.6 with 7.0 you need to run the below to have multiple versions of PHP 7:
yum install centos-release-scl
yum install rh-php71 rh-php71-php-mysqlnd
yum install rh-php72 rh-php72-php-mysqlnd
2. Create a server templete to install wordpress automaticly
Next, I want to have a special server template and have some customization done for WordPress like installing it automatically when I add a domain and having the user and DB already added. Below are the steps to have this done:
- Download WordPress and add it to a dir:
For this I will use a directory under /etc/wordpress, you can run the below commands to have everything set up:
# cd /etc/
# mkdir wordpress
# cd wordpress/
# mkdir public_html
# cd public_html/
# wget https://wordpress.org/latest.zip
# unzip latest.zip
# mv wordpress/* .
# rm -rf wordpress
- Rename sample-wp-config.php to wp-config and replace the below values:
#cp wp-config-sample.php wp-config.php
- Edit wp-config.php and use the below values so when you create a new account to have Virtualmin populate them by default.
define( 'DB_NAME', '${USER}' );
/** MySQL database username */
define( 'DB_USER', '${USER}' );
/** MySQL database password */
define( 'DB_PASSWORD', '${PASS}' );
- Add the New Server Template in the Virtualmin GUI
Now you need to create the template to have it configured to do so go to Virtualmin > System Settings > Server Templates and hit create a template from the default settings:
Then give it name like WordPress and hit Create and Next. Now in the Home Directory use these configurations:
- Skeleton directory for files – choose Directory and use the previous path where you stored
WordPresss : /etc/wordpress - Substitute variables in contents? –
Use : Yes - File patterns to
only substitute: wp-config.php
Then hit Save
With this configuration, while choosing a WordPress template you will have by default WordPress installed.
3. Add the Below In the /etc/nginx /nginx.conf
Next to that, we want to do is to add some nginx configurations to have a better performance. All that is needed to be done is to add below in the /etc/nginx/nginx.conf. This can be done in the Virtualmin UI from the region: Webmin – Servers- Nginx
Next, you need to add the below code:
open_file_cache max=200000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
##
# Gzip Settings
##
gzip on;
gzip_comp_level 9;
gzip_proxied expired no-cache no-store private auth;
gzip_min_length 500;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
map $sent_http_content_type $expires {
default off;
text/html epoch;
text/css max;
application/javascript max;
~image/ max;
}
The configuration will look like this:
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
open_file_cache max=200000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
##
# Gzip Settings
##
gzip on;
gzip_comp_level 9;
gzip_proxied expired no-cache no-store private auth;
gzip_min_length 500;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
map $sent_http_content_type $expires {
default off;
text/html epoch;
text/css max;
application/javascript max;
~image/ max;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2 default_server;
# listen [::]:443 ssl http2 default_server;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# location / {
# }
#
# error_page 404 /404.html;
# location = /40x.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
server_names_hash_bucket_size 128;
}
Now you just need to hit save
Extra Config Video
C. Create the First Virtual Server
We have everything we need to have our first website added into Virtualmin, until now we have:
- Installed Virtualmin
- Configure the DNS on to domain
- Made some small changes to enhance virtualmin
The configuration will run and Virtualmin will add everything needed to have your first site. The site will be with SSL but it will have a self-signed one. If you visit the link you will see an exception, next we will need to add a LetsEncrypt SSL and make some Nginx configs:
- Create a LetsEncypt SSL for your Nginx Website
All websites should have an SSL certificate and LetsEncypt helps you in generating a free one for you. You also need to renew it in 3 by 3 months. Virtualmin helps you generate the certificate automatically very easily and handle also the renewal. To have the certificate you go to Virtualmin – Server Configuration – SSL Certificate > Let’s
Now you have the website with WordPress and the Let’s Encrypt certificate up and running. Next, you access the site URL with HTTPS and go thru the WordPress Installation process.
- Additional Nginx Configs
To have all the traffic redirected from
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
Add support for WordPress permalinks:
location / {
try_files $uri $uri/ /index.php?$args;
}
Add HTTP2:
Nginx support http2 for faster loading of the websites under HTTPS, to enable this you just need to add into location the http2 like below
listen 159.203.100.92:443 default ssl http2;
Then Save and Close and Apply Nginx Config
Then your server will look like this:
server {
server_name wpdoze.site www.wpdoze.site;
listen 159.203.100.92;
root /home/wpdoze/public_html;
index index.html index.htm index.php;
access_log /var/log/virtualmin/wpdoze.site_access_log;
error_log /var/log/virtualmin/wpdoze.site_error_log;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_FILENAME /home/wpdoze/public_html$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT /home/wpdoze/public_html;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param HTTPS $https;
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/php-nginx/155437756624142.sock/socket;
}
listen 159.203.100.92:443 default ssl http2;
ssl_certificate /home/wpdoze/ssl.combined;
ssl_certificate_key /home/wpdoze/ssl.key;
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
location / {
try_files $uri $uri/ /index.php?$args;
}