Create a full CI/CD pipeline and production deployment guide that is fully consistent with Forgejo Actions workflow, docker-compose.yml, and nginx config
Some checks are pending
Some checks are pending
This commit is contained in:
parent
7eee42cea8
commit
7c9afdd686
6 changed files with 2133 additions and 1289 deletions
|
@ -8,7 +8,7 @@ on:
|
|||
|
||||
env:
|
||||
REGISTRY: ${{ secrets.CI_HOST }}:5000
|
||||
IMAGE_NAME: sharenet
|
||||
IMAGE_NAME: ${{ secrets.APP_NAME || 'sharenet' }}
|
||||
|
||||
jobs:
|
||||
test-backend:
|
||||
|
@ -20,7 +20,7 @@ jobs:
|
|||
image: postgres:15
|
||||
env:
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: sharenet_test
|
||||
POSTGRES_DB: ${{ secrets.APP_NAME || 'sharenet' }}_test
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
|
@ -135,10 +135,19 @@ jobs:
|
|||
username: ${{ secrets.PROD_USER }}
|
||||
key: ${{ secrets.PROD_SSH_KEY }}
|
||||
script: |
|
||||
cd /opt/sharenet
|
||||
cd /opt/${{ secrets.APP_NAME || 'sharenet' }}
|
||||
|
||||
# Pull latest code from repository (includes docker-compose.yml and nginx config)
|
||||
git pull origin main
|
||||
|
||||
# Create environment file for this deployment
|
||||
echo "IMAGE_TAG=${{ github.sha }}" > .env
|
||||
echo "REGISTRY=${{ secrets.CI_HOST }}:5000" >> .env
|
||||
echo "IMAGE_NAME=sharenet" >> .env
|
||||
docker-compose pull
|
||||
docker-compose up -d
|
||||
docker system prune -f
|
||||
echo "IMAGE_NAME=${{ secrets.APP_NAME || 'sharenet' }}" >> .env
|
||||
echo "POSTGRES_PASSWORD=${{ secrets.POSTGRES_PASSWORD || 'your_secure_password_here' }}" >> .env
|
||||
echo "DATABASE_URL=postgresql://${{ secrets.POSTGRES_USER || 'sharenet' }}:${{ secrets.POSTGRES_PASSWORD || 'your_secure_password_here' }}@postgres:5432/${{ secrets.POSTGRES_DB || 'sharenet' }}" >> .env
|
||||
echo "NODE_ENV=production" >> .env
|
||||
echo "RUST_LOG=info" >> .env
|
||||
|
||||
# Run deployment using the repository's docker-compose.yml
|
||||
sudo ./deploy.sh
|
1676
CI_CD_PIPELINE_SETUP_GUIDE.md
Normal file
1676
CI_CD_PIPELINE_SETUP_GUIDE.md
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,819 +0,0 @@
|
|||
# CI/CD Linode Setup Guide
|
||||
|
||||
This guide covers setting up your CI/CD Linode with Forgejo Actions runner and a local Docker registry for automated deployments.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Forgejo Host │ │ CI/CD Linode │ │ Production Linode│
|
||||
│ (Repository) │ │ (Actions Runner)│ │ (Docker Deploy) │
|
||||
│ │ │ + Docker Registry│ │ │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│ │ │
|
||||
│ │ │
|
||||
└─────────── Push ──────┼───────────────────────┘
|
||||
│
|
||||
└─── Deploy ────────────┘
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Ubuntu 24.04 LTS Linode with root access
|
||||
- Basic familiarity with Linux commands and SSH
|
||||
- Forgejo repository with Actions enabled
|
||||
- Production Linode IP address (for SSH key exchange)
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. **Follow this complete CI/CD setup guide**
|
||||
2. **Set up SSH keys** for secure communication with Production server
|
||||
3. **Configure Forgejo Actions runner**
|
||||
4. **Test registry and runner functionality**
|
||||
5. **Exchange SSH keys** with Production server
|
||||
6. **Configure Forgejo repository secrets**
|
||||
|
||||
## What's Included
|
||||
|
||||
### CI/CD Linode Features
|
||||
- Forgejo Actions runner for automated builds
|
||||
- Local Docker registry for image storage
|
||||
- Registry web UI for image management
|
||||
- Automated cleanup of old images
|
||||
- Secure SSH communication with production
|
||||
|
||||
## Prerequisites and Initial Setup
|
||||
|
||||
### What's Already Done (Assumptions)
|
||||
|
||||
This guide assumes you have already:
|
||||
|
||||
1. **Created an Ubuntu 24.04 LTS Linode** with root access
|
||||
2. **Set root password** for the Linode
|
||||
3. **Have SSH client** installed on your local machine
|
||||
4. **Have Production Linode IP address** ready for SSH key exchange
|
||||
|
||||
**Note**: The CI/CD Linode will be accessed via IP address only, as it's primarily used for internal services (Docker registry, Forgejo Actions runner) that don't require public web access.
|
||||
|
||||
### Step 0: Initial SSH Access and Verification
|
||||
|
||||
Before proceeding with the setup, you need to establish initial SSH access to your CI/CD Linode.
|
||||
|
||||
#### 0.1 Get Your Linode IP Address
|
||||
|
||||
From your Linode dashboard, note the IP address for:
|
||||
- **CI/CD Linode**: `YOUR_CI_CD_IP` (IP address only, no domain needed)
|
||||
|
||||
#### 0.2 Test Initial SSH Access
|
||||
|
||||
Test SSH access to your CI/CD Linode:
|
||||
|
||||
```bash
|
||||
# Test CI/CD Linode (IP address only)
|
||||
ssh root@YOUR_CI_CD_IP
|
||||
```
|
||||
|
||||
**Expected output**: SSH login prompt asking for root password.
|
||||
|
||||
**If something goes wrong**:
|
||||
- Verify the IP address is correct
|
||||
- Check that SSH is enabled on the Linode
|
||||
- Ensure your local machine can reach the Linode (no firewall blocking)
|
||||
|
||||
#### 0.3 Choose Your Names
|
||||
|
||||
Before proceeding, decide on:
|
||||
|
||||
1. **Service Account Name**: Choose a username for the service account (e.g., `appuser`, `deploy`, `service`)
|
||||
- Replace `SERVICE_USER` in this guide with your chosen name
|
||||
|
||||
2. **Application Name**: Choose a name for your application (e.g., `myapp`, `webapp`, `api`)
|
||||
- Replace `APP_NAME` in this guide with your chosen name
|
||||
|
||||
**Example**:
|
||||
- If you choose `appuser` as service account and `myapp` as application name:
|
||||
- Replace all `SERVICE_USER` with `appuser`
|
||||
- Replace all `APP_NAME` with `myapp`
|
||||
|
||||
---
|
||||
|
||||
## CI/CD Linode Setup
|
||||
|
||||
### Step 1: Initial System Setup
|
||||
|
||||
#### 1.1 Update the System
|
||||
|
||||
```bash
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
```
|
||||
|
||||
**What this does**: Updates package lists and upgrades all installed packages to their latest versions.
|
||||
|
||||
**Expected output**: A list of packages being updated, followed by completion messages.
|
||||
|
||||
**If something goes wrong**:
|
||||
- Check your internet connection
|
||||
- Try running `sudo apt update` first, then `sudo apt upgrade -y` separately
|
||||
- If you get package conflicts, run `sudo apt --fix-broken install`
|
||||
|
||||
#### 1.2 Install Essential Packages
|
||||
|
||||
```bash
|
||||
sudo apt install -y \
|
||||
curl \
|
||||
wget \
|
||||
git \
|
||||
build-essential \
|
||||
pkg-config \
|
||||
libssl-dev \
|
||||
ca-certificates \
|
||||
apt-transport-https \
|
||||
software-properties-common \
|
||||
apache2-utils
|
||||
```
|
||||
|
||||
**What this does**: Installs development tools, SSL libraries, and utilities needed for Docker and application building.
|
||||
|
||||
**Expected output**: Package installation progress, ending with completion messages.
|
||||
|
||||
**If something goes wrong**:
|
||||
- Check if any packages failed to install
|
||||
- Run `sudo apt install -f` to fix broken dependencies
|
||||
- Ensure you have sufficient disk space: `df -h`
|
||||
|
||||
### Step 2: Create Service Account
|
||||
|
||||
#### 2.1 Create the SERVICE_USER User
|
||||
|
||||
```bash
|
||||
sudo useradd -r -s /bin/bash -m -d /home/SERVICE_USER SERVICE_USER
|
||||
sudo usermod -aG sudo SERVICE_USER
|
||||
echo "SERVICE_USER:$(openssl rand -base64 32)" | sudo chpasswd
|
||||
```
|
||||
|
||||
**What this does**:
|
||||
- Creates a dedicated service account named `SERVICE_USER`
|
||||
- Gives it sudo privileges for administrative tasks
|
||||
- Generates a random 32-character password
|
||||
|
||||
**Expected output**: No output (successful user creation is silent).
|
||||
|
||||
**If something goes wrong**:
|
||||
- If user already exists: `sudo userdel -r SERVICE_USER` then retry
|
||||
- Check user creation: `id SERVICE_USER`
|
||||
- Verify sudo access: `sudo -u SERVICE_USER sudo -l`
|
||||
|
||||
#### 2.2 Verify Service Account
|
||||
|
||||
```bash
|
||||
sudo su - SERVICE_USER
|
||||
whoami
|
||||
pwd
|
||||
```
|
||||
|
||||
**What this does**: Switches to the SERVICE_USER user and verifies the setup.
|
||||
|
||||
**Expected output**:
|
||||
```
|
||||
SERVICE_USER
|
||||
/home/SERVICE_USER
|
||||
```
|
||||
|
||||
### Step 3: Install Docker
|
||||
|
||||
#### 3.1 Add Docker Repository
|
||||
|
||||
```bash
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
sudo apt update
|
||||
```
|
||||
|
||||
**What this does**: Adds Docker's official repository to your system for the latest Docker versions.
|
||||
|
||||
**Expected output**: GPG key import confirmation and package list update.
|
||||
|
||||
#### 3.2 Install Docker Packages
|
||||
|
||||
```bash
|
||||
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
|
||||
```
|
||||
|
||||
**What this does**: Installs Docker Engine, CLI, container runtime, and Docker Compose.
|
||||
|
||||
**Expected output**: Package installation progress, ending with completion messages.
|
||||
|
||||
#### 3.3 Configure Docker for Service Account
|
||||
|
||||
```bash
|
||||
sudo usermod -aG docker SERVICE_USER
|
||||
```
|
||||
|
||||
**What this does**: Adds the SERVICE_USER user to the docker group so it can run Docker commands without sudo.
|
||||
|
||||
### Step 4: Install Docker Compose
|
||||
|
||||
```bash
|
||||
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
||||
sudo chmod +x /usr/local/bin/docker-compose
|
||||
```
|
||||
|
||||
**What this does**: Downloads the latest Docker Compose binary and makes it executable.
|
||||
|
||||
### Step 5: Configure Docker for Local Registry
|
||||
|
||||
```bash
|
||||
echo '{"insecure-registries": ["localhost:5000"]}' | sudo tee /etc/docker/daemon.json
|
||||
sudo systemctl restart docker
|
||||
```
|
||||
|
||||
**What this does**: Configures Docker to allow connections to the local registry without SSL verification.
|
||||
|
||||
### Step 6: Install Development Tools
|
||||
|
||||
#### 6.1 Install Rust
|
||||
|
||||
```bash
|
||||
sudo su - SERVICE_USER
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
source $HOME/.cargo/env
|
||||
```
|
||||
|
||||
**What this does**: Installs Rust programming language and Cargo package manager for building the backend.
|
||||
|
||||
#### 6.2 Install Node.js
|
||||
|
||||
```bash
|
||||
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
||||
sudo apt install -y nodejs
|
||||
```
|
||||
|
||||
**What this does**: Installs Node.js version 20 for building the frontend.
|
||||
|
||||
### Step 7: Set Up Docker Registry
|
||||
|
||||
#### 7.1 Create Registry Directory
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /opt/registry
|
||||
sudo chown SERVICE_USER:SERVICE_USER /opt/registry
|
||||
```
|
||||
|
||||
**What this does**: Creates a directory for the Docker registry and sets ownership to the SERVICE_USER user.
|
||||
|
||||
#### 7.2 Create Docker Compose File for Registry
|
||||
|
||||
```bash
|
||||
cat > /opt/registry/docker-compose.yml << 'EOF'
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
registry:
|
||||
image: registry:2
|
||||
container_name: docker-registry
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "5000:5000"
|
||||
environment:
|
||||
REGISTRY_STORAGE_DELETE_ENABLED: "true"
|
||||
REGISTRY_STORAGE_FILESYSTEM_MAXTHREADS: "100"
|
||||
volumes:
|
||||
- registry_data:/var/lib/registry
|
||||
- ./config.yml:/etc/docker/registry/config.yml:ro
|
||||
networks:
|
||||
- registry-network
|
||||
|
||||
registry-ui:
|
||||
image: joxit/docker-registry-ui:latest
|
||||
container_name: registry-ui
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "8080:80"
|
||||
environment:
|
||||
REGISTRY_URL: http://registry:5000
|
||||
DELETE_IMAGES: "true"
|
||||
depends_on:
|
||||
- registry
|
||||
networks:
|
||||
- registry-network
|
||||
|
||||
volumes:
|
||||
registry_data:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
registry-network:
|
||||
driver: bridge
|
||||
EOF
|
||||
```
|
||||
|
||||
#### 7.3 Create Registry Configuration
|
||||
|
||||
```bash
|
||||
cat > /opt/registry/config.yml << 'EOF'
|
||||
version: 0.1
|
||||
log:
|
||||
fields:
|
||||
service: registry
|
||||
storage:
|
||||
delete:
|
||||
enabled: true
|
||||
cache:
|
||||
blobdescriptor: inmemory
|
||||
filesystem:
|
||||
rootdirectory: /var/lib/registry
|
||||
http:
|
||||
addr: :5000
|
||||
headers:
|
||||
X-Content-Type-Options: [nosniff]
|
||||
health:
|
||||
storagedriver:
|
||||
enabled: true
|
||||
interval: 10s
|
||||
threshold: 3
|
||||
EOF
|
||||
```
|
||||
|
||||
#### 7.4 Start the Registry
|
||||
|
||||
```bash
|
||||
cd /opt/registry
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
**What this does**: Starts the Docker registry and web UI in detached mode.
|
||||
|
||||
**Expected output**: Container creation and startup messages.
|
||||
|
||||
### Step 8: Set Up SSH Keys
|
||||
|
||||
#### 8.1 Create SSH Directory
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
```
|
||||
|
||||
#### 8.2 Generate SSH Key Pair
|
||||
|
||||
```bash
|
||||
ssh-keygen -t ed25519 -C "ci-cd-server" -f ~/.ssh/id_ed25519 -N ""
|
||||
```
|
||||
|
||||
**What this does**: Generates an Ed25519 SSH key pair for secure communication with the production server.
|
||||
|
||||
**Expected output**: Key generation messages and file creation confirmation.
|
||||
|
||||
#### 8.3 Create SSH Config
|
||||
|
||||
```bash
|
||||
cat > ~/.ssh/config << 'EOF'
|
||||
Host production
|
||||
HostName YOUR_PRODUCTION_IP
|
||||
User SERVICE_USER
|
||||
IdentityFile ~/.ssh/id_ed25519
|
||||
StrictHostKeyChecking no
|
||||
UserKnownHostsFile /dev/null
|
||||
EOF
|
||||
|
||||
chmod 600 ~/.ssh/config
|
||||
```
|
||||
|
||||
**What this does**: Creates SSH configuration for easy connection to the production server.
|
||||
|
||||
**Note**: You'll update `YOUR_PRODUCTION_IP` with the actual production server IP later.
|
||||
|
||||
### Step 9: Install Forgejo Actions Runner
|
||||
|
||||
#### 9.1 Download Runner
|
||||
|
||||
```bash
|
||||
cd ~
|
||||
wget https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-x64-2.311.0.tar.gz
|
||||
tar -xzf actions-runner-linux-x64-2.311.0.tar.gz
|
||||
rm actions-runner-linux-x64-2.311.0.tar.gz
|
||||
```
|
||||
|
||||
**What this does**: Downloads and extracts the Forgejo Actions runner.
|
||||
|
||||
#### 9.2 Create Systemd Service
|
||||
|
||||
```bash
|
||||
sudo tee /etc/systemd/system/github-runner.service > /dev/null << 'EOF'
|
||||
[Unit]
|
||||
Description=GitHub Actions Runner
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=SERVICE_USER
|
||||
WorkingDirectory=/home/SERVICE_USER/actions-runner
|
||||
ExecStart=/home/SERVICE_USER/actions-runner/run.sh
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
```
|
||||
|
||||
**What this does**: Creates a systemd service to automatically start and manage the Actions runner.
|
||||
|
||||
#### 9.3 Enable Service
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable github-runner.service
|
||||
```
|
||||
|
||||
**What this does**: Enables the Actions runner service to start automatically on boot.
|
||||
|
||||
### Step 10: Set Up Monitoring and Cleanup
|
||||
|
||||
#### 10.1 Create Monitoring Script
|
||||
|
||||
```bash
|
||||
cat > ~/monitor.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
|
||||
echo "=== CI/CD Server Status ==="
|
||||
echo "Date: $(date)"
|
||||
echo "Uptime: $(uptime)"
|
||||
echo ""
|
||||
|
||||
echo "=== Docker Status ==="
|
||||
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
||||
echo ""
|
||||
|
||||
echo "=== Registry Status ==="
|
||||
cd /opt/registry
|
||||
docker-compose ps
|
||||
echo ""
|
||||
|
||||
echo "=== Actions Runner Status ==="
|
||||
sudo systemctl status github-runner.service --no-pager
|
||||
echo ""
|
||||
|
||||
echo "=== System Resources ==="
|
||||
echo "CPU Usage:"
|
||||
top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1
|
||||
echo "Memory Usage:"
|
||||
free -h | grep Mem
|
||||
echo "Disk Usage:"
|
||||
df -h /
|
||||
echo ""
|
||||
|
||||
echo "=== Recent Logs ==="
|
||||
docker-compose logs --tail=10
|
||||
EOF
|
||||
|
||||
chmod +x ~/monitor.sh
|
||||
```
|
||||
|
||||
**What this does**: Creates a monitoring script to check the status of all CI/CD services.
|
||||
|
||||
#### 10.2 Create Cleanup Script
|
||||
|
||||
```bash
|
||||
cat > ~/cleanup.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
|
||||
echo "Cleaning up old Docker images..."
|
||||
|
||||
# Remove unused images
|
||||
docker image prune -f
|
||||
|
||||
# Remove unused volumes
|
||||
docker volume prune -f
|
||||
|
||||
# Remove unused networks
|
||||
docker network prune -f
|
||||
|
||||
# Remove old registry images (keep last 10 tags per repository)
|
||||
cd /opt/registry
|
||||
docker-compose exec registry registry garbage-collect /etc/docker/registry/config.yml
|
||||
|
||||
echo "Cleanup complete!"
|
||||
EOF
|
||||
|
||||
chmod +x ~/cleanup.sh
|
||||
```
|
||||
|
||||
**What this does**: Creates a cleanup script to remove old Docker images and registry data.
|
||||
|
||||
#### 10.3 Set Up Automated Cleanup
|
||||
|
||||
```bash
|
||||
(crontab -l 2>/dev/null; echo "0 3 * * * /home/SERVICE_USER/cleanup.sh") | crontab -
|
||||
```
|
||||
|
||||
**What this does**: Schedules daily cleanup at 3 AM.
|
||||
|
||||
### Step 11: Configure Firewall
|
||||
|
||||
```bash
|
||||
sudo ufw --force enable
|
||||
sudo ufw default deny incoming
|
||||
sudo ufw default allow outgoing
|
||||
sudo ufw allow ssh
|
||||
sudo ufw allow 5000/tcp # Docker registry
|
||||
sudo ufw allow 8080/tcp # Registry UI
|
||||
```
|
||||
|
||||
**What this does**: Configures firewall to allow only necessary ports.
|
||||
|
||||
### Step 12: Test CI/CD Setup
|
||||
|
||||
#### 12.1 Test Docker Installation
|
||||
|
||||
```bash
|
||||
docker --version
|
||||
docker-compose --version
|
||||
```
|
||||
|
||||
**Expected output**: Version information for both Docker and Docker Compose.
|
||||
|
||||
#### 12.2 Check Registry Status
|
||||
|
||||
```bash
|
||||
cd /opt/registry
|
||||
docker-compose ps
|
||||
```
|
||||
|
||||
**Expected output**: Status of registry and registry-ui containers showing "Up".
|
||||
|
||||
#### 12.3 Test Registry Access
|
||||
|
||||
```bash
|
||||
curl http://localhost:5000/v2/_catalog
|
||||
```
|
||||
|
||||
**Expected output**: `{"repositories":[]}` (empty initially).
|
||||
|
||||
#### 12.4 Get Public Key for Production Server
|
||||
|
||||
```bash
|
||||
cat ~/.ssh/id_ed25519.pub
|
||||
```
|
||||
|
||||
**Important**: Copy this public key - you'll need it for the production server setup.
|
||||
|
||||
### Step 13: Configure Forgejo Actions Runner
|
||||
|
||||
#### 13.1 Get Runner Token
|
||||
|
||||
1. Go to your Forgejo repository
|
||||
2. Navigate to Settings → Actions → Runners
|
||||
3. Click "New runner"
|
||||
4. Copy the registration token
|
||||
|
||||
#### 13.2 Configure Runner
|
||||
|
||||
```bash
|
||||
cd ~/actions-runner
|
||||
./config.sh --url https://your-forgejo-instance/your-username/APP_NAME --token YOUR_TOKEN
|
||||
```
|
||||
|
||||
#### 13.3 Start Runner
|
||||
|
||||
```bash
|
||||
sudo systemctl start github-runner.service
|
||||
sudo systemctl status github-runner.service
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## SSH Key Exchange
|
||||
|
||||
After setting up both servers, you need to exchange SSH public keys for secure communication:
|
||||
|
||||
### Step 1: Get Public Keys from Both Servers
|
||||
|
||||
```bash
|
||||
# On CI/CD server (get your public key)
|
||||
cat ~/.ssh/id_ed25519.pub
|
||||
|
||||
# On Production server (get their public key)
|
||||
# You'll need to get this from the Production server
|
||||
```
|
||||
|
||||
### Step 2: Add Production Server's Public Key
|
||||
|
||||
```bash
|
||||
# On CI/CD server (add Production's public key)
|
||||
echo "PRODUCTION_PUBLIC_KEY_HERE" >> ~/.ssh/authorized_keys
|
||||
sed -i 's/YOUR_PRODUCTION_IP/YOUR_ACTUAL_PRODUCTION_IP/g' ~/.ssh/config
|
||||
```
|
||||
|
||||
### Step 3: Test SSH Connection
|
||||
|
||||
```bash
|
||||
# Test from CI/CD to Production
|
||||
ssh production 'echo Connection successful'
|
||||
```
|
||||
|
||||
**Expected output**: `Connection successful`.
|
||||
|
||||
---
|
||||
|
||||
## Registry Configuration
|
||||
|
||||
The CI/CD registry is configured to allow connections from the production server.
|
||||
|
||||
### Step 1: Verify Registry Configuration
|
||||
|
||||
```bash
|
||||
# Check registry is running
|
||||
cd /opt/registry
|
||||
docker-compose ps
|
||||
|
||||
# Test registry API
|
||||
curl http://localhost:5000/v2/_catalog
|
||||
```
|
||||
|
||||
**Expected output**:
|
||||
- Registry containers showing "Up"
|
||||
- Registry API: `{"repositories":[]}` or list of images
|
||||
|
||||
### Step 2: Verify Registry UI Access
|
||||
|
||||
You can access the registry web interface to manage images:
|
||||
|
||||
```bash
|
||||
# Test registry UI
|
||||
curl -I http://localhost:8080
|
||||
```
|
||||
|
||||
**Expected output**: HTTP response (may be 404 initially, which is normal).
|
||||
|
||||
**Note**: The registry UI is accessible at `http://YOUR_CI_CD_IP:8080` for administrative purposes.
|
||||
|
||||
---
|
||||
|
||||
## Forgejo Configuration
|
||||
|
||||
### Step 1: Add Repository Secrets
|
||||
|
||||
Go to your Forgejo repository → Settings → Secrets and Variables → Actions, and add:
|
||||
|
||||
- `CI_HOST`: Your CI/CD Linode IP address
|
||||
- `PROD_HOST`: Your production Linode IP
|
||||
- `PROD_USER`: SSH username for production server (should be `SERVICE_USER`)
|
||||
- `PROD_SSH_KEY`: SSH private key for deployment
|
||||
|
||||
### Step 2: Generate SSH Key for Deployment
|
||||
|
||||
The setup automatically generates SSH keys for the SERVICE_USER service account. For Forgejo Actions deployment, use the CI/CD server's private key:
|
||||
|
||||
```bash
|
||||
# On CI/CD server
|
||||
cat ~/.ssh/id_ed25519
|
||||
```
|
||||
|
||||
Copy the entire private key content (including the BEGIN and END lines) for the `PROD_SSH_KEY` secret.
|
||||
|
||||
---
|
||||
|
||||
## Testing and Verification
|
||||
|
||||
### Step 1: Test Registry Functionality
|
||||
|
||||
```bash
|
||||
# Test registry API
|
||||
curl http://localhost:5000/v2/_catalog
|
||||
|
||||
# Test registry UI (optional)
|
||||
curl -I http://localhost:8080
|
||||
```
|
||||
|
||||
**Expected output**:
|
||||
- Registry API: `{"repositories":[]}` (empty initially)
|
||||
- Registry UI: HTTP response (may be 404 initially, which is normal)
|
||||
|
||||
### Step 2: Test Actions Runner
|
||||
|
||||
```bash
|
||||
# Check runner status
|
||||
sudo systemctl status github-runner.service
|
||||
|
||||
# Check runner logs
|
||||
sudo journalctl -u github-runner.service -f
|
||||
```
|
||||
|
||||
**Expected output**: Runner service showing as active and running.
|
||||
|
||||
### Step 3: Test Monitoring Script
|
||||
|
||||
```bash
|
||||
./monitor.sh
|
||||
```
|
||||
|
||||
**Expected output**: Status information for all CI/CD services.
|
||||
|
||||
### Step 4: Test SSH Connection to Production
|
||||
|
||||
```bash
|
||||
# Test from CI/CD to Production
|
||||
ssh production 'echo Connection successful'
|
||||
```
|
||||
|
||||
**Expected output**: `Connection successful`.
|
||||
|
||||
### Step 5: Trigger First Deployment
|
||||
|
||||
#### 5.1 Push Code Changes
|
||||
|
||||
Make a small change to your code and push to trigger the CI/CD pipeline:
|
||||
|
||||
```bash
|
||||
# In your local repository
|
||||
echo "# Test deployment" >> README.md
|
||||
git add README.md
|
||||
git commit -m "Test CI/CD pipeline"
|
||||
git push
|
||||
```
|
||||
|
||||
#### 5.2 Monitor Pipeline
|
||||
|
||||
1. Go to your Forgejo repository
|
||||
2. Navigate to Actions tab
|
||||
3. Monitor the workflow execution
|
||||
4. Check for any errors or issues
|
||||
|
||||
#### 5.3 Verify Deployment
|
||||
|
||||
After successful pipeline execution:
|
||||
|
||||
```bash
|
||||
# Check if images were pushed to registry
|
||||
curl http://localhost:5000/v2/_catalog
|
||||
|
||||
# Check registry UI for new images
|
||||
# Open http://YOUR_CI_CD_IP:8080 in browser
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Docker permission denied**:
|
||||
```bash
|
||||
sudo usermod -aG docker SERVICE_USER
|
||||
newgrp docker
|
||||
```
|
||||
|
||||
2. **Registry not accessible**:
|
||||
```bash
|
||||
cd /opt/registry
|
||||
docker-compose logs
|
||||
```
|
||||
|
||||
3. **Actions runner not starting**:
|
||||
```bash
|
||||
sudo systemctl status github-runner.service
|
||||
sudo journalctl -u github-runner.service -f
|
||||
```
|
||||
|
||||
4. **SSH key issues**:
|
||||
```bash
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
chmod 700 ~/.ssh
|
||||
```
|
||||
|
||||
5. **Registry connection failed**:
|
||||
```bash
|
||||
curl -v http://localhost:5000/v2/_catalog
|
||||
```
|
||||
|
||||
### Useful Commands
|
||||
|
||||
- **Check system resources**: `htop`
|
||||
- **Check disk space**: `df -h`
|
||||
- **Check memory usage**: `free -h`
|
||||
- **Check network**: `ip addr show`
|
||||
- **Check firewall**: `sudo ufw status`
|
||||
- **Check logs**: `sudo journalctl -f`
|
||||
|
||||
### Security Best Practices
|
||||
|
||||
1. **Service Account**: Use dedicated `SERVICE_USER` user with limited privileges
|
||||
2. **SSH Keys**: Use Ed25519 keys with proper permissions (600/700)
|
||||
3. **Firewall**: Configure UFW to allow only necessary ports
|
||||
4. **Container Isolation**: Registry runs in isolated Docker containers
|
||||
5. **Regular Cleanup**: Automated daily cleanup of old images
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Your CI/CD Linode is now ready to handle automated builds and deployments! The setup includes:
|
||||
|
||||
- **Forgejo Actions runner** for automated builds
|
||||
- **Local Docker registry** with web UI for image management
|
||||
- **Secure SSH communication** with production server
|
||||
- **Monitoring and cleanup** scripts
|
||||
- **Firewall protection** for security
|
||||
|
||||
For ongoing maintenance and troubleshooting, refer to the troubleshooting section and monitoring scripts provided in this guide.
|
File diff suppressed because it is too large
Load diff
|
@ -6,8 +6,8 @@ services:
|
|||
container_name: sharenet-postgres
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: sharenet
|
||||
POSTGRES_USER: sharenet
|
||||
POSTGRES_DB: ${POSTGRES_DB:-sharenet}
|
||||
POSTGRES_USER: ${POSTGRES_USER:-sharenet}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
|
@ -15,7 +15,7 @@ services:
|
|||
ports:
|
||||
- "5432:5432"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U sharenet"]
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-sharenet}"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
@ -27,7 +27,7 @@ services:
|
|||
container_name: sharenet-backend
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DATABASE_URL: postgresql://sharenet:${POSTGRES_PASSWORD:-changeme}@postgres:5432/sharenet
|
||||
DATABASE_URL: postgresql://${POSTGRES_USER:-sharenet}:${POSTGRES_PASSWORD:-changeme}@postgres:5432/${POSTGRES_DB:-sharenet}
|
||||
RUST_LOG: info
|
||||
RUST_BACKTRACE: 1
|
||||
ports:
|
||||
|
|
|
@ -52,8 +52,9 @@ http {
|
|||
server_name _;
|
||||
|
||||
# SSL configuration
|
||||
ssl_certificate /etc/nginx/ssl/cert.pem;
|
||||
ssl_certificate_key /etc/nginx/ssl/key.pem;
|
||||
# These paths match Let's Encrypt certificate files copied in the CI/CD setup guide
|
||||
ssl_certificate /etc/nginx/ssl/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
|
Loading…
Add table
Reference in a new issue