Updated procedure to have project cloned to /opt/APP_NAME to be with registry
Some checks are pending
Some checks are pending
This commit is contained in:
parent
9420de4105
commit
718343a3d0
5 changed files with 238 additions and 399 deletions
|
@ -498,21 +498,25 @@ exit
|
||||||
# Switch to SERVICE_USER (registry directory owner)
|
# Switch to SERVICE_USER (registry directory owner)
|
||||||
sudo su - SERVICE_USER
|
sudo su - SERVICE_USER
|
||||||
|
|
||||||
# Create SSL directory
|
# Create system SSL directory for registry certificates
|
||||||
mkdir -p /opt/registry/ssl
|
sudo mkdir -p /etc/ssl/registry
|
||||||
|
|
||||||
# Generate self-signed certificate
|
# Get your actual IP address
|
||||||
openssl req -x509 -newkey rsa:4096 -keyout /opt/registry/ssl/registry.key -out /opt/registry/ssl/registry.crt -days 365 -nodes -subj "/C=US/ST=State/L=City/O=Organization/CN=YOUR_CI_CD_IP"
|
YOUR_ACTUAL_IP=$(curl -4 -s ifconfig.me)
|
||||||
|
echo "Your IP address is: $YOUR_ACTUAL_IP"
|
||||||
|
|
||||||
|
# Generate self-signed certificate with actual IP in system directory
|
||||||
|
sudo openssl req -x509 -newkey rsa:4096 -keyout /etc/ssl/registry/registry.key -out /etc/ssl/registry/registry.crt -days 365 -nodes -subj "/C=US/ST=State/L=City/O=Organization/CN=$YOUR_ACTUAL_IP"
|
||||||
|
|
||||||
# Set proper permissions
|
# Set proper permissions
|
||||||
chmod 600 /opt/registry/ssl/registry.key
|
sudo chmod 600 /etc/ssl/registry/registry.key
|
||||||
chmod 644 /opt/registry/ssl/registry.crt
|
sudo chmod 644 /etc/ssl/registry/registry.crt
|
||||||
|
|
||||||
# Exit SERVICE_USER shell
|
# Exit SERVICE_USER shell
|
||||||
exit
|
exit
|
||||||
```
|
```
|
||||||
|
|
||||||
**Important**: Replace `YOUR_CI_CD_IP` with your actual CI/CD Linode IP address in the certificate generation command.
|
**Important**: The certificate is now generated in the system SSL directory `/etc/ssl/registry/` with your actual CI/CD Linode IP address automatically.
|
||||||
|
|
||||||
#### 4.3 Create Authentication File
|
#### 4.3 Create Authentication File
|
||||||
|
|
||||||
|
@ -520,155 +524,86 @@ exit
|
||||||
# Switch to SERVICE_USER (registry directory owner)
|
# Switch to SERVICE_USER (registry directory owner)
|
||||||
sudo su - SERVICE_USER
|
sudo su - SERVICE_USER
|
||||||
|
|
||||||
|
# Create system auth directory for registry authentication
|
||||||
|
sudo mkdir -p /etc/registry/auth
|
||||||
|
|
||||||
# Create htpasswd file for authentication (required for push operations only)
|
# Create htpasswd file for authentication (required for push operations only)
|
||||||
mkdir -p /opt/registry/auth
|
sudo htpasswd -Bbn push-user "$(openssl rand -base64 32)" > /tmp/auth.htpasswd
|
||||||
htpasswd -Bbn push-user "$(openssl rand -base64 32)" > /opt/registry/auth/auth.htpasswd
|
sudo mv /tmp/auth.htpasswd /etc/registry/auth/auth.htpasswd
|
||||||
|
|
||||||
# Exit SERVICE_USER shell
|
# Exit SERVICE_USER shell
|
||||||
exit
|
exit
|
||||||
```
|
```
|
||||||
|
|
||||||
**What this does**: Creates user credentials for registry authentication.
|
**What this does**: Creates user credentials for registry authentication in the system auth directory.
|
||||||
- `push-user`: Can push images (used by CI/CD pipeline for deployments)
|
- `push-user`: Can push images (used by CI/CD pipeline for deployments)
|
||||||
|
|
||||||
**Note**: Pull operations are public and don't require authentication, but push operations require these credentials.
|
**Note**: Pull operations are public and don't require authentication, but push operations require these credentials.
|
||||||
|
|
||||||
|
#### 4.3.1 Clone Repository for Registry Configuration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Switch to DEPLOY_USER (who has sudo access)
|
||||||
|
sudo su - DEPLOY_USER
|
||||||
|
|
||||||
|
# Create application directory and clone repository
|
||||||
|
sudo mkdir -p /opt/APP_NAME
|
||||||
|
sudo chown SERVICE_USER:SERVICE_USER /opt/APP_NAME
|
||||||
|
cd /opt
|
||||||
|
sudo git clone https://your-forgejo-instance/your-username/APP_NAME.git
|
||||||
|
sudo chown -R SERVICE_USER:SERVICE_USER APP_NAME/
|
||||||
|
|
||||||
|
# Verify the registry folder exists
|
||||||
|
ls -la /opt/APP_NAME/registry/
|
||||||
|
|
||||||
|
# Exit DEPLOY_USER shell
|
||||||
|
exit
|
||||||
|
```
|
||||||
|
|
||||||
|
**Important**: Replace `your-forgejo-instance`, `your-username`, and `APP_NAME` with your actual Forgejo instance URL, username, and application name.
|
||||||
|
|
||||||
|
**What this does**:
|
||||||
|
- DEPLOY_USER creates the directory structure and clones the repository
|
||||||
|
- SERVICE_USER owns all the files for security
|
||||||
|
- Registry configuration files are now available at `/opt/APP_NAME/registry/`
|
||||||
|
|
||||||
#### 4.4 Create Docker Compose for Registry
|
#### 4.4 Create Docker Compose for Registry
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Switch to SERVICE_USER (registry directory owner)
|
# Switch to SERVICE_USER (registry directory owner)
|
||||||
sudo su - SERVICE_USER
|
sudo su - SERVICE_USER
|
||||||
|
|
||||||
cat > /opt/registry/docker-compose.yml << 'EOF'
|
# The registry configuration files are already available in the cloned repository
|
||||||
version: '3.8'
|
# at /opt/APP_NAME/registry/
|
||||||
|
# No file copying is needed - we'll use the files directly from the repository
|
||||||
services:
|
|
||||||
registry:
|
|
||||||
image: registry:2
|
|
||||||
ports:
|
|
||||||
- "5000:5000"
|
|
||||||
volumes:
|
|
||||||
- ./config.yml:/etc/docker/registry/config.yml:ro
|
|
||||||
- ./auth/auth.htpasswd:/etc/docker/registry/auth/auth.htpasswd:ro
|
|
||||||
- ./ssl/registry.crt:/etc/docker/registry/ssl/registry.crt:ro
|
|
||||||
- ./ssl/registry.key:/etc/docker/registry/ssl/registry.key:ro
|
|
||||||
- registry_data:/var/lib/registry
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- registry_network
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "https://localhost:5000/v2/", "--no-check-certificate"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 40s
|
|
||||||
|
|
||||||
|
|
||||||
registry-ui:
|
|
||||||
image: joxit/docker-registry-ui:latest
|
|
||||||
expose:
|
|
||||||
- "80"
|
|
||||||
environment:
|
|
||||||
- REGISTRY_TITLE=APP_NAME Registry
|
|
||||||
- REGISTRY_URL=https://YOUR_CI_CD_IP:8080
|
|
||||||
depends_on:
|
|
||||||
registry:
|
|
||||||
condition: service_healthy
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- registry_network
|
|
||||||
|
|
||||||
nginx:
|
|
||||||
image: nginx:alpine
|
|
||||||
ports:
|
|
||||||
- "8080:443"
|
|
||||||
volumes:
|
|
||||||
- ./ssl:/etc/nginx/ssl:ro
|
|
||||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
|
||||||
depends_on:
|
|
||||||
- registry-ui
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- registry_network
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
registry_data:
|
|
||||||
|
|
||||||
networks:
|
|
||||||
registry_network:
|
|
||||||
driver: bridge
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Exit SERVICE_USER shell
|
# Exit SERVICE_USER shell
|
||||||
exit
|
exit
|
||||||
```
|
```
|
||||||
|
|
||||||
**Important**: Replace `YOUR_CI_CD_IP` with your actual CI/CD Linode IP address in the `REGISTRY_URL` environment variable.
|
**Important**: The repository should be cloned in the previous step (4.3.1) to `/opt/APP_NAME/`. The registry configuration files are used directly from the repository.
|
||||||
|
|
||||||
**Note**: We updated the volume mounts to explicitly map individual certificate files to their expected locations in the registry container.
|
#### 4.4.1 Update Configuration with Actual IP Address
|
||||||
|
|
||||||
#### 4.4.1 Create Nginx Configuration
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Switch to SERVICE_USER (registry directory owner)
|
# Switch to SERVICE_USER (registry directory owner)
|
||||||
sudo su - SERVICE_USER
|
sudo su - SERVICE_USER
|
||||||
|
|
||||||
cat > /opt/registry/nginx.conf << 'EOF'
|
cd /opt/APP_NAME/registry
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
# Get your actual IP address
|
||||||
upstream registry_ui {
|
YOUR_ACTUAL_IP=$(curl -4 -s ifconfig.me)
|
||||||
server registry-ui:80;
|
echo "Your IP address is: $YOUR_ACTUAL_IP"
|
||||||
}
|
|
||||||
|
|
||||||
upstream registry_api {
|
# Replace placeholder IP addresses in configuration files
|
||||||
server registry:5000;
|
sed -i "s/YOUR_CI_CD_IP/$YOUR_ACTUAL_IP/g" docker-compose.yml
|
||||||
}
|
sed -i "s/YOUR_CI_CD_IP/$YOUR_ACTUAL_IP/g" nginx.conf
|
||||||
|
|
||||||
server {
|
|
||||||
listen 443 ssl;
|
|
||||||
server_name YOUR_CI_CD_IP;
|
|
||||||
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry.crt;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry.key;
|
|
||||||
ssl_protocols TLSv1.2 TLSv1.3;
|
|
||||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
|
||||||
|
|
||||||
# Proxy registry API requests
|
|
||||||
location /v2/ {
|
|
||||||
proxy_pass https://registry_api;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_connect_timeout 30s;
|
|
||||||
proxy_send_timeout 30s;
|
|
||||||
proxy_read_timeout 30s;
|
|
||||||
proxy_ssl_verify off;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Proxy registry UI requests
|
|
||||||
location / {
|
|
||||||
proxy_pass http://registry_ui;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_connect_timeout 30s;
|
|
||||||
proxy_send_timeout 30s;
|
|
||||||
proxy_read_timeout 30s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Exit SERVICE_USER shell
|
# Exit SERVICE_USER shell
|
||||||
exit
|
exit
|
||||||
```
|
```
|
||||||
|
|
||||||
**Important**: Replace `YOUR_CI_CD_IP` with your actual CI/CD Linode IP address in the nginx configuration.
|
**Important**: This step replaces all instances of `YOUR_CI_CD_IP` with your actual CI/CD Linode IP address in both the docker-compose.yml and nginx.conf files in the repository.
|
||||||
|
|
||||||
#### 4.5 Install Required Tools
|
#### 4.5 Install Required Tools
|
||||||
|
|
||||||
|
@ -683,7 +618,7 @@ sudo apt install -y apache2-utils
|
||||||
# Switch to SERVICE_USER (registry directory owner)
|
# Switch to SERVICE_USER (registry directory owner)
|
||||||
sudo su - SERVICE_USER
|
sudo su - SERVICE_USER
|
||||||
|
|
||||||
cd /opt/registry
|
cd /opt/APP_NAME/registry
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
|
|
||||||
# Exit SERVICE_USER shell
|
# Exit SERVICE_USER shell
|
||||||
|
@ -693,11 +628,8 @@ exit
|
||||||
#### 4.7 Test Registry Setup
|
#### 4.7 Test Registry Setup
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Switch to SERVICE_USER (registry directory owner)
|
|
||||||
sudo su - SERVICE_USER
|
|
||||||
|
|
||||||
# Check if containers are running
|
# Check if containers are running
|
||||||
cd /opt/registry
|
cd /opt/APP_NAME/registry
|
||||||
docker compose ps
|
docker compose ps
|
||||||
|
|
||||||
# Test registry API (HTTPS via nginx)
|
# Test registry API (HTTPS via nginx)
|
||||||
|
@ -781,7 +713,7 @@ exit
|
||||||
```bash
|
```bash
|
||||||
# Get the push user credentials
|
# Get the push user credentials
|
||||||
PUSH_USER="push-user"
|
PUSH_USER="push-user"
|
||||||
PUSH_PASSWORD=$(grep push-user /opt/registry/auth/auth.htpasswd | cut -d: -f2)
|
PUSH_PASSWORD=$(grep push-user /etc/registry/auth/auth.htpasswd | cut -d: -f2)
|
||||||
|
|
||||||
# Copy the certificate to Docker's trusted certificates
|
# Copy the certificate to Docker's trusted certificates
|
||||||
sudo cp /opt/registry/ssl/registry.crt /usr/local/share/ca-certificates/registry.crt
|
sudo cp /opt/registry/ssl/registry.crt /usr/local/share/ca-certificates/registry.crt
|
||||||
|
@ -1121,273 +1053,3 @@ curl http://localhost:5000/v2/_catalog
|
||||||
```bash
|
```bash
|
||||||
cat ~/.ssh/id_ed25519.pub
|
cat ~/.ssh/id_ed25519.pub
|
||||||
```
|
```
|
||||||
|
|
||||||
**Important**: Copy this public key - you'll need it for the production server setup.
|
|
||||||
|
|
||||||
### Step 11: Configure Forgejo Actions Runner
|
|
||||||
|
|
||||||
#### 11.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
|
|
||||||
|
|
||||||
#### 11.2 Configure Runner
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Get the registration token from your Forgejo repository
|
|
||||||
# Go to Settings → Actions → Runners → New runner
|
|
||||||
# Copy the registration token
|
|
||||||
|
|
||||||
# Configure the runner
|
|
||||||
forgejo-runner register \
|
|
||||||
--instance https://your-forgejo-instance \
|
|
||||||
--token YOUR_TOKEN \
|
|
||||||
--name "ci-cd-runner" \
|
|
||||||
--labels "ubuntu-latest,docker" \
|
|
||||||
--no-interactive
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 11.3 Start Runner
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo systemctl start forgejo-runner.service
|
|
||||||
sudo systemctl status forgejo-runner.service
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 11.4 Test Runner Configuration
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check if the runner is running
|
|
||||||
sudo systemctl status forgejo-runner.service
|
|
||||||
|
|
||||||
# Check runner logs
|
|
||||||
sudo journalctl -u forgejo-runner.service -f --no-pager
|
|
||||||
|
|
||||||
# Test runner connectivity (in a separate terminal)
|
|
||||||
forgejo-runner list
|
|
||||||
|
|
||||||
# Verify runner appears in Forgejo
|
|
||||||
# Go to your Forgejo repository → Settings → Actions → Runners
|
|
||||||
# You should see your runner listed as "ci-cd-runner" with status "Online"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Expected Output**:
|
|
||||||
- `systemctl status` should show "active (running)"
|
|
||||||
- `forgejo-runner list` should show your runner
|
|
||||||
- Forgejo web interface should show the runner as online
|
|
||||||
|
|
||||||
**If something goes wrong**:
|
|
||||||
- Check logs: `sudo journalctl -u forgejo-runner.service -f`
|
|
||||||
- Verify token: Make sure the registration token is correct
|
|
||||||
- Check network: Ensure the runner can reach your Forgejo instance
|
|
||||||
- Restart service: `sudo systemctl restart forgejo-runner.service`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Part 2: Production Linode Setup
|
|
||||||
|
|
||||||
### Step 12: Initial System Setup
|
|
||||||
|
|
||||||
#### 12.1 Update the System
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo apt update && sudo apt upgrade -y
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 12.2 Configure Timezone
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Configure timezone interactively
|
|
||||||
sudo dpkg-reconfigure tzdata
|
|
||||||
|
|
||||||
# Verify timezone setting
|
|
||||||
date
|
|
||||||
```
|
|
||||||
|
|
||||||
**What this does**: Opens an interactive dialog to select your timezone. Navigate through the menus to choose your preferred timezone (e.g., UTC, America/New_York, Europe/London, Asia/Tokyo).
|
|
||||||
|
|
||||||
**Expected output**: After selecting your timezone, the `date` command should show the current date and time in your selected timezone.
|
|
||||||
|
|
||||||
#### 12.3 Configure /etc/hosts
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Add localhost entries for both IPv4 and IPv6
|
|
||||||
echo "127.0.0.1 localhost" | sudo tee -a /etc/hosts
|
|
||||||
echo "::1 localhost ip6-localhost ip6-loopback" | sudo tee -a /etc/hosts
|
|
||||||
echo "YOUR_PRODUCTION_IPV4_ADDRESS localhost" | sudo tee -a /etc/hosts
|
|
||||||
echo "YOUR_PRODUCTION_IPV6_ADDRESS localhost" | sudo tee -a /etc/hosts
|
|
||||||
|
|
||||||
# Verify the configuration
|
|
||||||
cat /etc/hosts
|
|
||||||
```
|
|
||||||
|
|
||||||
**What this does**:
|
|
||||||
- Adds localhost entries for both IPv4 and IPv6 addresses to `/etc/hosts`
|
|
||||||
- Ensures proper localhost resolution for both IPv4 and IPv6
|
|
||||||
|
|
||||||
**Important**: Replace `YOUR_PRODUCTION_IPV4_ADDRESS` and `YOUR_PRODUCTION_IPV6_ADDRESS` with the actual IPv4 and IPv6 addresses of your Production Linode obtained from your Linode dashboard.
|
|
||||||
|
|
||||||
**Expected output**: The `/etc/hosts` file should show entries for `127.0.0.1`, `::1`, and your Linode's actual IP addresses all mapping to `localhost`.
|
|
||||||
|
|
||||||
#### 12.4 Install Essential Packages
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo apt install -y \
|
|
||||||
curl \
|
|
||||||
wget \
|
|
||||||
git \
|
|
||||||
ca-certificates \
|
|
||||||
apt-transport-https \
|
|
||||||
software-properties-common \
|
|
||||||
ufw \
|
|
||||||
fail2ban \
|
|
||||||
htop \
|
|
||||||
nginx \
|
|
||||||
certbot \
|
|
||||||
python3-certbot-nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 13: Create Users
|
|
||||||
|
|
||||||
#### 13.1 Create the SERVICE_USER User
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create dedicated group for the service account
|
|
||||||
sudo groupadd -r SERVICE_USER
|
|
||||||
|
|
||||||
# Create service account user with dedicated group
|
|
||||||
sudo useradd -r -g SERVICE_USER -s /bin/bash -m -d /home/SERVICE_USER SERVICE_USER
|
|
||||||
echo "SERVICE_USER:$(openssl rand -base64 32)" | sudo chpasswd
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 13.2 Verify Users
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo su - SERVICE_USER
|
|
||||||
whoami
|
|
||||||
pwd
|
|
||||||
exit
|
|
||||||
|
|
||||||
sudo su - DEPLOY_USER
|
|
||||||
whoami
|
|
||||||
pwd
|
|
||||||
exit
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 14: Install Docker
|
|
||||||
|
|
||||||
#### 14.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
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 14.2 Install Docker Packages
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 14.3 Configure Docker for Service Account
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo usermod -aG docker SERVICE_USER
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 15: 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
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 16: Configure Security
|
|
||||||
|
|
||||||
#### 16.1 Configure Firewall
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo ufw --force enable
|
|
||||||
sudo ufw default deny incoming
|
|
||||||
sudo ufw default allow outgoing
|
|
||||||
sudo ufw allow ssh
|
|
||||||
sudo ufw allow 80/tcp
|
|
||||||
sudo ufw allow 443/tcp
|
|
||||||
sudo ufw allow 3000/tcp
|
|
||||||
sudo ufw allow 3001/tcp
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 16.2 Configure Fail2ban
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo systemctl enable fail2ban
|
|
||||||
sudo systemctl start fail2ban
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 17: Create Application Directory
|
|
||||||
|
|
||||||
#### 17.1 Create Directory Structure
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo mkdir -p /opt/APP_NAME
|
|
||||||
sudo chown SERVICE_USER:SERVICE_USER /opt/APP_NAME
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note**: Replace `APP_NAME` with your actual application name. This directory name can be controlled via the `APP_NAME` secret in your Forgejo repository settings. If you set the `APP_NAME` secret to `myapp`, the deployment directory will be `/opt/myapp`.
|
|
||||||
|
|
||||||
#### 17.2 Create SSL Directory (Optional - for domain users)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo mkdir -p /opt/APP_NAME/nginx/ssl
|
|
||||||
sudo chown SERVICE_USER:SERVICE_USER /opt/APP_NAME/nginx/ssl
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 18: Clone Repository and Set Up Application Files
|
|
||||||
|
|
||||||
#### 18.1 Switch to SERVICE_USER User
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo su - SERVICE_USER
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 18.2 Clone Repository
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /opt/APP_NAME
|
|
||||||
git clone https://your-forgejo-instance/your-username/APP_NAME.git .
|
|
||||||
```
|
|
||||||
|
|
||||||
**Important**: The repository includes a pre-configured `nginx/nginx.conf` file that handles both SSL and non-SSL scenarios, with proper security headers, rate limiting, and CORS configuration. This file will be automatically used by the Docker Compose setup.
|
|
||||||
|
|
||||||
**Important**: The repository also includes a pre-configured `.forgejo/workflows/ci.yml` file that handles the complete CI/CD pipeline including testing, building, and deployment. This workflow is already set up to work with the private registry and production deployment.
|
|
||||||
|
|
||||||
**Note**: Replace `your-forgejo-instance` and `your-username/APP_NAME` with your actual Forgejo instance URL and repository path.
|
|
||||||
|
|
||||||
#### 18.3 Create Environment File
|
|
||||||
|
|
||||||
The repository doesn't include a `.env.example` file for security reasons. The CI/CD pipeline will create the `.env` file dynamically during deployment. However, for manual testing or initial setup, you can create a basic `.env` file:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cat > /opt/APP_NAME/.env << 'EOF'
|
|
||||||
# Production Environment Variables
|
|
||||||
POSTGRES_PASSWORD=your_secure_password_here
|
|
||||||
REGISTRY=YOUR_CI_CD_IP:5000
|
|
||||||
IMAGE_NAME=APP_NAME
|
|
||||||
IMAGE_TAG=latest
|
|
||||||
|
|
||||||
# Database Configuration
|
|
||||||
POSTGRES_DB=sharenet
|
|
||||||
POSTGRES_USER=sharenet
|
|
||||||
DATABASE_URL=postgresql://sharenet:your_secure_password_here@postgres:5432/sharenet
|
|
||||||
|
|
||||||
# Application Configuration
|
|
||||||
NODE_ENV=production
|
|
||||||
RUST_LOG=info
|
|
||||||
RUST_BACKTRACE=1
|
|
||||||
EOF
|
|
||||||
```
|
|
||||||
|
|
||||||
**Important**: Replace `YOUR_CI_CD_IP`
|
|
52
registry/README.md
Normal file
52
registry/README.md
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
# Docker Registry Configuration
|
||||||
|
|
||||||
|
This folder contains the configuration files for the Docker Registry setup used in the CI/CD pipeline.
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
- `docker-compose.yml` - Docker Compose configuration for registry, registry-ui, and nginx services
|
||||||
|
- `nginx.conf` - Nginx reverse proxy configuration for SSL termination and routing
|
||||||
|
- `config.yml` - Docker Registry configuration file
|
||||||
|
- `README.md` - This file
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
This setup uses a hybrid approach for optimal maintainability and security:
|
||||||
|
|
||||||
|
### Repository Files (Version Controlled)
|
||||||
|
- Configuration files in `/opt/APP_NAME/registry/`
|
||||||
|
- Easy to update via git pull
|
||||||
|
- Version controlled and tracked
|
||||||
|
|
||||||
|
### System Files (Not Version Controlled)
|
||||||
|
- SSL certificates in `/etc/ssl/registry/`
|
||||||
|
- Authentication files in `/etc/registry/auth/`
|
||||||
|
- Registry data in Docker volume `/var/lib/registry`
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
The setup process will:
|
||||||
|
|
||||||
|
1. Clone the repository to `/opt/APP_NAME/`
|
||||||
|
2. Create system directories for certificates and auth
|
||||||
|
3. Generate SSL certificates in `/etc/ssl/registry/`
|
||||||
|
4. Create authentication files in `/etc/registry/auth/`
|
||||||
|
5. Start the registry services using the hybrid configuration
|
||||||
|
|
||||||
|
## Configuration Notes
|
||||||
|
|
||||||
|
- **Registry**: Runs on port 5000 with HTTPS
|
||||||
|
- **Nginx**: Provides SSL termination and reverse proxy on port 8080
|
||||||
|
- **Registry UI**: Web interface accessible via nginx on port 8080
|
||||||
|
- **Authentication**: Uses htpasswd for push authentication
|
||||||
|
- **Storage**: Uses Docker volume for persistent data
|
||||||
|
- **Configuration**: Version controlled in repository
|
||||||
|
- **Certificates**: Stored in system SSL directory
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
- SSL certificates are self-signed and stored in system SSL directory
|
||||||
|
- Authentication files are stored in system auth directory
|
||||||
|
- Configuration is version controlled and easily auditable
|
||||||
|
- All communication uses HTTPS
|
||||||
|
- Clear separation between config, auth, and data
|
21
registry/config.yml
Normal file
21
registry/config.yml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
version: 0.1
|
||||||
|
log:
|
||||||
|
level: info
|
||||||
|
storage:
|
||||||
|
filesystem:
|
||||||
|
rootdirectory: /var/lib/registry
|
||||||
|
delete:
|
||||||
|
enabled: true
|
||||||
|
http:
|
||||||
|
addr: :5000
|
||||||
|
tls:
|
||||||
|
certificate: /etc/docker/registry/ssl/registry.crt
|
||||||
|
key: /etc/docker/registry/ssl/registry.key
|
||||||
|
headers:
|
||||||
|
X-Content-Type-Options: [nosniff]
|
||||||
|
X-Frame-Options: [DENY]
|
||||||
|
X-XSS-Protection: [1; mode=block]
|
||||||
|
auth:
|
||||||
|
htpasswd:
|
||||||
|
realm: basic-realm
|
||||||
|
path: /etc/docker/registry/auth/auth.htpasswd
|
56
registry/docker-compose.yml
Normal file
56
registry/docker-compose.yml
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
registry:
|
||||||
|
image: registry:2
|
||||||
|
ports:
|
||||||
|
- "5000:5000"
|
||||||
|
volumes:
|
||||||
|
- /opt/APP_NAME/registry/config.yml:/etc/docker/registry/config.yml:ro
|
||||||
|
- /etc/registry/auth/auth.htpasswd:/etc/docker/registry/auth/auth.htpasswd:ro
|
||||||
|
- /etc/ssl/registry/registry.crt:/etc/docker/registry/ssl/registry.crt:ro
|
||||||
|
- /etc/ssl/registry/registry.key:/etc/docker/registry/ssl/registry.key:ro
|
||||||
|
- registry_data:/var/lib/registry
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- registry_network
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "https://localhost:5000/v2/", "--no-check-certificate"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
|
|
||||||
|
registry-ui:
|
||||||
|
image: joxit/docker-registry-ui:latest
|
||||||
|
expose:
|
||||||
|
- "80"
|
||||||
|
environment:
|
||||||
|
- REGISTRY_TITLE=ShareNet Registry
|
||||||
|
- REGISTRY_URL=https://YOUR_CI_CD_IP:8080
|
||||||
|
depends_on:
|
||||||
|
registry:
|
||||||
|
condition: service_healthy
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- registry_network
|
||||||
|
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
ports:
|
||||||
|
- "8080:443"
|
||||||
|
volumes:
|
||||||
|
- /etc/ssl/registry:/etc/nginx/ssl:ro
|
||||||
|
- /opt/APP_NAME/registry/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
depends_on:
|
||||||
|
- registry-ui
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- registry_network
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
registry_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
registry_network:
|
||||||
|
driver: bridge
|
48
registry/nginx.conf
Normal file
48
registry/nginx.conf
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
upstream registry_ui {
|
||||||
|
server registry-ui:80;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream registry_api {
|
||||||
|
server registry:5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name YOUR_CI_CD_IP;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/ssl/registry.crt;
|
||||||
|
ssl_certificate_key /etc/nginx/ssl/registry.key;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
|
||||||
|
# Proxy registry API requests
|
||||||
|
location /v2/ {
|
||||||
|
proxy_pass https://registry_api;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_connect_timeout 30s;
|
||||||
|
proxy_send_timeout 30s;
|
||||||
|
proxy_read_timeout 30s;
|
||||||
|
proxy_ssl_verify off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Proxy registry UI requests
|
||||||
|
location / {
|
||||||
|
proxy_pass http://registry_ui;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_connect_timeout 30s;
|
||||||
|
proxy_send_timeout 30s;
|
||||||
|
proxy_read_timeout 30s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue