19.Wordpress Ec2
1-Click Deployment
Description: Animals4Life base VPC Template + Public Instance
Parameters:
  LatestAmiId:
    Description: AMI for EC2 (default is latest AmaLinux2023)
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64
Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.16.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: a4l-vpc1
  IPv6CidrBlock:
    Type: AWS::EC2::VPCCidrBlock
    Properties:
      VpcId: !Ref VPC
      AmazonProvidedIpv6CidrBlock: true
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: A4L-vpc1-igw
  InternetGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway
  RouteTableWeb:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: A4L-vpc1-rt-web
  RouteTableWebDefaultIPv4:
    Type: AWS::EC2::Route
    DependsOn: InternetGatewayAttachment
    Properties:
      RouteTableId: !Ref RouteTableWeb
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
  RouteTableWebDefaultIPv6:
    Type: AWS::EC2::Route
    DependsOn: InternetGatewayAttachment
    Properties:
      RouteTableId: !Ref RouteTableWeb
      DestinationIpv6CidrBlock: '::/0'
      GatewayId: !Ref InternetGateway
  RouteTableAssociationWebA:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref SubnetWEBA
      RouteTableId: !Ref RouteTableWeb
  RouteTableAssociationWebB:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref SubnetWEBB
      RouteTableId: !Ref RouteTableWeb
  RouteTableAssociationWebC:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref SubnetWEBC
      RouteTableId: !Ref RouteTableWeb
  SubnetReservedA:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 0
        - !GetAZs ''
      CidrBlock: 10.16.0.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 00::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-reserved-A
  SubnetReservedB:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 1
        - !GetAZs ''
      CidrBlock: 10.16.64.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 04::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-reserved-B
  SubnetReservedC:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 2
        - !GetAZs ''
      CidrBlock: 10.16.128.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 08::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-reserved-C
  SubnetDBA:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 0
        - !GetAZs ''
      CidrBlock: 10.16.16.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 01::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-db-A
  SubnetDBB:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 1
        - !GetAZs ''
      CidrBlock: 10.16.80.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 05::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-db-B
  SubnetDBC:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 2
        - !GetAZs ''
      CidrBlock: 10.16.144.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 09::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-db-C
  SubnetAPPA:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 0
        - !GetAZs ''
      CidrBlock: 10.16.32.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 02::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-app-A
  SubnetAPPB:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 1
        - !GetAZs ''
      CidrBlock: 10.16.96.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 06::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-app-B
  SubnetAPPC:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 2
        - !GetAZs ''
      CidrBlock: 10.16.160.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 0A::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-app-C
  SubnetWEBA:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 0
        - !GetAZs ''
      CidrBlock: 10.16.48.0/20
      MapPublicIpOnLaunch: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 03::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-web-A
  SubnetWEBB:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 1
        - !GetAZs ''
      CidrBlock: 10.16.112.0/20
      MapPublicIpOnLaunch: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 07::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-web-B
  SubnetWEBC:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 2
        - !GetAZs ''
      CidrBlock: 10.16.176.0/20
      MapPublicIpOnLaunch: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 0B::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-web-C
  IPv6WorkaroundSubnetWEBA:
    Type: Custom::SubnetModify
    Properties:
      ServiceToken: !GetAtt IPv6WorkaroundLambda.Arn
      SubnetId: !Ref SubnetWEBA
  IPv6WorkaroundSubnetWEBB:
    Type: Custom::SubnetModify
    Properties:
      ServiceToken: !GetAtt IPv6WorkaroundLambda.Arn
      SubnetId: !Ref SubnetWEBB
  IPv6WorkaroundSubnetWEBC:
    Type: Custom::SubnetModify
    Properties:
      ServiceToken: !GetAtt IPv6WorkaroundLambda.Arn
      SubnetId: !Ref SubnetWEBC
  IPv6WorkaroundRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: !Sub ipv6-fix-logs-${AWS::StackName}
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: arn:aws:logs:*:*:*
        - PolicyName: !Sub ipv6-fix-modify-${AWS::StackName}
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - ec2:ModifySubnetAttribute
                Resource: '*'
  IPv6WorkaroundLambda:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.lambda_handler
      Code:
        #import cfnresponse below required to send respose back to CFN
        ZipFile: !Sub |
          import cfnresponse
          import boto3
          def lambda_handler(event, context):
            if event['RequestType'] is 'Delete':
              cfnresponse.send(event, context, cfnresponse.SUCCESS)
              return
            responseValue = event['ResourceProperties']['SubnetId']
            ec2 = boto3.client('ec2', region_name='${AWS::Region}')
            ec2.modify_subnet_attribute(AssignIpv6AddressOnCreation={
                            'Value': True
                            },
                            SubnetId=responseValue)
            responseData = {}
            responseData['SubnetId'] = responseValue
            cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
      Runtime: python3.9
      Role: !GetAtt IPv6WorkaroundRole.Arn
      Timeout: 30
  PublicEC2:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      ImageId: !Ref LatestAmiId
      IamInstanceProfile: !Ref SessionManagerInstanceProfile
      SubnetId: !Ref SubnetWEBA
      SecurityGroupIds:
        - !Ref InstanceSecurityGroup
      Tags:
        - Key: Name
          Value: A4L-PublicEC2
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !Ref VPC
      GroupDescription: Enable SSH access via port 22 IPv4 & v6
      SecurityGroupIngress:
        - Description: Allow SSH IPv4 IN
          IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          CidrIp: 0.0.0.0/0
        - Description: Allow HTTP IPv4 IN
          IpProtocol: tcp
          FromPort: '80'
          ToPort: '80'
          CidrIp: 0.0.0.0/0
        - Description: Allow SSH IPv6 IN
          IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          CidrIpv6: '::/0'
  SessionManagerRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - ssm:DescribeAssociation
                  - ssm:GetDeployablePatchSnapshotForInstance
                  - ssm:GetDocument
                  - ssm:DescribeDocument
                  - ssm:GetManifest
                  - ssm:GetParameter
                  - ssm:GetParameters
                  - ssm:ListAssociations
                  - ssm:ListInstanceAssociations
                  - ssm:PutInventory
                  - ssm:PutComplianceItems
                  - ssm:PutConfigurePackageResult
                  - ssm:UpdateAssociationStatus
                  - ssm:UpdateInstanceAssociationStatus
                  - ssm:UpdateInstanceInformation
                Resource: '*'
              - Effect: Allow
                Action:
                  - ssmmessages:CreateControlChannel
                  - ssmmessages:CreateDataChannel
                  - ssmmessages:OpenControlChannel
                  - ssmmessages:OpenDataChannel
                Resource: '*'
              - Effect: Allow
                Action:
                  - ec2messages:AcknowledgeMessage
                  - ec2messages:DeleteMessage
                  - ec2messages:FailMessage
                  - ec2messages:GetEndpoint
                  - ec2messages:GetMessages
                  - ec2messages:SendReply
                Resource: '*'
  SessionManagerInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref SessionManagerRole
