scripts/deploy_host.rb

#!/usr/bin/env ruby

require 'erb'
require 'etc'
require 'securerandom'
require 'net/http'

# based originally on my
# https://thomaspowell.com/2017/07/03/migrating-wordpress-dreamhost-linode/
# post

def reload_apache
  `service apache2 reload`
end

DOMAIN=ARGV[0]
USER=ARGV[1]
etc_passwd=Etc.getpwnam(USER)

# `sudo apt-get install -y apache2 mysql-client mysql-server`

http_template=<<-HTTP_TEMPLATE
<Directory /var/www/html/<%= DOMAIN %>/public_html>
        Require all granted
</Directory>
<VirtualHost *:80>
        ServerName <%= DOMAIN %>
        ServerAlias www.<%= DOMAIN %>
        ServerAdmin webmaster@<%= DOMAIN %>
        DocumentRoot /var/www/html/<%= DOMAIN %>/public_html

        ErrorLog /var/www/html/<%= DOMAIN %>/logs/error.log
        CustomLog /var/www/html/<%= DOMAIN %>/logs/access.log combined
</VirtualHost>
HTTP_TEMPLATE

https_template=<<-HTTPS_TEMPLATE
<Directory /var/www/html/<%= DOMAIN %>/public_html>
        Require all granted
</Directory>
<VirtualHost *:80>
        ServerName <%= DOMAIN %>
        ServerAlias www.<%= DOMAIN %>
        Redirect / https://<%= DOMAIN %>/
</VirtualHost>
<VirtualHost *:443>
        SSLEngine On
        # comment these three lines out
        # sudo apache restart
        # run letsencrypt
        # sudo apache restart (reload seemed to get in a weird state)
        SSLCertificateFile /etc/letsencrypt/live/<%= DOMAIN %>/cert.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/<%= DOMAIN %>/privkey.pem
        SSLCertificateChainFile /etc/letsencrypt/live/<%= DOMAIN %>/chain.pem

        ServerName <%= DOMAIN %>
        ServerAlias www.<%= DOMAIN %>
        ServerAdmin webmaster@<%= DOMAIN %>
        DocumentRoot /var/www/html/<%= DOMAIN %>/public_html


        ErrorLog /var/www/html/<%= DOMAIN %>/logs/error.log
        CustomLog /var/www/html/<%= DOMAIN %>/logs/access.log combined
</VirtualHost>
HTTPS_TEMPLATE


# Set up the virtual host
conf_file=ERB.new(http_template)
conf_filename=File.join('/etc/apache2/sites-available', "#{DOMAIN}.conf")
File.write(conf_filename, conf_file.result)

`a2ensite #{DOMAIN}`

reload_apache

def remodown(perms, etc_passwd, filepath)
  File.chmod(perms, filepath)
  File.chown(etc_passwd.uid, etc_passwd.gid, filepath)
end

remodown(0644, etc_passwd, conf_filename)

# Create subdirs and set permissions
[
  File.join('/var/www/html/', DOMAIN),
  File.join('/var/www/html/', DOMAIN, 'logs'),
  File.join('/var/www/html/', DOMAIN, 'public_html')
].each do |dir_path|
  Dir.mkdir(dir_path) unless Dir.exists?(dir_path)
  remodown(0755, etc_passwd, dir_path)
end



# set up a db
database_name="wp_#{DOMAIN.gsub(/\./, '_')}"
username=DOMAIN.gsub(/\./,'')
password=SecureRandom.base64(20)
db_string=<<DBSTRING
CREATE DATABASE #{database_name};
CREATE USER '#{username}' IDENTIFIED BY '#{password}';
GRANT ALL PRIVILEGES ON #{database_name}.* TO '#{username}';
DBSTRING


mysql_invoke_string=ENV['MYSQLPASSWORD'] ? "mysql -u root -p'#{ENV['MYSQLPASSWORD']}'" : "mysql -u root"

# need to either pass the password or change to trusted root?
# pass the password with mysql -pP455w0rd (no space between)
IO.popen(mysql_invoke_string, mode="w+") do |io|
  io.puts db_string
  io.close_write
  puts io.read
end

public_html=File.join('/var/www/html', DOMAIN, 'public_html')

`
  cd #{public_html}
  wget https://wordpress.org/latest.tar.gz
  # curl https://wordpress.org/latest.tar.gz --output latest.tar.gz
  tar zxvf latest.tar.gz
  cd wordpress
  mv * ..
  cd ..
  rm -rf wordpress
`

config_sample=File.open(File.join(public_html, 'wp-config-sample.php')).read

def set_secrets(string, key_name, secret)
  string.gsub(
    /'#{key_name}',\s*'.*'/,
    "'#{key_name}', '#{secret}'"
  )
end

config = set_secrets(config_sample, 'DB_NAME', database_name)
config = set_secrets(config, 'DB_USER', username)
config = set_secrets(config, 'DB_PASSWORD', password)

keys=%w(AUTH_KEY SECURE_AUTH_KEY LOGGED_IN_KEY NONCE_KEY AUTH_SALT SECURE_AUTH_SALT LOGGED_IN_SALT NONCE_SALT)
config = keys.inject(config) do |config, key|
  set_secrets(config, key, SecureRandom::hex(16))
end

File.open(File.join(public_html,'wp-config.php'), 'w') do |f|
  f.puts config
end

letsencryptupdate='/usr/local/sbin/letsencryptupdate.sh'

# FIXME: this method takes user input!
`/opt/letsencrypt/letsencrypt-auto certonly -d #{DOMAIN}`

conf_file=ERB.new(https_template)
conf_filename=File.join('/etc/apache2/sites-available', "#{DOMAIN}.conf")
File.write(conf_filename, conf_file.result)

reload_apache


lines=File.open(letsencryptupdate, 'r').readlines
lines.insert(-2, "/opt/letsencrypt/letsencrypt-auto certonly --quiet --apache --renew-by-default -d #{DOMAIN} >> /var/log/letsencrypt/letsencrypt-auto-update.log")

FileUtils.copy(letsencryptupdate, "#{letsencryptupdate}.#{$$}")

File.open(letsencryptupdate, 'w') do |f|
  lines.each { |line| f.puts line }
end

reload_apache

# also in /etc/apache/apache2.conf
#<Directory /home/#{DOMAIN}/public_html/>
#        Options Indexes FollowSymLinks
#        AllowOverride All
#        Require all granted
#</Directory>