Skip to content

Instantly share code, notes, and snippets.

@abhishekpankar
Forked from kimyvgy/MANUAL.md
Created August 28, 2021 07:55
Show Gist options
  • Select an option

  • Save abhishekpankar/ae0afd2f2699f80d4930819b3b33e076 to your computer and use it in GitHub Desktop.

Select an option

Save abhishekpankar/ae0afd2f2699f80d4930819b3b33e076 to your computer and use it in GitHub Desktop.

Revisions

  1. @PJHL PJHL created this gist Sep 15, 2017.
    268 changes: 268 additions & 0 deletions MANUAL.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,268 @@
    Deploy nodejs app with gitlab.com and pm2
    =========================================

    This manual is about setting up an automatic deploy workflow using [nodejs](https://nodejs.org/en/),
    [PM2](http://pm2.keymetrics.io/), [nginx](https://nginx.org/) and
    [GitLab CI](https://about.gitlab.com/features/gitlab-ci-cd/). It is tested on:

    * Target server: **Ubuntu 16.04 x64.** This is suitable for Ubuntu 14.x.
    * **Windows 10** on my PC to work.

    I use **Alpine Linux** in Docker container (gitlab) to speed up deployment.

    What do we need:

    * Account on gitlab.com
    * New virtual server with **Ubuntu 16.04 x64** (or 14.x) to run application
    (i will call it the "target server")


    Configure target server
    -----------------------

    ### 1. Create new sudo-user

    Login with SSH user "root " and run:

    ```bash
    adduser ubuntu
    usermod -aG sudo ubuntu
    ```

    To check sudo access run:

    ```bash
    su ubuntu
    sudo ls -la /root
    ```

    ### 2. Install nodejs and npm

    You can find official instruction
    [here](https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions).

    For Ubuntu 16.04 run:

    ```bash
    curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
    sudo apt-get install -y nodejs
    ```

    To check an installation run:

    ```bash
    node -v
    npm -v
    ```

    ### 3. Install process manager pm2

    [PM2](http://pm2.keymetrics.io/) is a beautiful production process manager for nodejs. It will observe, log and
    automatically restart your application if it fall. Run now:

    ```bash
    sudo npm install -g pm2@latest
    ```

    To enable auto start pm2 on reboot run:

    ```bash
    pm2 startup
    ```

    then **(!important)** follow the instructions on your screen (run displayed command).

    ### 4. Install git

    ```bash
    sudo apt-get install git -y
    ```

    If you haven't deploy git keys yet, you should run:

    ```bash
    ssh-keygen -t rsa -b 4096 -C "[email protected]"
    ```

    This command will generate private (`/home/ubuntu/.ssh/id_rsa`) and public
    (`/home/ubuntu/.ssh/id_rsa.pub`) key. Print public key:

    ```bash
    cat /home/ubuntu/.ssh/id_rsa.pub
    ```

    copy it clipboard and paste to gitlab (Repo settings / Tab "Repository" / Deploy Keys).

    Check ssh access to repository:
    ```bash
    ssh -T [email protected]
    ```

    On the question "The authenticity of host...?" answer "yes".
    If all is okay, you should see string like *"Welcome to GitLab, yourUsername!"*.

    ### 5. Generate SSH keys for current server

    Now we should generate SSH keys to access current server without password.
    Run next command again, but set file path to `/home/ubuntu/access`:

    ```bash
    ssh-keygen -t rsa -b 4096 -C "[email protected]"
    ```

    This command will generate private (`/home/ubuntu/access`) and public (`/home/ubuntu/access.pub`) key.
    Move new generated key to *authorized_keys*:

    ```bash
    cat /home/ubuntu/access.pub >> ~/.ssh/authorized_keys
    ```

    You must copy and save private key on your computer. To print this key on screen use:

    ```bash
    cat ~/access
    ```

    ### 6. Install nginx

    ```bash
    sudo apt-get install nginx -y
    sudo rm /etc/nginx/sites-enabled/default
    ```

    Open nginx config:

    ```bash
    sudo nano /etc/nginx/sites-available/app
    ```

    and replace it with:

    ```nginx
    server {
    listen 80;
    server_name app;
    location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-NginX-Proxy true;
    proxy_pass http://127.0.0.1:3000;
    proxy_redirect off;
    proxy_buffering off;
    }
    }
    ```

    Then run:

    ```bash
    sudo ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/app
    sudo systemctl restart nginx
    # Note: for Ubuntu 14.x run instead: sudo service nginx restart
    ```

    And check nginx status (it should be "active"):

    ```bash
    sudo systemctl status nginx
    ```


    Configure deployment with Gitlab CI
    -----------------------------------

    ### 1. Create file `ecosystem.config.js`in root directory of your project:

    ```javascript
    // Target server hostname or IP address
    const TARGET_SERVER_HOST = process.env.TARGET_SERVER_HOST ? process.env.TARGET_SERVER_HOST.trim() : '';
    // Target server username
    const TARGET_SERVER_USER = process.env.TARGET_SERVER_USER ? process.env.TARGET_SERVER_USER.trim() : '';
    // Target server application path
    const TARGET_SERVER_APP_PATH = `/home/${TARGET_SERVER_USER}/app`;
    // Your repository
    const REPO = '[email protected]:yourUsername/test-server.git';

    module.exports = {
    /**
    * Application configuration section
    * http://pm2.keymetrics.io/docs/usage/application-declaration/
    */
    apps: [
    {
    name: 'testApp',
    script: 'index.js',
    env: {
    NODE_ENV: 'development'
    },
    env_production: {
    NODE_ENV: 'production',
    PORT: 3000
    }
    }
    ],

    /**
    * Deployment section
    * http://pm2.keymetrics.io/docs/usage/deployment/
    */
    deploy: {
    production: {
    user: TARGET_SERVER_USER,
    host: TARGET_SERVER_HOST,
    ref: 'origin/master',
    repo: REPO,
    ssh_options: 'StrictHostKeyChecking=no',
    path: TARGET_SERVER_APP_PATH,
    'post-deploy': 'npm install --production'
    + ' && pm2 startOrRestart ecosystem.config.js --env=production'
    + ' && pm2 save'
    }
    }
    };
    ```

    ### 2. Add secret variables in gitlab:

    Go to [gitlab.com](https:/gitlab.com) -> Your project -> "Settings" -> "CI/CD" -> "Secret variables".
    Add some variables:

    | Variable | Description |
    |---------------------------------|----------------------------------------------------------|
    | TARGET_SERVER_HOST | Target server host like `127.0.0.1` or `your.host.com` |
    | TARGET_SERVER_USER | SSH username for login. Example `ubuntu` |
    | TARGET_SERVER_SECRET_KEY_BASE64 | Base64 encoded private RSA key to login target server. Make it protected |

    ### 3. Create file `.gitlab-ci.yml` in root directory of project:

    ```yaml
    image: keymetrics/pm2:6

    stages:
    - deploy

    deploy_prod:
    stage: deploy
    script:
    - echo "====== Deploy to production server ======"
    - apk update && apk upgrade
    - apk add git openssh bash
    # Add target server`s secret key
    - mkdir ~/.ssh
    - echo $TARGET_SERVER_SECRET_KEY_BASE64 | base64 -d > ~/.ssh/id_rsa
    - chmod 700 ~/.ssh && chmod 600 ~/.ssh/*
    - echo "Test ssh connection"
    - ssh -o StrictHostKeyChecking=no -T "ubuntu@$TARGET_SERVER_HOST"
    # Delploy
    - echo "Setup tagget server directories"
    - pm2 deploy ecosystem.config.js production setup 2>&1 || true
    - echo "make deploy"
    - pm2 deploy ecosystem.config.js production
    environment:
    name: deploying
    only:
    - master
    ```
    If all is okay, your project will be automatically deployed every push and merge to master branch.