【AWS】GiteaをEC2で起動してみた

## はじめに

この記事ではAWSでGiteaを起動する方法を記載しています。

## Giteaとは

セルフホスト可能なリポジトリ管理ソフトウェアであり、強力なCI/CDをあらゆるところで起動できるソフトウェアです。

主な特徴は以下のとおりです。

- Goでできている
- MIT LICENSE
- Dockerに対応

[サイト](https://about.gitea.com/)

## 準備するもの

- EC2が起動できるAWSアカウント
    - AWS Systems Manager Session Manager（SSM）も利用します
- ほんの少しのやる気

## 実際に動かしてみよう

おおおまかな手順

- EC2の構築
- SSMを使ってEC2にログイン
- シェル上でDocker Compose upを実行

## EC2の構築

EC2はコンソールぽちぽちしても良いですが、今回はCloudFormation Templateを用意しましたので
テンプレート作ります。

以下のテンプレートをCloudFormationで適用してください。

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: CloudFormation template to create a VPC, and an EC2 instance within that VPC with a specified IAM role for Systems Manager

Parameters:
  EC2ImageId:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64"

Resources:
  VPC:
    Type: 'AWS::EC2::VPC'
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: MyVPC

  InternetGateway:
    Type: 'AWS::EC2::InternetGateway'
    Properties: 
      Tags:
        - Key: Name
          Value: MyInternetGateway

  AttachGateway:
    Type: 'AWS::EC2::VPCGatewayAttachment'
    Properties: 
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  PublicSubnet:
    Type: 'AWS::EC2::Subnet'
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: MyPublicSubnet

  RouteTable:
    Type: 'AWS::EC2::RouteTable'
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: MyRouteTable

  PublicRoute:
    Type: 'AWS::EC2::Route'
    DependsOn: AttachGateway
    Properties:
      RouteTableId: !Ref RouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  SubnetRouteTableAssociation:
    Type: 'AWS::EC2::SubnetRouteTableAssociation'
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref RouteTable

  InstanceSecurityGroupA:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      VpcId: !Ref VPC
      GroupDescription: Allow HTTPS traffic for SSM
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '443'
          ToPort: '443'
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: '3000'
          ToPort: '3000'
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: '5432'
          ToPort: '5432'
          CidrIp: 0.0.0.0/0


  MyInstanceA:
    Type: 'AWS::EC2::Instance'
    Properties: 
      InstanceType: t3.micro
      ImageId: !Ref EC2ImageId
      IamInstanceProfile: !Ref SSMRoleInstanceProfile
      SecurityGroupIds: 
        - !Ref InstanceSecurityGroupA
      SubnetId: !Ref PublicSubnet
      Tags:
        - Key: Name
          Value: MyEC2InstanceA

  SSMRoleInstanceProfile:
    Type: 'AWS::IAM::InstanceProfile'
    Properties: 
      Roles: 
        - !Ref SSMRole

  SSMRole:
    Type: 'AWS::IAM::Role'
    Properties: 
      AssumeRolePolicyDocument: 
        Version: '2012-10-17'
        Statement: 
          - Effect: Allow
            Principal: 
              Service: 
                - ec2.amazonaws.com
            Action: 
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
      Policies:
        - PolicyName: ListBucketsPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - s3:ListAllMyBuckets
                  - s3:CreateBucket
                  - s3:DeleteBucket
                  - s3:DeleteObject
                  - s3:ListBucket
                  - s3:PutObject
                  - s3:GetObject
                Resource: "*"
Outputs:
  VPCId:
    Description: The VPC ID
    Value: !Ref VPC

  InstanceIdA:
    Description: The Instance ID
    Value: !Ref MyInstanceA

  PublicSubnetId:
    Description: The Subnet ID
    Value: !Ref PublicSubnet
```

escして :wq を実行し、保存します。

## SSMを使ってEC2にログイン

今回はAmazon Linux 2023をOSとする1つのEC2にGiteaをインストールします。
AWSマネジメントコンソールからEC2を開きます。検索画面でEC2と入力してEC2を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/06206ac9-5961-90d2-4fc3-a92152cdf02e.png)

SSMを使ってEC2(MyEC2InstanceA)にログインします。MyEC2InstanceAにチェックを入れます。
※私の環境ではMyEC2InstanceBが起動されていますが、今回は使いません。前述のCloudFormationテンプレートでは`MyEC2InstanceA`のみ作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/ee5d619c-a9af-815e-883c-aa63adf80ada.png)

画面右上の`Connect`をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/00794432-e156-2f18-a403-67b29fdf275b.png)

`Session Manager`を選択して`Connect`をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/5596613b-1f12-9ddb-f6dd-dac5682ad6f0.png)

黒い画面が表示されたら、bashを起動します。

```bash
bash
```

カレントディレクトリに移動します。

```bash
cd
```

これで準備完了です。

## シェル上でDocker Compose upを実行

では、Giteaを実行できるようにファイルを定義していきましょう。
今回はEC2上にDocker Composeを起動してGiteaを起動します。

viでyamlを作成します。

```bash
vi docker-compose.yml
```

viを開いたら`i`でインサートモードに入り、以下のyamlをコピーしてください。

```yaml:docker-compose.yml
version: "3"

networks:
  gitea:
    external: false

services:
  server:
    image: gitea/gitea:latest
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=postgres
      - GITEA__database__HOST=db:5432
      - GITEA__database__NAME=gitea
      - GITEA__database__USER=gitea
      - GITEA__database__PASSWD=gitea
    restart: always
    networks:
      - gitea
    volumes:
      - ./gitea:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
    depends_on:
      - db

  db:
    image: postgres:14
    restart: always
    environment:
      - POSTGRES_USER=gitea
      - POSTGRES_PASSWORD=gitea
      - POSTGRES_DB=gitea
    networks:
      - gitea
```

## dockerのインストール

今回はdocker composeで対応するため、dockerのセットアップを実行します。

```bash
sudo yum install docker -y
```

dockerグループにec2-userを所属させます。

```bash
sudo usermod -a -G docker ec2-user
```

つぎにsystemctlでdockerをプロセスとして起動します。

```bash
sudo systemctl start docker
```

これでdockerのセットアップは完了です。

### docker-composeのインストール

つぎにdocker-composeをセットします。

最初にDOCKER_CONFIGの環境変数をセットします。

```bash
DOCKER_CONFIG=/usr/local/lib/docker
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
```

cli-pluginsディレクトリを作成します。

```bash
sudo mkdir -p /usr/local/lib/docker/cli-plugins
```

docker-composeをダウンロードして指定の位置に保存します。

```bash
sudo curl -SL https://github.com/docker/compose/releases/download/v2.29.2/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose
```

`docker-compose`の権限を変更します。

```bash
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
```

シンボリックリンクを作成します。

```bash
sudo ln -s /usr/local/lib/docker/cli-plugins/docker-compose /usr/bin/docker-compose
```

最後に`docker-compose up`を実行します。

```bash
sudo docker-compose up
```

## 実行結果

localhost:3000 にブラウザでアクセスすると以下の画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/1505820a-fb83-4c22-ca3c-06bcb1683f28.png)

## まとめ

今回は起動だけに終わりましたが、次はGiteaについて深掘りしたいと思います。