Ravindra BagaleCourses & study guides मराठी Track your progress

How to Fix WordPress After the Server IP Changes

Your WordPress site runs on EC2. Stop the instance, start it again, and the site opens without any styling, its links hang and you cannot log in. In this chapter you find out why, look inside the database where the old address is stored, back up and restore the whole database with mysqldump, and change the address the safe way with WP-CLI. Then you install new themes, understand why WordPress suddenly asks for FTP details, and fix the next three problems every new WordPress server meets: a 404 after a theme change, "cannot generate responsive image sizes", and the upload size limit.

What you'll learn in this class

  • Why a WordPress site breaks after an EC2 stop and start, and where the old IP is stored
  • Preventing it: an Elastic IP or a domain before the site goes live
  • Backing up a database with mysqldump and >, and reading the .sql file
  • Copying the backup to your laptop and back with scp
  • Restoring with DROP, CREATE and <, and the common ERROR 1049
  • The safe address change: siteurl and home, then WP-CLI wp search-replace
  • Why a plain text replace in a dump can break serialized settings
  • Tab completion, history, and why files must be inside /usr/share/nginx/html
  • Installing themes, the "Connection Information" prompt and its real cause
  • vsftpd as an option, and why SFTP is safer than FTP
  • Fixing a 404 after a theme change, missing image sizes, and the upload size limit
  • Earning from a WordPress site, and building portfolio sites

1. Why the site breaks after a stop and start

Why: an EC2 instance without an Elastic IP gets a new public IP every time it is stopped and started. The server works at the new IP, but WordPress does not know that.

What: WordPress stores full addresses, including the IP, in its database:

  1. In the wp_options table, siteurl and home hold the address you installed WordPress at, for example http://3.3.3.3. Every page builds its CSS, script and link addresses from it.
  2. In the wp_posts table, every post you wrote keeps its links and images as full URLs, such as <img src="http://3.3.3.3/wp-content/uploads/bread.jpg">.

Classroom line

Every post we publish is saved inside the database.

What you see at the new IP, for example http://13.13.13.13:

  1. The page text arrives, but without styling: the stylesheet link still points to the old IP, where nobody answers.
  2. Clicking a post or an image goes to the old IP and hangs. The browser's status bar shows it waiting for the old address.
  3. /wp-admin/ redirects to the old IP's wp-login.php, so you cannot log in to fix it from the dashboard.

How to see it in the database:

    sudo mysql -u root -p
    USE wordpressdb;
    SHOW TABLES;
    SELECT option_name, option_value FROM wp_options WHERE option_name IN ('siteurl','home');
    SELECT post_content FROM wp_posts;
A black terminal. MariaDB prints Database changed, then the prompt MariaDB [wordpressdb]> show tables; and a table headed Tables_in_wordpressdb listing wp_commentmeta, wp_comments, wp_links, wp_options, wp_postmeta, wp_posts, wp_term_relationships, wp_term_taxonomy, wp_termmeta, wp_terms, wp_usermeta and wp_users.

Whiteboard: SHOW TABLES in wordpressdb: the 12 wp_ tables that the WordPress installer created, including wp_options and wp_posts.

Classroom line

We didn't create these tables; WordPress did.

After a stop and start: the server has anew IP, the database still has the old one The browser at the new IP http://13.13.13.13/ The page arrives, but:1. No styling: the stylesheet link points to the old IP, where nobody answers.2. Post links and images lead to the old IP.3. /wp-admin/ redirects to the old IP's wp-login.php, so you cannot log in.The browser status bar shows it waitingfor the old IP. Inside the database wordpressdb wp_options siteurl http://3.3.3.3 home http://3.3.3.3 The address WordPress was installed at. wp_posts (post_content) <img src="http://3.3.3.3/wp-content/ uploads/bread.jpg"> Full URLs saved inside every post you wrote. See them: SELECT * FROM wp_posts;

Figure 1. After a stop and start the browser is at the new IP, but wp_options (siteurl, home) and the HTML inside wp_posts still hold the old IP, so styling, links and wp-admin point to an address that no longer answers.

2. Prevent it: a fixed address before going live

Why: repairing the address is work and carries risk. Not needing it is better.

How:

  1. Elastic IP: in the EC2 console, allocate an Elastic IP and associate it with the instance. The public IP then stays the same across stops and starts.
  2. Domain name: point a domain, such as www.example.com, at the Elastic IP with an A record, and install WordPress at the domain. WordPress then saves the name, not the IP.
  3. Do this before you install WordPress or show the site to anyone. A company website gets its Elastic IP or domain from day one.
  4. Release an Elastic IP you no longer use.

Classroom line

To avoid this, companies always use a static IP.

Prevent it: give the server anaddress that never changes, beforeyou go live Auto-assigned public IP Monday 3.3.3.3 stop + start Tuesday 13.13.13.13 A new IP after every stop andstart: WordPress breaks. Elastic IP Monday 3.3.3.3 stop + start Tuesday 3.3.3.3 A static public IP you allocateand associate with the instance. A domain name www.example.com -> A record -> Elastic IP Install WordPress at the domain,so the saved address is thename, not an IP. In a company: Elastic IP or domain from day one.For a site that already moved, change the storedaddress (this chapter).

Figure 2. An auto-assigned public IP changes after a stop and start; an Elastic IP stays the same; a domain pointing at the Elastic IP lets WordPress save a name instead of an IP.

