Skip to content
/ parse-starter Public template

A powerful backend ready for your next app πŸš€

License

Notifications You must be signed in to change notification settings

hatemhosny/parse-starter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

8 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

A powerful backend ready for your next app πŸš€

CI/CD

This is a starter template with a feature-rich ready-to-use backend that works out of the box for local development and can be easily deployed.

You get a fully functional backend so that you can focus on what matters most: your app!

Feature Summary

Table of Contents

Requirements

Getting Started

Run the shell command:

docker-compose up

By default, the following will be served:

After production build:

When CMS is enabled:

Now you can edit/replace the app in the frontend directory and start building your own app making use of the feature-rich backend.

Configuration

Environment Variables

Several configuration options can be set using environments variables exposed while running the docker-compose command. Please refer to docs on Environment variables in Compose for different ways to achieve that.

Variables in .env file will be automatically used.

Note: DO NOT commit secrets to version control.

.env file is not tracked by git (added to .gitignore) to avoid accidentally committing secrets. A sample in provided in sample.env. You may rename it to .env for local development. For deployment, use GitHub Secrets instead.

Environment

  • NODE_ENV:

    If set to "development", running docker-compose up starts frontend local development server with hot module replracement (HMR) on port 1234, and watches the backend source code and reloads on changes (e.g. in cloud code).

    If set to "production", running docker-compose up triggers frontend build generating static files that will be served on the default port (443), and the backend server runs on pm2 which restarts the server on crash.

    valid values: development, production

    default: development

Server Settings

  • HOST_NAME:

    The DNS name for the server hosting the app. HTTPS is used automatically with TLS certificates issued and renewed from Let's Encrypt. If "localhost" or an IP address is used, self-signed (locally trusted) certificates will be used.

    examples: mywebsite.com, blog.mywebsite.com

    default: localhost

    Required for remote deployment

  • BACKEND_PORT:

    The port for backend server.

    default: 1337

  • PARSE_SERVER_PATH:

    Route to parse-server REST API

    default: /api

  • PARSE_SERVER_GRAPHQL_PATH:

    Route to parse-server graphql API

    default: /graphql

  • PARSE_DASHBOARD_PATH:

    Route to parse dashboard

    default: /dashboard

  • PARSE_DASHBOARD_ENABLED:

    Enables parse dashboard if set to "yes"

    default: yes

  • CMS_ENABLED:

    Enables CMS if set to "yes"

    default: no

  • FRONTEND_DEV_SERVER_PORT:

    The port for frontend development server

    default: 1234

  • HMR_PORT:

    The port for hot module replacement (HMR) for frontend development server

    default: 1235

Keys and Secrets

  • APP_ID:

    Parse server app id

    default: myappid

  • APP_NAME:

    default: myappname

  • MASTER_KEY:

    Parse server master key

    default: mymasterkey

  • PARSE_SERVER_DATABASE_URI:

    Parse server database URI.

    By default it uses the included MongoDB container. You may change this if you wish to use another MongoDB instance.

    default: mongodb://mongo:27017/dev

  • PARSE_DASHBOARD_USER_ID:

    Parse dashboard user ID

  • PARSE_DASHBOARD_USER_PASSWORD:

    Parse dashboard user password

  • CMS_USER_EMAIL:

    Chisel CMS user email

  • CMS_USER_PASSWORD:

    Chisel CMS user password

App Structure

  • BACKEND_SRC_DIR:

    The backend source code directory.

    default: backend

  • FRONTEND_SRC_DIR:

    The frontend source code directory.

    default: frontend

  • FRONTEND_DIST_DIR:

    The directory containing the frontend production build inside the frontend source code directory.

    default: dist

  • DATA_DIR:

    The directory for data persistence (see Data Persistance).

    default: data

  • BACKEND_NPM_SCRIPT:

    The npm script to run after starting the backend container.

    default: start

  • FRONTEND_NPM_SCRIPT:

    The npm script to run after starting the frontend container.

    default: start

Mail Settings

