Showing posts sorted by relevance for query VPS. Sort by date Show all posts
Showing posts sorted by relevance for query VPS. Sort by date Show all posts

Sunday, 31 March 2024

Implementing CI/CD for a Laravel App with Jenkins Using Docker Cloud Agents

1. Architecture
- Source Repository for store source code (Github)
- Jenkins server for master server handle Pipeline CICD (using local)
- Docker host to clone source, build, test for CI (using local)

- Server to deploy Laravel app for CD (VPS || Cloud)

2. Install tools & prepare source code
- Prepare source code Laravel
- Install Docker in local
- Install Jenkins using Docker in local: Using Docker plugin | Docker pipeline plugin
- Setup Docker cloud agent for CI (to clone source, build, test)
- Setup Permanent Agent server (using VPS) for CD (to deploy Laravel app)
||
Cloud Agent server (using AWS||GCP||Azure) for CD (to deploy Laravel app)

3. Setup Pipeline CICD
- Create job DeployLaraveApp
+ Type: pipeline
+  Trigger: schedule to check source change || when source code change (case Jenkin server not using in local by using webhook in github)
+ Using jenkinFile
- Run build when trigger happen.

-------------------------
Detailed instructions

* Prerequisite
- Install Jenkins, Docker

* Source Repository (Github)
- Source Laravel
- dockerfile/ docker_compose
file
- Jenkinfile

* Setup Docker cloud agent for CI (to clone source, build, test)
+ Using: Docker Pipeline Plugin in Jenkins
Or using: Docker Cloud Agent in Jenkins

* Setup Permanent Agent server (using VPS) for CD (to deploy Laravel app)

* Create job DeployLaraveApp

* Using Ngrok for Jenkins in localhost: https://ngrok.com
- run: ngrok http http://localhost:8090
- endpoint page: https://dashboard.ngrok.com/cloud-edge/endpoints

* Setting webhook github for Jenkins in localhost

- When create Pipeline:.../ Build Triggers: select Github hook trigger for GITScm polling.

- Add webhook in Github: Select Repository/ Setting/ Webhooks/ Add webhook/ Payload Url: enter url get from Ngrok (for jenkins localhost)/: {JenkinServer}/github-webhook/ / Content type: application/json / Which event would you like to trigger this webhook: Let me select individual events: Enable Pull request, Pushes.. / Add webhook.

* Set permission for jenkin handle with /var/www

- Copy source code from workspace in jenkins to VPS server

cp -r * /var/www/html

- When install nginx/ apache2, then auto create group www-data
- or using this: groupadd www-data
- Add user jenkin to this group: 

sudo usermod -aG www-data jenkins
sudo newgrp www-data // to switch to www-data group for current user (because one user can has many groups)

- Change owner directory, change permission

sudo chown jenkins:www-data -R html
sudo chmod -R 2771 html 
// 2: is the set-group-id: ensure that the created file in html directory inherit the group ownership of html directory

Thank you.

Saturday, 25 March 2023

Four ways to secure a VPS

1. Using a non-root user

# add new user
adduser phong
new password:...
# check group info user
id phong
# add user phong to sudo group
usermod -aG sudo phong
# switch to the user account name "phong"
su - phong
# logout accout
exit 

- Configure SSH for the new user

# create ssh dirctory
mkdir ~/.ssh

# chnage the pemissions of ~/.ssh to 'rwx------',
# mean owner has read, write, excute, orther users have no permissions at all

chmod 700 ~/.ssh

# authorized_keys is used to store public keys that are authorized
# to access the current uesr's account

nano ~/.ssh/authorized_keys
 
# copy the content id_rsa.pub to clipboard
.ssh pbcopy < id_rsa.pub 

# past content to ~/.ssh/authorized_keys and save
Ctrl S > Ctrl X 

# change the permissions of authorized_keys file to 'rw----'
# only onwner has read, write permissions

chmod 600 ~/.ssh/authorized_keys

- SSH to vps with new user

ssh phong@vps-ip

2. Disable password and root login

# open the sshd_config
sudo nano /etc/ssh/sshd_config 
 
# change content
PermitRootLogin yes => no 
PasswordAuthentication  yes => no
 
# reload sshd
sudo systemctl reload sshd 
 
# now we can not login as root  

3. Block incoming traffic on non-public ports

sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https 
sudo ufw enable 
 
# confirm ufw
sudo ufw status 

4. Enable automatic security updates