For a site that has already moved, the rest of this chapter shows how to take a backup and then change the stored address safely.

3. Back up the database with mysqldump

Why: before you change anything inside a database, keep a copy you can go back to. A backup is also how you move a site to another server.

What: mysqldump writes a whole database as one plain-text file of SQL commands. The > sign sends a command's output into a file instead of the screen.

How:

    sudo mysqldump -u root -p wordpressdb > wp.sql
    ls -l wp.sql
  1. Type the MariaDB root password when asked. The file wp.sql appears in your current folder.
  2. > creates the file, or overwrites it if it already exists. Use a new name, such as wp-before-change.sql, to keep an older backup.
  3. Open it with nano wp.sql or less wp.sql, and close it without saving.

What is inside wp.sql:

  1. For each of the 12 tables: DROP TABLE IF EXISTS, then CREATE TABLE with its columns, then INSERT INTO with all its rows.
  2. Your posts, settings and the old IP are all there as readable text.
  3. There is no CREATE DATABASE line, so a restore needs a database that already exists.
What is inside wp.sql: plain SQLthat rebuilds every table -- MariaDB dump ... Database:wordpressdbDROP TABLE IF EXISTS `wp_options`;CREATE TABLE `wp_options` (`option_id` bigint(20) unsigned NOTNULL ...`option_name` varchar(191) ...) ENGINE=InnoDB ...;INSERT INTO `wp_options` VALUES(1,'siteurl','http://3.3.3.3','on'),(2,'home','http://3.3.3.3','on'), ... For each of the 12 tables:DROP TABLE IF EXISTS removes the old table,CREATE TABLE builds it again,INSERT INTO puts the rows back.There is no CREATE DATABASE:restore into a database thatalready exists.The old IP is in here as text. Use the same database name everywhere: mysqldumpwordpressdb, CREATE DATABASE wordpressdb,mysql wordpressdb.

Figure 3. wp.sql is plain SQL: for every table DROP TABLE IF EXISTS, CREATE TABLE and INSERT INTO. There is no CREATE DATABASE, and the old IP is inside as text.

4. Copy the backup off the server with scp

Why: a backup that lives only on the server is lost together with the server. Keep a copy on your laptop.

How: run these on your laptop, in the folder that holds your key:

  1. Download, server to laptop (the . at the end means "this folder"):

    scp -i mykey.pem ec2-user@PUBLIC_IP:/home/ec2-user/wp.sql .
    
  2. Upload, laptop to server:

    scp -i mykey.pem wp.sql ec2-user@PUBLIC_IP:/home/ec2-user/
    
  3. scp uses the same key and user as ssh. Replace PUBLIC_IP with the server's current IP.

  4. Before you upload a changed file with the same name, rename the old one on the server, for example mv wp.sql old-wp.sql, so that you still have it.

5. Restore the database

Why: a restore puts the backup back, after a mistake or on a new server.

How:

  1. Log in with sudo mysql -u root -p and empty the database by dropping it and creating it again:

    DROP DATABASE wordpressdb;
    CREATE DATABASE wordpressdb;
    EXIT;
    
  2. Feed the file back in. < sends a file into a command:

    sudo mysql -u root -p wordpressdb < wp.sql
    
  3. Check: USE wordpressdb; and SHOW TABLES; list the 12 tables again.

  4. Drop the database only after you have checked that wp.sql is complete; it is your only copy of the site's content.
  5. The same database name is used everywhere: in mysqldump, in CREATE DATABASE, in the restore command and in wp-config.php.

Classroom line

Drop the old database, create an empty one, and restore into it.

A common error:

    ERROR 1049 (42000): Unknown database 'wordpresdb'

This means there is no database with that name: here wordpresdb is a typo for wordpressdb. Run SHOW DATABASES;, compare the spelling letter by letter, and run the command again.

Back up and restore a WordPress database withmysqldump 1. Back up: mysqldump writes the whole database into onefile sudo mysqldump -u root -p wordpressdb > wp.sql ls -l wp.sql -rw-r--r--. 1 ec2-user ec2-user 114776 wp.sql &gt; sends the output INTO the file wp.sql (a new file each time). wp.sql is plain text: open it with nano or less. 2. Copy it to your laptop with scp (run these on the laptop) scp -i mykey.pemec2-user@PUBLIC_IP:/home/ec2-user/wp.sql . scp -i mykey.pem wp.sqlec2-user@PUBLIC_IP:/home/ec2-user/ Download: server to laptop. Upload: laptop to server. A copy off the server survives even if the server is lost. 3. Restoring into a fresh database: drop it and create itempty MariaDB [(none)]> DROP DATABASE wordpressdb; MariaDB [(none)]> CREATE DATABASE wordpressdb; Query OK, 1 row affected The dump has no CREATE DATABASE line, so the database must existfirst. Only drop it when wp.sql is safe. 4. Restore: mysql reads the file back into the database sudo mysql -u root -p wordpressdb < wp.sql sudo mysql -u root -p wordpresdb < wp.sql ERROR 1049 (42000): Unknown database 'wordpresdb' &lt; feeds the file INTO the command. All 12 tables come back. ERROR 1049 is a typo in the database name: check the spelling.

