Creating a Server Image

Provision the Server

Here's the script we used to provision the server:

1#!/usr/bin/env bash
2 
3set -e
4 
5###
6# Note: This script is assumed to be run as user root
7##
8 
9 
10 
11## Add PHP repository
12add-apt-repository -y ppa:ondrej/php
13apt-get update
14 
15 
16 
17## Install utilities and PHP
18## Configure PHP-FPM to run as user "ubuntu"
19apt-get install -y ca-certificates curl wget jq zip unzip ripgrep pv \
20 nginx supervisor \
21 php8.1-fpm php8.1-cli \
22 php8.1-pgsql php8.1-sqlite3 php8.1-gd \
23 php8.1-curl php8.1-memcached \
24 php8.1-imap php8.1-mysql php8.1-mbstring \
25 php8.1-xml php8.1-zip php8.1-bcmath php8.1-soap \
26 php8.1-intl php8.1-readline \
27 php8.1-msgpack php8.1-igbinary php8.1-ldap \
28 php8.1-redis \
29 && php -r "readfile('http://getcomposer.org/installer');" | php -- --install-dir=/usr/bin/ --filename=composer \
30 && sed -i "s/user = .*/user = ubuntu/" /etc/php/8.1/fpm/pool.d/www.conf \
31 && service php8.1-fpm restart \
32 && curl -sL https://deb.nodesource.com/setup_16.x -o nodesource_setup.sh \
33 && bash nodesource_setup.sh \
34 && apt-get install -y nodejs \
35 && rm nodesource_setup.sh
36 
37 
38 
39## Configure Nginx to host site at location /home/ubuntu/onboarding-aws
40tee /etc/nginx/sites-available/default > /dev/null <<EOT
41server {
42 listen 80 default_server;
43 
44 root /home/ubuntu/onboarding-aws/public;
45 
46 index index.html index.htm index.php;
47 
48 server_name _;
49 
50 charset utf-8;
51 
52 location = /favicon.ico { log_not_found off; access_log off; }
53 location = /robots.txt { log_not_found off; access_log off; }
54 
55 client_max_body_size 100M;
56 
57 location / {
58 try_files $uri $uri/ /index.php$is_args$args;
59 }
60 
61 location ~ \.php$ {
62 include snippets/fastcgi-php.conf;
63 fastcgi_pass unix:/run/php/php8.1-fpm.sock;
64 }
65 
66 error_page 404 =200 /index.php;
67 
68 location ~ /\.ht {
69 deny all;
70 }
71}
72EOT
73 
74service nginx reload
75 
76 
77 
78## CloudWatch Agent
79cd /tmp
80wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
81dpkg -i -E ./amazon-cloudwatch-agent.deb
82rm amazon-cloudwatch-agent.deb
83 
84# To check if it's running:
85# service amazon-cloudwatch-agent status
86 
87# Configure CloudWatch Agent for our application + Nginx logs
88tee /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/config.json > /dev/null <<EOT
89{
90 "agent": {
91 "metrics_collection_interval": 60,
92 "region": "us-east-2",
93 "logfile": "/var/log/amazon-cloudwatch-agent.log",
94 "debug": false
95 },
96 "logs": {
97 "logs_collected": {
98 "files": {
99 "collect_list": [
100 {
101 "file_path": "/home/ubuntu/onboarding-aws/storage/logs/laravel.log",
102 "log_group_name": "onboarding-aws-production-app",
103 "log_stream_name": "app-log-{hostname}",
104 "timestamp_format": "[%Y-%m-%d %H:%M:%S]",
105 "multi_line_start_pattern": "{timestamp_format}"
106 },
107 {
108 "file_path": "/var/log/nginx/access.log",
109 "log_group_name": "onboarding-aws-production-access",
110 "log_stream_name": "web-access-{hostname}",
111 "timestamp_format" :"[%d/%b/%Y:%H:%M:%S %z]"
112 },
113 {
114 "file_path": "/var/log/nginx/error.log",
115 "log_group_name": "onboarding-aws-production-error",
116 "log_stream_name": "web-error-{hostname}",
117 "timestamp_format" :"[%d/%b/%Y:%H:%M:%S %z]"
118 }
119 ]
120 }
121 }
122 }
123}
124EOT

Create an AMI

We create an image from a snapshot of the EBS disk, but you can also create an image directly from the server. However it's recommended the server is off when doing so (so data isn't actively being written to the disk drive).

Don't miss out

Sign up to learn when new content is released! Courses are in production now.