Outputs:
  a4lvpc1:
    Description: Animals4Life VPC1_ID
    Value: !Ref VPC
    Export:
      Name: a4l-vpc1
  a4lvpc1subnetweba:
    Description: Animals4Life VPC1 SubnetWEBA
    Value: !Ref SubnetWEBA
    Export:
      Name: a4l-vpc1-subnet-weba
  a4lvpc1subnetwebb:
    Description: Animals4Life VPC1 SubnetWEBB
    Value: !Ref SubnetWEBB
    Export:
      Name: a4l-vpc1-subnet-webb
  a4lvpc1subnetwebc:
    Description: Animals4Life VPC1 SubnetWEBC
    Value: !Ref SubnetWEBC
    Export:
      Name: a4l-vpc1-subnet-webc
  a4lvpc1subnetappa:
    Description: Animals4Life VPC1 SubnetAPPA
    Value: !Ref SubnetAPPA
    Export:
      Name: a4l-vpc1-subnet-appa
  a4lvpc1subnetappb:
    Description: Animals4Life VPC1 SubnetAPPB
    Value: !Ref SubnetAPPB
    Export:
      Name: a4l-vpc1-subnet-appb
  a4lvpc1subnetappc:
    Description: Animals4Life VPC1 SubnetAPPC
    Value: !Ref SubnetAPPC
    Export:
      Name: a4l-vpc1-subnet-appc
  a4lvpc1subnetdba:
    Description: Animals4Life VPC1 SubnetDBA
    Value: !Ref SubnetDBA
    Export:
      Name: a4l-vpc1-subnet-dba
  a4lvpc1subnetdbb:
    Description: Animals4Life VPC1 SubnetDBB
    Value: !Ref SubnetDBB
    Export:
      Name: a4l-vpc1-subnet-dbb
  a4lvpc1subnetdbc:
    Description: Animals4Life VPC1 SubnetDBC
    Value: !Ref SubnetDBC
    Export:
      Name: a4l-vpc1-subnet-dbc
  a4lvpc1subnetreserveda:
    Description: Animals4Life VPC1 SubnetReservedA
    Value: !Ref SubnetReservedA
    Export:
      Name: a4l-vpc1-subnet-reserveda
  a4lvpc1subnetreservedb:
    Description: Animals4Life VPC1 SubnetReservedB
    Value: !Ref SubnetReservedB
    Export:
      Name: a4l-vpc1-subnet-reservedb
  a4lvpc1subnetreservedc:
    Description: Animals4Life VPC1 SubnetReservedC
    Value: !Ref SubnetReservedC
    Export:
      Name: a4l-vpc1-subnet-reservedc