Figure 4. Animation: back up with mysqldump and >, copy the file with scp, drop and create an empty database, restore with mysql and <. ERROR 1049 means the database name is misspelled.

6. The safe way to change the address

Why: after a stop and start, the old IP sits in many places in the database. You need to replace all of them without damaging the settings.

What goes wrong with a plain text replace: you could download wp.sql, open it in an editor, replace http://3.3.3.3 with http://13.13.13.13 everywhere, upload it and restore it. Posts and links then work, but some settings may be silently lost:

  1. Themes, plugins and widgets save their settings in a serialized format, where every piece of text carries its length, for example s:42:"http://3.3.3.3/wp-content/uploads/logo.png".
  2. A text editor or sed changes the text but not the number. With a new IP of a different length the number is now wrong, WordPress cannot read the value, and that setting is lost without any error.
  3. A plain replace is only harmless when the old and new addresses have exactly the same length. Even then, the method below is better.

Classroom line

For many changes inside the database, you have to find and replace.

Why a plain text replace can break WordPresssettings 1. A theme or plugin setting is saved "serialized": everytext has its length a:1:{s:4:"logo";s:42: "http://3.3.3.3/wp-content/uploads/logo.png";} s:42 means "the next text is 42 characters long". It matches:WordPress reads the setting. 2. Plain find and replace in wp.sql (an editor, or sed)changes the text, not the length a:1:{s:4:"logo";s:42: "http://13.13.13.13/wp-content/uploads/logo.png";} The text is now 46 characters but still says s:42. WordPress cannotread it, gets nothing, and that setting is silently lost: a logo, a menu,widget settings. No error is shown. 3. WP-CLI wp search-replace understands serialized dataand fixes the length a:1:{s:4:"logo";s:46: "http://13.13.13.13/wp-content/uploads/logo.png";} Now s:46 matches the 46-character text. Tested: the setting stillreads correctly. Plain replace is only safe when old and new have the same length, andeven then search-replace is better.

Figure 5. Animation: a serialized setting stores the length of each text (s:42). A plain replace changes the text to 46 characters but leaves s:42, so WordPress cannot read it; wp search-replace updates the length to s:46.

How, step by step:

  1. Back up first: sudo mysqldump -u root -p wordpressdb > before-ip-change.sql.
  2. Fix the two saved addresses so that wp-admin works again. In sudo mysql -u root -p:

    USE wordpressdb;
    UPDATE wp_options SET option_value='http://13.13.13.13' WHERE option_name IN ('siteurl','home');
    
  3. Install WP-CLI, the WordPress command line:

    curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
    php wp-cli.phar --info
    chmod +x wp-cli.phar
    sudo mv wp-cli.phar /usr/local/bin/wp
    
  4. Preview the replace. Run it as apache, the php-fpm user, from the WordPress folder. --dry-run only counts:

    cd /usr/share/nginx/html/wordpress
    sudo -u apache /usr/local/bin/wp search-replace 'http://3.3.3.3' 'http://13.13.13.13' --skip-columns=guid --dry-run
    
  5. Run it for real by repeating the command without --dry-run. It changes posts, links and serialized settings, and fixes each length.

  6. Check: curl -I http://13.13.13.13/, then open a post and /wp-admin/. Styling, links and login are all on the new IP.

Notes:

  1. Include http:// in both addresses, so that only URLs change and not some other number that happens to look like the IP.
  2. --skip-columns=guid leaves the guid column alone; it is a permanent ID of each post, not a link.
  3. Keep before-ip-change.sql until you are sure everything works. If something goes wrong, restore it as in section 5.

Classroom line

Now click any post; it works.

The safe way to change a WordPress address 1. Back up first Your way back if anything goes wrong. sudo mysqldump -u root -p wordpressdb >before-ip-change.sql 2. Fix the two saved addresses In MariaDB. wp-admin works again. UPDATE wp_options SET option_value='http://13.13.13.13'WHERE option_name IN ('siteurl','home'); 3. Preview the full replace Shows how many replacements; changes nothing. wp search-replace 'http://3.3.3.3' 'http://13.13.13.13'--skip-columns=guid --dry-run 4. Run it for real Posts, links and serialized settings, lengths fixed. wp search-replace 'http://3.3.3.3' 'http://13.13.13.13'--skip-columns=guid 5. Check, and keep the backup Then open posts and /wp-admin/: all on the new IP. curl -I http://13.13.13.13/ Run it as the PHP user, in the WordPress folder: sudo -u apache/usr/local/bin/wp search-replace ...

Figure 6. The safe address change in five steps: back up, fix siteurl and home in wp_options, preview wp search-replace with --dry-run, run it for real, then check and keep the backup.

7. Two terminal habits: Tab and history

Why: WordPress paths are long (/usr/share/nginx/html/wordpress/wp-content/...). Tab saves typing and typos, and history lets you repeat a long command you ran earlier.

Tab completion: type the start of a file or folder name and press Tab; the shell completes it.

  1. If two names start the same way, such as Documents and Downloads, then cd Do + Tab cannot choose. Press Tab twice to see both.
  2. Type one more letter, cd Dow + Tab, and it completes to Downloads.
  3. Tab also prevents typos such as wordpresdb in file names and paths.

Classroom line

Two folders start with DO, Documents and Downloads; so which should it open?

Classroom line

Type DOW and it understands.

