The following script creates a webapp substrate for WordPress webapps/websites on Ubunu-Nginx with PHP-FPM and Mysql environments, with Certbot, while all software is uncustomized.

Such substrate includes, based on the 1 or more domains given as an argument ( /opt/nwsm.sh domain1.tld domain2.tld):

  1. /etc/nginx/sites-available/example.com.conf.
  2. etc/nginx/sites-enabled/ symlink.
  3. Appropriate DB user and instance, named example.com.
  4. Suitable wp-config.php file.

I especially hope to learn how I could shorten this code in at least 10 rows, if at all.

Installing the script

Just copy and paste in Bash and it willl be created under /opt/nwsm.sh.

cat <<-"NWSM" > /opt/nwsm.sh
    for domain; do
        cat <<-WEBAPPCONF > "/etc/nginx/sites-available/${domain}.conf" 
            server {
                root /var/www/html/${domain};
                server_name ${domain} www.${domain};
                location ~*  \.(jpg|jpeg|png|gif|ico|css|js|ttf|woff|pdf)$ {
                    expires 365d; 
                location / {
                    index index.php index.html index.htm fastcgi_index;
                    try_files $uri $uri =404 $uri/ /index.php?$args;
                location ~ \.php$ {
                    fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
                    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                    include fastcgi_params;
        ln -s /etc/nginx/sites-available/${domain}.conf /etc/nginx/sites-enabled/

        echo "Please enter database user password for user ${domain}: "
        read -s waps
        echo "Please enter database root password"
        mysql -u root -p <<-MYSQL
            create user "${domain}"@"localhost" identified by "${waps}";
            create database ${domain};
            GRANT ALL PRIVILEGES ON ${domain}.* TO ${domain}@localhost;

        certbot --nginx -d ${domain} -d www.${domain}

    cd /var/www/html/
    wget http://wordpress.org/latest.tar.gz
    tar xzvf latest.tar.gz && rm latest.tar.gz
    mv wordpress ${domain}

    cp /var/www/html/${domain}/wp-config-sample.php /var/www/html/${domain}/wp-config.php
    echo "1/1: Please enter the password of the site's DB user." && read -s dbup
    sed -i "s/database_name_here/${domain}"/g /var/www/html/${domain}/wp-config.php
    sed -i "s/username_here/${domain}"/g /var/www/html/${domain}/wp-config.php
    sed -i "s/password_here/${dbup}"/g /var/www/html/${domain}/wp-config.php

    chown www-data:www-data /var/www/html/* -R
    find /var/www/html/* -type d -exec chmod 755 {} \;
    find /var/www/html/* -type f -exec chmod 644 {} \;
    systemctl restart nginx.service
chmod +x /opt/nwsm.sh

Using the script

Call the script with a domain and tld as an argument, say:

/opt/nwsm.sh example.com
  • 1
    \$\begingroup\$ Why start by with cat <<-"NWSM" > /opt/nwsm.sh which will fail when run on a machine that doesn't have opt, or by a user that doesn't have write permissions to it? \$\endgroup\$
    – Jenny D
    Commented Jan 12, 2018 at 10:01
  • \$\begingroup\$ This mistake is because there I put all my scripts. What other dir do you recommend? \$\endgroup\$ Commented Jan 12, 2018 at 10:05
  • \$\begingroup\$ To start with, I'd recommend not using a heredoc to create the script; just let the person who's testing your scripts put them where they like. As for directory, I'd probably use a subdirectory somewhere - which one would depend on the general filesystem layout. Possible candidates could be /root/bin, /opt/bin, /usr/local/bin, /opt/scripts, /home/jenny/bin, ... \$\endgroup\$
    – Jenny D
    Commented Jan 12, 2018 at 10:30

1 Answer 1

  • The outer heredoc construct isn't really required.
  • You do not verify that you have command line arguments.
  • You do not assign your command line arguments to the variable domain.
  • You use the variable domain when it is uninitialised.

You make a number of assumptions, any one of which could bite you hard.

  • You assume that the nginx package has been installed and that it has created the paths and other things you require.
  • You assume that the MySQL packages have been installed.
  • You assume that the certbot package has been installed.
  • You assume that the /var/www/html directory exists.
  • You assume that the www-data user exists.
  • You assume that this is the first time that the script has been run for domain. It will have unexpected results if domain already exists.

Think about those assumptions and what would happen if they were incorrect and things didn't exist as you expect.

Your variable names are not good - why, for example, is the database user's password assigned to waps and not something like dbpassword?

It's not clear if you are planning on passing more than one domain to the script per invocation. If you only plan one domain per invocation you do not need the for loop.

You assume that all of your commands will complete correctly. You really should check the exit status of those that could reasonably be expected to fail. For example the wget could fail for many reasons. If it does then everything after it should not be run. What happens if certbot fails or mysql or tar or ...

Your chown -R... command assumes that nothing else is installed in /var/www/html or that everything installed there should be owned by www-data, this may not be the case, use /var/www/html/${domain}. Your find commands are the same.

Your find commands will exec chmod for every file found. It is more efficient to use find ... -exec {} + which optimises the size of the command line and reduces the number of execs.

I especially hope to learn how I could shorten this code in at least 10 rows, if at all.

How sweet, I can see it being considerably larger.

  • \$\begingroup\$ Comments are not for extended discussion; this conversation has been moved to chat. \$\endgroup\$ Commented Jan 13, 2018 at 14:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.