Ghost CMS installeren met Docker op Ubuntu 20.04

Ghost is een open-source blogging platform om je te helpen een professioneel uitziende blog te maken. Het werd in 2013 gelanceerd als alternatief voor WordPress omdat dat te ingewikkeld werd. Ghost is geschreven in JavaScript en wordt aangedreven door Node.js.

In deze zelfstudie onderzoeken we hoe je Ghost CMS kunt installeren met Docker op een server aangedreven door Ubuntu 20.04. We zullen ook Nginx gebruiken als proxy en een Let’s Encrypt SSL certificaat om onze installatie te beveiligen.

Vereisten

  • Een server met Ubuntu 20.04.

  • Een niet-root sudo gebruiker.

  • Zorg ervoor dat alles bijgewerkt is.

    $ sudo apt update 
    $ sudo apt upgrade
    

Stap 1 - Configureer UFW Firewall

De eerste stap is het instellen van de firewall. Ubuntu wordt standaard geleverd met ufw (Uncomplicated Firewall).

Controleer of de firewall draait.

$ sudo ufw status

Je zou de volgende uitvoer moeten krijgen.

Status: inactive

Sta SSH poort toe, zodat de firewall de huidige verbinding niet verbreekt bij het inschakelen ervan.

$ sudo ufw allow OpenSSH

Sta ook HTTP en HTTPS poorten toe.

$ sudo ufw allow 80
$ sudo ufw allow 443

Schakel de firewall in

$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

Controleer nogmaals de status van de firewall.

$ sudo ufw status

Je zou een gelijkaardige uitvoer moeten zien.

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80                         ALLOW       Anywhere
443                        ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80 (v6)                    ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)

Stap 2 - Installeer Certbot en verkrijg het SSL certificaat

Voor we verder gaan, moeten we het Certbot gereedschap installeren en een SSL certificaat voor ons domein installeren.

Om Certbot te installeren, gebruiken we het Snapd pakket installatieprogramma. De officiële repository van Certbot is afgeschreven en het Certbot pakket van Ubuntu is meer dan een jaar oud. Snapd draagt altijd de nieuwste stabiele versie van Certbot en die kun je het beste gebruiken. Gelukkig wordt Ubuntu 20.04 geleverd met Snapd voorgeïnstalleerd.

Zorg ervoor dat je versie van Snapd up-to-date is.

$ sudo snap install core 
$ sudo snap refresh core

Verwijder eventuele oude versies van Certbot.

$ sudo apt remove certbot

Installeer Certbot.

$ sudo snap install --classic certbot

Gebruik het volgende commando om ervoor te zorgen dat het Certbot commando uitgevoerd kan worden door een symbolische link te maken naar de /usr/bin directory.

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

Genereer een SSL certificaat.

$ sudo certbot certonly --standalone -d example.com

Het bovenstaande commando downloadt een certificaat naar de /etc/letsencrypt/live/example.com directory op je server.

Stap 3 - Installeer Docker en Docker Compose

De eerste stap is het installeren van de Docker Engine en Docker Compose. Verwijder eerst eventuele oude versies van Docker.

$ sudo apt remove docker docker-engine docker.io containerd runc

Installeer enkele pakketten die nodig zijn om Docker te laten draaien.

$ sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release

Voeg de officiële GPG sleutel van Docker toe.

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Voeg Docker's officiële repository toe.

$ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Werk de systeem repositories bij.

$ sudo apt update

Installeer de nieuwste versie van Docker Engine.

$ sudo apt install docker-ce docker-ce-cli containerd.io

Controleer of Docker Engine draait en correct geïnstalleerd is.

$ sudo docker run hello-world

Standaard vereist Docker sudo om te draaien. Om dat te omzeilen kunnen we de huidige gebruikersaccount toevoegen aan de docker gebruikersgroep.

$ sudo usermod -aG docker ${USER}

Om het nieuwe groepslidmaatschap toe te passen, log je uit en log je weer in, of gebruik het volgende commando.

$ su - ${USER}

Nu kun je docker commando's uitvoeren zonder sudo te gebruiken.

Download vervolgens de huidige stabiele release van Docker compose.

sudo curl -L "https://github.com/docker/compose/releases/download/1.28.6/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Op het moment van schrijven van deze tutorial is 1.28.6 de nieuwste versie van Docker compose. Je kunt in het commando altijd een andere versie veranderen of kiezen door te kijken op de Github releases pagina van Docker compose.

Pas executable toestemming toe op de geïnstalleerde versie van Docker compose.

$ sudo chmod +x /usr/local/bin/docker-compose

Test de installatie.

$ docker-compose --version
docker-compose version 1.28.6, build 5db8d86f

Stap 4 - Installeer Ghost