history: history prints the commands you ran in this shell, numbered, in order. history | grep vsftpd shows only the lines with vsftpd. Use it to review the steps you followed or to write your own notes.

8. Your files must be inside /usr/share/nginx/html

Why: nginx on Amazon Linux serves only what is inside its web root, /usr/share/nginx/html (or the root you set in the server block). A page saved in your home folder, /home/ec2-user, is never shown.

How:

  1. Move or copy the file into the web root:

    sudo mv ~/index.php /usr/share/nginx/html/
    
  2. WordPress itself lives in /usr/share/nginx/html/wordpress, and nginx's root points there.

  3. A 404 Not Found for a file you are sure you created usually means it is in the wrong folder. Check with ls -l /usr/share/nginx/html.

Classroom line

The page shows only if it's exactly inside that folder.

9. Install a theme

Why: a theme changes the whole look of the site without touching the content. The directory at wordpress.org has thousands of free themes.

How:

  1. Log in to /wp-admin/ and go to Appearance > Themes > Add New.
  2. Search or browse, click Install, then Activate.
  3. Open the site and compare. Many themes look like their demo only after you customise them under Appearance > Customize or the site editor.
  4. Some themes have a free version with a paid upgrade for extra features; the free version is enough for practice.

Classroom line

Theme makers say they need to earn money too.

10. "Connection Information": why WordPress asks for FTP

Why: when you click Install, WordPress may show a Connection Information form asking for a Hostname, FTP Username and FTP Password, instead of installing the theme.

What: WordPress must write the theme's files into wp-content/themes. It runs as the php-fpm user, apache. If that user cannot write to the folder, for example because it belongs to root after sudo unzip, WordPress asks for an FTP login so it can write the files another way. On a test server, the form appeared when root owned the folder and disappeared when apache owned it.

A white form titled Connection Information. Text: To perform the requested action, WordPress needs to access your web server. Please enter your FTP credentials to proceed. If you do not remember your credentials, you should contact your web host. Empty fields Hostname (placeholder example: www.wordpress.org), FTP Username and FTP Password, a note that the password will not be stored on the server, and Connection Type options FTP (selected) and FTPS (SSL).

Whiteboard: The Connection Information form: WordPress cannot write to its own folder, so it asks for FTP details.

Classroom line

We must let the website transfer files onto our server.

Fix A, the best: give the folder to the php-fpm user, as in the previous chapter:

    sudo chown -R apache:apache /usr/share/nginx/html/wordpress
    sudo find /usr/share/nginx/html/wordpress -type d -exec chmod 755 {} \;
    sudo find /usr/share/nginx/html/wordpress -type f -exec chmod 644 {} \;

Reload the theme page. The form does not come back, and themes, plugins and updates install directly.

Fix B, only together with A: add this line to wp-config.php, above the line /* That's all, stop editing! */:

    define('FS_METHOD', 'direct');

It tells WordPress to skip the form and write directly. It does not give any permission: if apache still cannot write to the folder, the install fails with "Could not create directory".

"Connection Information" when you install atheme: a folder-ownership problem php-fpm runs WordPress as the user apache. To add a theme it mustwrite into wp-content/themes. If the folder belongs to root (forexample after sudo unzip), WordPress cannot write, so it asks for anFTP login instead: Hostname, FTP Username, FTP Password. Tested:owner root gives the form, owner apache does not. A. Fix the owner (best) cd /usr/share/nginx/html sudo chown -R apache:apache wordpress Folders 755, files 644, as in the previous chapter. The form nevercomes back; themes, plugins and updates install directly. B. FS_METHOD direct define('FS_METHOD','direct'); In wp-config.php, above "That's all, stop editing". It only skips theform: the folder must still be writable by apache, or the install fails.Use it together with A. C. An FTP server (vsftpd) Hostname localhost: the FTP server runs on the same EC2 machine.Files are then written as ftpuser. FTP sends the passwordunencrypted. Prefer A; if you need file transfer, use SFTP (it rides onSSH).

Figure 7. Connection Information appears because php-fpm (user apache) cannot write to wp-content. Fix A: chown the folder to apache. B: FS_METHOD direct only skips the form. C: an FTP server, unencrypted, so prefer A or SFTP.

11. Option: an FTP server with vsftpd

Why: some hosting setups use FTP for WordPress updates, and you will meet the form again. On your own EC2 server you can give WordPress an FTP login with vsftpd. Fix A is simpler; learn this as an option.

How:

  1. Install and start the FTP server:

    sudo yum install vsftpd -y
    sudo service vsftpd start
    
  2. In /etc/vsftpd/vsftpd.conf, check that local_enable=YES and write_enable=YES are set; after any change run sudo service vsftpd restart.

  3. Create an FTP user with a strong password, and add it to the nginx group:

    sudo useradd ftpuser
    sudo passwd ftpuser
    sudo usermod -aG nginx ftpuser
    
  4. Let that group write to wp-content:

    sudo chgrp -R nginx /usr/share/nginx/html/wordpress/wp-content
    sudo chmod -R g+w /usr/share/nginx/html/wordpress/wp-content
    
  5. In the Connection Information form enter Hostname localhost (the FTP server runs on the same EC2 machine), the FTP username ftpuser and its password, Connection Type FTP. The theme installs; click Activate.

  6. Port 21 does not need to be opened in the security group, because WordPress connects to localhost.

