Setting up the OS and Virtualmin

Setup your SSH

Get your private key from Amazon. You will be prompted with this when you set up an instance. Save the key to your local machine and use a tool such as PuTTyGen to export the Private Key as a PPK. Keep it secret. Keep it safe. Create a new session in PuTTY, using the new keyfile. The username is centos@ or

Go ahead and SSH into your instance.

Update CentOS

sudo yum update -y

Wait patiently...

sudo yum install epel-release wget zip screen perl ncdu -y && sudo yum clean all

This installs some useful extras.

  • epel - the epel repo
  • wget - not included by default, for getting remote files
  • zip - provides support for working with zip archives
  • perl - needed for googleauth, amongst others
  • ncdu - nice easy disk usage analyser
  • screen - screens! if you dont need/use this then ignore it

Install VirtualMin

mkdir virtualmin
cd virtualmin
chmod +x
sudo ./

All in one:

mkdir virtualmin && cd virtualmin && wget && chmod +x && sudo ./

Wait for this to finish, then:

sudo yum update -y && sudo yum clean all

If you haven't already set a root password (usually on AWS installs) then you'll need to set a root password to be able to log in to VirtualMin. Do the following:

sudo /usr/libexec/webmin/ /etc/webmin root yourrootpassword

You can now log in at the admin panel:

You will get an error about the SSL certificate when you try and log in at this point. This is to be expected. It can take a minute/a couple of log-in attempts to get access to the admin panel. This appears to be normal.

Configure Virtualmin Network settings:

To stop Virtualmin error "Virtualmin is configured to setup DNS zones, but this system is not setup to use itself as a DNS server"

sudo vi /etc/dhcp/dhclient.conf

Add the following line to the start of the file:

prepend domain-name-servers;

Add the hostname to the network config:

sudo vi /etc/sysconfig/network

Add or edit the HOSTNAME to have the following value:

When you've changed these you'll need to restart the network service:

sudo systemctl restart network

Configure the Virtualmin install

Go to the web interface at: Complete the Virtualmin Setup guide and configure it according to your server needs and available resources. Note that the MySQL password process may fail, if so hit blue return button and then proceed with same password and it should work.

When the Virtualmin install has finished, go to: Virtualmin -> System Settings -> Virtualmin Configuration -> Networking settings Set Default IP address for DNS records to: Automatically detect external address

After completing the install have Virtualmin check its configuration. If you're not prompted to do this on the main Virtualmin System Information page it can be found at VirtualMin -> System Settings -> Re-Check Configuration.

Setup the firewall

The firewall isn't enabled by default on CentOS 7. We need to turn it on and setup some basic rules.

sudo systemctl start firewalld

Congrats! You've now locked yourself out of the Virtualmin interface. Run the following to add the relevant rules:

sudo firewall-cmd --zone=public --add-service=http --permanent
sudo firewall-cmd --zone=public --add-service=https --permanent
sudo firewall-cmd --zone=public --add-port=10000/tcp --permanent

If you want email on the domain (covered further later) also add these:

sudo firewall-cmd --zone=public --add-service=pop3s --permanent
sudo firewall-cmd --zone=public --add-service=imaps --permanent
sudo firewall-cmd --zone=public --add-service=smtps --permanent
sudo firewall-cmd --zone=public --add-service=smtp --permanent

Restart the firewall when you've added your rules.

sudo firewall-cmd --reload

You can now log back into the Virtualmin interface. You can manage firewall rules easily in the future by going to: Webmin -> Networking -> FirewallD.

Upgrading and Configuring PHP & Apache

Update PHP 5.4 to 5.6.*

Note: This replaces the default PHP 5.4 and replaces it with 5.6.* These commands are taken from Remi's excellent Wizard:

sudo yum install yum-utils -y
sudo yum-config-manager --enable remi-php56
sudo yum update -y

Optionally install additional packages:

sudo yum install php-xxx

Check the installed version and available extensions:

php --version
php --modules

Add Additional PHP 7.1.*

Note: This adds PHP 7.1.* in addition to 5.6.*. It assumes you have followed the steps above to add Remi's PHP Repository. If you haven't already done this then use the commands above to add the repository before doing the following.

sudo yum install php71 php71-php php71-php-bcmath php71-php-cli php71-php-common php71-php-curl php71-php-devel php71-php-fpm php71-php-gd php71-php-gmp php71-php-intl php71-php-json php71-php-mbstring php71-php-mcrypt php71-php-mysqlnd php71-php-opcache php71-php-pdo php71-php-pear php71-php-pecl-apcu php71-php-pecl-geoip php71-php-pecl-imagick php71-php-pecl-json-post php71-php-pecl-memcache php71-php-pecl-xmldiff php71-php-pecl-zip php71-php-process php71-php-pspell php71-php-simplexml php71-php-soap php71-php-tidy php71-php-xml php71-php-xmlrpc -y

