Installing contentjet with Docker
In this guide we will install contentjet onto a single host running Ubuntu 16.04 with Docker. By the end of this guide you will have a complete installation of contentjet secured with free TLS certificates provided by Let's Encrypt.
To complete this installation you must possess the following knowledge:
- Navigating a linux command line, specifically the BASH shell
- Connecting to a remote server over SSH
- Configuration of DNS
- An understanding of Docker
You must also have:
- A server running a fresh install of Ubuntu 16.04 which you can SSH into (DigitalOcean is a good choice)
- A domain name registered through a registrar which gives you full access to the domain's DNS records
We will host contentjet with the following 3 subdomains as follows:
- app.example.com Will host the contentjet frontend, contentjet-ui
- api.example.com Will host the contentjet backend, contentjet-api
- media.example.com Will host user uploaded media
You must log into your domain registrar and create 3x A records for app, api and media all pointing to the IP address of your server.
Install Docker & Docker Compose
Connect to your server over SSH and install Docker.
curl -fsSL get.docker.com -o get-docker.sh sh get-docker.sh
Refer to the official documentation on installing Docker Compose.
Generate certificates with Let's Encrypt
In this step we will generate the free certificates for your 3 subdomains.
Begin by creating our working directory at /opt/contentjet which we will run all subsequent commands from.
mkdir -p /opt/contentjet cd /opt/contentjet
Run the following command to start a temporary server on port 80. This will create 2 named volumes which are used for storing the certificates generated in the next step as well as the challenge files required as part of Let's Encrypt's validation step.
docker run \ --name temp-server \ --rm \ -d \ -v certs:/etc/letsencrypt \ -v certs-data:/data/letsencrypt \ -w /data/letsencrypt \ -p 80:8000 \ python:alpine3.7 \ python -m http.server 8000
Next, run the following command to request certificates from Let's Encrypt. Make sure you change the last 4 lines of this command to reflect your own email address and domain.
docker run \ -it \ --rm \ -v certs:/etc/letsencrypt \ -v certs-data:/data/letsencrypt \ certbot/certbot \ certonly \ --preferred-challenges http \ --agree-tos \ --webroot \ --webroot-path=/data/letsencrypt \ --non-interactive \ -m firstname.lastname@example.org \ -d app.example.com \ -d api.example.com \ -d media.example.com
Assuming the above command executes successfully the certificates will have been written to our named volume. You MUST now stop the temporary server.
docker stop temp-server
Now create a cron job which runs every 5 days to automatically renew your certificates. Edit your cron with
crontab -e and add the following:
0 0 */5 * * docker run --rm -v certs:/etc/letsencrypt -v certs-data:/data/letsencrypt certbot/certbot renew -n >> /var/log/certbot.log
Next we will configure NGINX. Copy the following text and save it to /opt/contentjet/nginx.conf on your server.
We now need to change every occurance of example.com to your actual domain. We can do this easily using
sed. For example if your domain name was acme.com you would run the following command from within the /opt/contentjet/ directory.
sed -i -e 's/example.com/acme.com/g' nginx.conf
Configure Docker Compose
Next copy the following and save it to /opt/contentjet/docker-compose.yml.
version: '3.4' services: nginx: image: nginx:1.12.2 ports: - 80:80 - 443:443 volumes: - ./nginx.conf:/etc/nginx/nginx.conf - certs:/etc/letsencrypt - certs-data:/data/letsencrypt - media:/opt/contentjet-api/media/ db: image: postgres:9.6.2 restart: always environment: POSTGRES_USER: yourdbuser # CHANGE ME POSTGRES_PASSWORD: yourdbpassword # CHANGE ME POSTGRES_DB: contentjet-api api: image: contentjet/contentjet-api restart: always environment: NODE_ENV: production POSTGRES_HOST: db POSTGRES_USER: yourdbuser # CHANGE ME POSTGRES_PASSWORD: yourdbpassword # CHANGE ME POSTGRES_DB: contentjet-api SECRET_KEY: yoursupersecretkey # CHANGE ME SMTP_HOST: smtphost # CHANGE ME SMTP_PORT: smtpport # CHANGE ME SMTP_USER: smtpuser # CHANGE ME SMTP_PASSWORD: smtppassword # CHANGE ME MAIL_FROM: email@example.com # CHANGE ME BACKEND_URL: https://api.example.com MEDIA_URL: https://media.example.com FRONTEND_URL: https://app.example.com volumes: - media:/opt/contentjet-api/media/ ui: image: contentjet/contentjet-ui restart: always environment: BACKEND_URL: https://api.example.com PORT: 9000 volumes: media: certs: external: true certs-data: external: true
Similar to the change we made to nginx.conf we need to replace all occurances of example.com with your domain name. Again, this can be done quickly using
sed by running the following from within the /opt/contentjet directory.
sed -i -e 's/example.com/acme.com/g' docker-compose.yml
We need to make some additional edits to the environment variables within this file. As you can see there are 4 services defined nginx, db, api and ui. You MUST provide values for the lines commented with
SECRET_KEY simply needs to be a unique random string of your choosing. Make sure you keep it secret as it's used in encrypting passwords and tokens.
docker-compose up -d
Docker will now automatically pull the necessary images and start all services. To confirm everything is running navigate to
Create an administrator
At this point contentjet should be running on your domain however there are no users! Create your first user by running the following command and entering your email address and your desired password at the prompt.
docker-compose exec api npm run create-admin-user