CI/CD Setup

SSH Key Configuration

Generate SSH Key

# Generate SSH key pair
ssh-keygen -t rsa -b 4096 -C "[email protected]"
 
# Or with custom path
ssh-keygen -t rsa -b 4096 -f ~/.ssh/deployment_key -C "[email protected]"
 
# Generate ED25519 key (more secure)
ssh-keygen -t ed25519 -C "[email protected]"
 
# View public key
cat ~/.ssh/id_rsa.pub

Configure Server (Destination)

# Copy public key to server
ssh-copy-id -i ~/.ssh/id_rsa.pub username@server-ip
 
# Or manually add to authorized_keys
cat ~/.ssh/id_rsa.pub | ssh username@server-ip "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
 
# Or manually edit
sudo nano ~/.ssh/authorized_keys
# Paste the public key content

SSH Configuration

# Edit SSH daemon config
sudo nano /etc/ssh/sshd_config
 
# Important settings for CI/CD
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no
PermitRootLogin no
Protocol 2
 
# Test configuration
sudo sshd -t
 
# Restart SSH service
sudo systemctl restart ssh
# Or
sudo service ssh restart

Test SSH Connection

# Test connection
ssh -i ~/.ssh/id_rsa username@server-ip
 
# Test specific key
ssh -i ~/.ssh/deployment_key username@server-ip
 
# Test with verbose output
ssh -v -i ~/.ssh/id_rsa username@server-ip

CI/CD Pipeline Setup (Jenkins Example)

Add SSH Credentials in Jenkins

1. Manage Jenkins Manage Credentials
2. Click "Add Credentials"
3. Select "SSH Username with private key"
4. Enter:
   - Username: your_username
   - Private Key: Paste contents of ~/.ssh/id_rsa
   - Passphrase: (if key has one)
5. Click "Create"

Jenkins Pipeline Script

pipeline {
    agent any
    
    stages {
        stage('Build') {
            steps {
                echo 'Building...'
                sh 'npm install'
                sh 'npm run build'
            }
        }
        
        stage('Test') {
            steps {
                echo 'Testing...'
                sh 'npm test'
            }
        }
        
        stage('Deploy') {
            steps {
                echo 'Deploying...'
                sshagent(['deployment-credentials']) {
                    sh '''
                        ssh -o StrictHostKeyChecking=no username@server-ip << 'ENDSSH'
                        cd /var/www/app
                        git pull origin main
                        npm install
                        npm run build
                        sudo systemctl restart myapp
ENDSSH
                    '''
                }
            }
        }
    }
    
    post {
        always {
            echo 'Pipeline completed'
        }
        success {
            echo 'Deployment successful'
        }
        failure {
            echo 'Deployment failed'
        }
    }
}

GitHub Actions Setup

GitHub Workflow File

# .github/workflows/deploy.yml
name: Deploy
 
on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
 
jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v2
    
    - name: Setup Node.js
      uses: actions/setup-node@v2
      with:
        node-version: '16'
    
    - name: Install dependencies
      run: npm install
    
    - name: Run tests
      run: npm test
    
    - name: Build
      run: npm run build
    
    - name: Deploy to server
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.SERVER_IP }}
        username: ${{ secrets.SERVER_USER }}
        key: ${{ secrets.SSH_PRIVATE_KEY }}
        script: |
          cd /var/www/app
          git pull origin main
          npm install
          npm run build
          sudo systemctl restart myapp

Add GitHub Secrets

1. Go to GitHub repository
2. Settings Secrets
3. Add new secret:
   - SERVER_IP: your-server-ip
   - SERVER_USER: username
   - SSH_PRIVATE_KEY: (contents of ~/.ssh/id_rsa)

GitLab CI/CD Setup

GitLab CI Configuration

# .gitlab-ci.yml
stages:
  - build
  - test
  - deploy
 
build:
  stage: build
  script:
    - npm install
    - npm run build
  artifacts:
    paths:
      - dist/
 
test:
  stage: test
  script:
    - npm install
    - npm test
 
deploy:
  stage: deploy
  script:
    - eval $(ssh-agent -s)
    - ssh-add <(cat $SSH_PRIVATE_KEY)
    - ssh -o StrictHostKeyChecking=no $DEPLOY_USER@$DEPLOY_HOST "cd /var/www/app && git pull origin main && npm install && npm run build && sudo systemctl restart myapp"
  only:
    - main

SSH Key Permissions

# Correct directory permissions
chmod 700 ~/.ssh
 
# Correct file permissions
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 600 ~/.ssh/authorized_keys
chmod 644 ~/.ssh/config
 
# Fix server side permissions
sudo chmod 700 /home/username/.ssh
sudo chmod 600 /home/username/.ssh/authorized_keys
sudo chown -R username:username /home/username/.ssh

Troubleshooting

# Check SSH connectivity
ssh -v -i ~/.ssh/id_rsa username@server-ip
 
# Check server SSH settings
sudo sshd -t
 
# View SSH auth logs
sudo tail -f /var/log/auth.log
 
# Check if key is authorized
cat ~/.ssh/authorized_keys
 
# List available keys
ssh-add -l
 
# Add key to SSH agent
ssh-add ~/.ssh/id_rsa
 
# Test without password
ssh -o PasswordAuthentication=no username@server-ip
 
# Check SSH service status
sudo systemctl status ssh
sudo service ssh status

Best Practices

# Use strong key
ssh-keygen -t ed25519 -C "[email protected]"
 
# Use deployment-specific keys
ssh-keygen -t rsa -b 4096 -f ~/.ssh/deployment_key
 
# Protect private keys
chmod 600 ~/.ssh/*_key
 
# Rotate keys regularly
# Keep old key for backup, generate new one
 
# Use SSH agent to avoid typing passphrase
eval $(ssh-agent)
ssh-add ~/.ssh/id_rsa
 
# Disable password authentication on server
PasswordAuthentication no
 
# Restrict root login
PermitRootLogin no
 
# Limit SSH attempts
MaxAuthTries 3
MaxSessions 10