Add explicit Forgejo deployment structure with artifact build pipeline
- Introduce clear directory separation for docker, infra, ci, and config - Add CloudFormation pipeline for S3 → CodeBuild → ECR - Implement explicit artifact build script for flat deployment zip - Provide example runtime configuration and ignore secrets
This commit is contained in:
commit
46ec47aa2d
8 changed files with 323 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
artifacts/*
|
||||
config/app.ini
|
||||
30
README.md
Normal file
30
README.md
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
## Purpose
|
||||
This repository contains deployment sources for running Forgejo on AWS ECS.
|
||||
Infrastructure is managed using CloudFormation, and application artifacts are
|
||||
built explicitly for use in CI/CD pipelines.
|
||||
|
||||
## Structure
|
||||
- docker/
|
||||
Container definition for Forgejo (Dockerfile and entrypoint)
|
||||
|
||||
- config/
|
||||
Runtime configuration templates
|
||||
(actual configuration is injected at runtime)
|
||||
|
||||
- ci/
|
||||
CI/CD definitions (e.g. AWS CodeBuild buildspec)
|
||||
|
||||
- infra/
|
||||
Infrastructure as Code (CloudFormation templates)
|
||||
|
||||
- artifacts/
|
||||
Build artifacts used as inputs for deployment pipelines
|
||||
|
||||
- scripts/
|
||||
Helper scripts for building deployment artifacts
|
||||
|
||||
## Artifact Build
|
||||
Deployment artifacts are built explicitly using a helper script.
|
||||
|
||||
```sh
|
||||
scripts/build-artifact.sh
|
||||
18
ci/buildspec.yml
Normal file
18
ci/buildspec.yml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
version: 0.2
|
||||
phases:
|
||||
pre_build:
|
||||
commands:
|
||||
- set -e
|
||||
- ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
|
||||
- REPOSITORY_URI=${ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/forgejo-repository
|
||||
- aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | docker login --username AWS --password-stdin ${REPOSITORY_URI}
|
||||
- GIT_TAG=$(date +%s)
|
||||
build:
|
||||
commands:
|
||||
- set -e
|
||||
- docker build -t ${REPOSITORY_URI}:${GIT_TAG} -t ${REPOSITORY_URI}:latest .
|
||||
post_build:
|
||||
commands:
|
||||
- set -e
|
||||
- docker push ${REPOSITORY_URI}:${GIT_TAG}
|
||||
- docker push ${REPOSITORY_URI}:latest
|
||||
6
config/app.ini.example
Normal file
6
config/app.ini.example
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[storage]
|
||||
STORAGE_TYPE = minio
|
||||
MINIO_USE_SSL = true
|
||||
MINIO_ENDPOINT = s3.amazonaws.com
|
||||
MINIO_BUCKET = forgejo-bucket
|
||||
MINIO_LOCATION = ap-northeast-1
|
||||
13
docker/Dockerfile
Normal file
13
docker/Dockerfile
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
FROM codeberg.org/forgejo/forgejo:11-rootless
|
||||
|
||||
# Copy your custom app.ini from the build context into a safe location not masked by EFS.
|
||||
COPY app.ini /defaults/app.ini
|
||||
|
||||
# Copy the custom entrypoint script.
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
|
||||
# Set the custom entrypoint.
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
|
||||
# Optionally, retain a CMD if needed.
|
||||
CMD []
|
||||
50
docker/entrypoint.sh
Executable file
50
docker/entrypoint.sh
Executable file
|
|
@ -0,0 +1,50 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# Define the target configuration file path where Forgejo (or Gitea) expects it.
|
||||
CONFIG_DIR="/var/lib/gitea/custom/conf"
|
||||
CONFIG_FILE="${CONFIG_DIR}/app.ini"
|
||||
|
||||
# Define the path to the default configuration file bundled in the image.
|
||||
DEFAULT_CONFIG="/defaults/app.ini"
|
||||
|
||||
# Read the optional environment variable to force the configuration update.
|
||||
# Set FORCE_COPY_APP_CONF=true to force overwriting the configuration file.
|
||||
FORCE_COPY=${FORCE_COPY_APP_CONF:-false}
|
||||
|
||||
echo "Starting container initialization..."
|
||||
|
||||
# If the force option is enabled, remove the existing configuration file (if any)
|
||||
if [ "$FORCE_COPY" = "true" ]; then
|
||||
echo "Force option enabled. Removing any existing configuration file at ${CONFIG_FILE}..."
|
||||
rm -f "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# If the configuration file does not exist, prepopulate it from the default copy.
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "Configuration file not found at ${CONFIG_FILE}."
|
||||
echo "Prepopulating the EFS volume with the default configuration."
|
||||
|
||||
# Make sure the configuration directory exists.
|
||||
mkdir -p "$CONFIG_DIR"
|
||||
|
||||
# Copy the default configuration file into the mounted volume.
|
||||
cp "$DEFAULT_CONFIG" "$CONFIG_FILE"
|
||||
|
||||
# Set proper ownership and permissions.
|
||||
# Replace '1000:1000' with the UID:GID used by Forgejo if different.
|
||||
chown 1000:1000 "$CONFIG_FILE"
|
||||
chmod 644 "$CONFIG_FILE"
|
||||
|
||||
echo "Prepopulation complete. Configuration is now available at ${CONFIG_FILE}."
|
||||
else
|
||||
echo "Configuration file already exists at ${CONFIG_FILE}. Skipping prepopulation."
|
||||
fi
|
||||
|
||||
# Optionally, log the first few lines of the configuration file for verification.
|
||||
echo "Current configuration (first few lines):"
|
||||
head -n 10 "$CONFIG_FILE"
|
||||
|
||||
# Hand over execution to the original entrypoint.
|
||||
# The official Forgejo image typically uses the entrypoint at '/usr/local/bin/docker-entrypoint.sh'
|
||||
exec /usr/local/bin/docker-entrypoint.sh "$@"
|
||||
181
infra/cfn/forgejo.yaml
Normal file
181
infra/cfn/forgejo.yaml
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
AWSTemplateFormatVersion: "2010-09-09"
|
||||
Description: S3 -> CodePipeline -> CodeBuild(ARM) -> ECR pipeline for Forgejo
|
||||
|
||||
Parameters:
|
||||
SourceBucketName:
|
||||
Type: String
|
||||
Default: forgejo-source-bucket
|
||||
|
||||
SourceObjectKey:
|
||||
Type: String
|
||||
Default: forgejo-source.zip
|
||||
|
||||
ForgejoRepositoryName:
|
||||
Type: String
|
||||
Default: forgejo-repository
|
||||
|
||||
Resources:
|
||||
|
||||
# S3 Bucket (Source)
|
||||
SourceBucket:
|
||||
Type: AWS::S3::Bucket
|
||||
Properties:
|
||||
BucketName: !Sub "ap-northeast-1-${AWS::AccountId}-${SourceBucketName}"
|
||||
Tags:
|
||||
- Key: Project
|
||||
Value: Git-server
|
||||
VersioningConfiguration:
|
||||
Status: Enabled
|
||||
|
||||
# ECR Repository
|
||||
ForgejoRepository:
|
||||
Type: AWS::ECR::Repository
|
||||
Properties:
|
||||
RepositoryName: !Ref ForgejoRepositoryName
|
||||
ImageScanningConfiguration:
|
||||
ScanOnPush: true
|
||||
|
||||
# IAM Role for CodeBuild
|
||||
CodeBuildRole:
|
||||
Type: AWS::IAM::Role
|
||||
Properties:
|
||||
AssumeRolePolicyDocument:
|
||||
Version: "2012-10-17"
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Principal:
|
||||
Service: codebuild.amazonaws.com
|
||||
Action: sts:AssumeRole
|
||||
Policies:
|
||||
- PolicyName: CodeBuildPolicy
|
||||
PolicyDocument:
|
||||
Version: "2012-10-17"
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- logs:CreateLogGroup
|
||||
- logs:CreateLogStream
|
||||
- logs:PutLogEvents
|
||||
Resource: "*"
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- ecr:GetAuthorizationToken
|
||||
Resource: "*"
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- ecr:BatchCheckLayerAvailability
|
||||
- ecr:InitiateLayerUpload
|
||||
- ecr:UploadLayerPart
|
||||
- ecr:CompleteLayerUpload
|
||||
- ecr:PutImage
|
||||
Resource:
|
||||
- !Sub "arn:aws:ecr:ap-northeast-1:${AWS::AccountId}:repository/forgejo-repository"
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- s3:GetObject
|
||||
- s3:PutObject
|
||||
- s3:ListBucket
|
||||
Resource:
|
||||
- !Sub "arn:aws:s3:::codebuild-ap-northeast-1-${AWS::AccountId}-input-bucket"
|
||||
- !Sub "arn:aws:s3:::codebuild-ap-northeast-1-${AWS::AccountId}-input-bucket/*"
|
||||
- !Sub "arn:aws:s3:::ap-northeast-1-${AWS::AccountId}-${SourceBucketName}"
|
||||
- !Sub "arn:aws:s3:::ap-northeast-1-${AWS::AccountId}-${SourceBucketName}/*"
|
||||
|
||||
|
||||
# CodeBuild Project (ARM)
|
||||
ForgejoBuildProject:
|
||||
Type: AWS::CodeBuild::Project
|
||||
Properties:
|
||||
ServiceRole: !GetAtt CodeBuildRole.Arn
|
||||
Artifacts:
|
||||
Type: CODEPIPELINE
|
||||
Environment:
|
||||
Type: ARM_CONTAINER
|
||||
ComputeType: BUILD_GENERAL1_MEDIUM
|
||||
Image: aws/codebuild/amazonlinux2-aarch64-standard:3.0
|
||||
PrivilegedMode: true
|
||||
EnvironmentVariables:
|
||||
- Name: ECR_REPOSITORY
|
||||
Value: !Ref ForgejoRepositoryName
|
||||
Source:
|
||||
Type: CODEPIPELINE
|
||||
TimeoutInMinutes: 30
|
||||
|
||||
# IAM Role for CodePipeline
|
||||
CodePipelineRole:
|
||||
Type: AWS::IAM::Role
|
||||
Properties:
|
||||
AssumeRolePolicyDocument:
|
||||
Version: "2012-10-17"
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Principal:
|
||||
Service: codepipeline.amazonaws.com
|
||||
Action: sts:AssumeRole
|
||||
Policies:
|
||||
- PolicyName: CodePipelinePolicy
|
||||
PolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
# Permissions for accessing the artifacts bucket
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- s3:GetObject
|
||||
- s3:GetObjectVersion
|
||||
- s3:PutObject
|
||||
- s3:ListBucket
|
||||
- s3:GetBucketLocation
|
||||
- s3:GetBucketVersioning
|
||||
Resource:
|
||||
- !Sub "arn:aws:s3:::codebuild-ap-northeast-1-${AWS::AccountId}-input-bucket"
|
||||
- !Sub "arn:aws:s3:::codebuild-ap-northeast-1-${AWS::AccountId}-input-bucket/*"
|
||||
- !Sub "arn:aws:s3:::ap-northeast-1-${AWS::AccountId}-${SourceBucketName}"
|
||||
- !Sub "arn:aws:s3:::ap-northeast-1-${AWS::AccountId}-${SourceBucketName}/*"
|
||||
# Permissions for CodeBuild (if used)
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- codebuild:StartBuild
|
||||
- codebuild:BatchGetBuilds
|
||||
Resource: "*"
|
||||
# Permissions for manual approval actions in CodePipeline
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- codepipeline:PutApprovalResult
|
||||
Resource: "*"
|
||||
|
||||
# CodePipeline
|
||||
ForgejoPipeline:
|
||||
Type: AWS::CodePipeline::Pipeline
|
||||
Properties:
|
||||
PipelineType: V2
|
||||
RoleArn: !GetAtt CodePipelineRole.Arn
|
||||
ArtifactStore:
|
||||
Type: S3
|
||||
Location: !Sub "codebuild-ap-northeast-1-${AWS::AccountId}-input-bucket"
|
||||
Stages:
|
||||
- Name: Source
|
||||
Actions:
|
||||
- Name: S3Source
|
||||
ActionTypeId:
|
||||
Category: Source
|
||||
Owner: AWS
|
||||
Provider: S3
|
||||
Version: "1"
|
||||
Configuration:
|
||||
S3Bucket: !Ref SourceBucket
|
||||
S3ObjectKey: !Ref SourceObjectKey
|
||||
PollForSourceChanges: true
|
||||
OutputArtifacts:
|
||||
- Name: SourceOutput
|
||||
- Name: Build
|
||||
Actions:
|
||||
- Name: BuildImage
|
||||
ActionTypeId:
|
||||
Category: Build
|
||||
Owner: AWS
|
||||
Provider: CodeBuild
|
||||
Version: "1"
|
||||
InputArtifacts:
|
||||
- Name: SourceOutput
|
||||
Configuration:
|
||||
ProjectName: !Ref ForgejoBuildProject
|
||||
23
scripts/build-artifact.sh
Executable file
23
scripts/build-artifact.sh
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
ARTIFACT_DIR="${ROOT_DIR}/artifacts"
|
||||
ZIP_PATH="${ARTIFACT_DIR}/forgejo-source.zip"
|
||||
|
||||
mkdir -p "${ARTIFACT_DIR}"
|
||||
|
||||
tmpdir="$(mktemp -d)"
|
||||
trap 'rm -rf "${tmpdir}"' EXIT
|
||||
|
||||
cp "${ROOT_DIR}/docker/Dockerfile" "${tmpdir}/Dockerfile"
|
||||
cp "${ROOT_DIR}/docker/entrypoint.sh" "${tmpdir}/entrypoint.sh"
|
||||
cp "${ROOT_DIR}/config/app.ini" "${tmpdir}/app.ini"
|
||||
cp "${ROOT_DIR}/ci/buildspec.yml" "${tmpdir}/buildspec.yml"
|
||||
|
||||
(
|
||||
cd "${tmpdir}"
|
||||
zip -r "${ZIP_PATH}" .
|
||||
)
|
||||
|
||||
echo "Artifact created: ${ZIP_PATH}"
|
||||
Loading…
Add table
Add a link
Reference in a new issue