Todd Rodzen

Agile Application Development, DevOps, Cloud Architecture Engineering



Yet another UBUNTU EC2 server config

Here is another Linux (Ubuntu) AWS EC2 config with multiple nginx virtual servers and SSL using Let’s Encrypt free certificates and CertBot. For this, I spin up an Amazon Ubuntu 16.04 LTS AMI and use Putty terminal to the system with SSH using ubuntu and private key.

sudo -i
apt update -y
apt upgrade
# auto start nginx
sudo systemctl enable nginx.service
# add ubuntu to the root and www-data groups
usermod -a -G root ubuntu
usermod -a -G www-data ubuntu
# give root group write permissions to nginx conf file
chmod 664 /etc/nginx/nginx.conf
# create directory for nginx domain configs
mkdir -p /www/nginx-conf/domains
chmod -R 2775 /www

Modify /etc/nginx/nginx.conf file to include the following line at the bottom of the http section. Also, the default server section can be removed.

# add to the bottom of the http section of the /etc/nginx/conf file
include /www/nginx-conf/domains/*.conf;

Now create an example_com.conf file in /www/nginx-conf/domains/ for each domain. (replace with your domain.)

# save as /www/nginx-conf/domains/example_com.conf file
server {
 listen 80;
 return 302 $scheme://$request_uri;

 listen 443 ssl;
  ssl_certificate /etc/letsencrypt/live/;
  ssl_certificate_key /etc/letsencrypt/live/;


server {
 listen 80;
 root /www/html/;
 include /www/nginx-conf/global_restrictions.conf;

 listen 443 ssl;
  ssl_certificate /etc/letsencrypt/live/;
  ssl_certificate_key /etc/letsencrypt/live/;

 location / {
  try_files $uri $uri/ /index.php?$args;
  index index.php index.html index.htm;
 location ~ \.php$ {
  fastcgi_pass unix:/run/php/php7.0-fpm.sock;
  include snippets/fastcgi-php.conf;


Create a CertBot conf file for each domain.

# save as /www/letsencrypt/example_com.conf file

# domains to retrieve certificate
domains =,

# increase key size
rsa-key-size = 4096

# the CA endpoint server
server =

# the email to receive renewal reminders, IIRC
email =

# turn off the ncurses UI, we want this to be run as a cronjob
text = True

Now install CertBot for letsEncrypt certificates from the EPEL.

# install certbot
add-apt-repository ppa:certbot/certbot
apt update
apt upgrade
apt install python-certbot-nginx
# run certbot for each domain
certbot --standalone --config /www/letsencrypt/example_com.conf certonly

# allow write to cron file
chmod 664 /etc/crontab

Add the following line to the /etc/crontab file. This will run the Certbot certificate renew every day at 8am. By default Let’s Encrypt certificates last 90 days and must be renewed.

0 8 * * * root certbot renew --no-self-upgrade


Since this server is only serving Nginx and Node I will not install the Apache httpd server. This also installs from the Amazon Linux extras repo.

# install php and mysql/mariadb
apt install -y php mariadb-server php-mysqlnd
# php modules (gd needed for WordPress, zip needed for phplist plugins)
apt install php-pear php-gd php-mbstring php-zip
# modify mariaDB config file to allow remote bind
chmod 0664 /etc/mysql/mariadb.conf.d/50-server.cnf
# change the following line in the 50-server.cnf file
# restart the mariadb sysql server
systemctl restart mysql.service
# follow the prompts to create a root password and remove anon access
# set MariaDB to autostart
systemctl enable mysql.service
# create a test php script 
echo "<?php phpinfo(); ?>" > /www/html/

Next login locally to the MySQL server to create a remote access user

# login locally to the mysql server
mysql -u root -p mysql
# enter the root password and the following commands to create a remote access user and password
CREATE USER 'remoteuser'@'localhost' IDENTIFIED BY 'remotepassword';
CREATE USER 'remoteuser'@'%' IDENTIFIED BY 'remotepassword';
GRANT ALL PRIVILEGES ON *.* to remoteuser@localhost IDENTIFIED BY 'remotepassword' WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON *.* to remoteuser@'%' IDENTIFIED BY 'remotepassword' WITH GRANT OPTION;

# Finally start the nginx server
systemctl start nginx.service

That’s All!


AMI Build All-in-One

Full build process

  1. Create an EC2 Linux Instance base – Amazon Linux AMI 2016.09.1 (HVM), SSD Volume Type – ami-0b33d91d
  2. Install the LAMP Stack default Apache port set to 8080 as it will be served to an Nginx reverse proxy server on the same instance (Apache 2.4, MySQL, PHP 6.7)
  3. Install the MEAN Stack
  4. Install Nginx Reverse Proxy Server
  5. Install ColdFusion 2016 update 3 Server

The server is setup and available for Free with a service contract from GTK Solutions.

Building a public Amazon AMI

A frustrating issue with building a public Amazon AMI is the authorize key that you use to build and modify the instance must be removed (which removes your own access to the instance.) The private key must be removed before it is shared.


It’s like the old problem, which comes first the chicken or the egg. So you remove the key but now you can’t login to your own system. You can only rebuild an EC2 from the ami image. Beyond that, you only do an rm to delete the file but the block of key data is still there in the EBS disk image. Someone could easily unpack the block and undelete the file to restore the authorize key file, connect to your private instances and run up your AWS bill or worse.

What’s the solution? Using additional EBS connections to create an image. Here is the procedure:

  1. Create a new 1gb EBS volume, attach, and mount it on the running instance, say under /keys Use the Amazon EBS guide to format and attach the EBS volume
  2. Copy your authorized_keys to the /keys on the new EBS
  3. Delete all sensitive files and all authorized_keys (from the primary EBS) Also delete the bash.history file and any other logs or passwords.
     sudo chmod 660 /root/.bash_history


  4. Exit Putty terminal windows and using Filezilla save empty history files to /root/.bash_history and /home/ec2-user/.bash_history
  5. Delete /tmp files
  6. Do not snapshot the live EBS volume as it still contains the deleted files and you don’t want to make them public in the new AMI. Instead,
  7. Create a new EBS volume, attach, and mount it on the running instance, say under /ebsimage
  8. Copy the root file system over to the new EBS volume. This only copies the current view of the undeleted files and does not copy the blocks containing the deleted files or any other modified file information. The command might look something like:
    rsync -axvSHAX --exclude 'ebsimage' / /ebsimage/
  9. Copy you authorize_keys back to your primary EBS
  10. unmount and detach the new EBS volume.
  11. Create an EBS snapshot of the new EBS volume.
  12. Register the EBS snapshot as a new AMI.

Powered by

Up ↑