Lesson Commands
# DBName=database name for wordpress
# DBUser=mariadb user for wordpress
# DBPassword=password for the mariadb user for wordpress
# DBRootPassword = root password for mariadb
# STEP 1 - Configure Authentication Variables which are used below
DBName='a4lwordpress'
DBUser='a4lwordpress'
DBPassword='4n1m4l$4L1f3'
DBRootPassword='4n1m4l$4L1f3'
# STEP 2 - Install system software - including Web and DB
sudo dnf install wget php-mysqlnd httpd php-fpm php-mysqli mariadb105-server php-json php php-devel -y
# STEP 3 - Web and DB Servers Online - and set to startup
sudo systemctl enable httpd
sudo systemctl enable mariadb
sudo systemctl start httpd
sudo systemctl start mariadb
# STEP 4 - Set Mariadb Root Password
sudo mysqladmin -u root password $DBRootPassword
# STEP 5 - Install Wordpress
sudo wget http://wordpress.org/latest.tar.gz -P /var/www/html
cd /var/www/html
sudo tar -zxvf latest.tar.gz
sudo cp -rvf wordpress/* .
sudo rm -R wordpress
sudo rm latest.tar.gz
# STEP 6 - Configure Wordpress
sudo cp ./wp-config-sample.php ./wp-config.php
sudo sed -i "s/'database_name_here'/'$DBName'/g" wp-config.php
sudo sed -i "s/'username_here'/'$DBUser'/g" wp-config.php
sudo sed -i "s/'password_here'/'$DBPassword'/g" wp-config.php   
sudo chown apache:apache * -R
# STEP 7 Create Wordpress DB
echo "CREATE DATABASE $DBName;" >> /tmp/db.setup
echo "CREATE USER '$DBUser'@'localhost' IDENTIFIED BY '$DBPassword';" >> /tmp/db.setup
echo "GRANT ALL ON $DBName.* TO '$DBUser'@'localhost';" >> /tmp/db.setup
echo "FLUSH PRIVILEGES;" >> /tmp/db.setup
mysql -u root --password=$DBRootPassword < /tmp/db.setup
sudo rm /tmp/db.setup
# STEP 8 - Browse to http://your_instance_public_ipv4_ip
💻 Cài đặt WordPress thủ công trên EC2 – Phần 1 (Học cách KHÔNG nên làm)¶
1. Mục tiêu & Bối cảnh¶
- Mục tiêu: Trải nghiệm quy trình cài đặt một ứng dụng (WordPress) thủ công trên EC2 để hiểu rõ các nhược điểm của phương pháp này.
- Tại sao? Hiểu được sự phức tạp và rủi ro của việc cài đặt thủ công sẽ giúp ta đánh giá đúng giá trị của các công cụ tự động hóa trên AWS sau này.
- Kiến trúc cuối cùng:- Một trang WordPress hoạt động trên một EC2 instance duy nhất.
- Kiến trúc đơn khối (monolithic): Cả web server (Apache) và database (MariaDB) đều chạy trên cùng một instance.
- Không có tính sẵn sàng cao (High Availability).
 
2. Bước 1: Chuẩn bị môi trường¶
- Đăng nhập AWS: Sử dụng tài khoản Management Account của bạn.
- Chọn Region: us-east-1(N. Virginia).
- Deploy CloudFormation Stack:- Sử dụng link "one-click deployment" được cung cấp kèm bài học.
- Stack name sẽ là WordPress.
- Kéo xuống dưới, tick vào ô "capabilities".
- Nhấn Create stack.
- Quan trọng: Đợi đến khi trạng thái stack chuyển thành CREATE_COMPLETE.
 
- Mở tài liệu lệnh: Mở file "Lesson Commands Document" đính kèm để copy-paste các lệnh cần thiết.
3. Bước 2: Kết nối vào EC2 Instance¶
- Truy cập EC2 Console.
- Vào mục Instances (running).
- Bạn sẽ thấy một instance có tên A4LE public EC2.
- Chuột phải vào instance → Connect.
- Chọn tab EC2 Instance Connect.
- Username: ec2-user.
- Nhấn Connect.
4. Bước 3: Cài đặt thủ công trên EC2 (qua Terminal)¶
3.1. Thiết lập biến môi trường¶
Mục đích: Lưu trữ các thông tin nhạy cảm (tên database, user, password) vào biến để tái sử dụng, tránh gõ lại và giảm lỗi.
# Đặt tên database
export DB_NAME='a4l_wordpress_db'
# Đặt tên user database
export DB_USER='a4l_wordpress_user'
# Đặt mật khẩu cho user database
export DB_PASSWORD='Password123!!'
# Đặt mật khẩu cho user root của database
export DB_ROOT_PASSWORD='Password321!!'
# Kiểm tra lại một biến để chắc chắn
echo $DB_NAME
3.2. Cài đặt các gói phần mềm cần thiết¶
Cài đặt web server (Apache), database server (MariaDB) và công cụ tải file (wget).
(Lưu ý:-y để tự động đồng ý cài đặt)
3.3. Kích hoạt và khởi động các dịch vụ¶
Đảm bảo web server và database tự động chạy khi instance khởi động lại và khởi chạy chúng ngay bây giờ.
# Kích hoạt dịch vụ httpd (Apache)
sudo systemctl enable httpd
# Kích hoạt dịch vụ mariadb
sudo systemctl enable mariadb
# Khởi động dịch vụ httpd
sudo systemctl start httpd
# Khởi động dịch vụ mariadb
sudo systemctl start mariadb
3.4. Thiết lập mật khẩu root cho Database¶
Bảo mật cơ sở dữ liệu bằng cách đặt mật khẩu cho người dùng quản trị cao nhất (root).
# Đặt mật khẩu root cho MariaDB, sử dụng biến đã tạo
sudo mysqladmin -u root password "$DB_ROOT_PASSWORD"
3.5. Tải và giải nén mã nguồn WordPress¶
- 
Tải WordPress về thư mục gốc của web server ( /var/www/html):
- 
Di chuyển vào thư mục web root và giải nén: 
- 
Di chuyển file từ thư mục con ra thư mục gốc: Sau khi giải nén, các file nằm trong thư mục /var/www/html/wordpress. Ta cần chuyển chúng ra/var/www/html.
- 
Dọn dẹp các file không cần thiết: Xóa thư mục wordpressrỗng và file nénlatest.tar.gz.
- 
Kiểm tra lại kết quả: 
Bạn sẽ thấy toàn bộ file và thư mục của WordPress đã nằm trực tiếp trong /var/www/html.