These settings are used to send mail from parse server (e.g. to verify user emails)

  • MAIL_SMTP_HOST:

    SMTP host server

    example: smtp.sendgrid.net

  • MAIL_SMTP_PORT:

    SMTP server port

    default: 587

  • MAIL_SMTP_USERNAME:

    SMTP username

  • MAIL_SMTP_PASSWORD:

    SMTP password

  • MAIL_FROM_ADDRESS:

    The send-from email address

Docker Settings

  • BACKEND_IMAGE:

    The docker image for backend

    default for local build: backend

    default for CI/CD: docker.pkg.github.com/{owner}/{repo}/{repo}-backend

  • FRONTEND_IMAGE:

    The docker image for frontend

    default for local build: frontend

    default for CI/CD: docker.pkg.github.com/{owner}/{repo}/{repo}-frontend

  • IMAGE_TAG:

    The tag for docker images

    default for local build: latest

    default for CI/CD: git short SHA

Parse Server Configuration

Additional parse server configurations can be defined in ./backend/config.js

Data Persistance

The data generated (e.g. MongoDB data, parse server logs and caddy certificates) are stored by default in the ./data directory (can be configured by the DATA_DIR environment variable).

Cloud Code

Cloud code can be used to run custom server-side logic. It is built on Parse JavaScript SDK.

The main entry to cloud code is ./backend/cloud/main.js

Any npm package can be installed in the backend and used (see Installing Dependencies).

To run code on server start (e.g. creating default users and roles, enforcing security rules, ...etc.), add your code to ./backend/server/initialize-server.js

Static Files

Files added to the directory ./backend/public will be served by the backend server under the route /public.

Express Middleware

Express middleware can be added to ./backend/server/index.js

Parse Dashboard