De Ghost installatie zal uit drie componenten bestaan - Ghost pakket, een databaseserver zoals MySQL en een webserver (Nginx). Al deze diensten kunnen geïnstalleerd worden met een enkel Docker compose bestand.

Docker compose bestand maken

Maak eerst een directory om je Docker compose bestand in op te slaan en van daaruit te starten.

$ mkdir ghost && cd ghost

Maak een bestand met de naam docker-compose.yml en open het met Nano editor.

$ nano docker-compose.yml

Plak de volgende code in het bestand. Vervang example.com door je domein en voeg op de plaats van de waarde your_password een databankwachtwoord in. Houd de waarden voor database__connection__password en MYSQL_ROOT_PASSWORD gelijk. Vervang <username> door de gebruikersnaam van je server.

version: '3.3'
services:

  ghost:
    image: ghost:latest
    restart: always
    depends_on:
      - db
    environment:
      url: https://example.com
      database__client: mysql
      database__connection__host: db
      database__connection__user: ghost
      database__connection__password: ghostdbpass
      database__connection__database: ghostdb
      mail__transport: SMTP
      mail__options__host: {Your Mail Service host}
      mail__options__port: {Your Mail Service port}
      mail__options__secureConnection: {true/false}
      mail__options__service: {Your Mail Service}
      mail__options__auth__user: {Your User Name}
      mail__options__auth__pass: {Your Password}
    volumes:
      - /home/<username>/ghost/content:/var/lib/ghost/content

  db:
    image: mariadb:latest
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: your_mysql_root_password
	  MYSQL_USER: ghost
      MYSQL_PASSWORD: ghostdbpass
      MYSQL_DATABASE: ghostdb
    volumes:
      - /home/<username>/ghost/mysql:/var/lib/mysql

  nginx:
    build:
      context: ./nginx
      dockerfile: Dockerfile
    restart: always
    depends_on:
      - ghost
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /etc/letsencrypt/:/etc/letsencrypt/
      - /usr/share/nginx/html:/usr/share/nginx/html

Het Docker compose bestand maakt een paar mount points aan, d.w.z. het mapt bepaalde directories op de server naar directories binnen de container.

  • De /var/lib/ghost/content en /var/lib/mysql directories binnen je containers worden gemapt naar /home/<username>/ghost/content en /home/<username>/ghost/mysql op de server.
  • Nginx gebruikt de /etc/letsencrypt/ binding om toegang te krijgen tot Let's Encrypt certificaten van de server.
  • Nginx heeft ook toegang nodig tot de gebruikersmap /usr/share/nginx/html zodat het Let's Encrypt Challenge bestanden voor het certificaat kan benaderen.

In het bovenstaande bestand hebben we ook opties opgenomen voor het instellen van mail. Als je een populaire SMTP mail dienst gebruikt zoals Mailgun, Mailjet, Mandrill, Postmark, Sendgrid, SendCloud, SES, Zoho of Gmail, kun je gewoon de naam van de dienst en je SMTP gebruikersnaam en wachtwoord toevoegen en de rest van de velden weglaten. Vul anders alle andere opties in en verwijder de naam van de dienst en het zou nog moeten werken. Je kunt meer mail opties bekijken in Ghost's documentatie over Mail opties.

Maak directories voor alle hierboven beschreven bind mounts (behalve voor /etc/letsencrypt, dat al was aangemaakt toen we eerder het certificaat maakten)

$ cd ~/ghost
$ mkdir content
$ mkdir mysql
$ sudo mkdir -p /usr/share/nginx/html

Maak het Nginx Docker Image

Het Docker compose bestand dat we maakten vertrouwt op het Nginx Docker image. Om het te laten werken moeten we een aangepast configuratiebestand voor Nginx opnemen dat met Ghost zal werken.

Maak een map voor deze image in de huidige directory.

$ mkdir nginx

Maak in deze directory een bestand met de naam Dockerfile.

$ touch nginx/Dockerfile

Plak de volgende code in het Dockerfile.

FROM nginx:latest
RUN rm /etc/nginx/conf.d/default.conf
COPY ghost.conf /etc/nginx/conf.d

De bovenstaande code instrueert Docker om het nieuwste Nginx image te gebruiken. Het verwijdert ook het standaard Nginx configuratiebestand en kopieert het aangepaste configuratiebestand dat we voor ons Ghost CMS gemaakt hebben.

Maak een bestand met de naam ghost.conf in de map nginx.

$ touch nginx/ghost.conf

Plak de volgende code in het ghost.conf bestand. Vervang alle instanties van example.com door je domein.

