Set Up Multilingual Ghost.org Blog

In this post I’ll try to explain my method for setup multilingual Ghost.org blog.

Motivation

I was looking for a blogging framework for long time to start my own blog. (Yes, this is it.) Beside Ghost.org I consider Wordpress, blogger, medium or jekyll. But I have some base rules to choose. Easy to set up, minimal and clean design, fast responding structure, self-hosting option and support for multi language. After giving some thought about this, I was nearly deciding for ghost.org but there was a minor problem. Ghost doesn’t support multilingual structure in single domain.

What Did I Use

As a server I use Digital Ocean standard droplet. (5$/mo, the cheapest one). And here is $10 gift from me. That may cover you for two whole month. Click here to get $10.

Ghost Set Up Guide

You can use for Ghost.org install guide for this. It is more than enough.

Let’s Begin

I set up Ubuntu 16.04 version on my droplet. I use PuTTYGen to generate SSH key. It comes with PuTTY installation. You can and need to use this key to connect SSH and/or FTP (SFTP).

sudo mkdir -p /var/www/html/en sudo mkdir -p /var/www/html/tr
sudo chown [user]:[user] /var/www/html/en sudo chown [user]:[user] /var/www/html/tr
sudo chmod 775 /var/www/html/en sudo chmod 775 /var/www/html/tr
cd /var/www/html/en ghost installcd /var/www/html/tr ghost install
  • For MySQL use root user and it’s password with all installations.
  • If you want to install Ghost with Sqlite3, please read how here
  • Checkout Prompts heading, which explains all the questions you’ll be asked during install.
  • Use different database names with root user. Example: en_prod, tr_prod.

Prompts

Here I give example answers for prompts that you will see in installation process. You can also checkout Ghost.org’s detailed prompts guide for some detailed explanation.

Enter your blog URL: https://irensaltali.com/en 
Enter your MySQL hostname: (localhost) localhost
Enter your MySQL username: root
Enter your MySQL password: [input is hidden] **********
Enter your Ghost database name: (en_prod) ghost_en_prod
Do you wish to set up "ghost" mysql user? (Y/n) Y
Do you wish to set up Nginx? (Y/n) Y
Do you wish to set up SSL? (Y/n) Y
Do you wish to set up Systemd? (Y/n) Y
Do you want to start Ghost? (Y/n) n
Enter your blog URL: https://irensaltali.com/tr 
Enter your MySQL hostname: (localhost) localhost
Enter your MySQL username: root
Enter your MySQL password: [input is hidden] **********
Enter your Ghost database name: (tr_prod) ghost_tr_prod
Do you wish to set up "ghost" mysql user? (Y/n) n
Do you wish to set up Nginx? (Y/n) n
Do you wish to set up SSL? (Y/n) Y
Do you wish to set up Systemd? (Y/n) Y
Do you want to start Ghost? (Y/n) n

Nginx Configuration

With these settings both ghost blogs should be successfully set up. Now we need to configure nginx to reach both blog via https.

cd /etc/ngnix/site-available 
rm -rf *
cd /etc/ngnix/site-enabled
rm -rf *
cd /var/www/html/en/system/files vi irensaltali.com.conf
server {
listen 80;
listen [::]:80;
server_name irensaltali.com;
root /var/www/html;
location ^~ /en {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:2368;
alias /var/www/html/en/system/nginx-root;
proxy_redirect off;
}
location ^~ /tr {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:2369;
alias /var/www/html/tr/system/nginx-root;
proxy_redirect off;
}
location ~ /.well-known {
allow all;
}
client_max_body_size 50m;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name irensaltali.com;
root /var/www/html;
ssl_certificate /etc/letsencrypt/irensaltali.com/fullchain.cer;
ssl_certificate_key /etc/letsencrypt/irensaltali.com/irensaltali.com.key;
include /etc/nginx/snippets/ssl-params.conf;
location ^~ /en {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:2368;
alias /var/www/html/en/system/nginx-root;
proxy_redirect off;
}
location ^~ /tr {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:2369;
alias /var/www/html/tr/system/nginx-root;
proxy_redirect off;
}
location ~ /.well-known {
allow all;
}
client_max_body_size 50m;
}

Explanation of configuration

Actually there only three lines of change from original configuration that ghost script would do.

alias /var/www/html/en/system/nginx-root;
alias /var/www/html/en/system/nginx-root;
root /var/www/html;

MSc. Computer Engineer. Founder of @image4io, .NET Software Consultant @kloia_com, co-organizer in @serverlesstr, Community Builder of @awscloud.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store