From 14b6eaeffa12f738596c677a76f84f5223b47b62 Mon Sep 17 00:00:00 2001 From: continuist Date: Fri, 4 Jul 2025 15:16:14 -0400 Subject: [PATCH] Use different names for deploy and service users on both servers --- CI_CD_PIPELINE_SETUP_GUIDE.md | 269 ++++++++++++++++++---------------- 1 file changed, 142 insertions(+), 127 deletions(-) diff --git a/CI_CD_PIPELINE_SETUP_GUIDE.md b/CI_CD_PIPELINE_SETUP_GUIDE.md index 916ec22..7d316ca 100644 --- a/CI_CD_PIPELINE_SETUP_GUIDE.md +++ b/CI_CD_PIPELINE_SETUP_GUIDE.md @@ -99,17 +99,17 @@ This setup uses a **principle of least privilege** approach with separate users - **SSH Access**: Disabled after setup - **Privileges**: Full system access (used only during initial configuration) -2. **Deployment User (`DEPLOY_USER`)** +2. **Deployment User (`CI_DEPLOY_USER` on CI Linode, `PROD_DEPLOY_USER` on Production Linode)** - **Purpose**: SSH access, deployment tasks, system administration - **SSH Access**: Enabled with key-based authentication - **Privileges**: Sudo access for deployment and administrative tasks - - **Examples**: `deploy`, `ci`, `admin` + - **Example**: `ci-deploy` / `prod-deploy` -3. **Service Account (`SERVICE_USER`)** +3. **Service Account (`CI_SERVICE_USER` on CI Linode, `PROD_SERVICE_USER` on Production Linode)** - **Purpose**: Running application services (Docker containers, databases) - **SSH Access**: None (no login shell) - **Privileges**: No sudo access, minimal system access - - **Examples**: `appuser`, `service`, `app` + - **Example**: `ci-service` / `prod-service` ### Security Benefits @@ -121,9 +121,9 @@ This setup uses a **principle of least privilege** approach with separate users ### File Permissions -- **Application files**: Owned by `SERVICE_USER` for security -- **Docker operations**: Run by `DEPLOY_USER` with sudo (deployment only) -- **Service execution**: Run by `SERVICE_USER` (no sudo needed) +- **Application files**: Owned by `CI_SERVICE_USER` for security (CI Linode) / `PROD_SERVICE_USER` for security (Production Linode) +- **Docker operations**: Run by `CI_SERVICE_USER` with Docker group access (CI Linode) / `PROD_SERVICE_USER` with Docker group access (Production Linode) +- **Service execution**: Run by `CI_SERVICE_USER` (no sudo needed) / `PROD_SERVICE_USER` (no sudo needed) --- @@ -172,30 +172,30 @@ ssh root@YOUR_PRODUCTION_IP 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 - - This account runs the actual application services +1. **CI Service Account Name**: Choose a username for the CI service account (e.g., `ci-service`) + - Replace `CI_SERVICE_USER` in this guide with your chosen name + - This account runs the CI pipeline and Docker operations on the CI Linode -2. **Deployment User Name**: Choose a username for deployment tasks (e.g., `deploy`, `ci`, `admin`) - - Replace `DEPLOY_USER` in this guide with your chosen name +2. **CI Deployment User Name**: Choose a username for CI deployment tasks (e.g., `ci-deploy`) + - Replace `CI_DEPLOY_USER` in this guide with your chosen name - This account has sudo privileges for deployment tasks -3. **Application Name**: Choose a name for your application (e.g., `myapp`, `webapp`, `api`) +3. **Application Name**: Choose a name for your application (e.g., `sharenet`) - Replace `APP_NAME` in this guide with your chosen name 4. **Domain Name** (Optional): If you have a domain, note it for SSL configuration - Replace `your-domain.com` in this guide with your actual domain **Example**: -- If you choose `appuser` as service account, `deploy` as deployment user, and `myapp` as application name: - - Replace all `SERVICE_USER` with `appuser` - - Replace all `DEPLOY_USER` with `deploy` - - Replace all `APP_NAME` with `myapp` +- If you choose `ci-service` as CI service account, `ci-deploy` as CI deployment user, and `sharenet` as application name: + - Replace all `CI_SERVICE_USER` with `ci-service` + - Replace all `CI_DEPLOY_USER` with `ci-deploy` + - Replace all `APP_NAME` with `sharenet` - If you have a domain `example.com`, replace `your-domain.com` with `example.com` **Security Model**: -- **Service Account (`SERVICE_USER`)**: Runs application services, no sudo access -- **Deployment User (`DEPLOY_USER`)**: Handles deployments via SSH, has sudo access +- **CI Service Account (`CI_SERVICE_USER`)**: Runs CI pipeline and Docker operations, no sudo access +- **CI Deployment User (`CI_DEPLOY_USER`)**: Handles SSH communication and orchestration, has sudo access - **Root**: Only used for initial setup, then disabled for SSH access #### 0.4 Set Up SSH Key Authentication for Local Development @@ -257,50 +257,74 @@ ssh root@YOUR_PRODUCTION_IP 'echo "SSH key authentication works for Production"' On both Linodes, create the deployment user with sudo privileges: +**For CI Linode:** ```bash -# Create deployment user -sudo useradd -m -s /bin/bash DEPLOY_USER -sudo usermod -aG sudo DEPLOY_USER +# Create CI deployment user +sudo useradd -m -s /bin/bash CI_DEPLOY_USER +sudo usermod -aG sudo CI_DEPLOY_USER # Set a secure password (for emergency access only) -echo "DEPLOY_USER:$(openssl rand -base64 32)" | sudo chpasswd +echo "CI_DEPLOY_USER:$(openssl rand -base64 32)" | sudo chpasswd -# Copy your SSH key to the deployment user -sudo mkdir -p /home/DEPLOY_USER/.ssh -sudo cp ~/.ssh/authorized_keys /home/DEPLOY_USER/.ssh/ -sudo chown -R DEPLOY_USER:DEPLOY_USER /home/DEPLOY_USER/.ssh -sudo chmod 700 /home/DEPLOY_USER/.ssh -sudo chmod 600 /home/DEPLOY_USER/.ssh/authorized_keys +# Copy your SSH key to the CI deployment user +sudo mkdir -p /home/CI_DEPLOY_USER/.ssh +sudo cp ~/.ssh/authorized_keys /home/CI_DEPLOY_USER/.ssh/ +sudo chown -R CI_DEPLOY_USER:CI_DEPLOY_USER /home/CI_DEPLOY_USER/.ssh +sudo chmod 700 /home/CI_DEPLOY_USER/.ssh +sudo chmod 600 /home/CI_DEPLOY_USER/.ssh/authorized_keys # Configure sudo to use SSH key authentication (most secure) -echo "DEPLOY_USER ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/DEPLOY_USER -sudo chmod 440 /etc/sudoers.d/DEPLOY_USER +echo "CI_DEPLOY_USER ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/CI_DEPLOY_USER +sudo chmod 440 /etc/sudoers.d/CI_DEPLOY_USER ``` -**Security Note**: This configuration allows the DEPLOY_USER to use sudo without a password, which is more secure for CI/CD automation since there are no passwords to store or expose. The random password is set for emergency console access only. +**For Production Linode:** +```bash +# Create production deployment user +sudo useradd -m -s /bin/bash PROD_DEPLOY_USER +sudo usermod -aG sudo PROD_DEPLOY_USER + +# Set a secure password (for emergency access only) +echo "PROD_DEPLOY_USER:$(openssl rand -base64 32)" | sudo chpasswd + +# Copy your SSH key to the production deployment user +sudo mkdir -p /home/PROD_DEPLOY_USER/.ssh +sudo cp ~/.ssh/authorized_keys /home/PROD_DEPLOY_USER/.ssh/ +sudo chown -R PROD_DEPLOY_USER:PROD_DEPLOY_USER /home/PROD_DEPLOY_USER/.ssh +sudo chmod 700 /home/PROD_DEPLOY_USER/.ssh +sudo chmod 600 /home/PROD_DEPLOY_USER/.ssh/authorized_keys + +# Configure sudo to use SSH key authentication (most secure) +echo "PROD_DEPLOY_USER ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/PROD_DEPLOY_USER +sudo chmod 440 /etc/sudoers.d/PROD_DEPLOY_USER +``` + +**Security Note**: This configuration allows the deployment users to use sudo without a password, which is more secure for CI/CD automation since there are no passwords to store or expose. The random password is set for emergency console access only. ##### 0.4.5 Test Sudo Access -Test that the deployment user can use sudo without password prompts: +Test that the deployment users can use sudo without password prompts: ```bash -# Test sudo access -ssh DEPLOY_USER@YOUR_CI_CD_IP 'sudo whoami' -ssh DEPLOY_USER@YOUR_PRODUCTION_IP 'sudo whoami' +# Test CI deployment user sudo access +ssh CI_DEPLOY_USER@YOUR_CI_CD_IP 'sudo whoami' + +# Test production deployment user sudo access +ssh PROD_DEPLOY_USER@YOUR_PRODUCTION_IP 'sudo whoami' ``` **Expected output**: Both commands should return `root` without prompting for a password. ##### 0.4.6 Test Deployment User Access -Test that you can access both servers as the deployment user: +Test that you can access both servers as the deployment users: ```bash # Test CI/CD Linode -ssh DEPLOY_USER@YOUR_CI_CD_IP 'echo "Deployment user SSH access works for CI/CD"' +ssh CI_DEPLOY_USER@YOUR_CI_CD_IP 'echo "CI deployment user SSH access works for CI/CD"' # Test Production Linode -ssh DEPLOY_USER@YOUR_PRODUCTION_IP 'echo "Deployment user SSH access works for Production"' +ssh PROD_DEPLOY_USER@YOUR_PRODUCTION_IP 'echo "Production deployment user SSH access works for Production"' ``` **Expected output**: The echo messages should appear without password prompts. @@ -314,13 +338,13 @@ On your local machine, create an SSH config file for easy access: cat > ~/.ssh/config << 'EOF' Host ci-cd-dev HostName YOUR_CI_CD_IP - User DEPLOY_USER + User CI_DEPLOY_USER IdentityFile ~/.ssh/id_ed25519 StrictHostKeyChecking no Host production-dev HostName YOUR_PRODUCTION_IP - User DEPLOY_USER + User PROD_DEPLOY_USER IdentityFile ~/.ssh/id_ed25519 StrictHostKeyChecking no EOF @@ -405,26 +429,26 @@ sudo apt install -y \ ### Step 2: Create Users -#### 2.1 Create Service Account +#### 2.1 Create CI Service Account ```bash -# Create dedicated group for the service account -sudo groupadd -r SERVICE_USER +# Create dedicated group for the CI service account +sudo groupadd -r CI_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 +# Create CI service account user with dedicated group +sudo useradd -r -g CI_SERVICE_USER -s /bin/bash -m -d /home/CI_SERVICE_USER CI_SERVICE_USER +echo "CI_SERVICE_USER:$(openssl rand -base64 32)" | sudo chpasswd ``` #### 2.2 Verify Users ```bash -sudo su - SERVICE_USER +sudo su - CI_SERVICE_USER whoami pwd exit -sudo su - DEPLOY_USER +sudo su - CI_DEPLOY_USER whoami pwd exit @@ -433,15 +457,15 @@ exit ### Step 3: Clone Repository for Registry Configuration ```bash -# Switch to DEPLOY_USER (who has sudo access) -sudo su - DEPLOY_USER +# Switch to CI_DEPLOY_USER (who has sudo access) +sudo su - CI_DEPLOY_USER # Create application directory and clone repository sudo mkdir -p /opt/APP_NAME -sudo chown SERVICE_USER:SERVICE_USER /opt/APP_NAME +sudo chown CI_SERVICE_USER:CI_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/ +sudo chown -R CI_SERVICE_USER:CI_SERVICE_USER APP_NAME/ # Verify the registry folder exists ls -la /opt/APP_NAME/registry/ @@ -450,8 +474,8 @@ ls -la /opt/APP_NAME/registry/ **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 +- CI_DEPLOY_USER creates the directory structure and clones the repository +- CI_SERVICE_USER owns all the files for security - Registry configuration files are now available at `/opt/APP_NAME/registry/` ### Step 4: Install Docker @@ -470,10 +494,10 @@ sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin ``` -#### 4.3 Configure Docker for Service Account +#### 4.3 Configure Docker for CI Service Account ```bash -sudo usermod -aG docker SERVICE_USER +sudo usermod -aG docker CI_SERVICE_USER ``` ### Step 5: Set Up Harbor Container Registry @@ -493,8 +517,8 @@ echo "harbor:$(openssl rand -base64 32)" | sudo chpasswd # Add harbor user to docker group sudo usermod -aG docker harbor -# Add DEPLOY_USER to harbor group for monitoring access -sudo usermod -aG harbor DEPLOY_USER +# Add CI_DEPLOY_USER to harbor group for monitoring access +sudo usermod -aG harbor CI_DEPLOY_USER # Set proper permissions on /opt/harbor directory sudo chown harbor:harbor /opt/harbor @@ -573,8 +597,8 @@ echo "DB_PASSWORD: $DB_PASSWORD" # Download and install Harbor cd /opt/harbor -# Switch to the DEPLOY_USER -sudo su - DEPLOY_USER +# Switch to the CI_DEPLOY_USER +sudo su - CI_DEPLOY_USER sudo wget https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-offline-installer-v2.10.0.tgz sudo tar -xzf harbor-offline-installer-v2.10.0.tgz @@ -594,8 +618,8 @@ sudo nano harbor.yml **Note**: The default Harbor admin password is "Harbor12345" and will be changed in Step 5.6 ```bash -# Run the following as the DEPLOY_USER -sudo su - DEPLOY_USER +# Run the following as the CI_DEPLOY_USER +sudo su - CI_DEPLOY_USER cd /opt/harbor/harbor @@ -613,7 +637,7 @@ cd /opt/harbor/harbor # Run the following to patially adjust the permissions correctly for the harbor user ./install.sh --with-trivy -# Exit harbor user shell to switch back to the DEPLOY_USER +# Exit harbor user shell to switch back to the CI_DEPLOY_USER exit cd /opt/harbor/harbor @@ -634,7 +658,7 @@ docker compose up -d docker compose ps -a # Verify using the Harbor API that all Harbor processes are healthy -curl -I -k https://localhost/api/v2.0/health +curl -k https://localhost/api/v2.0/health ``` #### 5.5 Create Systemd Service @@ -682,30 +706,30 @@ sudo journalctl -u harbor.service -f #### 5.7 Test Harbor Setup ```bash -# Switch to DEPLOY_USER for testing -sudo su - DEPLOY_USER +# Switch to CI_SERVICE_USER for testing (CI_SERVICE_USER runs CI pipeline and Docker operations) +sudo su - CI_SERVICE_USER # Test Docker login and push -docker login YOUR_CI_CD_IP:80 -u ci-user -p "your-secure-password" +echo "your-secure-password" | docker login YOUR_CI_CD_IP -u ci-user --password-stdin # Create and push test image echo "FROM alpine:latest" > /tmp/test.Dockerfile -docker build -f /tmp/test.Dockerfile -t YOUR_CI_CD_IP:80/APP_NAME/test:latest /tmp -docker push YOUR_CI_CD_IP:80/APP_NAME/test:latest +docker build -f /tmp/test.Dockerfile -t YOUR_CI_CD_IP/APP_NAME/test:latest /tmp +docker push YOUR_CI_CD_IP/APP_NAME/test:latest # Test public pull (no authentication) -docker logout YOUR_CI_CD_IP:80 -docker pull YOUR_CI_CD_IP:80/APP_NAME/test:latest +docker logout YOUR_CI_CD_IP +docker pull YOUR_CI_CD_IP/APP_NAME/test:latest # Test that unauthorized push is blocked echo "FROM alpine:latest" > /tmp/unauthorized.Dockerfile -docker build -f /tmp/unauthorized.Dockerfile -t YOUR_CI_CD_IP:80/APP_NAME/unauthorized:latest /tmp -docker push YOUR_CI_CD_IP:80/APP_NAME/unauthorized:latest +docker build -f /tmp/unauthorized.Dockerfile -t YOUR_CI_CD_IP/APP_NAME/unauthorized:latest /tmp +docker push YOUR_CI_CD_IP/APP_NAME/unauthorized:latest # Expected: This should fail with authentication error # Clean up -docker rmi YOUR_CI_CD_IP:80/APP_NAME/test:latest -docker rmi YOUR_CI_CD_IP:80/APP_NAME/unauthorized:latest +docker rmi YOUR_CI_CD_IP/APP_NAME/test:latest +docker rmi YOUR_CI_CD_IP/APP_NAME/unauthorized:latest exit ``` @@ -715,33 +739,24 @@ exit - ✅ Unauthorized push is blocked - ✅ Web UI accessible at `https://YOUR_CI_CD_IP` - -cat /etc/docker/daemon.json - -# 2. Check if certificate is in system CA store -ls -la /usr/local/share/ca-certificates/registry.crt - -# 3. Update CA certificates and restart Docker -sudo update-ca-certificates -sudo systemctl restart docker -``` - ### Step 6: Set Up SSH for Production Communication #### 6.1 Generate SSH Key Pair -**Important**: Run this command as the **DEPLOY_USER** (not root or SERVICE_USER). The DEPLOY_USER is responsible for deployment orchestration and SSH communication with the production server. +**Important**: Run this command as the **CI_SERVICE_USER** (not root or CI_DEPLOY_USER). The CI_SERVICE_USER runs the CI pipeline and needs to SSH to the production server for automated deployments. ```bash -ssh-keygen -t ed25519 -C "ci-cd-server" -f ~/.ssh/id_ed25519 -N "" +ssh-keygen -t ed25519 -C "CI_SERVICE_USER" -f ~/.ssh/id_ed25519 -N "" ``` **What this does**: - Creates an SSH key pair for secure communication between CI/CD and production servers -- The DEPLOY_USER uses this key to SSH to the production server for deployments -- The key is stored in the DEPLOY_USER's home directory for security +- The CI_SERVICE_USER uses this key to SSH to the production server for automated deployments +- The key is stored in the CI_SERVICE_USER's home directory for security -**Security Note**: The DEPLOY_USER handles deployment orchestration, while the SERVICE_USER runs the actual CI pipeline. This separation provides better security through the principle of least privilege. +**Security Note**: The CI_SERVICE_USER runs the CI pipeline and performs deployments, so it needs direct SSH access to the production server. This provides a clean, direct execution path without user switching. + +**Deployment Flow**: When the CI pipeline completes successfully, the CI_SERVICE_USER will automatically SSH to the production server (using this key) to pull the latest images from Harbor and deploy the application stack. #### 6.2 Create SSH Config @@ -749,7 +764,7 @@ ssh-keygen -t ed25519 -C "ci-cd-server" -f ~/.ssh/id_ed25519 -N "" cat > ~/.ssh/config << 'EOF' Host production HostName YOUR_PRODUCTION_IP - User DEPLOY_USER + User PROD_SERVICE_USER IdentityFile ~/.ssh/id_ed25519 StrictHostKeyChecking no UserKnownHostsFile /dev/null @@ -762,7 +777,7 @@ chmod 600 ~/.ssh/config #### 7.1 Download Runner -**Important**: Run this step as the **DEPLOY_USER** (not root or SERVICE_USER). The DEPLOY_USER handles deployment tasks including downloading and installing the Forgejo runner. +**Important**: Run this step as the **CI_DEPLOY_USER** (not root or CI_SERVICE_USER). The CI_DEPLOY_USER handles deployment tasks including downloading and installing the Forgejo runner. ```bash cd ~ @@ -880,8 +895,8 @@ To add an existing user as an Administrator of an existing repository in Forgejo **Step 3: Register the Runner** ```bash -# Switch to DEPLOY_USER to register the runner -sudo su - DEPLOY_USER +# Switch to CI_DEPLOY_USER to register the runner +sudo su - CI_DEPLOY_USER cd ~ @@ -899,7 +914,7 @@ forgejo-runner register \ **Note**: The `your-forgejo-instance` should be the **base URL** of your Forgejo instance (e.g., `https://git./`), not the full path to the repository. The runner registration process will handle connecting to the specific repository based on the token you provide. **What this does**: -- Creates the required `.runner` configuration file in the DEPLOY_USER's home directory +- Creates the required `.runner` configuration file in the CI_DEPLOY_USER's home directory - Registers the runner with your Forgejo instance - Sets up the runner with appropriate labels for Ubuntu and Docker environments @@ -910,10 +925,10 @@ forgejo-runner register \ sudo mkdir -p /etc/forgejo-runner # Copy the runner configuration to system location -sudo cp /home/DEPLOY_USER/.runner /etc/forgejo-runner/.runner +sudo cp /home/CI_DEPLOY_USER/.runner /etc/forgejo-runner/.runner # Set proper ownership and permissions -sudo chown SERVICE_USER:SERVICE_USER /etc/forgejo-runner/.runner +sudo chown CI_SERVICE_USER:CI_SERVICE_USER /etc/forgejo-runner/.runner sudo chmod 600 /etc/forgejo-runner/.runner ``` @@ -921,7 +936,7 @@ sudo chmod 600 /etc/forgejo-runner/.runner **What this does**: - Copies the configuration to the system location (`/etc/forgejo-runner/.runner`) -- Sets proper ownership and permissions for SERVICE_USER to access the config +- Sets proper ownership and permissions for CI_SERVICE_USER to access the config - Registers the runner with your Forgejo instance - Sets up the runner with appropriate labels for Ubuntu and Docker environments @@ -935,7 +950,7 @@ After=network.target [Service] Type=simple -User=SERVICE_USER +User=CI_SERVICE_USER WorkingDirectory=/etc/forgejo-runner ExecStart=/usr/bin/forgejo-runner daemon Restart=always @@ -1005,8 +1020,8 @@ sudo journalctl -u forgejo-runner.service -f --no-pager ```bash -# Switch to DEPLOY_USER (who has sudo access for Docker operations) -sudo su - DEPLOY_USER +# Switch to CI_DEPLOY_USER (who has sudo access for Docker operations) +sudo su - CI_DEPLOY_USER # Navigate to the application directory cd /opt/APP_NAME @@ -1030,7 +1045,7 @@ sudo docker exec ci-dind docker version - **Health checks**: Ensures DinD is fully ready before proceeding - **Simple setup**: Direct Docker commands for maximum flexibility -**Why DEPLOY_USER**: The DEPLOY_USER handles deployment orchestration and has sudo access for Docker operations, following the principle of least privilege. +**Why CI_DEPLOY_USER**: The CI_DEPLOY_USER handles deployment orchestration and has sudo access for Docker operations, following the principle of least privilege. #### 8.2 Configure DinD for Harbor Registry @@ -1281,35 +1296,35 @@ sudo apt install -y \ ### Step 12: Create Users -#### 12.1 Create the SERVICE_USER User +#### 12.1 Create the PROD_SERVICE_USER User ```bash -# Create dedicated group for the service account -sudo groupadd -r SERVICE_USER +# Create dedicated group for the production service account +sudo groupadd -r PROD_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 +# Create production service account user with dedicated group +sudo useradd -r -g PROD_SERVICE_USER -s /bin/bash -m -d /home/PROD_SERVICE_USER PROD_SERVICE_USER +echo "PROD_SERVICE_USER:$(openssl rand -base64 32)" | sudo chpasswd ``` -#### 12.2 Create the DEPLOY_USER User +#### 12.2 Create the PROD_DEPLOY_USER User ```bash -# Create deployment user -sudo useradd -m -s /bin/bash DEPLOY_USER -sudo usermod -aG sudo DEPLOY_USER -echo "DEPLOY_USER:$(openssl rand -base64 32)" | sudo chpasswd +# Create production deployment user +sudo useradd -m -s /bin/bash PROD_DEPLOY_USER +sudo usermod -aG sudo PROD_DEPLOY_USER +echo "PROD_DEPLOY_USER:$(openssl rand -base64 32)" | sudo chpasswd ``` #### 12.3 Verify Users ```bash -sudo su - SERVICE_USER +sudo su - PROD_SERVICE_USER whoami pwd exit -sudo su - DEPLOY_USER +sudo su - PROD_DEPLOY_USER whoami pwd exit @@ -1331,10 +1346,10 @@ sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin ``` -#### 13.3 Configure Docker for Service Account +#### 13.3 Configure Docker for Production Service Account ```bash -sudo usermod -aG docker SERVICE_USER +sudo usermod -aG docker PROD_SERVICE_USER ``` ### Step 14: Install Docker Compose @@ -1372,7 +1387,7 @@ sudo systemctl start fail2ban ```bash sudo mkdir -p /opt/APP_NAME -sudo chown SERVICE_USER:SERVICE_USER /opt/APP_NAME +sudo chown PROD_SERVICE_USER:PROD_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`. @@ -1381,15 +1396,15 @@ sudo chown SERVICE_USER:SERVICE_USER /opt/APP_NAME ```bash sudo mkdir -p /opt/APP_NAME/nginx/ssl -sudo chown SERVICE_USER:SERVICE_USER /opt/APP_NAME/nginx/ssl +sudo chown PROD_SERVICE_USER:PROD_SERVICE_USER /opt/APP_NAME/nginx/ssl ``` ### Step 17: Clone Repository and Set Up Application Files -#### 17.1 Switch to SERVICE_USER User +#### 17.1 Switch to PROD_SERVICE_USER User ```bash -sudo su - SERVICE_USER +sudo su - PROD_SERVICE_USER ``` #### 17.2 Clone Repository @@ -1453,7 +1468,7 @@ sudo systemctl restart docker #### 18.1 Add CI/CD Public Key ```bash -# Create .ssh directory for SERVICE_USER +# Create .ssh directory for PROD_SERVICE_USER mkdir -p ~/.ssh chmod 700 ~/.ssh @@ -1669,9 +1684,9 @@ Go to your Forgejo repository and add these secrets in **Settings → Secrets an **Required Secrets:** - `CI_HOST`: Your CI/CD Linode IP address (used for Harbor registry access) - `PRODUCTION_IP`: Your Production Linode IP address -- `DEPLOY_USER`: The deployment user name (e.g., `deploy`, `ci`, `admin`) -- `SERVICE_USER`: The service user name (e.g., `appuser`, `service`, `app`) -- `APP_NAME`: Your application name (e.g., `sharenet`, `myapp`) +- `PROD_DEPLOY_USER`: The production deployment user name (e.g., `prod-deploy`) +- `PROD_SERVICE_USER`: The production service user name (e.g., `prod-service`) +- `APP_NAME`: Your application name (e.g., `sharenet`) - `POSTGRES_PASSWORD`: A strong password for the PostgreSQL database - `HARBOR_CI_USER`: Harbor username for CI operations (e.g., `ci-user`) - `HARBOR_CI_PASSWORD`: Harbor password for CI operations (the password you set for ci-user)