Hello! This template is a MERN template for people who want to self host. This was created for the sole reason that when working on MERN projects I always ended up repeating the same boilerplate steps.
This template comes with the following features:
- React Fontend
- Express Backend
- MongoDB Database
- NGINX Web Server
- Docker Compose to package it up real nice and tidy for production
- HTTPS using certbot & letsencrypt
- Github actions to automate linting and building status checks for master and develop branches
- OPTIONAL Automatic redeploy on your server for github pushes to master branch using webhook
- OPTIONAL Automatic weekend dependency updates using Renovate and Renovate-Approve
This project is broken up into 3 sub folders, all corresponding to their respective part of the MERN.
- React files are located in
react-app/
- Express files are located in
express-api/
- MongoDB files are locally mounted in
mongo-db/
(you should never have to touch this folder)
For local development you're going to have to install MongoDB and NGINX yourself and have them set up as their own services. I have included a sample nginx.conf that is made for this project. Any changes you do to the react-app/nginx.conf
file make sure you mirror in the service nginx.conf
so local development does not break.
-
Make sure both NGINX and MongoDB are running
-
Navigate to
react-app/
and run
npm start
- Navigate to
express-api/
and run
npm start
Local development instances of the application will have the NODE_ENV
environment variable set to development
.
For example, if I needed to do something with cookies I would want the name to begin with __Host
, but I can not do that with local development due to the lack of https. To get around that I would do something like
const cookieName = `${process.env.NODE_ENV === 'development' ? '__Host-' : ''}JWT`
- Edit the
server_name
in bothreact-app/nginx.conf
server blocks by replacinglocalhost
with your domain
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com *.example.com;
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com www.example.com *.example.com;
- Edit
ssl_certificate
andssl_certificate_key
inreact-app/nginx.conf
by replacinglocalhost
with your domain. Because of how nginx does their pathing, the easiest way is to do the non-www version. Don't fret, the certificates will be signed for both www and non-www versions
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
- Edit
init-letsencrypt.sh
with your domain and email address. Make sure the first domain in your list is the non-www version
domains=(example.com www.example.com)
...
email="example@example.com"
- For nginx to start the first time it needs to perform the Let's Encrypt validation but nginx won't start if the certificates are missing. To get around this run
chmod +x ./init-letsencrypt.sh
sudo ./init-letsencrypt.sh
-
Install webhook
-
Create a Github Webhook for your repository with a Payload URL of
http://yourdomain:9000/hooks/redeploy-webhook
and a secret -
Edit the
trigger-rule
block inhooks.json
with your Github Webhook secret
"trigger-rule": {
"and": [
{
"match": {
"type": "payload-hash-sha1",
"secret": "mysecret", // Github Webhook secret
"parameter": {
"source": "header",
"name": "X-Hub-Signature"
}
}
},
- Run
chmod +x ./redeploy.sh
webhook -hooks hooks.json -verbose
-
Configure Renovate for your repository
-
Configure Renovate-Approve for your repository
docker-compose up -d
This should now be hosed at https://yourdomain
via nginx.