server {
  listen 80;
  listen [::]:80;
  server_name example.com;
  # Useful for Let's Encrypt
  location /.well-known/acme-challenge/ { root /usr/share/nginx/html; allow all; }
  location / { return 301 https://$server_name$request_uri; }
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name example.com;
    
  access_log /var/log/nginx/ghost.access.log;
  error_log /var/log/nginx/ghost.error.log;
  client_max_body_size 20m;

  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
  ssl_prefer_server_ciphers on;
  ssl_session_timeout 1d;
  ssl_session_cache shared:SSL:10m;

  ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

  location / {
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://ghost:2368;
  }
}

De bovenstaande configuratie zal alle HTTP verzoeken omleiden naar HTTPS en zal dienen als proxy voor de Ghost dienst om die via je domein te bedienen.

Stap 5 - Voer de site uit

Voer het volgende commando uit vanuit de ghost directory om de Ghost service te starten.

$ docker-compose up -d

Nu kun je je installatie controleren door https://example.com in je webbrowser te openen. Het kan enkele minuten duren voor de Docker alle diensten heeft ingeschakeld, dus het kan zijn dat je moet verversen als je je blog niet meteen ziet.

Spook Homepage

Als je site niet in de browser verschijnt, moet je de Docker logs bekijken. Om dat te doen sluit je eerst je container.

$ cd ghost
$ docker-compose down

Voer Docker compose uit in een aangekoppelde toestand om de logs te bekijken die door elke container gegenereerd worden.

$ docker-compose up

Om de container af te sluiten, en terug te keren naar de bash prompt, druk je op CTRL+C. Als je klaar bent met het oplossen van problemen, kun je de container opnieuw draaien en je blog zou ditmaal zichtbaar moeten zijn.

Stap 6 - Voltooi de instelling

Om het instellen van je Ghost blog te voltooien, bezoek je https://example.com/ghost in je browser. De extra /ghost aan het eind van het domein van je blog leidt je door naar Ghost's Admin Panel, of in dit geval de setup omdat je die voor het eerst opent.

Spook opzetten pagina

Hier moet je je Administrator account aanmaken en een blog titel kiezen.

Spook Opzet Details

Je kunt ook extra medewerkers of medewerkers voor je blog uitnodigen, wat je later ook kunt doen als je nu verkiest over te slaan.

Spookpersoneel Invite Page

Aan het eind van de setup word je begroet met het Ghost's Beheerpaneel.

Ghost Admin Dashboard

Als je naar de donkere modus wilt overschakelen, kun je dat doen door op de tuimelschakelaar te klikken naast de instellingen tandwiel knop onderaan de instellingen pagina.

Spook Donkere Modus Toggle

Je ziet nu al een aantal standaard berichten, die in feite gidsen zijn om je te helpen navigeren en Ghost te gebruiken. Je kunt ze uitpubliceren of verwijderen en beginnen met posten.

Stap 7 - Werk Ghost bij

In ons Docker compose bestand trekken we de laatste versie van Ghost die op het moment van installatie beschikbaar is, wat het gemakkelijk maakt om je Ghost blog bij te werken.

Om te updaten moet je je container afsluiten, de nieuwste images ophalen en dan de container opnieuw draaien.

$ docker-compose down
$ docker-compose pull && docker-compose up -d

Stap 8 - Vernieuw je Let's Encrypt SSL Certificaat

Let's Encrypt certificaten zijn maar 90 dagen geldig. Daarom moeten we een cronjob instellen die het certificaat automatisch vernieuwt.

Open Crontab in je editor.

$ sudo crontab -e

Plak de volgende regel aan het eind die Certbot elke dag om 11 PM zal laten lopen. Vervang example.com door je domein.

0 23 * * *   certbot certonly -n --webroot -w /usr/share/nginx/html -d example.com --deploy-hook='docker exec ghost_nginx_1 nginx -s reload'

Elke dag om 11 uur draaien betekent niet dat je certificaat elke dag vernieuwd wordt, want Certbot vernieuwt je certificaat alleen als de vervaldatum binnen 30 dagen ligt. Door dit elke avond uit te voeren geeft het script een aantal kansen om het te proberen voor de vervaldatum.

Het bovenstaande commando herstart ook de Nginx server binnen de Docker container na succesvolle vernieuwing.

Je kunt de cronjob testen met de --dry-run optie van Certbot.

$ sudo bash -c "certbot certonly -n --webroot --dry-run -w /usr/share/nginx/html -d example.com --deploy-hook='docker exec ghost_nginx_1 nginx -s reload'"

Conclusie

Dit beëindigt onze zelfstudie over hoe je Ghost CMS op je Ubuntu 20.04 gebaseerde server kunt instellen met Docker. Als je vragen of feedback hebt, deel ze dan in de opmerkingen hieronder.