Know the risk: FTP sends the username and password unencrypted. Use a long, unique password, never something like 12345678. To move files from your laptop, prefer SFTP, which uses your existing SSH key, or FTPS with TLS. Files written over FTP belong to ftpuser, which is one more reason Fix A is the cleaner choice.

Classroom line

With FTP we can transfer files.

12. A 404 after activating a theme

Why: after you activate a theme, the site's pages and post links may show 404 Not Found from nginx, because many themes use pretty links such as /hello-world/.

What: such addresses are not real files. nginx needs the try_files line to hand them to index.php.

How: in the server block, inside location /:

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

Then sudo nginx -t and sudo service nginx reload.

13. "Cannot generate responsive image sizes"

Why: when you upload an image, WordPress also makes smaller copies of it for phones and thumbnails. It needs a PHP image library for that.

What: without one, every image upload shows "The web server cannot generate responsive image sizes for this image. Convert it to JPEG or PNG before uploading." Converting does not help; the server is missing the library.

How:

    sudo yum install php-gd -y
    sudo service php-fpm restart

The restart matters: php-fpm loads its extensions only when it starts. Upload the image again; the message is gone.

WordPress block editor with a Video block: Drag and drop a video, upload, or choose from your library, and the buttons Upload, Media Library and Insert from URL. Below are three dark notices: twice The web server cannot generate responsive image sizes for this image. Convert it to JPEG or PNG before uploading., and myvideo.mp4: This file exceeds the maximum upload size for this site.

Whiteboard: A video block in the editor with two image-size notices and an upload size error. The video file name in the last notice was replaced with myvideo.mp4.

14. Raise the upload size limit

Why: a video or a large image fails with "This file exceeds the maximum upload size for this site." Media > Add New shows the current limit as "Maximum upload file size".

What: an upload passes three limits, and the smallest wins:

  1. nginx client_max_body_size, default 1 MB. A bigger upload gets 413 Request Entity Too Large, and PHP never sees it.
  2. PHP post_max_size, default 8M, for the whole request. A bigger upload arrives empty.
  3. PHP upload_max_filesize, default 2M, for one file. WordPress shows the "exceeds the maximum upload size" message.

How:

  1. In /etc/php.ini set both lines, then restart php-fpm:

    upload_max_filesize = 64M
    post_max_size = 64M
    
    sudo service php-fpm restart
    
  2. In the nginx server block add client_max_body_size 64M;, then:

    sudo nginx -t
    sudo service nginx reload
    
  3. Reload Media > Add New: it now shows "Maximum upload file size: 64 MB." On a test server, a 1.5 MB file failed with 413 at nginx's default, and after all three changes a 9 MB file uploaded.

  4. Upload your own videos and images, or ones whose licence allows reuse, not files downloaded from random sites.
A file upload passes three limits; the smallest onewins nginx client_max_body_size default 1 MB Bigger: 413 Request Entity Too Large, PHP never sees it. Set: client_max_body_size 64M; PHP: whole request post_max_size default 8M Bigger: the upload arrives empty. Set: post_max_size = 64M PHP: one file upload_max_filesize default 2M Bigger: "This file exceeds the maximum upload size for this site." Set: upload_max_filesize = 64M nginx: in the server block of /etc/nginx/nginx.conf, then sudo nginx -t andsudo service nginx reload. PHP: both lines in /etc/php.ini, then sudo service php-fpm restart. Media&gt; Add New then shows "Maximum upload file size: 64 MB." Tested: 1.5 MB failed with 413 at nginx's default; after all three changes 9MB uploaded.

Figure 8. An upload passes nginx client_max_body_size (default 1 MB), PHP post_max_size (8M) and upload_max_filesize (2M); raise all three, then reload nginx and restart php-fpm.

15. Earning from a site, and building a portfolio

Why: Hosting a site is a skill people pay for. A site on its own domain, and a portfolio of sites you built, is how you show that skill.

Earning from a site:

  1. Put the site on its own domain, with an Elastic IP behind it.
  2. Write original, useful content. Google AdSense shows ads on approved sites and pays for them; the site must meet its policies to be approved.
  3. SEO (search engine optimisation): clear titles, good content and fast pages help the site appear in Google search. More visitors means more ad income.

Classroom line

You can build a proper website and just add Google ads to it.

Classroom line

Do SEO and it shows up in Google search.

Building a portfolio:

  1. Build a different practice site often: a shop, a hospital, a restaurant, a school. Switch themes and fill each with sample content.
  2. Share screenshots of them, for example on WhatsApp status or Instagram. People who see them ask you to build theirs.
  3. Use your own images or freely licensed ones, and mark sample shops as demos.

Classroom line

Make a WordPress site every day and put it on your WhatsApp status.

16. When something goes wrong

Why: Most WordPress problems repeat. A short checklist in the right order fixes them faster than guessing.

  1. The site does not open at all: start the services: sudo service nginx start, sudo service mariadb start, sudo service php-fpm start.
  2. No styling, old IP in the links: the address changed. Use an Elastic IP, or the safe address change in section 6.
  3. Your page does not show: it is not inside /usr/share/nginx/html. Check with ls -l.
  4. The installer appears again, or "Error establishing a database connection": wp-config.php is missing, or the database name, user or password in it does not match.
  5. ERROR 1049 Unknown database: a typo in the database name. Compare with SHOW DATABASES;.
  6. You cannot find the admin page: it is http://YOUR-ADDRESS/wp-admin/.
  7. Post links or the page after a theme change give 404: add the try_files line and reload nginx.
  8. Installing a theme asks for FTP: give the folder to apache with chown.
  9. "Cannot generate responsive image sizes": install php-gd and restart php-fpm.
  10. "Exceeds the maximum upload size" or 413: raise the PHP limits and nginx's client_max_body_size.
