A basic app that has all the features that all platforms have like authentication, validation, error handling and more.
Similar to the MEAN stack just with Neo4j rather than Mongo.
Client pages
Make sure you have Node.js and Docker installed.
node -v
docker -v
git clone git@github.com:CharlBest/nean-stack-starter.git
cd nean-stack-starter
npm install
npm start
Your app should have automatically opened the browser and be running on localhost:4200
Change to yours.
In the environments folder there are 2 files. one for dev and one for production. The angular CLI switches them at build time.
In the environments folder there is 1 file. In development default values are used. In production your hosting service should set process.env with the appropriate variables
Note: firebase storage has authentication on their buckets. Whitelist your url or something
Source: https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-18-04
Heroku charges $7 per instance that doesn't go to sleep after 30 minutes. That means if I want 3 Node instances, 2 for load balancing and zero downtime updates and 1 for the background worker process I have to pay ~$21. The VM is ~$25 and +- 7 instances can be run on it.
When building the client project with the Angular CLI the server freezes and a possible cause is the shared CPU because it doesn't happen with the standard machine types or it could be an out of memory problem.
Source: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-vnc-on-ubuntu-18-04
sudo apt update
sudo apt upgrade
Packages repo site: https://packages.ubuntu.com/
sudo apt install xfce4 xfce4-goodies tightvncserver nano firefox
Optional: autocopysel (clipboard copy paste library but consumes lots of memory and scared of multiple running instances)
vncserver
Enter password and set view-only password to NO
1 represents the number of vnc server running
vncserver -kill :1
cp ~/.vnc/xstartup ~/.vnc/xstartup_backup
nano ~/.vnc/xstartup
#!/bin/bash
xsetroot -solid grey
/etc/X11/Xsession
export XKL_XMODMAP_DISABLE=1
startxfce4 &
Then hit Ctrl + X, and then Y to save and exit Nano
Start server again (higher resolution and color depth can degrade performance)
vncserver -geometry 1280x720 -depth 24
Go to https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html
Download and install PuTTY and puttygen.exe
Open puttygen
Open PuTTY
Buy a domain name and set the name servers to cloudflare
Source: https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-18-04
Complete source: https://medium.com/@jgefroh/a-guide-to-using-nginx-for-static-websites-d96a9d034940
Example: https://github.com/FranciscoKnebel/nginx-reverseproxy
Proxy summary: https://www.digitalocean.com/community/tutorials/understanding-nginx-http-proxying-load-balancing-buffering-and-caching
sudo apt install nginx
sudo nginx -v
server {
listen 443 http2;
# IPv6 addresses
listen [::]:443 http2;
ssl on;
ssl_certificate /etc/letsencrypt/live/nean.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/nean.io/privkey.pem;
server_name nean.io www.nean.io;
root /var/www/nean.io/dist/client;
access_log /var/www/nean.io/nginx/nginx.access.log;
error_log /var/www/nean.io/nginx/nginx.access.log;
include snippets/static-files.conf;
location /api/ {
proxy_pass http://localhost:3010;
include snippets/api-params.conf;
}
location /analytics/ {
proxy_pass http://localhost:32768/;
}
}
server {
listen 443 http2;
# IPv6 addresses
listen [::]:443 http2;
ssl on;
ssl_certificate /etc/letsencrypt/live/dev.nean.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dev.nean.io/privkey.pem;
server_name dev.nean.io;
root /var/www/nean.io/dev/dist/client;
access_log /var/log/dev.nean.io/nginx.access.log;
error_log /var/log/dev.nean.io/nginx.error.log;
include snippets/static-files.conf;
location /api/ {
proxy_pass http://localhost:3020;
include snippets/api-params.conf;
}
}
index index.html;
location / {
# First attempt to serve request as file, then as directory, then fall back to displaying the index.html
try_files $uri $uri/ /index.html;
# Cacheing
# expires 1d;
# add_header Cache-Control "public, no-cache";
}
proxy_http_version 1.1;
# Set host header
proxy_set_header Host $host;
# List of IP addresses
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Log IP on nginx proxy server
proxy_set_header X-Real-IP $remote_addr;
# HTTP or HTTPS?
proxy_set_header X-Forwarded-Proto $scheme;
# CORS https://www.digitalocean.com/community/questions/allow-cors-origin-for-node-angular-api-on-nginx
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Authorization $http_authorization;
# proxy_set_header X-NginX-Proxy true;
# proxy_max_temp_file_size 0;
# proxy_redirect off;
# proxy_read_timeout 240s;
# TODO: proxy_cache_bypass $http_upgrade;
ln -s /etc/nginx/sites-available/nean.io /etc/nginx/sites-enabled/nean.io
ln -s /etc/nginx/sites-available/dev.nean.io /etc/nginx/sites-enabled/dev.nean.io
ln: make link command -s: symbolic link flag
sudo nginx -t
sudo service nginx restart
sudo chown -R $USER:$USER /var/www/nean.io
sudo chmod -R 755 /var/www/nean.io
# If the above doesn't work use this
# sudo chown -R www-data:www-data /var/www/nean.io
Note:
4 different cache location exist:
Install & Update NVM (Node version manager: https://github.com/creationix/nvm)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
Test NVM
nvm --version
List Node versions
nvm ls-remote
Install Node
nvm install v10.13.0
Important: when installing a new Node version you need to reinstall the global packages like pm2
Test Node
node --version
NPM packages to work (those that require compiling code from source, for example)
sudo apt install build-essential
Notes:
Install PM2
npm install pm2 -g
Test PM2
pm2 -v
Create ecosystem.config.js in /var/www/nean.io/
Replace ecosystem.config.js text
// Options reference: https://pm2.io/doc/en/runtime/reference/ecosystem-file/
const environmentVariables = {
APP_HOST: "",
AUTHENTICATION_KEY: "37LvDSm4XvjYOh9Y",
NODE_ENV: "production",
SENDGRID_API_KEY: "***",
SENDGRID_TEMPLATE_FEEDBACK: "***",
SENDGRID_TEMPLATE_FORGOT_PASSWORD: "***",
SENDGRID_TEMPLATE_INVITE: "***",
SENDGRID_TEMPLATE_NOTIFICATION: "***",
SENDGRID_TEMPLATE_PASSWORD_UPDATED: "***",
SENDGRID_TEMPLATE_PAYMENT_SUCCESSFUL: "***",
SENDGRID_TEMPLATE_RESEND_EMAIL_VERIFICATION_LINK: "***",
SENDGRID_TEMPLATE_SYSTEM: "***",
SENDGRID_TEMPLATE_WELCOME: "***",
STRIPE_KEY: "***",
VAPID_PRIVATE_KEY: "***",
VAPID_PUBLIC_KEY: "***",
};
function generate(environment, server, env, port = 0, instances = 1) {
return {
name: `${environment}_${server}`,
script: `${server}.bundle.js`,
cwd: `${environment}/dist/server/${server}`,
instances: instances,
env: { ...environmentVariables, PORT: port, ...env },
// Time in ms to wait before restarting a crashing app
restart_delay: 10000,
// Number of times a script is restarted when it exits in less than min_uptime
max_restarts: 10,
// Minimum uptime of the app to be considered started
min_uptime: 1000,
};
}
module.exports = {
apps: [
generate(
"prod",
"web",
{
AMQP_URL: "amqp://server_api:<PASSWORD>@localhost:5672",
DATABASE_PASSWORD: "<PASSWORD>",
DATABASE_URI: "bolt://localhost:7687",
DATABASE_USERNAME: "server_api",
},
3010,
2
),
generate("prod", "worker", {
AMQP_URL: "amqp://server_worker:<PASSWORD>@localhost:5672",
DATABASE_PASSWORD: "<PASSWORD>",
DATABASE_URI: "bolt://localhost:7687",
DATABASE_USERNAME: "server_worker",
}),
generate(
"dev",
"web",
{
AMQP_URL: "amqp://server_api:<PASSWORD>@localhost:5673",
DATABASE_PASSWORD: "<PASSWORD>",
DATABASE_URI: "bolt://localhost:7688",
DATABASE_USERNAME: "server_api",
},
3020,
2
),
generate("dev", "worker", {
AMQP_URL: "amqp://server_worker:<PASSWORD>@localhost:5673",
DATABASE_PASSWORD: "<PASSWORD>",
DATABASE_URI: "bolt://localhost:7688",
DATABASE_USERNAME: "server_worker",
}),
],
deploy: {
dev: {
host: "localhost",
ref: "origin/dev",
repo: "https://github.com/heroku/node-js-getting-started.git",
path: "var/www/nean.io/deploy/dev",
"post-deploy":
"npm install && npm run build && pm2 reload ecosystem.config.js",
},
staging: {
host: "localhost",
ref: "origin/staging",
repo: "https://github.com/heroku/node-js-getting-started.git",
path: "var/www/nean.io/deploy/staging",
"post-deploy":
"npm install && npm run build && pm2 reload ecosystem.config.js",
},
},
};
pm2 startup
Copy paste command to setup
Take snapshot of what processes should start on startup
pm2 save
sudo systemctl status pm2-<USERNAME>
pm2 link <key> <key> MACHINE_NAME
https://github.com/adnanh/webhook
Source: https://medium.com/@riyadhalnur/managing-and-deploying-nodejs-apps-with-pm2-173fbc7d3f95
Source: https://www.digitalocean.com/community/tutorials/how-to-install-git-on-ubuntu-18-04
sudo apt install git
git config --global user.name "Your Name"
git config --global user.email "youremail@domain.com"
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx
sudo certbot --nginx certonly
Automatic cron job will be created to renew certificates
Remember to set disable HTTP access to server in Google Cloud firewall settings
Remember to set Cloudflare > Crypto > SSL to "Full (strict)"
Add http2 in NGINX conf after port numbers
listen 443 http2;
Source: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-18-04
sudo apt update
sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
sudo apt update
sudo apt install docker-ce
sudo systemctl status docker
sudo usermod -aG docker ${USER}
version: "3"
services:
countly:
container_name: countly
image: countly/countly-server
ports:
- "32768:80"
volumes:
- ./countly:/data/db
restart: unless-stopped
neo4j.nean.io:
container_name: neo4j.nean.io
image: neo4j/3.5-enterprise
ports:
- "7474:7474" ## Browser
- "7687:7687" ## Bolt connection
volumes:
- $HOME/neo4j/nean.io/data:/data
- $HOME/neo4j/nean.io/backup:/backup
- $HOME/neo4j/nean.io/logs:/logs
- $HOME/neo4j/nean.io/plugins:/plugins
environment:
NEO4J_dbms_memory_heap_max__size: "512M"
NEO4J_dbms_memory_pagecache_size: "512M"
NEO4J_AUTH: "neo4j/password"
NEO4J_ACCEPT_LICENSE_AGREEMENT: "yes"
restart: unless-stopped
rabbitmq.nean.io:
container_name: rabbitmq.nean.io
image: rabbitmq:3.7
hostname: rabbitmq.nean.io
ports:
- "5672:5672"
restart: unless-stopped
neo4j.dev.nean.io:
container_name: neo4j.dev.nean.io
image: neo4j/3.5-enterprise
ports:
- "7475:7474" ## Browser
- "7688:7687" ## Bolt connection
volumes:
- $HOME/neo4j/dev.nean.io/data:/data
- $HOME/neo4j/dev.nean.io/backup:/backup
- $HOME/neo4j/dev.nean.io/logs:/logs
- $HOME/neo4j/dev.nean.io/plugins:/plugins
environment:
NEO4J_dbms_memory_heap_max__size: "512M"
NEO4J_dbms_memory_pagecache_size: "512M"
NEO4J_AUTH: "neo4j/password"
NEO4J_ACCEPT_LICENSE_AGREEMENT: "yes"
restart: unless-stopped
rabbitmq.dev.nean.io:
container_name: rabbitmq.dev.nean.io
image: rabbitmq:3.7
hostname: rabbitmq.dev.nean.io
ports:
- "5673:5672"
restart: unless-stopped
docker-compose up -d
# terminal within container
docker exec -it <container_name> bash
# Execute cyper in container
bin/cypher-shell -u server_api -p password
# process monitoring for containers
docker stats
# process monitoring for specific container
docker top <container_name>
# RabbitMQ
## Create virtual host
docker exec -it rabbitmq.nean.io rabbitmqctl add_vhost nean
## Create user
docker exec -it rabbitmq.nean.io rabbitmqctl add_user server_api password
docker exec -it rabbitmq.nean.io rabbitmqctl add_user server_worker password
## Set permissions
docker exec -it rabbitmq.nean.io rabbitmqctl set_permissions -p nean server_api ".*" ".*" ".*"
docker exec -it rabbitmq.nean.io rabbitmqctl set_permissions -p nean server_worker ".*" ".*" ".*"
export VISUAL=nano; crontab -e
Short codes
@hourly docker exec neo4j.nean.io bin/neo4j-admin backup --from=localhost:6362 --backup-dir=/backup --name=graph.db-backup --fallback-to-full=true --check-consistency=true --pagecache=2G
Save file
Repeat for neo4j.dev.nean.io instance
Optionally send emails after cron job. https://cloud.google.com/compute/docs/tutorials/sending-mail/using-sendgrid
sudo apt install openjdk-8-jre
wget -O - https://debian.neo4j.org/neotechnology.gpg.key | sudo apt-key add -
echo 'deb https://debian.neo4j.org/repo stable/' | sudo tee -a /etc/apt/sources.list.d/neo4j.list
sudo apt update
sudo apt-get install neo4j=1:3.4.9
sudo service neo4j status
sudo systemctl enable neo4j
Navigate to localhost:7474 in your browser
/usr/bin/cypher-shell -u neo4j -p neo4j
CALL dbms.security.createUser('nean_dev', 'nean_dev', false)
wget -O - "https://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc" | sudo apt-key add -
echo "deb https://dl.bintray.com/rabbitmq/debian bionic main erlang" | sudo tee /etc/apt/sources.list.d/bintray.rabbitmq.list
sudo apt update
sudo apt install rabbitmq-server
sudo service rabbitmq-server status
sudo rabbitmq-plugins enable rabbitmq_management
Navigate to localhost:15672 in your browser
https://winscp.net/eng/download.php
gcloud compute scp --recurse <FROM_DIR> <USERNAME>@<VM_INSTANCE_NAME>:/var/www/nean.io/
cd /var/www/nean.io/
docker-compose up --detach
cd /var/www/nean.io/
pm2 reload ecosystem.config.js --update-env
# save the process list
pm2 save
Local
# Get latest code from base
git fetch upstream
git merge upstream/master
npm run build
Server