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!
- Parse server: Backend-as-a-Service (BaaS) that features:
- SDKs for popular platforms
- REST API
- Graphql API
- LiveQuery for realtime apps
- Security features including authentication, users, roles, access control lists (ACL) and class-level permissions (CLP)
- 3rd party authentication
- Push notifications
- Adapters for file storage and caching
- Analytics
- Cloud code for custom server-side logic
- Web hooks
- Runs on top of Express allowing the use of Express middleware
- Comprehensive documentation
- Large community
- MongoDB database.
- Parse dashboard (optional): a powerful dashboard for managing the parse server.
- API-First Headless CMS (optional): using chisel-cms.
- A sample realtime frontend app.
- Automatic HTTPS for the frontend and backend using Caddy server.
- Reproducible setup using Docker containers managed by a single Docker Compose file.
- Local development workflow with hot reload for frontend and backend.
- Easy deployment.
- CI/CD (continuous integration and deployment): using github actions.
- Optional deployment to multiple environments (e.g. development, staging and production).
- The whole stack is open source with no vendor lock-in or pay-per-request restrictions.
- Requirements
- Getting Started
- Configuration
- Data Persistance
- Cloud Code
- Static Files
- Express Middleware
- Parse Dashboard
- Headless CMS
- Automatic HTTPS
- Frontend App
- Local Development
- Deployment
- Contributing
- License
Run the shell command:
docker-compose up
By default, the following will be served:
- parse server backend: https://localhost:1337/api
- parse graphql API: https://localhost:1337/graphql
- parse dashboard: https://localhost:1337/dashboard
- frontend local dev server (with HMR): https://localhost:1234
After production build:
- frontend app: https://localhost
When CMS is enabled:
- chisel CMS: https://localhost:1337
Now you can edit/replace the app in the frontend
directory and start building your own app making use of the feature-rich backend.
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.
-
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 onpm2
which restarts the server on crash.valid values: development, production
default: development
-
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
-
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
-
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
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
-
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
Additional parse server configurations can be defined in ./backend/config.js
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 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
Files added to the directory ./backend/public will be served by the backend server under the route /public
.
Express middleware can be added to ./backend/server/index.js
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
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.
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.
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.
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
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.
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
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
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.
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.
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.
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.
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.
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.
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 >
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.
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.
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.
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
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 toPROD_ENV_VARS
github secret. - add a github secret with the name
PROD_DOCKER_COMPOSE_UP_ARGS
and the value:
--no-deps backend frontend caddy
- add the
Pull requests are welcome!