WordPress on EC2: what you see, what to check Site does not open at all → Are nginx, mariadb and php-fpm started? sudo service nginx status Page without styling, old IP in links → The address changed: Elastic IP, or the safe address change Your page does not show → Is it inside /usr/share/nginx/html (the root)? ls -l it there Installer asks again / DB error → wp-config.php present? DB name, user, password exactly right? ERROR 1049 Unknown database → Typo in the database name: SHOW DATABASES; and compare Cannot find the admin page → It is http://YOUR-ADDRESS/wp-admin/ Post links 404 (e.g. after a theme) → try_files line in the nginx server block, then nginx -t, reload Theme install asks for FTP → Ownership: chown -R apache:apache the wordpress folder "Cannot generate responsive image sizes" → sudo yum install php-gd -y, then sudo service php-fpm restart "Exceeds the maximum upload size" / 413 → php.ini limits + nginx client_max_body_size, restart/reload Logs tell you the rest: /var/log/nginx/error.log and/var/log/php-fpm/www-error.log

Figure 9. WordPress on EC2: what you see and what to check, from services and the web root to the address, try_files, folder ownership, php-gd and the upload limits. The logs are in /var/log/nginx/error.log and /var/log/php-fpm/www-error.log.

Ravindra Bagale's Tip

Before you change anything in a WordPress database, run mysqldump and copy the file to your laptop with scp. With a backup, any mistake is one restore away. And never use a plain find-and-replace for a new address: wp search-replace with --dry-run first shows you what will change, and keeps the serialized settings intact.

When you're done practising, stop the EC2 instance. Without an Elastic IP its public IP will change, and now you know how to repair that.

17. The whole class on one page

  1. WordPress stores full addresses: siteurl and home in wp_options, and full URLs inside wp_posts. A new EC2 IP leaves the site unstyled and wp-admin unreachable.
  2. Prevent it with an Elastic IP or a domain before the site goes live.
  3. Back up: sudo mysqldump -u root -p wordpressdb > wp.sql; the file is plain SQL with DROP TABLE, CREATE TABLE and INSERT INTO, but no CREATE DATABASE.
  4. scp -i mykey.pem ec2-user@PUBLIC_IP:/home/ec2-user/wp.sql . downloads; scp -i mykey.pem wp.sql ec2-user@PUBLIC_IP:/home/ec2-user/ uploads.
  5. Restore: DROP DATABASE, CREATE DATABASE, then sudo mysql -u root -p wordpressdb < wp.sql. ERROR 1049 is a misspelled database name.
  6. Change the address safely: back up, update siteurl and home, then wp search-replace 'http://OLD' 'http://NEW' --skip-columns=guid, first with --dry-run.
  7. A plain text replace can break serialized settings when the lengths differ.
  8. Tab completes names; history lists your commands; web files must be inside /usr/share/nginx/html.
  9. Themes: Appearance > Themes > Add New. "Connection Information" means apache cannot write to the folder: chown -R apache:apache. FS_METHOD direct only skips the form.
  10. vsftpd is an option: useradd ftpuser, passwd, usermod -aG nginx, Hostname localhost. FTP is unencrypted; prefer SFTP and a strong password.
  11. A 404 after a theme change needs try_files; missing image sizes need php-gd and a php-fpm restart.
  12. Uploads: upload_max_filesize and post_max_size in /etc/php.ini, client_max_body_size in nginx, then restart and reload.
  13. Earn with your own domain, original content, AdSense and SEO; build practice sites as your portfolio.

18. Hands-on lab: back up, then fix the address after an IP change

