Skip to content →

Tag: Cloudflare

Migrating self-hosted WordPress

When I started this website in 2009, I was using Joomla. Then at some point I switch to WordPress because it was much easier to manage my posts. And it was hosted at, where I initially registered this domain name. However, the network and service wasn’t really stable and I had a lot of hiccups back then. As a result, in 2017 I migrated the website to, which offers very cheap virtual machines and small bare metal instances.

Another reason why I switched was because I was also running a real-time crypto price crawling and algorithmic trading service with a few servers, and since my website didn’t have a ton of visitors, I could put it together with other services. Back then a small instance cost only 5 euros per month, and I found it to be more cost-effective than other cloud computing providers like AWS, GCP or Vultr. As time went by, I had more resource intensive services running, such as staking pools which require large volumes. I ended up upgrading those tiny instances, and adding more resources from Scaleway. Then later when I phased out such services and reduced the number of instances, I couldn’t switch back to the smaller instances because either they didn’t exist any more or I couldn’t downgrade the volume size. So in the end I was paying a large monthly bill to run a small WordPress application.

And today I finally managed to spare a few hours reviewing the services I need, and decided it to migrate it back to, which I was already paying anyway. As a side note, the price of subscription also increase by 4x or 5x in 10 years.

Migrating WordPress alone is easy: backup all the files and database, then copy files to, import the database, and setup the DNS on Cloudflare. I asked ChatGPT to draw me this flowchart:

+-------------+                                +-------------+
| Old Server  |   Backup files and database   | Local Server |
+-------------+ ----------------------------> +-------------+
                                                    | Import database
                                               | New Server  |
                                                    | Update URLs in database
                                               | New Server  |

During the process, I also tried setting up a local LAMP+WP service with docker-compose (this repo is very useful: and tried exporting my posts into GoHugo format. In the end I believed it was too much hassle and not worth it.

A few issues I encountered during the migration process:

  1. .htaccess files should be set up properly, otherwise WP complains about 404 for sub pages.
  2. Some WP plugins were outdated (code highlighting, for example), so it caused some page rendering issues. When I replaced the plugin such issues are gone.
  3. File permissions has to be 744 or 755 for the wp-content/uploads folder.
  4. I used nslookup to get the IP of’s server, and manually updated it on Cloudflare, since I prefer to use Cloudflare to manage my DNS. In the future I may need to automate this process, in case moves my VM to another server. Or at lease I should monitor the output from versus

Besides migrating WP, I also had a few other websites to migrate. But since they are all static websites, I used Cloudflare Pages to host them and assigned the domains to the corresponding Pages project.

I probably spent 3 to 4 hours migrating everything, and double checking everything works fine. Then I went ahead and terminated all instances, elastic IPs and volumes on Scaleway. That would save me a couple of hundred euros a year. Not bad ROI!

Leave a Comment

Raspberry Pi as a toy web server

1. Tell my router to route certain traffic to the Raspberry Pi. For example, I route HTTP and SSH traffic to one of my Pi’s. I disabled password login for  SSH, using public key authentication instead: in /etc/ssh/sshd_config, use the following setting and restart SSH service using `sudo service ssh restart’.

RSAAuthentication yes
PubkeyAuthentication yes

# To disable password authentication:
ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no

# To disable root login:
PermitRootLogin no

2. Getting my IP address of the Raspberry Pi. I firstly created a PHP script on my domain to record the IP address in a text file.

$token = 'secret';                   
if ($_GET['token'] == $token) {                                                  
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {                                    
        $ip = $_SERVER['HTTP_CLIENT_IP'];                                        
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {                        
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];                                  
    } else {                                                                     
        $ip = $_SERVER['REMOTE_ADDR'];                                           
    $fp = fopen('home_ip.txt', 'w');                                             
    fwrite($fp, $ip);                                                            

Then tell the Raspberry Pi to report its IP address every 5 minutes, using crontab:

pi@alice ~ $ crontab -l
*/5 * * * * curl

After a while the IP address is recorded in the text file and updated every 5 minutes.

3. Optionally create a DNS record for the Pi. I use Cloudflare to manage DNS settings by myself, so just add/update an entry in Cloudflare’s settings. I point to the IP address of one Pi. This can be done automatically in the future.

4. Install Flask on the Pi.

sudo apt-get update
sudo apt-get install python-pip
sudo pip install Flask

5. Install nginx and uwsgi on the Pi.

sudo apt-get install nginx
sudo apt-get install build-essential python python-dev
sudo apt-get install python-virtualenv
sudo pip install uwsgi

6. Set up nginx along with uwsgi and Flask.

mkdir flask && cd $_
virtualenv env
. env/bin/activate
pip install Flask

Edit nginx config:

~/flask $ cat flask_nginx.conf 
server {
    listen      5000;
    server_name localhost;
    charset     utf-8;
    client_max_body_size 75M;

    location / { try_files $uri @flask; }
    location @flask{
        include uwsgi_params;
        uwsgi_pass unix:/home/pi/flask/uwsgi.sock;
sudo rm /etc/nginx/sites-enabled/default
sudo ln -s flask_nginx.conf /etc/nginx/sites-enabled/default 
sudo service nginx restart

Edit uwsgi config:

~/flask $ cat flask_uwsgi.ini 
#application's base folder
base = /home/pi/flask

#python module to import
app = hello
module = %(app)

home = %(base)/env
pythonpath = %(base)

#socket file's location
socket = /home/pi/flask/uwsgi.sock

#permissions for the socket file
chmod-socket    = 666

#the variable that holds a flask application inside the module imported at line #6
callable = app

#location of log files
logto = /home/pi/flask/uwsgi.log

Create a simple Flask app:

~/flask $ cat
from flask import Flask
app = Flask(__name__)

def hello():
    return "Hello World!"

if __name__ == "__main__":

Start up uwsgi:

uwsgi --ini flask_uwsgi.ini &

7. Done!

 Update on June 24, 2014:

Getting the external address in step 2 can be done by running this command in Raspberry Pi:



Leave a Comment