DEV Community

loading...
Cover image for Production deployment Strapi + Gatsby app on VPS Shared Hosting: Deploy,  web hooks & https. (3)

Production deployment Strapi + Gatsby app on VPS Shared Hosting: Deploy, web hooks & https. (3)

danielkrupnyy profile image Daniel Krupnyy ・8 min read

Production deployment Strapi + Gatsby app on VPS Shared Hosting: Deploy, web hooks & https.(3)

Welcome to the last part of Strapi + Gatsby deployment tutorial πŸ‘‹

If you don't like to read a lot of text, the finished project is here πŸ€—

Let's go to work πŸ’ͺ


Table Of Contents:


Deployment Strapi and Gatsby

Some hosts may provide you with a user interface to deploy data, but unfortunately not each. That's why in our case we will using classic FTP/SFTP connection.

Opening FTP/SFTP connection

All data for connection by FTP/SFTP you can find on your host.

I prefer to use Cyberduck client for such purposes. You can use it or something like FileZilla.

Here is the video how to open FTP/SFTP connection using Cyberduck.

Preparing to upload

Before you upload Gatsby files to server, you need to
install fs-extra package:

npm install fs-extra
Enter fullscreen mode Exit fullscreen mode

Then change "gatsby-node.js" file or create it and put this code inside:

const fs = require("fs-extra");
const path = require("path");

// ...

exports.onPostBuild = () => {
  fs.copySync(
    path.join(__dirname, "public"),
    path.join(__dirname, "public_shtml"),
    { overwrite: true }
  );
  fs.removeSync(path.join(__dirname, "public"));
};
Enter fullscreen mode Exit fullscreen mode

This code will change the name of the "public" folder to "public_html" so that VestaCP can read the statically generated files after build.

Creating Authenticated Requests

In the first part we Configured Authenticated Requests in Strapi and created new Role and User for it.
Now is time to create Authenticated Requests.

Installing necessary dependencies

First install all dependencies to Gatsby:

yarn add axios isomorphic-fetch gatsby-source-graphql @apollo/client
Enter fullscreen mode Exit fullscreen mode

Then install dependencies for Strapi:

yarn strapi install graphql
Enter fullscreen mode Exit fullscreen mode

Now explanations. Let's start with ApolloClient(@apollo/client).

ApolloClient is a comprehensive state management library for JavaScript that enables you to manage both local and remote data with GraphQL. Use it to fetch, cache, and modify application data, all while automatically updating your UI.

In our case that library will be helpful to get token from Strapi.

Since Apollo working with GraphQL we installed to Strapi graphql package that recreate data in GraphQL format. And also we installed gatsby-source-graphql in Gatsby to get data in this format.

Packages axios and isomorphic-fetch will be helpful for fetching data.

Adjusting Configs

Go to gatsby-config.js file and find there gatsby-source-strapi plugin. Extend it add:

    {
      resolve: "gatsby-source-strapi",
      options: {
        apiURL: process.env.API_URL || "http://localhost:1337",
        contentTypes: ["article", "category", "writer"],
        singleTypes: [`homepage`, `global`],
        queryLimit: 1000,
        // new ---
        loginData: {
          identifier: process.env.GATSBY_API_IDENTIFIER,
          password: process.env.GATSBY_API_PASS,
        },
        // new ---
      },
    },
Enter fullscreen mode Exit fullscreen mode

Then add config for gatsby-source-graphql plugin:

    {
      resolve: "gatsby-source-graphql",
      options: {
        typeName: "Strapi",
        fieldName: "strapi",
        url: process.env.API_GRAPHQL_ENDPOINT,
      },
    },
Enter fullscreen mode Exit fullscreen mode

After go to the root folder of Gatsby and rename .env.example file to .env and change code inside to:

GATSBY_ROOT_URL=https://yoursite.com
API_URL=https://subdomain.yoursite.com
API_GRAPHQL_ENDPOINT=https://subdomain.yoursite.com/graphql
GATSBY_API_AUTH=https://subdomain.yoursite.com/auth/local
GATSBY_API_IDENTIFIER=user@mail.com
GATSBY_API_PASS=userPassword
Enter fullscreen mode Exit fullscreen mode

Then in the root folder create of Gatsby file gatsby-browser.js:

import React from "react";
import {
  ApolloClient,
  ApolloProvider,
  InMemoryCache,
  createHttpLink,
} from "@apollo/client";
import { setContext } from "@apollo/client/link/context";
import fetch from "isomorphic-fetch";

const httpLink = createHttpLink({
  uri: process.env.API_GRAPHQL_ENDPOINT,
  fetch,
});

const authLink = setContext(async (_, { headers }) => {
  const token = localStorage.getItem("token");

  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : "",
    },
  };
});

const client = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache(),
});

export const wrapRootElement = ({ element }) => (
  <ApolloProvider client={client}>{element}</ApolloProvider>
);
Enter fullscreen mode Exit fullscreen mode

Inside this file Apollo will get token from Strapi and also get access to fetching authenticated data.

But if you remember the first part, in order to get Token we need to sand POST request to Strapi with data about user email and password.

For that go to src folder in Gatsby and create there path: helpers/getToken.js:

import axios from "axios";

const getToken = async () => {
  const { data } = await axios.post(`${process.env.GATSBY_API_AUTH}`, {
    identifier: `${process.env.GATSBY_API_IDENTIFIER}`,
    password: `${process.env.GATSBY_API_PASS}`,
  });

  return data.jwt;
};

export default getToken;
Enter fullscreen mode Exit fullscreen mode

Function getToken takes url to Strapi auth, user email and password from .env file. Then it returns token.

Since token refreshes, we can save it in LocalHost. The best way to do it get and save token in layout.js component:

import React, { useEffect } from "react";
import PropTypes from "prop-types";
import { StaticQuery, graphql } from "gatsby";
import Nav from "./nav";
import Seo from "./seo";
import getToken from "../helpers/getToken";

const Layout = ({ children, seo }) => {
  // new ---
  useEffect(() => {
    async function fetchData() {
      const token = await getToken();
      localStorage.setItem("token", token);
    }
    fetchData();
  }, []);
  // new ---

  return (
    <StaticQuery
      query={graphql`
        query {
          strapiHomepage {
            seo {
              metaTitle
              metaDescription
              shareImage {
                publicURL
              }
            }
          }
        }
      `}
      render={(data) => (
        <>
          <Seo seo={seo} />
          <Nav />
          <main>{children}</main>
        </>
      )}
    />
  );
};

Layout.propTypes = {
  children: PropTypes.node.isRequired,
};

export default Layout;
Enter fullscreen mode Exit fullscreen mode

Now, when layout.js component is gererated it get request to Strapi, gets token and save it in LocalStorage. In turn ApolloClient at file gatsby-browser.js get token from LocalStorage and gets with it help GraphQL data.

Uploading

When you connected to your server. You need to follow the path: home/username/web/yoursite.com and drop there your Gatsby app. Then delete "public_shtml" folder.

☝️ But don't forget to exclude node_modules if you don't want to wait all your life for the download to finish πŸ™„

After follow the: home/username/web/subdomainprefix.yoursite.com/public_shtml and drop there Strapi app.

☝️ In my case, I was using Strapi with its own SQLite database and forgot to upload it to the server because it was hidden on my system and after running on the server, Strapi created a new empty database. So if you don't want to lose your data, don't make my mistakes. Path:.tmp/data.db ☝️

If you want to use Strapi with another DB. Strapi has excellent docs on this. .

Installing Dependencies

Then switch to your SSH and go to these paths and in each path write command npm install to install all projects dependencies (if you forgot how to connecting by SSH you can find this info in previous part).

Enabling SSL(HTTPS)

In VestaCP go to "WEB" choose your domain and there enable "SSL Support".

Then in "SSL Home" select "public_shtml" folder.

Then fill in the following fields with your SSL details: "SSL certificate", "SSL key", "SSL certificate/credentials" or enable "Lets Encrypt support" if installed on your Vesta panel.
Save all changes.

Do the same with the subdomain.

Testing our apps

Now you can connect by SSH in your terminal and try to fire projects. npm run develop for Strapi.
Then open new terminal window and do the same for Gatsby.
All should be work.

Automatisation with PM2

In order to your apps don't stops when you close terminal windows. You need to install PM2 β€” process manager that will help you manage and keep your application online.

In your SSH terminal go to the server root folder and type:

npm install pm2 -g
Enter fullscreen mode Exit fullscreen mode

After installation go to Strapi app:
home/username/web/subdomainprefix.yoursite.com/public_shtml and create there file "server.js".

Then put inside:

const strapi = require("strapi");
strapi({ NODE_ENV: "production" }).start();
Enter fullscreen mode Exit fullscreen mode

Now it terminal type:

pm2 start server.js
Enter fullscreen mode Exit fullscreen mode

That's it! Strapi app is working πŸ€—

Also You must read this awesome docs about pm2.
This docs will help you fast understand how to use pm2!

Creating Weebhooks

Since Gatsby Static Site Generator. It generate html at build time.

Whenever we change something in Strapi, it should send a request to Gatsby that the data has changed, and Gatsby should perform the rebuild.

In order to solve this problem and similar problems exists Webhooks.

Installing GO

First you need to install GO language in your server.

Like I sad in previous part, In my case on server was installed CentOS.

I'll show you how you can install GO on it using yum:

sudo yum install go
Enter fullscreen mode Exit fullscreen mode

If you have different OS you need to find out how to install app on your system. Sample Ubuntu.

Installing Webhook tool

Now install webhook β€” is a lightweight configurable tool written in Go, that allows you to easily create HTTP endpoints (hooks) on your server.

Install weebhook on CentOS:

go build github.com/adnanh/webhook
Enter fullscreen mode Exit fullscreen mode

Install on another OS

Creating configs for webhook tool

In your server root directory create folder "webhooks" and put inside folder "fronted-rebuild" and file "hooks.json":

[
  {
    "id": "frontend-rebuild",
    "execute-command": "/root/webhooks/frontend-rebuild/rebuild.sh",
    "command-working-directory": "/home/username/web/yourdomain.com",
    "response-message": "Executing rebuild script..."
  }
]
Enter fullscreen mode Exit fullscreen mode

After put in to the "fronted-rebuild" folder file rebuild.sh:

#!/bin/bash

yarn clean 
yarn build
Enter fullscreen mode Exit fullscreen mode

You'll get structure:
Structure Folder

Then create file start.sh in the root folder:

/root/go/bin/webhook -hooks /root/webhooks/hooks.json -ip "00.0.000.000" -port 0000 -verbose -hotreload
Enter fullscreen mode Exit fullscreen mode

Instead "00.0.000.000" and "0000" put your ip and port.

After will read this article and you will find out how to add webhooks to Strapi.

Your webhook will be looks like:

http://00.0.00.000:0000/hooks/frontend-rebuild
Enter fullscreen mode Exit fullscreen mode

And finally use pm2 command to start webhook:

pm2 start start.sh
Enter fullscreen mode Exit fullscreen mode

That's it!
You've deployed the Strapi and Gatsby apps on a VPS hosting with VestaCP installed πŸ‘

If you like this series and you feeling thankfulness. You can support me πŸ˜‰

Buy Me A Coffee

Also if you have a question or want to add something, drop it in the comments πŸ‘‡ or find me on Twitter.

Discussion (0)

Forem Open with the Forem app