Why this lab. After a stop and start, a WordPress site on a plain public IP loads without styles or redirects to the old address. This lab backs up first, tries the change as a dry run, and only then makes it.

  1. See the old address in the database
    • Command: sudo mysql -u root -p wordpressdb -e "SELECT option_name, option_value FROM wp_options WHERE option_name IN ('siteurl','home');"
    • You should see: Two rows, both with the old http:// address.
    • Check: The value differs from your new public IP.
    • Why: WordPress stores full addresses in the database, so it keeps sending browsers to the old IP.
  2. Back up the database
    • Command: sudo mysqldump -u root -p wordpressdb > wp.sql
    • You should see: Nothing.
    • Check: ls -l wp.sql shows a size above 0, and head -3 wp.sql starts with a -- MariaDB dump comment.
    • Why: Every later step changes the database. With wp.sql you can undo any mistake.
  3. Copy the backup to your laptop
    • Command: scp -i mykey.pem ec2-user@PUBLIC_IP:/home/ec2-user/wp.sql .
    • You should see: A progress line ending in 100%.
    • Check: wp.sql is in your laptop folder.
    • Why: Run this on the laptop. A backup only on the server is lost together with the server.
  4. Install WP-CLI
    • Command: curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && chmod +x wp-cli.phar && sudo mv wp-cli.phar /usr/local/bin/wp
    • You should see: curl's download progress, then the prompt.
    • Check: wp --info prints the WP-CLI and PHP versions.
    • Why: WP-CLI replaces addresses everywhere, including inside serialized data that a plain SQL UPDATE would corrupt.
  5. Dry run the replacement
    • Command: cd /usr/share/nginx/html/wordpress && sudo -u apache wp search-replace 'http://OLD_IP' 'http://NEW_IP' --skip-columns=guid --dry-run
    • You should see: A table of tables and how many replacements each would get, then Success: ... replacements to be made.
    • Check: Nothing has changed yet: the siteurl query from step 1 still shows the old address.
    • Why: --dry-run shows what would change without changing it. --skip-columns=guid leaves post IDs alone, as WordPress recommends.
  6. Run it for real
    • Command: sudo -u apache wp search-replace 'http://OLD_IP' 'http://NEW_IP' --skip-columns=guid
    • You should see: The same table, then Success: Made ... replacements.
    • Check: Step 1's query now shows the new address, and http://NEW_IP/ loads with styles.
    • Why: Running as apache keeps file ownership correct. Only now, after a backup and a dry run, is the change safe.
  7. Know how to restore
    • Command: sudo mysql -u root -p wordpressdb < wp.sql
    • You should see: Nothing.
    • Check: Step 1's query shows the old address again. Repeat step 6 to return to the new one.
    • Why: A backup you have never restored is a guess. Restoring once proves it works.
  8. Stop, and plan a fixed address
    • Do: Stop the instance. Before going live, attach an Elastic IP or use a domain name (section 2).
    • Check: State Stopped.
    • Why: With a fixed address you never need this repair again.

19. Try at home

Try at home

Task 1: see the problem

  1. On your WordPress server, run SELECT option_name, option_value FROM wp_options WHERE option_name IN ('siteurl','home'); and write down the address.
  2. Stop and start the instance, open the new IP, and note what is broken.

Task 2: backup and restore

  1. Take a backup with mysqldump, look inside it with less, and download it with scp.
  2. Drop and create wordpressdb, restore the backup, and check SHOW TABLES;.
  3. Run the restore once with a misspelled database name and read the error.

Task 3: change the address

  1. Install WP-CLI, update siteurl and home, and run wp search-replace with --dry-run. How many replacements does it report?
  2. Run it for real and check that styling, posts and wp-admin work at the new IP.

Task 4: themes and uploads

  1. Make root the owner of wp-content/themes, try to install a theme, and see the form. Then fix it with chown -R apache:apache.
  2. Install php-gd, restart php-fpm, and upload an image of your own.
  3. Raise the upload limit to 64M and check Media > Add New.

Recap

In short

  1. WordPress saves its address and full URLs in the database, so a new EC2 IP breaks the styling, the links and the login.
  2. An Elastic IP or a domain before going live avoids the problem.
  3. mysqldump ... > wp.sql backs up a database as plain SQL; scp copies it off the server; mysql ... < wp.sql restores it into an empty database.
  4. Change an address with a backup, siteurl and home, and wp search-replace, because a plain replace can break serialized settings.
  5. "Connection Information" means WordPress cannot write to its folder; make apache the owner. FTP works but is unencrypted.
  6. try_files fixes 404s, php-gd with a php-fpm restart fixes image sizes, and three settings control the upload limit.
  7. A site earns with a domain, good content, AdSense and SEO, and practice sites make a portfolio.

Practice Tasks

About this scenario

Mumbai Dabba Express is a food delivery business in Mumbai. Tukaram Gaikwad looks after its IT and cloud work. They count money in INR and run their AWS resources in the ap-south-1 Region. In the tasks below you do real jobs for them using what this lesson teaches. All names, account IDs, IP addresses and numbers are made up for practice.

0 / 12

Easy Biggest orders first

Why: Querying the database is daily work after you set up RDS.

What to do: Show order id and amount, biggest amount first.

Tables: customers(id, name, city) and orders(id, customer_id, amount, odate).

How:
  1. Find the table the task is about (see the table list above the box).
  2. Write the SQL statement step by step: what, from where, which rows.
  3. End the statement with ;
  4. Click Check answer. Your query runs on a practice copy of the table.

Easy Filter customers by city

Why: Querying the database is daily work after you set up RDS.

What to do: List the names of customers in Pune.

Tables: customers(id, name, city) and orders(id, customer_id, amount, odate).

How:
  1. Find the table the task is about (see the table list above the box).
  2. Write the SQL statement step by step: what, from where, which rows.
  3. End the statement with ;
  4. Click Check answer. Your query runs on a practice copy of the table.

Easy Install a package on Ubuntu

Why: Ubuntu uses apt. Package names differ: on Ubuntu Apache is apache2.

What to do: Install the apache2 package on Ubuntu without being asked to confirm.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Easy Test a website from the server

Why: curl shows whether the web server answers, even before DNS is ready.

What to do: Request http://localhost and show only the response headers.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Medium Remove small orders

Why: Querying the database is daily work after you set up RDS.

What to do: Delete orders with amount below 200.

Tables: customers(id, name, city) and orders(id, customer_id, amount, odate).

How:
  1. Find the table the task is about (see the table list above the box).
  2. Write the SQL statement step by step: what, from where, which rows.
  3. End the statement with ;
  4. Click Check answer. Your query runs on a practice copy of the table.