Run the following to test the install. This should generate an error "no package php71-php-xxx found", this is desired:

sudo yum --enablerepo=remi-test install php71-php-xxx

Check the installed version and available extensions:

php71 --version
php71 --modules

Change Apache default settings

Go to: Webmin -> Others -> PHP Configuration -> Manage -> Resource Limits Set Maximum file upload size to 32M (or suitable value) Set Maximum HTTP POST size to 32M (or suitable value)

GNU Terry Pratchett

A man is not dead while his name is still spoken This adds a custom server header named X-Clacks, in memorium of the author Terry Pratchett. See for more information.

Open the apache config file:

sudo vi /etc/httpd/conf/httpd.conf

Insert after last :

<IfModule headers_module>
  header set X-Clacks-Overhead "GNU Terry Pratchett"

Save and restart apache:

sudo systemctl restart httpd

Installing Node, Gem, SASS and LESS.

Install Node from the EPEL Repository

sudo yum install epel-release -y
sudo yum install nodejs -y
node --version

Optionally install LESS

sudo npm install -g less

Optionally install SASS

sudo gem install sass

If installing Gem doesn't work and the install fails to compile, chances are you need gcc.

sudo yum install gcc -y

The npm version of SASS won't work with the CMSMS module CSSPreProcessor and you must use the Gem version instead.

Securing your admin panel with SSL

At this point, reboot your server and run the Virtualmin Configuration check. It can be found at: Virtualmin -> System Settings -> Re-Check Configuration. If everything here passes, you're good to go!

Setup the Domain

It's best to create a website for the main FQDN that you're using for the server admin panel. In this example we use Note you can use for your regular website as the admin panel will only be visible at

Go to Virtualmin -> Create Virtual Server

Set Domain name: (without http/https/www or trailing /) Set Admin password: Something decent. You'll only need it once for setting up SSH keys. Set Admin username: Up to you. Something short, relevant and ideally not a direct copy of your domain name.

Under Enabled Features ensure "Setup SSL website too?" is ticked. Create the site. Give Virtualmin a while to make all the various config files.

Go to Virtualmin -> -> Edit Virtual Server Check that Quotas and Limits are suitable.

Get the SSL Certificate

Go to Virtualmin -> -> Server Configuration -> Manage SSL Certificate -> Let's Encrypt Set Months between automatic renewal to 2. 2 months between renewals will be sufficient as default expiry is 3 months. Ensure all domains needed are in the box. Click Request Certificate

If the cetificate fails with an error similar to the folowing: "DNS problem: NXDOMAIN looking up TXT for _acme-challenge" Chances are that it'll work for but not This means that the DNS record needs a *or www. TXT record.

The following steps are only needed if the admin panel has it own domain, ignore this most likely:

Go to Webmin -> Webmin -> Webmin Configuration -> SSL Encryption -> Let's Encrypt Ensure that:

  • Website root directory for validation file: Other directory
  • Copy new key and certificate to Webmin: Yes.
  • Enable Auto Renew (2 months). Request certificate

Copy the Cert to Webmin and Email

Go to Virtualmin -> -> Server Configuration -> Manage SSL Certificate Click the buttons:

  • Copy to Webmin
  • Copy to Usermin
  • Copy to Postfix
  • Copy to Dovecot

If you get an error when copying to Postfix about "no such file at /etc/postfix/ssl/*" then do the following and retry:

sudo mkdir /etc/postfix/ssl

If the certificate request succeeded and you've copied the certificate over to Webmin then your admin panel should now be valid HTTPS. If Chrome is being awkward and not detecting the new certifcate, open the admin panel in a new Incognito Tab, then re-open it in a regular tab.

Redirect http to https

Go to Virtualmin -> Services -> Configure Website -> Aliases and Redirects Add a rule for "Permanent URL redirects" From: / To:

To finish and apply click "Apply Changes" button at top right

Enable 2-Factor Authentication with GoogleAuth

We can setup Virtualmin to use GoogleAuth on all logins for extra security.

Note: some installs may fail with an error about being unable to untar the package. Particularly on low-memory instances such as the t1 and t2 series. This is due to low memory. Workaround is to use systemctl to temporarily stop httpd and mariadb

Install dependencies

