I have the following ansible playbook
- name: "update apt package."
become: yes
apt:
update_cache: yes
- name: "update packages"
become: yes
apt:
upgrade: yes
- name: "Remove dependencies that are no longer required"
become: yes
apt:
autoremove: yes
- name: "Install Dependencies"
become: yes
apt:
name: ["nodejs", "npm"]
state: latest
update_cache: yes
- name: Install pm2
become: yes
npm:
name: pm2
global: yes
production: yes
state: present
- name: Creates Directory
become: yes
file:
path: ~/backend
state: directory
mode: 0755
- name: Copy backend dist files web server
become: yes
copy:
src: ~/project/artifact.tar.gz
dest: ~/backend/artifact.tar.gz
- name: Extract backend files
become: yes
shell: |
cd ~/backend
tar -vxf artifact.tar.gz
#pwd
- name: Executing node
become: true
become_method: sudo
become_user: root
shell: |
cd ~/backend
npm install
npm run build
pm2 stop default
pm2 start npm --name "backend" -- run start --port 3030
pm2 status
cd ~/backend/dist
pm2 start main.js --update-env
pm2 status
I have the following issue with the task Executing node. So on my remote server, if I run each of the commands manually, after logging onto the remote machine via SSH, as root user, pm2 starts the services as expected as I can also confirm from pm2 status. I can also verify that the service is bound to port 3030 and listening on it (as expected).
But when I try doing the same using Ansible playbook, PM2 does start the service, but for some reason it does not bind the service to the port 3030 as I can see there is nothing listening on 3030.
Can someone please help?
Major edit 1
I also tried breaking up the entire task into smaller ones and run them as individual commands through the command module. But the results are still the same.
Updated roles playbook:
- name: "update apt package."
become: yes
apt:
update_cache: yes
- name: "update packages"
become: yes
apt:
upgrade: yes
- name: "Remove dependencies that are no longer required"
become: yes
apt:
autoremove: yes
- name: "Install Dependencies"
become: yes
apt:
name: ["nodejs", "npm"]
state: latest
update_cache: yes
- name: Install pm2
become: yes
npm:
name: pm2
global: yes
production: yes
state: present
- name: Creates Directory
become: yes
file:
path: ~/backend
state: directory
mode: 0755
- name: Copy backend dist files web server
become: yes
copy:
src: ~/project/artifact.tar.gz
dest: ~/backend/artifact.tar.gz
#dest: /home/ubuntu/backend/artifact.tar.gz
- name: Extract backend files
become: yes
shell: |
cd ~/backend
tar -vxf artifact.tar.gz
- name: NPM install
become: true
command: npm install
args:
chdir: /root/backend
register: shell_output
- name: NPM build
become: true
command: npm run build
args:
chdir: /root/backend
register: shell_output
- name: PM2 start backend
become: true
command: pm2 start npm --name "backend" -- run start
args:
chdir: /root/backend
register: shell_output
- name: PM2 check backend status in pm2
become: true
command: pm2 status
args:
chdir: /root/backend
register: shell_output
- name: PM2 start main
become: true
command: pm2 start main.js --update-env
args:
chdir: /root/backend/dist
register: shell_output
- debug: var=shell_output
No change in the result even with the above:
while running the same manually, either individually each command on the bash shell or through a .sh script (as below) works just fine.
#!/bin/bash
cd ~/backend
pm2 start npm --name "backend" -- run start
pm2 status
cd dist
pm2 start main.js --update-env
pm2 status
pm2 save
Sometimes, even the manual steps also do not get the port up and listening while the service is still up. But this happens rarely and I am unable to consistently reproduce this issue.
Why is this not working is my primary question. What's am I doing wrong? My assumption is that, conceptually, it should work.
My secondary question is how can I make this work?
Related
I am writing an ansible playbook to perform various pm2 functions.
I have searched a bit and cannot find an example of someone setting up pm2-logrotate.
I believe I am close but I'm not sure my shell commands are working. When I ssh into the child node and run sudo pm2 ls it says In-memory PM2 is out-of-date, do: $ pm2 update even though I am running that command from my playbook. What am I missing here?
---
# RUN playbook
# ansible-playbook -K pm2-setup.yml
- name: Setup pm2 and pm2-logrotate
hosts: devdebugs
remote_user: ansible
become: true
tasks:
- name: Install/Update pm2 globally
community.general.npm:
name: pm2
global: yes
state: latest
- name: Update In-memory pm2
ansible.builtin.shell: pm2 update
- name: Install/Update pm2-logrotate globally
ansible.builtin.shell: pm2 install pm2-logrotate
- name: Copy pm2-logrotate config
ansible.builtin.copy:
src: /home/ubuntu/files/pm2-logrotate-conf.json
dest: /home/ubuntu/.pm2/module_conf.json
owner: root
group: root
mode: '0644'
...
Bonus question: is there a way to skip the shell commands if they aren't needed (i.e. if pm2-logrotate is already installed)?
I was mixing up the users on my server. I fixed this by specifying to run as ubuntu for the update command.
I am trying to deploy a nodejs app from github to a remote ubuntu server via ssh. Here is my main.yml:
name: Node Github CI
on:
push:
branches:
- master
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Node Js
uses: actions/setup-node#v1
- name: SSH and deploy node app
uses: appleboy/ssh-action#master
with:
host: ${{ secrets.SERVER_IP }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SERVER_KEY }}
script: |
service myservice stop
cd leancrm-backend
git pull git://myuser#github.com/mycmp/myapp-backend.git master
npm install
service myservice start
When I run this, I get this error:
======CMD======
service myservice stop
cd myapp-backend
git pull git://myuser#github.com/mycmp/myapp-backend.git master
npm install
service myservice start
======END======
err: fatal: Unable to look up myuser#github.com (port 9418) (Name or service not known)
err: bash: line 3: npm: command not found
==============================================
Screenshot:
Since you are connected to your server I assume you already have the repo there, so you only need to execute git pull.
Also you should add these lines at the beginning of the script:
export NVM_DIR=~/.nvm
source ~/.nvm/nvm.sh
My yml file looks like these at the end:
script: |
git pull
export NVM_DIR=~/.nvm
source ~/.nvm/nvm.sh
npm install
npm run start_server
Reason:
I use nvm for the server node environment, and nvm will not install the node environment in the /usr/local/bin/ directory, so that sudo can't find the corresponding instructions, and finally create a soft connection to solve
sudo ln -s "$NVM_DIR/versions/node/$(nvm version)/bin/node" "/usr/local/bin/node"
sudo ln -s "$NVM_DIR/versions/node/$(nvm version)/bin/npm" "/usr/local/bin/npm"
sudo ln -s "$NVM_DIR/versions/node/$(nvm version)/bin/pm2" "/usr/local/bin/pm2"
sudo ln -s "$NVM_DIR/versions/node/$(nvm version)/bin/yarn" "/usr/local/bin/yarn"
you can test "sudo npm -v"
Your first step
name: Node Js
uses: actions/setup-node#v1
sets up Node.js on the GitHub build runner. Your second step however...
name: SSH and deploy node app
uses: appleboy/ssh-action#master
with:
host: ${{ secrets.SERVER_IP }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SERVER_KEY }}
script: |
service myservice stop
cd leancrm-backend
git pull git://myuser#github.com/mycmp/myapp-backend.git master
npm install
service myservice start
... SSHs to your server and then runs script instructions there. You're also attempting to check out your source code repo there.
What you probably wanna do is check out your repo on the GitHub build runner...
- name: Checkout repo
uses: actions/checkout#v2
.. then run npm install there, then scp the output to your server, and finally ssh to that machine and restart your service.
Check if you did install npm on your remote ubuntu.
npm also needs to be installed on the remote server for the deployment.
What is the proper way to setup node.js app on Ubuntu server with Ansible?
Now I'm trying to register pm2 as a service like code below:
- name: install pm2
npm:
name: pm2
global: yes
state: present
- name: create pm2 init.d script
template:
src: pm2_init_config.j2
dest: "/etc/init.d/pm2"
backup: yes
- name: ensure pm2 service is started
service:·
name: pm2
state: started
enabled: yes
but meet strange error:
pm2 unrecognized service in Ansible console
The pm2_init_config is similar to this one
if I ssh to the box and run sudo service pm2 start everything works as expected
The change below fixed the problem:
- name: create pm2 init.d script
template:
src: pm2_init_config.j2
dest: "/etc/init.d/pm2"
backup: yes
mode: 0751
I don't know why it works. Can somebody explain this trick with mode?
In a playbook, I copy files using sudo. It used to work... Until we migrated to Ansible 1.9... Since then, it fails with the following error message:
"ssh connection closed waiting for sudo password prompt"
I provide the ssh and sudo passwords (through the Ansible prompt), and all the other commands running through sudo are successful (only the file copy and template fail).
My command is:
ansible-playbook -k --ask-become-pass --limit=testhost -C -D playbooks/debug.yml
and the playbookd contains:
- hosts: designsync
gather_facts: yes
tasks:
- name: Make sure the syncmgr home folder exists
action: file path=/home/syncmgr owner=syncmgr group=syncmgr mode=0755 state=directory
sudo: yes
sudo_user: syncmgr
- name: Copy .cshrc file
action: copy src=roles/designsync/files/syncmgr.cshrc dest=/home/syncmgr/.cshrc owner=syncmgr group=syncmgr mode=0755
sudo: yes
sudo_user: syncmgr
Is this a bug or did I miss something?
François.
Your playbook should look like:
- hosts: designsync
gather_facts: yes
tasks:
- name: Make sure the syncmgr home folder exists
sudo: yes
sudo_user: syncmgr
file:
path: "/home/syncmgr"
owner: syncmgr
group: syncmgr
mode: 0755
state: directory
- name: Copy .cshrc file
sudo: yes
sudo_user: syncmgr
copy:
src: "roles/designsync/files/syncmgr.cshrc"
dest: "/home/syncmgr/.cshrc"
owner: syncmgr
group: syncmgr
mode: 0755
Depending on the exact version of Ansible you're using, there may be a bug with sudo_user (experienced it myself).
Trying changing your playbooks from "sudo_user" to "remote_user".
I've come across a problem with Anisble hanging when trying to start a forever process on an Ansible node. I have a very simple API server I'm creating in vagrant and provisioning with Ansible like so:
---
- hosts: all
sudo: yes
roles:
- Stouts.nodejs
- Stouts.mongodb
tasks:
- name: Install Make Dependencies
apt: name={{ item }} state=present
with_items:
- gcc
- make
- build-essential
- name: Run NPM Update
shell: /usr/bin/npm update
- name: Create MongoDB Database Folder
shell: /bin/mkdir -p /data/db
notify:
- mongodb restart
- name: Generate Dummy Data
command: /usr/bin/node /vagrant/dataGen.js
- name: "Install forever (to run Node.js app)."
npm: name=forever global=yes state=latest
- name: "Check list of Node.js apps running."
command: /usr/bin/forever list
register: forever_list
changed_when: false
- name: "Start example Node.js app."
command: /usr/bin/forever start /vagrant/server.js
when: "forever_list.stdout.find('/vagrant/server.js') == -1"
But even though Ansible acts like everything is fine, no forever process is started. When I change a few lines to remove the when: statement and force it to run, Ansible just hands, possibly running the forever process (forever, I presume) but not launching the VM to where I can interact with it.
I've referenced essentially two points online; the only sources I can find.
as stated in the comments the variable content needs to be included in your question for anyone to provide a correct answer but to overcome this I suggest you can do it like so:
- name: "Check list of Node.js apps running."
command: /usr/bin/forever list|grep '/vagrant/server.js'|wc -l
register: forever_list
changed_when: false
- name: "Start example Node.js app."
command: /usr/bin/forever start /vagrant/server.js
when: forever_list.stdout == "0"
which should prevent ansible from starting the JS app if it's already running.