Medium Orders with customer names

Why: Querying the database is daily work after you set up RDS.

What to do: Show each customer name with each order amount.

Tables: customers(id, name, city) and orders(id, customer_id, amount, odate).

How:
  1. Find the table the task is about (see the table list above the box).
  2. Write the SQL statement step by step: what, from where, which rows.
  3. End the statement with ;
  4. Click Check answer. Your query runs on a practice copy of the table.

Medium Total sales

Why: Querying the database is daily work after you set up RDS.

What to do: Show the total of all order amounts as one number.

Tables: customers(id, name, city) and orders(id, customer_id, amount, odate).

How:
  1. Find the table the task is about (see the table list above the box).
  2. Write the SQL statement step by step: what, from where, which rows.
  3. End the statement with ;
  4. Click Check answer. Your query runs on a practice copy of the table.

Medium Fix a city

Why: Querying the database is daily work after you set up RDS.

What to do: Customer 5 moved to Rome. Update the record.

Tables: customers(id, name, city) and orders(id, customer_id, amount, odate).

How:
  1. Find the table the task is about (see the table list above the box).
  2. Write the SQL statement step by step: what, from where, which rows.
  3. End the statement with ;
  4. Click Check answer. Your query runs on a practice copy of the table.

Medium Open port 80 to the world

Why: Visitors can reach your website only if the security group allows HTTP.

What to do: Allow inbound TCP port 80 from 0.0.0.0/0 on security group sg-01a03134416a4c3b2.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Sales per customer

Why: Querying the database is daily work after you set up RDS.

What to do: Show customer_id and total amount per customer, only where total is above 1000.

Tables: customers(id, name, city) and orders(id, customer_id, amount, odate).

How:
  1. Find the table the task is about (see the table list above the box).
  2. Write the SQL statement step by step: what, from where, which rows.
  3. End the statement with ;
  4. Click Check answer. Your query runs on a practice copy of the table.

Hard Customers with no orders

Why: Querying the database is daily work after you set up RDS.

What to do: List names of customers who have never ordered.

Tables: customers(id, name, city) and orders(id, customer_id, amount, odate).

How:
  1. Find the table the task is about (see the table list above the box).
  2. Write the SQL statement step by step: what, from where, which rows.
  3. End the statement with ;
  4. Click Check answer. Your query runs on a practice copy of the table.

Hard Back up a database to a file

Why: mysqldump writes the whole database as SQL. Save it before big changes.

What to do: Dump the database mumbaidabba_wp as user root (ask for password) into mumbaidabba_wp.sql.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Quick revision cards

Revise this lesson in two minutes. Save the cards on your phone or download them as PNG files. The QR code on each card opens its lesson.

Comparison card: scp vs FTP / SFTP (FileZilla). scp: Command-line copy over SSH. FTP / SFTP (FileZilla): File transfer protocol; FileZilla is a GUI app for it.
Comparison: scp vs FTP / SFTP (FileZilla) · Download PNG
Revision card: Back up with mysqldump. Posts and users live in the database, not in files. Losing it loses the site. mysqldump writes the database as SQL statements into a .sql file. Dump with >, copy it off the server with scp. Dump:
Revision card: Back up with mysqldump · Download PNG
Revision card: Restore a database. A backup is useful only if you can restore it. Create the empty database, then feed the .sql file with <. ERROR 1049 means the database does not exist yet: create it first. Restore:
Revision card: Restore a database · Download PNG
Revision card: Change the site address: wp search-replace. After an IP change, WordPress still links to the old address. WP-CLI search-replace updates every URL safely, including serialized settings. Set siteurl and home, then run search-replace. Command:
Revision card: Change the site address: wp search-replace · Download PNG
Revision card: Theme install and Connection Information. Installing a theme asks for FTP details you do not have. WordPress asks when PHP cannot write to its folder. The real fix is ownership. Give the folder to the php-fpm user; no FTP needed. Fix:
Revision card: Theme install and Connection Information · Download PNG
Comparison: mysqldump > file vs mysql < file. mysqldump > file: Writes the database out as an SQL file. mysql < file: Reads an SQL file into a database.
Comparison: mysqldump > file vs mysql < file · Download PNG
Interview card: Why does WordPress break after a stop and start?. The public IP changed, and the old IP is saved in siteurl and home. All links and CSS point to the old IP. Prevent with an Elastic IP or domain; fix with wp search-replace.
Interview card: Why does WordPress break after a stop and start? · Download PNG
Interview card: Why not just find-and-replace the IP in the .sql dump?. Serialized settings store string lengths; a new length breaks them. Widgets and theme settings vanish. Use WP-CLI, which fixes lengths.
Interview card: Why not just find-and-replace the IP in the .sql dump? · Download PNG
Interview card: Why is SFTP safer than FTP?. SFTP runs over SSH and encrypts everything; FTP sends passwords in plain text. Anyone on the path can read FTP logins. SFTP uses port 22 and your key.
Interview card: Why is SFTP safer than FTP? · Download PNG
Interview card: How do you back up a WordPress site fully?. Dump the database and zip the WordPress folder, then copy both off the server. Posts are in the DB; themes and uploads are files. mysqldump + zip -r + scp.
Interview card: How do you back up a WordPress site fully? · Download PNG

More cards: Ravi Sir's Cards.