First we need to install the PERL modules:

sudo yum install perl-CPAN -y
cpan -or- sudo perl -MCPAN -e 

Choose: yes, sudo, yes

install Archive::Tar Authen:OATH Digest::HMAC Digest::SHA Math::BigInt Moo Moose Module::Build Test::More Test::Needs Type::Tiny Types::Standard

(Can't remember if we already installed gcc, so maybe this: sudo yum install gcc -y)

Activate and enroll

Then go to Webmin -> Webmin -> Webmin Configuration -> Two-Factor Authentication -> Enable Google Authenticator.

When you have enabled Google Authenticator, you will need to complete the enrollment. Go to Webmin -> Webmin -> Webmin Users -> Two-Factor Authentication

Don't forget to restart httpd and mariadb if you had to stop them for memory conservation.


Setting up additional virtual sites

Now your admin panel is all setup to run off the back of your primary FQDN, we can go ahead and setup other virtual sites for the server if they're needed. If not, you can follow this section (with some adjustments) to obtain a keyfile for the user you have already created.

Setup a new Virtual Server

Virtualmin -> Create Virtual Server

Domain name: (without http/https/www or trailing /) Admin password: Make it a decent one. You'll only need it for setting up SSH keys for the user below. Admin username: Up to you. Something short, relevant and ideally not a direct copy of your domain name.

Under Enabled Features ensure "Setup SSL website too" is ticked. Create the site. Give Virtualmin a while to make all the various config files.

Setup SSH for Virtualmin User


From an ssh console, su to the user. Use the password you entered when you created the virtual site:

su username
cd /home/username
mkdir .ssh && chmod 700 .ssh && ssh-keygen -t rsa

This will start the keygen process and you will be prompted to enter a name for the keyfile Enter name: sitename_key

This will output sitename_key and in the current directory. We're using the file, but first we need to edit it. Do the following:

cp .ssh/authorized_keys
vi .ssh/authorized_keys

Once in vi, remove the last part of the file that begins with username@hostname, leaving just the key itself. Exit vi by hitting Esc then type :wq and press Enter.

chmod 600 .ssh/authorized_keys
tar cvf public_html/sitename_key.tar sitename_key

Now we need to download the key. Go to

Take that file and extract it, open with PuTTyGen, export and save the Private key as a PPK. Use this to connect via SSH as the user@domain in PuTTy, FileZilla, etc.

Don't forget to cleanup after yourself:

rm sitename_key
rm public_html/sitename_key.tar

Done all this and getting an error in PuTTy about no suitable authentication method found? This means you saved the public key with PuTTyGen instead of the private key. Go back and try again.

Postfix Setup

Warning: here be dragons.

This section is a little rough around the edges, and may even be missing steps. I'll tidy this up one of these days...

Ensure you have already copied the LetsEncrypt certificate to Postfix and Webmin to get these to work properly.

Go to Webmin -> Servers -> Postfix -> Edit Config Files -> /etc/postfix/

Scroll all the way down to the bottom. Find the lines (677-679ish) containing: # readme_directory: The location of the Postfix README files. # readme_directory = /usr/share/doc/postfix-2.10.1/README_FILES

Remove everything beneath the lines above and insert the following:

allow_percent_hack = no
broken_sasl_auth_clients = yes
home_mailbox = Maildir/
mailbox_command = /usr/bin/procmail-wrapper -o -a $DOMAIN -d $LOGNAME
mailbox_size_limit = 0
sender_bcc_maps = hash:/etc/postfix/bcc
smtp_tls_note_starttls_offer = yes
smtp_tls_security_level = may
smtp_use_tls = yes
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_rbl_client, reject_rhsbl_helo, reject_rhsbl_sender
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain =
smtpd_sasl_security_options = noanonymous
smtpd_sender_restrictions = reject_unknown_sender_domain
smtpd_tls_CAfile = /etc/postfix/
smtpd_tls_cert_file = /etc/postfix/ssl/server.crt
smtpd_tls_key_file = /etc/postfix/ssl/server.key
smtpd_tls_loglevel = 1
smtpd_tls_mandatory_ciphers = high
smtpd_tls_mandatory_protocols = SSLv3, TLSv1
smtpd_tls_received_header = yes
smtpd_tls_security_level = may
smtpd_tls_session_cache_timeout = 3600s
smtpd_use_tls = yes
tls_random_source = dev:/dev/urandom
virtual_alias_maps = hash:/etc/postfix/virtual

Restart Postfix to enable Encrypted mail:

sudo systemctl restart postfix

Webmin -> Servers -> Postfix -> General Options

  • What domain to use in outbound mail: Use hostname
  • Send outgoing mail via host Deliver directly
  • Internet hostname of this mail system: Default
  • Local internet domain name: Default
  • Local networks: Default

Dovecot / Email in General

Go to Virtualmin -> System Settings -> Server Templates Edit template section: Mail for domain

Set "Format for usernames that include domain" to username@domain

Notes on DNS Settings:

Domain must have an MX record set Example (for Google DNS): @ MX 1H

To verify email you need an SPF record (this avoids emails showing in Gmail with a ?) Create an TXT record with the value: v=spf1 mx a -all Example: @ TXT 1H v=spf1 mx a -all

Set up Backups

Set up backups for both the virtual servers, as well as the Virtualmin/Webminconfiguration files.

Go to Virtualmin -> Backup and Restore -> Scheduled Backups

Webmin can backup all configuration files also. It is in a different section.

Go to Webmin - Webmin - Backup Configuration Files - Scheduled Backups - Add a new scheduled backup

  • Select all modules
  • Choose your backup destination
  • Destination folder/file name can contain vars if enabled in Setttings (click cog icon on main Backup Configuration Files page)
  • Ensure "Webmin module configuration files" is ticked.


Backing up a database via SSH

mysqldump -u username -p database > sql.sql

Importing a database via SSH

mysql -u username -p database < sql.sql


v=spf1 mx a -all

Tar Examples:

  • c create
  • v verbose output
  • z enable compression
  • p preserve permissions
  • f filename

Simple backup example:

tar cvzpf backup.tar.gz public_html/

Excluding a single sub-dir:

tar --exclude='public_html/uploads/_CGSmartImage' -cvzpf backup.tar.gz public_html/

Excluding mutliple sub-dirs:

tar --exclude='public_html/tmp' --exclude='public_html/assets/example' -cvzpf backup.tar.gz public_html/

Changing an Amazon Instance to a different type

  • Make an image of the instance
  • Wait until its finished
  • Go to AMIs
  • Choose the Image you just created
  • Launch the AMI as a new instance with the desired hardware.
  • When it boots, go to the new Virtualmin location on the temporary public address, something like:

  • Log in. Virtualmin will give you a warning that your systems primary IP address appears to have changed. Choose "Update incorrect IP Addresses" Ensure that "Address type to change" is set to "Real address" Ensure that "Servers to update" is set to "All servers" Click "Change Now" This process can take a while, depending on how many domains you're hosting.

Installing Ark on Centos 7.4

Create a new Virtual Site at the domain/subdomain you want: eg:

Following commands assume username ark from

Update sysctl.conf to allow more files to be open: Source:

sudo sysctl -w fs.file-max=100000

We need to make this permanant:

sudo vi /etc/sysctl.conf

Append the following line:

fs.file-max = 100000

Save and close the file. Users need to log out and log back in again to changes take effect or just type the following command:

sudo sysctl -p

Verify your settings with command:

sysctl fs.file-max

Now add higher hard and soft limits for the user we created:

sudo vi /etc/security/limits.conf

Add in the following entries, adjust your username as appropriate:

ark soft nofile 100000
ark hard nofile 100000

Give the user sudo priveledges via a root account:

sudo usermod -aG wheel <username>

On CentOS, if adding the user to the group does not work immediately, you may have to edit the /etc/sudoers file to uncomment the group name:

sudo visudo

Find and ensure the following is not commented out:

%wheel ALL=(ALL) ALL

Make a directory for and obtain the steam client

mkdir steam
cd steam
curl -sqL "" | tar zxvf -
chmod +x ./

Open all the ports:

sudo firewall-cmd --zone=public --add-port=27015/tcp --permanent
sudo firewall-cmd --zone=public --add-port=27015/udp --permanent
sudo firewall-cmd --zone=public --add-port=27016/tcp --permanent
sudo firewall-cmd --zone=public --add-port=27016/udp --permanent
sudo firewall-cmd --zone=public --add-port=7778/tcp --permanent
sudo firewall-cmd --zone=public --add-port=7778/udp --permanent
sudo firewall-cmd --zone=public --add-port=32330/tcp --permanent

Run steam once to install it:


Get ark-server-tools (

curl -sL | bash -s -- --me --perform-user-install

Backing up an Ark Save:

tar xvf ../../../../public_html/ragnarok.tar.gz Ragnarok.ark Ragnarok_AntiCorruptionBackup.bak Ragnarok_NewLaunchBackup.bak *.arkprofile *.profilebak *.arktribe *.tribebak