747 lines
No EOL
18 KiB
Markdown
747 lines
No EOL
18 KiB
Markdown
# 🚀 .NET Application Deployment Generator
|
|
|
|
**Purpose:** Generate complete deployment configuration for a new .NET application on your Forgejo CI/CD infrastructure.
|
|
|
|
**Infrastructure:**
|
|
- Server: 192.168.1.43 (Ubuntu 24.04)
|
|
- Forgejo: 192.168.1.63:3000
|
|
- Deploy User: `deploy`
|
|
- Reverse Proxy: Caddy
|
|
- Process Manager: systemd
|
|
- Deployment Method: self-contained .NET publish + rsync + SSH
|
|
|
|
---
|
|
|
|
## PART 1: INFORMATION COLLECTION
|
|
|
|
Ask the user the following questions and collect their answers:
|
|
|
|
### Application Configuration
|
|
1. **Application Name** (e.g., "BlogApp", "ShopAPI", "DashboardApp")
|
|
- Answer: `_______`
|
|
|
|
2. **.NET Version** (e.g., "9.0.x", "10.0.x")
|
|
- Answer: `_______`
|
|
|
|
3. **Executable Name** (defaults to Application Name if blank)
|
|
- Answer: `_______` (or blank to use app name)
|
|
|
|
### Environment Setup
|
|
4. **Deploy TEST environment?** (yes/no)
|
|
- Answer: `_______`
|
|
|
|
5. **Deploy PROD environment?** (yes/no)
|
|
- Answer: `_______`
|
|
|
|
### Network Configuration (TEST)
|
|
*Skip if TEST not enabled*
|
|
|
|
6a. **TEST Port Number** (e.g., 5002, 5010, 5020)
|
|
- Answer: `_______`
|
|
|
|
6b. **TEST Domain** (e.g., "test-blog.jarjarbinks", "staging-shop.jarjarbinks")
|
|
- Answer: `_______`
|
|
|
|
### Network Configuration (PROD)
|
|
*Skip if PROD not enabled*
|
|
|
|
7a. **PROD Port Number** (e.g., 5003, 5011, 5021)
|
|
- Answer: `_______`
|
|
|
|
7b. **PROD Domain** (e.g., "blog.jarjarbinks", "shop.jarjarbinks")
|
|
- Answer: `_______`
|
|
|
|
### Runner Configuration
|
|
8. **Forgejo Runner Setup** (existing/new)
|
|
- Answer: `_______`
|
|
|
|
9. **Runner Name** (if new runner selected, e.g., "blogapp-runner", "shop-runner")
|
|
- Answer: `_______` (skip if using existing)
|
|
|
|
---
|
|
|
|
## PART 2: VARIABLE MAPPING
|
|
|
|
Based on user answers, create these variables:
|
|
|
|
| Variable | Derivation | Example |
|
|
|----------|------------|---------|
|
|
| `{{APP_NAME}}` | Q1 answer | BlogApp |
|
|
| `{{APP_NAME_LOWER}}` | Q1 lowercase | blogapp |
|
|
| `{{DOTNET_VERSION}}` | Q2 answer | 9.0.x |
|
|
| `{{EXECUTABLE_NAME}}` | Q3 answer or Q1 | BlogApp |
|
|
| `{{INCLUDE_TEST}}` | Q4 = "yes" | true |
|
|
| `{{INCLUDE_PROD}}` | Q5 = "yes" | true |
|
|
| `{{TEST_PORT}}` | Q6a answer | 5002 |
|
|
| `{{TEST_DOMAIN}}` | Q6b answer | test-blog.jarjarbinks |
|
|
| `{{TEST_FOLDER}}` | `/opt/{{APP_NAME_LOWER}}-test/app` | /opt/blogapp-test/app |
|
|
| `{{TEST_SERVICE}}` | `{{APP_NAME_LOWER}}-test` | blogapp-test |
|
|
| `{{PROD_PORT}}` | Q7a answer | 5003 |
|
|
| `{{PROD_DOMAIN}}` | Q7b answer | blog.jarjarbinks |
|
|
| `{{PROD_FOLDER}}` | `/opt/{{APP_NAME_LOWER}}/app` | /opt/blogapp/app |
|
|
| `{{PROD_SERVICE}}` | `{{APP_NAME_LOWER}}` | blogapp |
|
|
| `{{CREATE_RUNNER}}` | Q8 = "new" | true |
|
|
| `{{RUNNER_NAME}}` | Q9 answer | blogapp-runner |
|
|
|
|
---
|
|
|
|
## PART 3: OUTPUT FOLDER STRUCTURE
|
|
|
|
Create this folder structure with generated files:
|
|
|
|
```
|
|
deployment-configs-{{APP_NAME_LOWER}}/
|
|
├── README.md
|
|
├── .forgejo/
|
|
│ └── workflows/
|
|
│ └── cicd.yml
|
|
├── systemd/
|
|
│ ├── {{APP_NAME_LOWER}}-test.service # if INCLUDE_TEST
|
|
│ └── {{APP_NAME_LOWER}}.service # if INCLUDE_PROD
|
|
├── caddy/
|
|
│ └── {{APP_NAME_LOWER}}-config.txt
|
|
├── scripts/
|
|
│ ├── setup-server.sh
|
|
│ └── setup-runner.sh # if CREATE_RUNNER
|
|
└── secrets-checklist.md
|
|
```
|
|
|
|
---
|
|
|
|
## PART 4: FILE TEMPLATES
|
|
|
|
### Template 1: .forgejo/workflows/cicd.yml
|
|
|
|
```yaml
|
|
name: {{APP_NAME}}-cicd
|
|
|
|
on:
|
|
push:
|
|
branches: [ "main" ]
|
|
workflow_dispatch: {}
|
|
|
|
jobs:
|
|
{{#if INCLUDE_TEST}}
|
|
build_test_deploy_test:
|
|
runs-on: docker
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-dotnet@v4
|
|
with:
|
|
dotnet-version: "{{DOTNET_VERSION}}"
|
|
|
|
- name: Test
|
|
run: dotnet test -c Release
|
|
|
|
- name: Publish (self-contained linux-x64)
|
|
run: dotnet publish -c Release -r linux-x64 --self-contained true -o out
|
|
|
|
- name: Install deploy tools
|
|
run: |
|
|
apt-get update
|
|
apt-get install -y rsync openssh-client
|
|
|
|
- name: Deploy TEST
|
|
env:
|
|
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
|
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
|
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
run: |
|
|
set -e
|
|
mkdir -p ~/.ssh
|
|
chmod 700 ~/.ssh
|
|
echo "$DEPLOY_SSH_KEY" > ~/.ssh/id_ed25519
|
|
chmod 600 ~/.ssh/id_ed25519
|
|
ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts
|
|
|
|
rsync -az --delete out/ "$DEPLOY_USER@$DEPLOY_HOST:{{TEST_FOLDER}}/"
|
|
ssh "$DEPLOY_USER@$DEPLOY_HOST" "chmod +x {{TEST_FOLDER}}/{{EXECUTABLE_NAME}} && sudo systemctl restart {{TEST_SERVICE}}"
|
|
{{/if}}
|
|
|
|
{{#if INCLUDE_PROD}}
|
|
deploy_prod_manual:
|
|
if: ${{ github.event_name == 'workflow_dispatch' }}
|
|
runs-on: docker
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-dotnet@v4
|
|
with:
|
|
dotnet-version: "{{DOTNET_VERSION}}"
|
|
|
|
- name: Publish (self-contained linux-x64)
|
|
run: dotnet publish -c Release -r linux-x64 --self-contained true -o out
|
|
|
|
- name: Install deploy tools
|
|
run: |
|
|
apt-get update
|
|
apt-get install -y rsync openssh-client
|
|
|
|
- name: Deploy PROD
|
|
env:
|
|
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
|
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
|
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
run: |
|
|
set -e
|
|
mkdir -p ~/.ssh
|
|
chmod 700 ~/.ssh
|
|
echo "$DEPLOY_SSH_KEY" > ~/.ssh/id_ed25519
|
|
chmod 600 ~/.ssh/id_ed25519
|
|
ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts
|
|
|
|
rsync -az --delete out/ "$DEPLOY_USER@$DEPLOY_HOST:{{PROD_FOLDER}}/"
|
|
ssh "$DEPLOY_USER@$DEPLOY_HOST" "chmod +x {{PROD_FOLDER}}/{{EXECUTABLE_NAME}} && sudo systemctl restart {{PROD_SERVICE}}"
|
|
{{/if}}
|
|
```
|
|
|
|
**Generation Rule:**
|
|
- Remove `{{#if INCLUDE_TEST}}...{{/if}}` block if TEST not enabled
|
|
- Remove `{{#if INCLUDE_PROD}}...{{/if}}` block if PROD not enabled
|
|
- Substitute all `{{VARIABLES}}` with actual values
|
|
|
|
---
|
|
|
|
### Template 2: systemd/{{APP_NAME_LOWER}}-test.service
|
|
|
|
**Generate only if INCLUDE_TEST = true**
|
|
|
|
```ini
|
|
[Unit]
|
|
Description={{APP_NAME}} TEST Environment
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=notify
|
|
WorkingDirectory={{TEST_FOLDER}}
|
|
ExecStart={{TEST_FOLDER}}/{{EXECUTABLE_NAME}}
|
|
Environment=ASPNETCORE_URLS=http://127.0.0.1:{{TEST_PORT}}
|
|
Environment=ASPNETCORE_ENVIRONMENT=Staging
|
|
User=minapp
|
|
Group=minapp
|
|
Restart=always
|
|
RestartSec=10
|
|
SyslogIdentifier={{TEST_SERVICE}}
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
---
|
|
|
|
### Template 3: systemd/{{APP_NAME_LOWER}}.service
|
|
|
|
**Generate only if INCLUDE_PROD = true**
|
|
|
|
```ini
|
|
[Unit]
|
|
Description={{APP_NAME}} PRODUCTION Environment
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=notify
|
|
WorkingDirectory={{PROD_FOLDER}}
|
|
ExecStart={{PROD_FOLDER}}/{{EXECUTABLE_NAME}}
|
|
Environment=ASPNETCORE_URLS=http://127.0.0.1:{{PROD_PORT}}
|
|
Environment=ASPNETCORE_ENVIRONMENT=Production
|
|
User=minapp
|
|
Group=minapp
|
|
Restart=always
|
|
RestartSec=10
|
|
SyslogIdentifier={{PROD_SERVICE}}
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
---
|
|
|
|
### Template 4: caddy/{{APP_NAME_LOWER}}-config.txt
|
|
|
|
```
|
|
{{#if INCLUDE_TEST}}
|
|
# TEST Environment
|
|
http://{{TEST_DOMAIN}} {
|
|
reverse_proxy 127.0.0.1:{{TEST_PORT}}
|
|
}
|
|
|
|
{{/if}}
|
|
{{#if INCLUDE_PROD}}
|
|
# PRODUCTION Environment
|
|
http://{{PROD_DOMAIN}} {
|
|
reverse_proxy 127.0.0.1:{{PROD_PORT}}
|
|
}
|
|
{{/if}}
|
|
```
|
|
|
|
**Note:** This content must be manually added to `/etc/caddy/Caddyfile` on the server.
|
|
|
|
---
|
|
|
|
### Template 5: scripts/setup-server.sh
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# Setup script for {{APP_NAME}} deployment
|
|
# Run this on the webserver (192.168.1.43)
|
|
|
|
set -e
|
|
|
|
echo "==================================="
|
|
echo "Setting up {{APP_NAME}} on server"
|
|
echo "==================================="
|
|
|
|
{{#if INCLUDE_TEST}}
|
|
# Create TEST directories
|
|
echo "Creating TEST environment directories..."
|
|
sudo mkdir -p {{TEST_FOLDER}}
|
|
sudo chown -R minapp:minapp /opt/{{APP_NAME_LOWER}}-test
|
|
|
|
# Install TEST systemd service
|
|
echo "Installing TEST systemd service..."
|
|
sudo cp systemd/{{APP_NAME_LOWER}}-test.service /etc/systemd/system/
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable {{TEST_SERVICE}}
|
|
echo "✓ TEST service installed: {{TEST_SERVICE}}"
|
|
|
|
{{/if}}
|
|
{{#if INCLUDE_PROD}}
|
|
# Create PROD directories
|
|
echo "Creating PROD environment directories..."
|
|
sudo mkdir -p {{PROD_FOLDER}}
|
|
sudo chown -R minapp:minapp /opt/{{APP_NAME_LOWER}}
|
|
|
|
# Install PROD systemd service
|
|
echo "Installing PROD systemd service..."
|
|
sudo cp systemd/{{APP_NAME_LOWER}}.service /etc/systemd/system/
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable {{PROD_SERVICE}}
|
|
echo "✓ PROD service installed: {{PROD_SERVICE}}"
|
|
|
|
{{/if}}
|
|
# Update Caddy configuration
|
|
echo ""
|
|
echo "==================================="
|
|
echo "MANUAL STEP REQUIRED:"
|
|
echo "==================================="
|
|
echo "Add the following to /etc/caddy/Caddyfile:"
|
|
echo ""
|
|
cat caddy/{{APP_NAME_LOWER}}-config.txt
|
|
echo ""
|
|
echo "Then run: sudo systemctl reload caddy"
|
|
echo ""
|
|
|
|
echo "==================================="
|
|
echo "Setup complete!"
|
|
echo "==================================="
|
|
{{#if INCLUDE_TEST}}
|
|
echo "TEST service: {{TEST_SERVICE}}"
|
|
echo "TEST folder: {{TEST_FOLDER}}"
|
|
echo "TEST URL: http://{{TEST_DOMAIN}}"
|
|
{{/if}}
|
|
{{#if INCLUDE_PROD}}
|
|
echo "PROD service: {{PROD_SERVICE}}"
|
|
echo "PROD folder: {{PROD_FOLDER}}"
|
|
echo "PROD URL: http://{{PROD_DOMAIN}}"
|
|
{{/if}}
|
|
echo "==================================="
|
|
```
|
|
|
|
---
|
|
|
|
### Template 6: scripts/setup-runner.sh
|
|
|
|
**Generate only if CREATE_RUNNER = true**
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# Setup Forgejo Runner for {{APP_NAME}}
|
|
# Run this on the Forgejo server (192.168.1.63)
|
|
|
|
set -e
|
|
|
|
RUNNER_NAME="{{RUNNER_NAME}}"
|
|
FORGEJO_URL="http://192.168.1.63:3000"
|
|
|
|
echo "==================================="
|
|
echo "Setting up Forgejo Runner: $RUNNER_NAME"
|
|
echo "==================================="
|
|
|
|
# Create runner directory
|
|
mkdir -p ~/forgejo-runners/$RUNNER_NAME
|
|
cd ~/forgejo-runners/$RUNNER_NAME
|
|
|
|
# Create docker-compose.yml
|
|
cat > docker-compose.yml <<'EOF'
|
|
version: '3'
|
|
|
|
services:
|
|
runner:
|
|
image: code.forgejo.org/forgejo/runner:latest
|
|
container_name: {{RUNNER_NAME}}
|
|
restart: unless-stopped
|
|
volumes:
|
|
- ./data:/data
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
environment:
|
|
- DOCKER_HOST=unix:///var/run/docker.sock
|
|
EOF
|
|
|
|
echo "✓ docker-compose.yml created"
|
|
|
|
# Start the runner
|
|
echo "Starting runner container..."
|
|
docker-compose up -d
|
|
|
|
echo "Waiting for runner to start..."
|
|
sleep 5
|
|
|
|
# Register runner
|
|
echo ""
|
|
echo "==================================="
|
|
echo "MANUAL STEP REQUIRED:"
|
|
echo "==================================="
|
|
echo "1. Go to Forgejo → Repository Settings → Actions → Runners"
|
|
echo "2. Click 'Create new Runner'"
|
|
echo "3. Copy the registration token"
|
|
echo "4. Run the following command:"
|
|
echo ""
|
|
echo "docker exec -it {{RUNNER_NAME}} forgejo-runner register \\"
|
|
echo " --instance $FORGEJO_URL \\"
|
|
echo " --token YOUR_REGISTRATION_TOKEN \\"
|
|
echo " --name {{RUNNER_NAME}} \\"
|
|
echo " --labels docker:docker://node:20-bookworm"
|
|
echo ""
|
|
echo "==================================="
|
|
```
|
|
|
|
---
|
|
|
|
### Template 7: README.md
|
|
|
|
```markdown
|
|
# {{APP_NAME}} - Deployment Configuration
|
|
|
|
**Generated:** $(date)
|
|
|
|
## Overview
|
|
|
|
This folder contains all configuration files needed to deploy **{{APP_NAME}}** to your infrastructure:
|
|
|
|
- **Server:** 192.168.1.43 (Ubuntu 24.04)
|
|
- **Forgejo:** 192.168.1.63:3000
|
|
- **.NET Version:** {{DOTNET_VERSION}}
|
|
|
|
## Environments
|
|
|
|
{{#if INCLUDE_TEST}}
|
|
### TEST Environment
|
|
- **Port:** {{TEST_PORT}}
|
|
- **Domain:** http://{{TEST_DOMAIN}}
|
|
- **Folder:** {{TEST_FOLDER}}
|
|
- **Service:** {{TEST_SERVICE}}
|
|
- **Deploy:** Automatic on `git push` to main
|
|
{{/if}}
|
|
|
|
{{#if INCLUDE_PROD}}
|
|
### PROD Environment
|
|
- **Port:** {{PROD_PORT}}
|
|
- **Domain:** http://{{PROD_DOMAIN}}
|
|
- **Folder:** {{PROD_FOLDER}}
|
|
- **Service:** {{PROD_SERVICE}}
|
|
- **Deploy:** Manual via workflow_dispatch
|
|
{{/if}}
|
|
|
|
## Setup Instructions
|
|
|
|
### 1. Configure Forgejo Secrets
|
|
|
|
Go to your repository in Forgejo → Settings → Actions → Secrets
|
|
|
|
Required secrets (should already exist):
|
|
- `DEPLOY_HOST` = `192.168.1.43`
|
|
- `DEPLOY_USER` = `deploy`
|
|
- `DEPLOY_SSH_KEY` = SSH private key for deploy user
|
|
|
|
### 2. Copy Workflow to Repository
|
|
|
|
```bash
|
|
# In your repository
|
|
mkdir -p .forgejo/workflows
|
|
cp .forgejo/workflows/cicd.yml YOUR_REPO/.forgejo/workflows/
|
|
cd YOUR_REPO
|
|
git add .forgejo/workflows/cicd.yml
|
|
git commit -m "Add CI/CD workflow"
|
|
git push
|
|
```
|
|
|
|
### 3. Setup Server
|
|
|
|
```bash
|
|
# Copy files to server
|
|
scp -r systemd caddy scripts deploy@192.168.1.43:~/{{APP_NAME_LOWER}}-setup/
|
|
|
|
# SSH to server
|
|
ssh deploy@192.168.1.43
|
|
|
|
# Run setup script
|
|
cd ~/{{APP_NAME_LOWER}}-setup
|
|
chmod +x scripts/setup-server.sh
|
|
./scripts/setup-server.sh
|
|
|
|
# Manually add Caddy configuration (as instructed by script)
|
|
sudo nano /etc/caddy/Caddyfile
|
|
# Add content from caddy/{{APP_NAME_LOWER}}-config.txt
|
|
sudo systemctl reload caddy
|
|
```
|
|
|
|
{{#if CREATE_RUNNER}}
|
|
### 4. Setup Forgejo Runner (Optional)
|
|
|
|
```bash
|
|
# Copy script to Forgejo server
|
|
scp scripts/setup-runner.sh forgejo@192.168.1.63:~/
|
|
|
|
# SSH to Forgejo server
|
|
ssh forgejo@192.168.1.63
|
|
|
|
# Run setup script
|
|
chmod +x setup-runner.sh
|
|
./setup-runner.sh
|
|
|
|
# Follow instructions to register runner
|
|
```
|
|
{{/if}}
|
|
|
|
## Deployment
|
|
|
|
{{#if INCLUDE_TEST}}
|
|
### Deploy to TEST
|
|
|
|
```bash
|
|
git push origin main
|
|
```
|
|
|
|
Check deployment:
|
|
```bash
|
|
# On server
|
|
sudo systemctl status {{TEST_SERVICE}}
|
|
sudo journalctl -u {{TEST_SERVICE}} -n 50
|
|
|
|
# Test locally
|
|
curl http://127.0.0.1:{{TEST_PORT}}
|
|
|
|
# Test via Caddy
|
|
curl http://{{TEST_DOMAIN}}
|
|
```
|
|
{{/if}}
|
|
|
|
{{#if INCLUDE_PROD}}
|
|
### Deploy to PROD
|
|
|
|
1. Go to Forgejo → Repository → Actions
|
|
2. Select the workflow
|
|
3. Click **Run workflow**
|
|
4. Confirm deployment
|
|
|
|
Check deployment:
|
|
```bash
|
|
# On server
|
|
sudo systemctl status {{PROD_SERVICE}}
|
|
sudo journalctl -u {{PROD_SERVICE}} -n 50
|
|
|
|
# Test locally
|
|
curl http://127.0.0.1:{{PROD_PORT}}
|
|
|
|
# Test via Caddy
|
|
curl http://{{PROD_DOMAIN}}
|
|
```
|
|
{{/if}}
|
|
|
|
## Troubleshooting
|
|
|
|
### Service Issues
|
|
|
|
```bash
|
|
{{#if INCLUDE_TEST}}
|
|
# TEST service
|
|
sudo systemctl status {{TEST_SERVICE}}
|
|
sudo journalctl -u {{TEST_SERVICE}} -n 100 -f
|
|
{{/if}}
|
|
|
|
{{#if INCLUDE_PROD}}
|
|
# PROD service
|
|
sudo systemctl status {{PROD_SERVICE}}
|
|
sudo journalctl -u {{PROD_SERVICE}} -n 100 -f
|
|
{{/if}}
|
|
```
|
|
|
|
### Check Ports
|
|
|
|
```bash
|
|
ss -lntp | grep {{TEST_PORT}}
|
|
ss -lntp | grep {{PROD_PORT}}
|
|
```
|
|
|
|
### Restart Services
|
|
|
|
```bash
|
|
{{#if INCLUDE_TEST}}
|
|
sudo systemctl restart {{TEST_SERVICE}}
|
|
{{/if}}
|
|
{{#if INCLUDE_PROD}}
|
|
sudo systemctl restart {{PROD_SERVICE}}
|
|
{{/if}}
|
|
sudo systemctl reload caddy
|
|
```
|
|
|
|
## File Structure
|
|
|
|
```
|
|
{{TEST_FOLDER}}/ # TEST deployment
|
|
{{PROD_FOLDER}}/ # PROD deployment
|
|
/etc/systemd/system/{{TEST_SERVICE}}.service
|
|
/etc/systemd/system/{{PROD_SERVICE}}.service
|
|
/etc/caddy/Caddyfile # Contains reverse proxy config
|
|
```
|
|
```
|
|
|
|
---
|
|
|
|
### Template 8: secrets-checklist.md
|
|
|
|
```markdown
|
|
# Forgejo Secrets Checklist
|
|
|
|
Repository: **YOUR_REPO_NAME**
|
|
|
|
Go to: Forgejo → Repository → Settings → Actions → Secrets
|
|
|
|
## Required Secrets
|
|
|
|
| Secret Name | Value | Status |
|
|
|-------------|-------|--------|
|
|
| `DEPLOY_HOST` | `192.168.1.43` | ☐ |
|
|
| `DEPLOY_USER` | `deploy` | ☐ |
|
|
| `DEPLOY_SSH_KEY` | SSH private key (ED25519) | ☐ |
|
|
|
|
## Verify Secrets
|
|
|
|
These secrets should already exist from previous deployments. Verify they are configured:
|
|
|
|
```bash
|
|
# Test SSH connection
|
|
ssh deploy@192.168.1.43 "echo Connection successful"
|
|
```
|
|
|
|
## If Secrets Missing
|
|
|
|
Generate SSH key pair:
|
|
```bash
|
|
ssh-keygen -t ed25519 -C "deploy@forgejo-ci"
|
|
```
|
|
|
|
Add public key to server:
|
|
```bash
|
|
ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@192.168.1.43
|
|
```
|
|
|
|
Add private key to Forgejo secrets:
|
|
```bash
|
|
cat ~/.ssh/id_ed25519
|
|
# Copy output and paste in Forgejo secret
|
|
```
|
|
```
|
|
|
|
---
|
|
|
|
## PART 5: GENERATION INSTRUCTIONS
|
|
|
|
### Step 1: Create Output Folder
|
|
|
|
```
|
|
mkdir deployment-configs-{{APP_NAME_LOWER}}
|
|
cd deployment-configs-{{APP_NAME_LOWER}}
|
|
```
|
|
|
|
### Step 2: Apply Variable Substitutions
|
|
|
|
For each template:
|
|
1. Replace all `{{VARIABLE}}` with actual values from mapping table
|
|
2. Process conditional blocks:
|
|
- Remove `{{#if CONDITION}}...{{/if}}` wrapper and keep content if condition is true
|
|
- Remove entire `{{#if CONDITION}}...{{/if}}` block if condition is false
|
|
3. Save to appropriate file in folder structure
|
|
|
|
### Step 3: Generate Files
|
|
|
|
Create each file based on conditions:
|
|
|
|
| File | Condition | Template |
|
|
|------|-----------|----------|
|
|
| `.forgejo/workflows/cicd.yml` | Always | Template 1 |
|
|
| `systemd/{{APP_NAME_LOWER}}-test.service` | INCLUDE_TEST | Template 2 |
|
|
| `systemd/{{APP_NAME_LOWER}}.service` | INCLUDE_PROD | Template 3 |
|
|
| `caddy/{{APP_NAME_LOWER}}-config.txt` | Always | Template 4 |
|
|
| `scripts/setup-server.sh` | Always | Template 5 |
|
|
| `scripts/setup-runner.sh` | CREATE_RUNNER | Template 6 |
|
|
| `README.md` | Always | Template 7 |
|
|
| `secrets-checklist.md` | Always | Template 8 |
|
|
|
|
### Step 4: Set Execute Permissions
|
|
|
|
```bash
|
|
chmod +x scripts/*.sh
|
|
```
|
|
|
|
### Step 5: Create Archive (Optional)
|
|
|
|
```bash
|
|
tar -czf deployment-configs-{{APP_NAME_LOWER}}.tar.gz deployment-configs-{{APP_NAME_LOWER}}/
|
|
```
|
|
|
|
---
|
|
|
|
## PART 6: EXAMPLE OUTPUT
|
|
|
|
For user answers:
|
|
- App Name: BlogApp
|
|
- .NET Version: 9.0.x
|
|
- Executable: BlogApp
|
|
- TEST: yes, port 5002, domain test-blog.jarjarbinks
|
|
- PROD: yes, port 5003, domain blog.jarjarbinks
|
|
- Runner: existing
|
|
|
|
Generated folder structure:
|
|
```
|
|
deployment-configs-blogapp/
|
|
├── README.md
|
|
├── .forgejo/
|
|
│ └── workflows/
|
|
│ └── cicd.yml
|
|
├── systemd/
|
|
│ ├── blogapp-test.service
|
|
│ └── blogapp.service
|
|
├── caddy/
|
|
│ └── blogapp-config.txt
|
|
├── scripts/
|
|
│ └── setup-server.sh
|
|
└── secrets-checklist.md
|
|
```
|
|
|
|
---
|
|
|
|
## USAGE
|
|
|
|
1. Copy this prompt to your AI assistant
|
|
2. Answer all questions in PART 1
|
|
3. AI will generate all files with substituted values
|
|
4. Review generated files
|
|
5. Follow README.md instructions to deploy
|
|
|
|
---
|
|
|
|
**Version:** 1.0
|
|
**Compatible with:** .NET 9+, Ubuntu 24.04, Forgejo Actions
|
|
**Author:** Janus |