# open sshd_config
# unattended-upgrades package is responsibile for automaticlly
# downloading and installing security opdates for the system
# --priority=low mean other packages and processes given higher priority 
# when system resources are limited
sudo dpkg-reconfigure --priority=low unattended-upgrades
choose yes
 
# displays the current config value for APT::Periodic::Unattended-Upgrade
# which is used to control the behavior for the unattended-upgrade
apt-config dump APT::Periodic::Unattended-Upgrade 

Thank you.

Thursday, 23 March 2023

Deployment Laravel with Nginx, SSL with Lets Encrypt

In this tutorial, i build vps for subdomain api.example.com

1. Access your Vps

ssh user@ip

2. Install PHP 8.1

sudo add-apt-repository ppa:ondrej/php -y
sudo apt install -y php8.1 php8.1-{cli,gd,curl,mysql,ldap,zip,fileinfo,fpm,xml,mbstring,exif,pspell,imagick,bcmath} 
 
# or install one by one modules
sudo apt install -y php8.1 php8.1-curl php8.1-mysql
 
# cmd for check status php
sudo nano /etc/php/8.1/fpm/php.ini 
sudo systemctl restart php8.1-fpm
 

3. Install composer

sudo wget -O composer-setup.php https://getcomposer.org/installer
sudo php composer-setup.php --install-dir=/usr/bin --filename=composer

4. Clone, build Laravel app

- install laravel project

composer create-project --prefer-dist laravel/laravel api.example.com
cd api.example.com
php artisan
nano .env
 
sudo mv ~/api.example.com /var/www/api.example.com
sudo chown -R www-data.www-data /var/www/api.example.com/storage
sudo chown -R www-data.www-data /var/www/api.example.com/bootstrap/cache
 

- Provide access for composer and install packages

sudo chmod -R 775 /var/www/api.example.com/storage
sudo chmod -R 775 /var/www/api.example.com/bootstrap/cache

- create file .env

cp -a .env.example .env
nano .env
php artisan key:generate 

4. Config Laravel app in Nginx

- I consume you installed Nginx

- Set Up Nginx Server Blocks (Virtual Hosts) for api.example.com

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/api.example.com
sudo nano /etc/nginx/sites-available/api.example.com

- Config for /etc/nginx/sites-available/api.example.com

server {
listen 80;
listen [::]:80;
server_name api.example.com; 
root /var/www/api.example.com/public;
  
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
 
    index index.html index.htm index.php;
  
    charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
 
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
 
    error_page 404 /index.php;
 
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_read_timeout 3600;
}
location ~ /\.(?!well-known).* {
deny all;
}
}

* Now that we have our server block file, we need to enable it. We can do this by creating symbolic link from this file to the sites-enabled directory, which Nginx reads from during startup.

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/ 

- Check nginx config status

# Check NGINX config site-avaiable
sudo nginx -t

# Restart NGINX
sudo service nginx restart 

7. Add record for domain

* This config for subdomain api.example.com

 Host    Type Value   TTL 
 api
 A
 your-vps-ip 
 3600

8. Using Supervisor (process manager for Linux)

- file supervisord.conf

[unix_http_server]
file=/run/supervisord.sock

[supervisord]
nodaemon=true
logfile=/dev/null
logfile_maxbytes=0
pidfile=/run/supervisord.pid

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///run/supervisord.sock

[program:php-fpm]
command=/usr/local/sbin/php-fpm -F
autostart=true
autorestart=true
priority=5
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
# stdout_events_enabled=true
# stderr_events_enabled=true

[program:nginx]
command=/usr/sbin/nginx -g 'daemon off;'
autostart=true
autorestart=true
priority=10
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
# stdout_events_enabled=true
# stderr_events_enabled=true

