Ghost Blog auf Laravel Forge installieren

Heute möchte ich die euch die Schritte zeigen die notwendig sind, um die Blogging Plattform Ghost auf einem mit Forge initialisierten Server zu installieren.

Folgende Anforderungen:


Lokale Entwicklungsumgebung einrichten

Ghost ist ja eine Node.js Applikation. Dies bedeutet wir benötigen natürlich auch eine aktuelle Installation von node.js. Homestead wird von Haus aus damit ausgeliefert, somit sind wir hier auf der sicheren Seite.

Ghost herunterladen und konfigurieren

Wir laden uns die aktuelle Ghost Version und entpacken sie in unsere Homestead Umgebung.

wget https://ghost.org/zip/ghost-0.5.6.zip
unzip ghost-0.5.6.zip -d ./ghost
rm ghost-0.5.6.zip
cd ./ghost/

Als nächstes werden wir gleich unseren Blog konfigurieren. Dazu kopieren wir die Beispiel-Konfigurationsdatei und benennen sie in config.js um.

cp config.example.js config.js

Wir müssen im Anschnitt production unsere Blog Adresse eintragen, sowie die Zugangsdaten zur MySql Datenbank die Forge für uns angelegt hat. Wenn man noch einen Mailgun oder ähnlichen Mailprovider Zugang hat, kann man diese Daten auch noch eingeben. Dasselbe machen wir auch für den Abschnitt development.

Die fertige config.js sieht dann ungefähr so aus:

# nano config.js
var path = require('path'),
    config;

config = {
    production: {
        url: 'http://mein-ghostblog.de',
        mail: {
            transport: 'SMTP',
            options: {
                service: 'Mailgun',
                auth: {
                    user: '*****', // mailgun username
                    pass: '*****'  // mailgun password
                }
            }
        },
        database: {
            client: 'mysql',
            connection: {
                host     : '127.0.0.1',
                user     : 'forge',
                password : '*****',
                database : 'forge',
                charset  : 'utf8'
            }
        },
        server: {
            host: '127.0.0.1',
            port: '2368'
        }
    },
    development: {
        url: 'http://localhost:2368',
        mail: {
           transport: 'SMTP',
           options: {
               service: 'Mailgun',
               auth: {
                   user: '*****', // mailgun username
                   pass: '*****'  // mailgun password
               }
           }
        },
        database: {
            client: 'mysql',
            connection: {
                host     : '10.0.2.15',
                user     : 'homestead',
                password : 'secret',
                database : 'ghost',
                charset  : 'utf8'
            }
        },
        server: {
            host: '127.0.0.1',
            port: '2368'
        },
        paths: {
            contentPath: path.join(__dirname, '/content/')
        }
    }
};

// Export config
module.exports = config;

Hinweis: Im development Abschnitt habe ich die IP genommen, an die unser Homestead MySQL Server gebunden ist. Das finden wir so heraus:

# cat /etc/mysql/my.cnf | grep bind
bind-address = 10.0.2.15

.gitignore Datei anlegen

Als nächstes müssen wir die .gitignore anpassen, damit nicht unsere installierten Produktionsdateien mit jedem deploy überschrieben werden.