The Parse dashboard is a powerful dashboard for managing the parse server. By default, it is enabled and accessible on the route /dashboard of the backend server (e.g. https://localhost:1337/dashboard)

It can be configured by setting the environment variables similar to this example:

PARSE_DASHBOARD_ENABLED=yes
PARSE_DASHBOARD_PATH=/dashboard
PARSE_DASHBOARD_USER_ID=myuser
PARSE_DASHBOARD_USER_PASSWORD=mypassword

Headless CMS

The API-first headless content management system, chisel-cms, is included. However, it is disabled by default.

To enable the CMS, set the environment variable:

CMS_ENABLED=yes

It is then accessible at the root of the backend server (by default: https://localhost:1337)

Parse server users can then login by their user credentials. Users can be added using the Parse SDK, REST API, Graphql API or Parse Dashboard.

Alternatively, a user can be added by setting the environment variables:

[email protected]
CMS_USER_PASSWORD=password

This creates a new user with these credentials in the parse server. If the user is already present, the password is reset to the supplied password.

Automatic HTTPS

The frontend and backend are served by Caddy server with automatic HTTPS.

Caddy serves all sites over HTTPS by default.

  • Caddy serves IP addresses and local/internal hostnames over HTTPS with locally-trusted certificates. Examples: localhost, 127.0.0.1.
  • Caddy serves public DNS names over HTTPS with certificates from Let's Encrypt. Examples: example.com, sub.example.com, *.example.com.
  • Caddy keeps all certificates renewed, and redirects HTTP (default port 80) to HTTPS (default port 443) automatically.

from https://caddyserver.com/docs/automatic-https

Frontend App

The frontend web app can use vanilla javascript or any javascript/typescript framework or library (see Installing Dependencies). The app can interact with the backend using the Parse JS SDK, REST API or Graphql API.

A minimal vanilla javascript app is provided as a sample. It is a simple realtime todo app that uses the Parse JS SDK, Bootstrap and Parcel bundler.

Feel free to edit/replace the app with your own.

Local Development

Running the Dev Server

With the environment variable NODE_ENV set to development (default), running docker-compose up starts the local development server on the front end with HMR. In addition, code in backend source directory is watched for changes which trigger backend server restart.

By default, the local development server runs on https://localhost:1234, mapping the port 1234 on the frontend container. The port can be configured by setting the environment variable FRONTEND_DEV_SERVER_PORT.

Hot Module Replacement (HMR) uses the port 1235. It can be configured using the environment variable HMR_PORT.

Example: if you have an angular CLI app, you may want to set the following environment variables:

FRONTEND_DEV_SERVER_PORT=4200
HMR_PORT=49153

Production Build

When the environment variable NODE_ENV is set to production, npm run build is called in the frontend container to generate the production build in the folder frontend/dist (configurable by setting FRONTEND_DIST_DIR variable). The generated static files are served directly by caddy server.

To trigger frontend production build while in development mode, run:

docker-compose exec frontend npm run build

See Running Shell Commands on Containers

With NODE_ENV=production, the backend server process is managed by PM2 which restarts the server on crash.

Running Shell Commands on Containers

Make sure the containers are running

docker-compose up -d

To start an interactive shell session on the frontend docker container run:

docker-compose exec frontend bash

and for the backend

docker-compose exec backend bash

Installing Dependencies

Dependencies for the backend (including cloud code) are defined in ./backend/package.json. While dependencies for the frontend app are defined in ./frontend/package.json.

Installing npm packages can be done like that:

docker-compose up -d
docker-compose exec frontend npm install lodash
docker-compose exec backend npm install lodash

Please note that adding dependencies have to be followed by docker image build to persist the changes in the docker images, by running:

docker-compose build

NPM Scripts

For convenience, a package.json file was added to the root of the repo, so that common commands can be saved as npm scripts for repeated tasks like starting the containers, starting shell sessions, running tests, ...etc.

Examples:

  • npm start
    

    Runs the docker containers

  • npm run docker-build
    

    Builds the docker images

  • npm run frontend-shell
    

    starts intercative shell session in the frontend container

  • npm run test
    

    runs tests on the frontend and backend containers

NPM needs to be installed on the host machine to be able to run npm scripts.

Deployment

Docker and Docker Compose significantly simplify deployment. All the setup and dependencies are already taken care of in the docker images.

So, in principle, the steps required for deployment are:

  • Defining the variables for the deployment environment.
  • Building the docker images and verifying them.
  • Running the containers on the host server.

Although this can be done manually, it is greatly simplified using the included automated CI/CD setup that uses github actions.

Quick Start

Assuming you can connect using SSH to your server which has Docker and Docker Compose installed (see Server Setup), and that you have a personal github access token (see Container Registry), add the following Github Secrets:

  • PROD_DOCKER_REGISTRY_TOKEN: your personal github access token

  • PROD_SSH_HOST: your server IP address

  • PROD_SSH_KEY: your server SSH private key

  • PROD_ENV_VARS: edit the following example with your values

    HOST_NAME=mywebsite.com
    APP_ID=myappid
    MASTER_KEY=mymasterkey
    PARSE_DASHBOARD_USER_ID=user
    PARSE_DASHBOARD_USER_PASSWORD=pass
    

    Note: The environment variable HOST_NAME is required for remote deployment.

Now pushing code to main/master branch should trigger build and deploy to your server. Note that you can follow the progress and read logs of CI/CD workflows on the "Actions" tab in the gihub repo.

Continue reading for details.

CI/CD using github actions

Pushing new code to the main branch (by default "main" or "master"), automatically triggers:

  • collecting configurations as environment variables
  • building docker images
  • running tests
  • pushing docker images to the container registry (by default, Github Packages)
  • the production server pulls the built docker images and code
  • docker-compose runs the containers on the deployment server

The same can be done for different deployment environments like staging (by default, the branch "staging") and development (by default, the branch "develop"). See Multiple Deployment Environments.

Pull requests and code push to other branches trigger only building and testing the code.

Pushing docker images to the container registry requires setting Github Secret {env}_DOCKER_REGISTRY_TOKEN (e.g. PROD_DOCKER_REGISTRY_TOKEN for production builds). Deployment requires setting Github Secrets {env}_SSH_HOST and {env}_SSH_KEY (e.g. PROD_SSH_HOST and PROD_SSH_KEY for production deployments). See Github Secrets for details.

Re-deploys can also be manually triggered (e.g. reverting to a previous build) by specifying the git SHA to revert to without having to re-build the images. See Manual Re-Deploys

Please note that github actions and github packages have limits for free accounts and are paid services. Check github pricing for details.

If you want to avoid running the CI/CD workflow on a commit (e.g. after updating a markdown file), include [skip ci] or [ci skip] to the commit message.

To limit usage of github packages storage in private repos, only the latest 10 versions of each docker image are kept, and older ones are deleted. This behaviour can be configured. Packages for public repos are free and cannot be deleted.

Server Setup

Any cloud hosting service can be used for deployment. The server needs to have docker and docker-compose installed and you should be able to connect to it by SSH.

I prefer Digital Ocean for the simplicity and ease of use. You can get your server up and running with minimal setup in a few minutes for as low as $5/month. If you do not have an account, this is a referral link to get started with $100 in credit over 60 days. I recommend using the Docker One-Click Droplet where you get docker and docker-compose pre-installed. Make sure to add SSH key to the created droplet.

Configure the DNS records, so that your domain points to the deployment server.

Multiple Deployment Environments

The CI/CD setup allows deployment to one or more of the following environments: Production, Staging and Development.

The selection of environment is based on the git branch that triggered the deploy. Each environment has a prefix for the Github Secrets used.

The following table summarizes the environments, the associated git branch and the prefix used for Github Secrets:

Environment Git branch Prefix Example
Production main, master PROD PROD_SSH_HOST
Staging staging STAG STAG_SSH_HOST
Development develop DEV DEV_SSH_HOST

For example, pushing code to the git branch "develop" triggers "Development" build and deploy which use Github secrets prefixed by "DEV" (e.g. DEV_DOCKER_REGISTRY, DEV_DOCKER_REGISTRY_USER, DEV_DOCKER_REGISTRY_TOKEN, DEV_SSH_HOST, DEV_SSH_KEY, DEV_ENV_VARS). This causes pushing the docker images to the "Development" container registry and deploying the app to the "Development" server with the specified environment variables.

Container Registry

By default, the included CI/CD setup uses Github Packages as the container registry to host the built docker images, but it can be configured to use any other container registry.

A github personal access token is required to allow for pushing to and pulling from the container registry. Note that the token needs to have permissions for repo, write:packages and read:packages (and delete:packages if you want to allow for automatic deletion of old images). This token should be saved as a value for the Github Secret: {env}_DOCKER_REGISTRY_TOKEN (e.g. PROD_DOCKER_REGISTRY_TOKEN).

To use a different container registry (other than Github Packages), all the following Github Secrets have to be set:

  • {env}_DOCKER_REGISTRY
  • {env}_DOCKER_REGISTRY_USER
  • {env}_DOCKER_REGISTRY_TOKEN

For example, to use Docker Hub for production images set the following Github Secrets:

  • PROD_DOCKER_REGISTRY: registry.hub.docker.com
  • PROD_DOCKER_REGISTRY_USER: < your docker hub username >
  • PROD_DOCKER_REGISTRY_TOKEN: < your docker hub password >

Github Secrets

Deployment settings should be stored in GitHub Secrets.

For each deployment environment, the following set of secrets can be used (prefixed by the environment prefix - see Multiple Deployment Environments for details):

  • {env}_DOCKER_REGISTRY

    (e.g. PROD_DOCKER_REGISTRY)

    The docker container registry to host the built images.

    default: docker.pkg.github.com

  • {env}_DOCKER_REGISTRY_USER

    (e.g. PROD_DOCKER_REGISTRY_USER)

    Container registry username.

    default: github user.

  • {env}_DOCKER_REGISTRY_TOKEN

    (e.g. PROD_DOCKER_REGISTRY_TOKEN)

    Container registry password/token. When using Github Packages as registry, this should be the github personal access token (see above).

    Required for pushing docker images.

  • {env}_SSH_HOST

    (e.g. PROD_SSH_HOST)

    Depolyment server address (used in SSH connection).

    Required for deployment

  • {env}_SSH_PORT

    (e.g. PROD_SSH_PORT)

    Depolyment server port (used in SSH connection).

    default: 22

  • {env}_SSH_USER

    (e.g. PROD_SSH_USER)

    User on deployment server (used in SSH connection)

    default: root

  • {env}_SSH_KEY

    (e.g. PROD_SSH_KEY)

    SSH key for deployment server (used in SSH connection)

    Required for deployment

  • {env}_SSH_PATH

    (e.g. PROD_SSH_PATH)

    Path on deployment server (used in SSH connection)

    default: ./deploy/

  • {env}_ENV_VARS

    (e.g. PROD_ENV_VARS)

    These are environment variables that will be available when running docker-compose up on deployment server. Add each variable in a separate line.

    Example:

    HOST_NAME=mywebsite.com
    APP_ID=myappid
    MASTER_KEY=mymasterkey
    PARSE_DASHBOARD_USER_ID=user
    PARSE_DASHBOARD_USER_PASSWORD=pass
    
  • {env}_DOCKER_COMPOSE_UP_ARGS

    (e.g. PROD_DOCKER_COMPOSE_UP_ARGS)

    When running docker-compose up on deployment server the following arguments are passed

    --no-build -d
    

    You may add here more arguments.

    This can be used to run specific services (see Using a Remote MongoDB Database), scaling, etc. See documentations for details.

Running Tests

During continuous integration, tests/checks are run by running npm run ci-test both on the frontend and backend containers. You may add all your tests/checks to this script.

Manual Re-Deploys

You can manually trigger a previous deploy, without having to re-build or test it (e.g. you find a bug in the current build and you want to revert to a previous deploy).

The CI/CD workflow can be triggered manually (from β€˜Run workflow’ button on the Actions tab)

You need to supply the git short SHA for the commit you want to revert to. This is the same as the tag used for the docker images. Make sure that the docker images with that tag are available (check https://github.com/{owner}/{repo}/packages).

When manual re-deploys are triggered, Github Secrets used will be the ones present at the time of the new trigger not those that were present at the initial build.

Using a Different Host Name for Backend (e.g. Subdomain)

By default, the backend server runs on the same host name provided (configured by HOST_NAME environment variable) on a separate port (by default, 1337).

For example by setting HOST_NAME=mywebsite.com, the backend is served on https://mywebsite.com:1337.

You may set the environment variable BACKEND_HOST_NAME to a seperate host name. By default the backend port becomes 443 (unless the variable BACKEND_PORT is set to a different port).

For example, to serve the backend on https://api.mywebsite.com, use this configuration:

HOST_NAME=mywebsite.com
BACKEND_HOST_NAME=api.mywebsite.com

Do not forget to configure the DNS records to point the backend host name to the same server.

Note that this can also be configured for localhost.

Example:

HOST_NAME=localhost
BACKEND_HOST_NAME=api.localhost

Using a Remote MongoDB Database

To use a remote MongoDB instance (e.g. managed database on MongoDB Atlas) instead of the included container, follow the following steps:

  • Set PARSE_SERVER_DATABASE_URI environment variable to point to your database, for example:

    PARSE_SERVER_DATABASE_URI=mongodb+srv://<user>:<pass>@cluster0.abcde.mongodb.net/dev?retryWrites=true&w=majority
    
  • Start the stack using the command:

    docker-compose up --no-deps backend frontend caddy
    
  • To do the same for the CI/CD setup:

    • add the PARSE_SERVER_DATABASE_URI environment variable to PROD_ENV_VARS github secret.
    • add a github secret with the name PROD_DOCKER_COMPOSE_UP_ARGS and the value:
    --no-deps backend frontend caddy
    

Contributing

Pull requests are welcome!

License

MIT

About

A powerful backend ready for your next app πŸš€

Resources

License

Stars

Watchers

Forks

Releases

No releases published