[include]
files = /etc/supervisor.d/*.conf

9. Add SSL with LetsEncrypt

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d api.example.com
 
# check certbot auto renew  
sudo systemctl status certbot.timer  
 
# or manually renew ssl (90 day will expired)
sudo certbot renew --dry-run 

* more option features

(1) install PostgreSQL

# install pgsql extension for php8.1
sudo apt-get install php8.1-pgsql

# install postgresSql
sudo apt update
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" | sudo tee /etc/apt/sources.list.d/postgresql-pgdg.list > /dev/null
sudo apt update
sudo apt install postgresql-14
sudo ss -atnp | grep 5432
dpkg -l | grep postgresql
sudo systemctl restart postgresql
sudo systemctl enable postgresql
sudo systemctl status postgresql
sudo -u postgres psql --version

# using postgre
sudo -i -u postgres
sudo -u postgres psql
sudo -u postgres createuser --interactive
sudo -u postgres createdb sammy
# example create myUser & myDB
sudo -u postgres psql
CREATE USER myUser WITH PASSWORD 'myPassword';
CREATE DATABASE mydb;
GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser

# show all DB, all users
\l  
\du

# export db
pg_dump -U postgres -d {dbname} -F p -f /{path-to-db}y/DB_backup.sql

# copy file to local
rsync -avz {user}@{IP}:/{path-to-db}y/DB_backup.sql /{path_to_store}

* Limit binlog data in database

Examle in postgresql.conf:
max_wal_size = 2GB
min_wal_size = 256MB

Examle in mysqld.cnf:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf binlog_expire_logs_seconds = 86400 sudo systemctl restart mysql

Thank you.

Deployment Node.js Nuxt App with Nginx, SSL with Lets Encrypt

1. Access your Vps

ssh user@ip

2.Install nodejs, npm, yarn

sudo apt update

# select node version
curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -

# install nodejs
sudo apt install nodejs

# check nodejs
node --version
npm --version

# install yarn
npm install -g yarn

3. Clone, build and run Nuxt app

git clone [your-url-project-on-github]
cd your-project
yarn install
yarn build
yarn start

4. Run Nuxt app using pm2 (process manager for Node.js)

- create file ecosystem.config.js in root Nuxt app

# create file
touch ecosystem.config.js
# with content
module.exports = {
apps: [
{
name: 'NuxtAppName',
exec_mode: 'cluster',
instances: 'max', // Or a number of instances
script: './node_modules/nuxt/bin/nuxt.js',
args: 'start'
}
]
}

- Build and run Nuxt app using pm2

# intall pm2
npm install pm2 -g

# run nuxt app
pm2 start
 
# check pm2
pm2 ls
pm2 logs (Show log stream)
pm2 flush (Clear logs)  
 
# stop nuxt app
pm2 stop [app_name_or_id]
 
# delete all process managed
pm2 delete all
 

- To make sure app starts when reboot

pm2 startup ubuntu
# test reboot server
reboot

5. Setup ufw firewall

# setup ufw
sudo ufw enable
sudo ufw allow http
sudo ufw allow https
sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'
# check ufw status
sudo ufw status

# output:
sudo ufw allow ssh (Port 22)
sudo ufw allow http (Port 80)
sudo ufw allow https (Port 443)

6. Install NGINX and configure

- Install nginx

# install nginx
sudo apt update
sudo apt install nginx

# check nginx working
sudo systemctl status nginx
sudo systemctl enable nginx
sudo systemctl stop nginx
sudo systemctl restart nginx

- Errors (if happen): unknow host Ubuntu-20.04

# open /ect/host
sudo nano /etc/hosts

# update line become
127.0.0.1 Ubuntu-20.04 localhost

- Set Up Nginx Server Blocks (Virtual Hosts) for example.com

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/example.com
sudo nano /etc/nginx/sites-available/example.com

- Config for /etc/nginx/sites-available/example.com

server {
listen 80 default_server;
listen [::]:80
default_server;
 
# Add the following to the location part of the server block
server_name example.com www.example.com;

location / {
proxy_pass http://localhost:3000; #whatever port your app runs on
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}

* Now that we have our server block file, we need to enable it. We can do this by creating symbolic link from this file to the sites-enabled directory, which Nginx reads from during startup.

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/  
# to delete symbolic link
cd /etc/nginx/sites-enabled/
rm site_want_delete

- Check nginx config status

# Check NGINX config
sudo nginx -t

# Restart NGINX
sudo service nginx restart

7. Add record for domain

Host Type Value TTL
  @
 A
 your-ip-vps  3600 
 www 
 CNAME 
 example.com 
 3600

8. Add SSL with LetsEncrypt

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
 
# check certbot auto renew  
sudo systemctl status certbot.timer  
 
# or manually renew ssl (90 day will expired)
sudo certbot renew --dry-run 

Thank you.


Publish npm package

  Để publish   pav-kit  lên NPM, bạn hãy làm theo các bước dưới đây. Tôi đã tạo thêm file  index.js  để đảm bảo gói tin hợp lệ. Bước 1: Tạo ...