$ nano .gitignore
.DS_STORE
node_modules/*
content/apps/*
content/data/*
content/images/*

Damit auch die noch leeren Verzeichnisse in unsere Forge umgebung gepusht werden müssen wir dort ebenfalls .gitignores anlegen.

wget -o ./content/images/.gitignore http://bit.ly/1saoicc
wget -o ./content/data/.gitignore http://bit.ly/1saoicc
wget -o ./content/apps/.gitignore http://bit.ly/1saoicc

Jetzt können wir alle Dependencies für Ghost installieren.

Hinweis: Auch wenn es erstmal unsere Development Umgebung ist, müssen wir den Flag production angeben. Ansonsten werden viele Dependencies installiert, die für die Core-Entwicklung wichtig sind, aber in unserem Fall nicht benötigt werden.

sudo npm install --production

Git Repositories anlegen

Zeit unsere arbeit zu sichern ;)

git init
git add .
git commit -m "Initialize"

Als nächstes muss über die Bitbucket Webseite entfernte Repository erstellt werden. Dann können wir unsere lokalen Dateien dort hinein pushen:

git remote add origin git@bitbucket.org:username/ghostblog.git
git push -u origin --all

Der lokale Teil ist geschafft.


Forge Server einrichten

Als erstes muss man natürlich einen virtuellen Server mit Forge erstellen und initialisieren:

Dazu verwende ich den kostengünstigsten Server bei Digital Ocean. Bei Bedarf kann man immer noch aufstocken. Zur Einrichtung benötigen auf jedenfall Zugang via SSH.

Ein Ghost Blog hat seinen eigenen Server, über node.js realisiert. Wir nutzen nginx nur als Proxy. Alle Anfragen an die eingerichtete Domain wird an den Ghost Server weitergeleitet. Forge ist auf PHP ausgelegt, daher müssen wir hier manuell eingreifen. Ist es erstmal eingerichtet, können wir aber dennoch z.B. ein Theme-Update einspielen, ohne dafür das Terminal zu öffnen.

Vorbereitung

Da Node.js standardmäßig nicht auf einem Forge Server installiert ist, müssen wir das nachholen:

sudo apt-get update
sudo apt-get install nodejs

Wir wechseln jetzt immer zwischen Terminal und Forge GUI hin und her.

Seite anlegen

Auf der gewohnten Maske in Forge legen wir unsere Seite mit der entsprechenden Domain, in diesem Fall mein-ghostblog.de an. Als Web Directory gebe ich nichts an. Das benötigen wir auch nicht, da nginx nur als Proxy dient.

nginx Konfigurieren

Ist die Seite angelegt, editieren wir die Nginx Konfigurationsdatei über Forge. Alles was mit PHP zu tun hat löschen wir und konfigurieren den Proxy. Wichtig ist hier die location / Angabe.

server {
    listen 80;
    server_name mein-ghostblog.de;
    root /home/forge/mein-ghostblog.de;

    # FORGE SSL (DO NOT REMOVE!)
    # ssl_certificate;
    # ssl_certificate_key;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    charset utf-8;

    location / {
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host      $http_host;
        proxy_pass         http://127.0.0.1:2368;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    access_log off;
    error_log  /var/log/nginx/mein-ghostblog.de-error.log error;

    location ~ /\.ht {
        deny all;
    }
}

Zur Sicherheit starten wir nginx einfach neu.

Automatisches Deployment der Seite

Damit wir bei jedem git push eine aktuelle Version unserer Ghost Installation bekommen, müssen wir das Deploy Skript etwas anpassen und Quick Deploy aktivieren.

Nach dem Deployment Prozess soll npm install angestoßen, sowie der Ghost Server neugestartet werden.

cd /home/forge/mein-ghostblog.de
git pull origin master
npm install --production
sudo /usr/bin/supervisorctl restart ghostblog

Start des Ghost Servers

Als Letztes müssen wir es nur noch hinbekommen, dass der Ghost Server automatisch nach einem Server reboot gestartet wird. Wir möchten ja nicht immer npm start --production eingeben müssen.

Dazu verwenden wir supervisord. Das auf dem Forge Server bereits installierte Programm überwacht Prozesse und kann diese ggf. neu starten.

Hier müssen wir erstmal eine Konfigurationsdatei anlegen:

supervisord konfigurieren

# sudo nano /etc/supervisord/conf.d/ghostblog.conf
[program:ghostblog]
command = node /home/forge/mein-ghostblog.de/index.js
directory = /home/forge/mein-ghostblog.de
user = forge
autostart = true
autorestart = true
stdout_logfile = /var/log/supervisor/ghostblog.log
stderr_logfile = /var/log/supervisor/ghostblog_err.log
environment = NODE_ENV="production"

Nur noch die neue Konfiguration einlesen:

sudo service supervisor restart

Sudo ohne Passwortabfrage

Damit unser Deploy Script auch den Ghost Server neu starten kann, müssen wir sudo so einrichten, dass kein Passwort abgefragt wird. Wir fügen folgende Zeile ans Ende der Konfigurationsdatei ein. Damit kann der Benutzer forge dieses eine Programm ohne Passwortabfrage benutzen.

# sudo visudo
forge ALL= NOPASSWD:/usr/bin/supervisorctl

Abschluss

Das sollte es bereits gewesen sein. Da wir Quick Deploy aktiviert haben, sollten wir nur eine Änderung an unsere entferntes Repository pushen. Das Deployment Skript übernimmt nun den Rest. Die Dependencies werden geladen und supervisord startet unseren Ghost Server. Beim ersten Start wird die Migration der MySQL Tabellen angestoßen - daher könnte das etwas länger dauern als sonst.


Weitere Quellen: http://support.ghost.org/deploying-ghost/ http://support.ghost.org/config/ http://www.allaboutghost.com/deploy-ghost-updates-with-git/