How To: Install WordPress Manually
In this complete guide, I'm going to show you how to install WordPress manually and why it is a good idea. We are going to setup and secure our Linux server, install the latest version of MySQL and PHP as well as install and configure Nginx. You will learn how to secure your server with a firewall and encrypt communication between the users and the website with a TLS certificate. At least, Cloudflare will be used for caching our content around the globe.
Besjan Sejrani
What is WordPress ?
WordPress is a content management system, also called CMS, which is mostly used for blogging, ecommerce and website presentation. It is Open Source, you can use it at any cost for personal or commercial use. These days in 2022, WordPress counts for about 40% of the entire web. Since it is such a large project, you can easily find help via the documentation or tutorials on the web.
Why installing WordPress manually is better
Installing WordPress manually compared to other WordPress hosting solutions isn't necessary a better choice. However, it will teaches you valuable information about the web, which you can use later on for other websites. You will never depend or be locked in by some WordPress hosting solutions, you will have total control.
Prerequisites
For this guide, you don't need to have any computer skills, you will learn the basics. However, it is recommended to have a strong will to learn new subjects and practice a long.
If you want to host your website, you will need to have a hosting provider, such as Vultr or Digital Ocean, and a domain name. You will have to pay $5-10 / month for hosting and $10 for a domain / year.
Hosting Provider
For this complete guide, Vultr will be used for hosting. The domain name selfticode.com has been bought and wit ill be managed via Infomaniak's DNS configuration panel.
You can use any hosting and DNS solution you want, as long as you can manage your server via SSH. Be careful, often shared hosting doesn't allow for SSH management.
Image: Create an instance on Vultr
Image: Choose your Vultr server, server location, server OS and server size
Image: Choose your Vultr server, server location, server OS and server size
In this guide, Ubuntu was chosen as the main operating system, but you can choose any Unix like OS you want, therefore, package manager commands may be differ.
SSH Configuration
Secure Shell, also known as SSH, is a network protocol which allows to connect to a server securely. The encryption algorithm generates a private key, which must stay private and a public key, which you can share with the server.
Generate a SSH key
Windows users must install Git Bash before executing the ssh-keygen command. For Mac and Linux users, it can be achieved by opening the Terminal. Enter the command and provide a valid email address.
By default, the ssh-keygen command will create two files, one file called id_ed25519 and an other file named id_ed25519.pub. If you want to change the name of the files and their locations, you can do it by editing the path file. However, it is strongly recommended to create the files under the hidden folder .ssh.
# Creates a private and public keyssh-keygen -t ed25519 -C "[email protected]"# Copy the id_ed25519.pub contentcat ~/.ssh/id_ed25519.pub
It is recommended to add your public SSH key to Vultr, this will make the connection process to the server much more easier and secure.
To show the content of the public SSH key, the cat command is used, then a simple copy and paste does the trick. Make sure to copy the file ending in .pub.
Image: Add your public SSH key to Vultr
# SSH connectionssh [email protected]_address
Create & secure new super user account
By default, the root account is the super user account and this is a problem since everyone knows that a root account exists.
The best practices are to create a new user and to add it to the sudo group which will grand super user permissions, disable SSH connection for the root account, and finally disable password authentication.
# Creates a new user and asks for new passwordadduser username# Add user to sudo group for super user permissionssudo usermod -aG sudo username# Verify that the user as been added to the sudo groupgroups username# Switch to user accountsu - username# Exit new super user accountexit# Exit serverexit
# Send public key over SSH on the new super user accountssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]_address# SSH connection with the new super user accountssh [email protected]_address
The ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]_address command will send the public SSH key on the new super user account. It's the same process as Vultr did when we pass to it the SSH public key.
# Edit the SSH serveur configuration filesudo nano /etc/ssh/sshd_config# Modify the following properties# If a # stands before the property, the line is commented outPermitRootLogin: noPubkeyAuthentication: yesAuthorizedKeysFile .ssh/authorized_keysPasswordAuthentication: no# Restart SSH serversudo systemctl restart sshd
You can now try to connect via SSH to the root account, it will not work. It will only work with the new super user created.
PHP Installation
WordPress uses PHP as the main programming language on the server. To install it, we first need to update all the packages on our server, then install PHP and some extensions which will add some further capabilities to PHP.
# Add package repository, Ondrej PPA maintains a repository that includes multiple PHP versionssudo add-apt-repository ppa:ondrej/php# Download packages informationsudo apt update# Upgrade packagessudo apt upgrade
The sudo command stands for super user do, it will allow you to execute some commands in privilege mode.
# Install PHP and PHP extensionssudo apt install php8.0-fpm php8.0-common php8.0-mysql \php8.0-xml php8.0-xmlrpc php8.0-curl php8.0-gd \php8.0-imagick php8.0-cli php8.0-dev php8.0-imap \php8.0-mbstring php8.0-opcache php8.0-redis \php8.0-soap php8.0-zip -y
The following extensions will enhance PHP's capabilities to support the MySQL database, XML format, image processing, mail support, zip compression and Redis database support.
# Verify your PHP versionphp --version# PHP 8.0.14 (cli) (built: Dec 20 2021 21:22:57) ( NTS )# Copyright (c) The PHP Group# Zend Engine v4.0.14, Copyright (c) Zend Technologies# with Zend OPcache v8.0.14, Copyright (c), by Zend Technologies
After the installation has been completed, verify the PHP version.
MySQL Installation
MySQL is a SQL relational database which is used for storing data. WordPress uses MySQL for it's internal functioning, especially in the case of themes and plugins.
You could also use MariaDB, which is a clone of MySQL. Side note, it was cloned of fear that Oracle, when it acquired the project, would transform it into a payed product.
# Download packages informationsudo apt update# Install MySQLsudo apt install mysql-server
After updating your packages, install MySQL.
# Configure MySQLsudo mysql_secure_installation
It is recommended to add a password to the MySQL root user, preferably, a strong password. Then remove anonymous users, disallow root login remotely and finally remove the test database.
# Connecting to MySQL as super usersudo mysql# Create WordPress databaseCREATE DATABASE wordpress;# Create MySQL userCREATE USER 'username'@'localhost' IDENTIFIED BY 'password';# Grant permissions to userGRANT CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, SELECT, REFERENCES, RELOAD on *.* TO 'username'@'localhost' WITH GRANT OPTION;# Frees any memory that the server has cachedFLUSH PRIVILEGES;# Exit MySQL shellEXIT;
After creating the wordpress database and creating a user identified by a password, the permissions of that user are enhanced so that it can perform basic database operations. Finally, the database memory is reset for security reasons before exiting the database.
Download WordPress
WordPress source code can be downloaded on the wordpress.org website via the wget command.
# Go to root user directorycd ~# Install WordPress tar files# wget downloads WordPress via the wordpress.org repositorywget http://wordpress.org/latest.tar.gz# Extract files# This will create a folder named wordpress containing all the WordPress files via extractiontar -xzvf latest.tar.gz
After WordPress is downloaded from the wordpress.org repository, the content still needs to be extracted into a folder named wordpress.
# Go to wordpress directorycd wordpress# Copy wp-config-sample.php filecp wp-config-sample.php wp-config.php# Editing wp-config.php with nano editornano wp-config.php
Nano is a text editor for Linux, you can use it for modifying your files. For beginners it is recommended to first start out with nano before using other text editors such as Vim or Emacs.
#/** The name of the database for WordPress */define( 'DB_NAME', 'database_name_here' );#/** MySQL database username */define( 'DB_USER', 'username_here' );#/** MySQL database password */define( 'DB_PASSWORD', 'password_here' );# Go to the following URL https://api.wordpress.org/secret-key/1.1/salt/# Copy and paste the following contentdefine('AUTH_KEY', 'YOUR AUTH_KEY');define('SECURE_AUTH_KEY', 'YOUR SECURE_AUTH_KEY');define('LOGGED_IN_KEY', 'YOUR LOGGED_IN_KEY');define('NONCE_KEY', 'YOUR NONCE_KEY');define('AUTH_SALT', 'YOUR AUTH_SALT');define('SECURE_AUTH_SALT', 'YOUR SECURE_AUTH_SALT');define('LOGGED_IN_SALT', 'YOUR LOGGED_IN_SALT');define('NONCE_SALT', 'YOUR NONCE_SALT');
After opening the wp-config.php file with your text editor, you must modify the database_name_here, username_here and password_here variables.
For security reasons, you should also modify the security variables. Via the following URL, https://api.wordpress.org/secret-key/1.1/salt/, WordPress generates automatically, random values for the security variables. Just copy the content and replace it on the file.
Nginx Installation & Setup
Nginx is a web server sitting just in front of a server, it is capable of reverse proxying and load balancing, which means it redirects traffic, depending on the URL that the user has entered, to a single server or to multiple servers.
Image: Request & response flow
Compared to other web server such as Apache, Nginx handles requests much more efficient, resulting in a greater capability of handling more requests.
# Download packagessudo apt update# Install Nginxsudo apt install nginx -y# Modify the nginx configuration filesudo nano /etc/nginx/sites-available/default
After updating you packages, install Nginx and update the default configuration file under /etc/nginx/sites-available/default with the following content. Modify your server_name with your domain name, use the nano editor to modify the file.
server {listen 80;server_name selfticode.com;root /var/www/html/wordpress;index index.php;# For security reasons the server_tokens is set to off# The browser will not be able to know which OS is the serverserver_tokens off;location / {# The requested URI is first tested, then the folder, and finally the index.php file with any query stringtry_files $uri $uri/ /index.php?$args;}location ~* /wp-sitemap.*\.xml {# The requested URI is first tested, then the folder, and finally the index.php file with any query stringtry_files $uri $uri/ /index.php$is_args$args;}client_max_body_size 100M;# Pass the php scripts to FastCGI server specified in upstream declaration.location ~ \.php(/|$) {include fastcgi.conf;fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;fastcgi_split_path_info ^(.+\.php)(/.*)$;fastcgi_param PATH_INFO $fastcgi_path_info;fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;fastcgi_param DOCUMENT_ROOT $realpath_root;try_files $uri $uri/ /app.php$is_args$args;fastcgi_intercept_errors on;}# GZIP is a compression algorithm, it reduces the files payloadgzip on;# The higher the gzip_comp_level is, the better it will compress files# The downside is that it's CPU load heavygzip_comp_level 4;gzip_min_length 1000;gzip_proxied any;# File types allowed for Gzip compressiongzip_typesapplication/geo+jsonapplication/javascriptapplication/x-javascriptapplication/jsonapplication/ld+jsonapplication/manifest+jsonapplication/rdf+xmlapplication/rss+xmlapplication/xmlfont/eotfont/otffont/ttfimage/svg+xmltext/csstext/javascripttext/plaintext/xml;# Files, Media# A large selection of file formats was selected for any use caselocation ~* \.(?:css?|js?|jpe?g|png|gif|ico|webp|tiff?|mp3|m4a|aac|ogg|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ {expires 90d;access_log off;}# Static assetslocation ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$ {add_header Access-Control-Allow-Origin "*";expires 90d;access_log off;}}
# Verify Nginx configuration filesudo nginx -t# Restart Nginxsudo systemctl restart nginx
Verify that the nginx configuration file is correct, and only then restart nginx.
# Moves the wordpress folder to a new locationsudo mv ~/wordpress /var/www/html/wordpress# Changes the the owner of the folder and it's content recursivelysudo chown -R www-data:www-data /var/www/html/wordpress/# Changes the the permissions of the folder and it's content recursivelysudo chmod -R 755 /var/www/html/wordpress/
By default, nginx runs with the www-data user, for this reason, we need to change the owner of the wordpress folder and change the folder's permissions.
The chown -R command changes the owner recursively, that means that the folder and all the content inside it will change owner to www-data.
The chmod -R command changes the folder's permissions. Folder permissions are arranged in user:group:other format. Each one of them gets some permissions. The number for the reading permission is 4, writing permission is 2 and for the execution permission is 1. Combined, the user can read, write and execute. The group can read and execute and finally the others can read and execute as well.
When you enter your IP address on the URL, you should see the WordPress installation wizard, but don't run it yet, we haven't finished installing and securing your website.
Image: WordPress Installation isn't completed yet
Firewall Issue
If you can't see the WordPress installation page, it may be the fault of the ufw service, ufw stands for uncomplicated firewall. We will stop and disable the ufw service in favor of the nftables firewall, which is a more granular firewall solution, we will install it at the end.
# List all services running on the serverservice --status-all# Restart Nginxsudo systemctl disable ufwsudo systemctl stop ufw
DNS Binding
When you purchase a hosting plan, you get your server and a public IP address which you can then link to a domain name. A domain name helps users remember your website via a human-readable URL. Otherwise, they would have to remember four-byte IP addresses, which is neither convenient nor useful when searching for information.
You can link your domain name to your server through any domain name provider, as long as you have direct access to your DNS control panel. After installing the server you need to change the DNS configuration settings, just add ns1.vultr.com and ns2.vultr.com to your custom DNS server settings, after a while it should work.
A DNS A record allows you to link a domain name to a IP address. A DNS CNAME record allows you to create an alias when you want redirect your trafic from www.selfticode.com to selfticode.com
Image: Infomaniak's DNS control panel
Type | Hostname | Value |
A | selfticode.com | 134.122.90.217 |
CNAME | www.selfticode.com | selfticode.com |
TLS certificate
Transport Layer Security, also known as TLS, is a security protocol used to encrypt the user's connection to the website they are visiting. With TLS, it is not possible to perform a "man in the middle" attack, which means that a malicious user impersonates the web browser from the user's point of view and he also impersonates the user from the browser's point of view with the ultimate goal of stealing security credentials.
The only thing that the malicious user will see is encrypted data.
Why are TLS certificates important ?
Security plays a major role in the modern Internet, especially with regard to search engine rankings and user trust. If you process sensitive information via a form or sell products on your website, users expect secure communication between the browser and the website.
In the recent years, Google has enhanced it's search ranking factors, and one of them is security. Google will rank your website higher in search engines result if your website implements a TLS certificate.
Let's Encrypt
Let's Encrypt is a non profit certificate authority which provides TLS certificates. Before Let's Encrypt, you would have to pay for implementing a TLS certificate from a certificate authority, these days, security is more then ever encouraged to implement.
Certbot
Certbot is a free and open source automation tool which will allow you to implement a TLS certificate on your web server for free, it will automatically generate a certificate and modify your nginx configuration file.
# Install snapd# Verify latest version of snapdsudo snap install core; sudo snap refresh core# Install Certbotsudo snap install --classic certbot# Create a symlinksudo ln -s /snap/bin/certbot /usr/bin/certbot# Run Certbot on Nginx web serversudo certbot --nginx
By running Certbot, it will add a new server section in the nginx configuration file listening on port 443 for HTTPS requests.
Certificate Renewal
By default, Let's Encrypt TLS certificates are only valid for a time period of 90 days. So you have to run the process over and over again without forgeting it. Fortunately, we can automate the process without doing any manual action, this can be done with the help of cron jobs.
Cron jobs are repetitive actions that can be executed by a script during a time interval. These intervals can be configured to fire multiple times during this period.
# Cron configuration filecrontab -e# Certbot will try to run the renew process daily@daily certbot renew -n -q
Firewall
A firewall is like a security guard, it controls the traffic which wants to come in and out. One important measure for securing a server would be to implement a firewall for filtering unwanted requests. Nftables will be used as a popular firewall solution.
# Download packagessudo apt update# Install ntablessudo apt install nftables -y# Modify the nftables configuration filesudo nano /etc/nftables.conf
After nftables is installed, the configuration file must still be edited and the service needs to be restarted.
#!/usr/sbin/nft -fflush rulesettable inet filter {chain input {type filter hook input priority 0; policy drop;iif lo acceptct state invalid drop comment "Drop invalid connections"ct state established,related accept comment "Accept traffic originated from us"icmp type echo-request dropicmp type echo-request limit rate 10/second accepttcp dport {80, 443} accepttcp dport 22 accept}chain forward {type filter hook forward priority 0; policy drop;}chain output {type filter hook output priority 0;}}
# Restart nftablessudo systemctl restart nftables
After configuring nftables correctly, restart the service and open a new terminal. Test your SSH connectivity as well as all the other rules you allowed in the configuration file. In the worse case scenario, you will be locked out of your server but you will still be able to modify the configuration file on the opened terminal tab.
Image: The firewall controls the in going and outgoing traffic
Cloudflare caching
Cloudflare is a CDN, also known as a Content Delivery Network, it acts like a reverse proxy and sits in front of a web server. The advantage of using Cloudflare is that they have servers all around the world so that they can cache our website's static content and protect us against DDOS attacks.
Caching is the process of storing the temporary content of a request, so that when a second request asks for the same resources, a faster response time can be delivered. This is really great if you main server is in Europe, but you have users all around the world. The CDN will act as a middleman, which will shorten the distance that the request will have to make.
Distributed Denial of Service, also known as DDoS, is the act of attacking a server with hundreds of thousand of requests so that it will be unable to respond to all of them. This attack as of purpose to harm the website's traffic and bring them down temporary.
Image: Cloudflare caching & DDoS protection diagram
Conclusion
I hope your learned something in this article and that it helped you to install WordPress as well as secure your server. Now you know the pros and cons of a manual WordPress installation, if you choose the manual way, you will have total control of your website.
Image: Congratulation you have installed WordPress
Subscribe to the Newsletter
Don't miss the latest news, get early updates on development