Master the Terminal

Advanced Command Wizardry with BashSenpai

May 31, 2023 - Bogdan Tatarov

Welcome back, terminal enthusiasts! We’ve shared the wonders of BashSenpai already, detailing how it stands as a reliable sidekick for those taking their first steps into the shell scripting world. Its thoughtful prompts and insightful commands make it an invaluable tool for beginners. But today, we’re diving into uncharted waters. BashSenpai isn’t just a guide for those just dipping their toes into the shell scripting pool; it’s a comprehensive aide for veterans too. Those of us who carry the weight of countless commands, tools, and scripts will find in BashSenpai an ally, as capable of sorting through the complexities of advanced shell environments as it is easing beginners into basic commands.

Let’s explore a few more advanced topics.

📡 Transcending Boundaries: Migrate your Wordpress site

In the realm of web development, one of the most frequent tasks is site migration. This task can often become a complex and time-consuming process, especially when dealing with robust platforms such as WordPress. Fortunatelly for all of us, there’s already a wonderful plugin All-in-One WP Migration tailored just for that task. It simplifies the process of moving a WordPress site from one location to another, whether it’s a move between domains, hosting services, or even between local and remote servers. It can export your WordPress database, media files, plugins, and themes, and pack them all into one file.

You’re free to delve into their meticulous documentation for a conventional understanding. However, if you prefer the fast lane, BashSenpai is primed to handle such tasks with ease. Let’s take a sneak peek:

john@linux:~$ senpai install All-in-One WP Migration plugin and migrate wordpress to a new server with a new domain name

# Install All-in-One WP Migration plugin
wp plugin install all-in-one-wp-migration --activate

# Export WordPress site using All-in-One WP Migration plugin
wp ai1wm backup

# Download backup file from old server to local computer
scp user@old_server:/path/to/backup/file.wpress /path/on/local/computer

# Upload backup file to new server
scp /path/on/local/computer/file.wpress user@new_server:/path/on/new/server

# Import backup file using All-in-One WP Migration plugin on new WordPress site
wp ai1wm import /path/on/new/server/file.wpress

# Update URLs in WordPress database to reflect new domain name
wp search-replace 'old_domain.com' 'new_domain.com' --skip-columns=guid

# Update WordPress configuration file to reflect new domain name
sed -i 's/old_domain.com/new_domain.com/g' /var/www/html/wp-config.php

# Update the permalinks structure in your new WordPress site
wp rewrite flush

# Restart Apache or Nginx web server
sudo systemctl restart apache2

Whew, Crisis successfully averted! You can always circle back to the documentation for an in-depth understanding. The bonus? Your site is already alive and kicking on your new server while you do so.

As illustrated, the queries posed to BashSenpai don’t have to be concise. They can include extensive context related to your task to optimize the response. If the answer leaves room for improvement, don’t hesitate to change the context of the query or just take another stab at it. Remember, ChatGPT is known to deliver varied responses to identical questions.

That went swimmingly, didn’t it? Let’s up the ante…

🗺️ Charting Uncharted Territory: Deploying a Django App

Let’s experiment with setting up the deployment of an entire Django app:

john@linux:~$ senpai deploy a django app inside a virtual environment using guniconrn and caddy2 with https enabled on ubuntu server

# Install necessary packages
sudo apt-get update
sudo apt-get install python3 python3-pip python3-venv
pip3 install gunicorn
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo tee /etc/apt/trusted.gpg.d/caddy-stable.asc >/dev/null
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list >/dev/null
sudo apt update
sudo apt install caddy

# Create and activate a virtual environment for your Django app
python3 -m venv myprojectenv
source myprojectenv/bin/activate

# Install Django and other dependencies
pip install django psycopg2-binary gunicorn

# Configure Gunicorn
sudo nano /etc/systemd/system/gunicorn.service

# Add the following content to the file:
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=
Group=www-data
WorkingDirectory=/path/to/your/project/
ExecStart=/path/to/your/virtual/environment/bin/gunicorn --access-logfile - --workers 3 --bind unix:/path/to/your/project/myproject.sock myproject.wsgi:application
[Install]
WantedBy=multi-user.target

# Configure Caddy2
sudo nano /etc/caddy/Caddyfile

# Add the following content to the file:
yourdomain.com {
reverse_proxy unix//path/to/your/project/myproject.sock
tls
}

# Enable and start Gunicorn and Caddy2 services
sudo systemctl enable gunicorn
sudo systemctl start gunicorn
sudo systemctl enable caddy
sudo systemctl start caddy

Not too shabby! But, we seem to be missing the static files. Let’s nudge for some corrections:

john@linux:~$ senpai you forgot to serve static files with caddy, respond with the updated config file only

# Configure Caddy2 to serve static files
sudo nano /etc/caddy/Caddyfile

# Add the following content to the file:
yourdomain.com {
reverse_proxy unix//path/to/your/project/myproject.sock
tls
root * /path/to/your/project/static
file_server
}

Impressive, but let’s not overlook the security…

🛡️ Fortifying the Fortress: Securing Our New Server

Our production server is up and running, but it lacks even the most elementary restrictions. Let’s remedy that:

john@linux:~$ senpai and now implement some base security settings on the same server we just configured using ufw and fail2ban

# Install ufw and fail2ban
sudo apt-get update
sudo apt-get install ufw fail2ban

# Configure ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw enable

# Configure fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo sed -i 's/# bantime = 10m/bantime = 1h/g' /etc/fail2ban/jail.local
sudo sed -i 's/# findtime = 10m/findtime = 5m/g' /etc/fail2ban/jail.local
sudo sed -i 's/# maxretry = 5/maxretry = 3/g' /etc/fail2ban/jail.local
sudo sed -i 's/# backend = auto/backend = systemd/g' /etc/fail2ban/jail.local
sudo sed -i 's/# banaction = iptables-multiport/banaction = ufw/g' /etc/fail2ban/jail.local
sudo sed -i 's/# action = %(action_)s/action = %(action_mwl)s/g' /etc/fail2ban/jail.local

# Restart fail2ban service to apply changes
sudo systemctl restart fail2ban.service

Whoa… Hold your horses, BashSenpai. That’s quite the barrage of configuration options, but without the adequate commentary. Let’s politely demand for some explanations:

john@linux:~$ senpai repeat the fail2ban configuration step you just did, but this time explain what each config option means

# Copy the default fail2ban configuration file to a local file
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

# Configure fail2ban
sudo sed -i 's/# bantime = 10m/bantime = 1h/g' /etc/fail2ban/jail.local

# Set the time in seconds an IP address will be banned for after too many failed login attempts. In this case, we set it to 1 hour.
sudo sed -i 's/# findtime = 10m/findtime = 5m/g' /etc/fail2ban/jail.local

# Set the amount of time in seconds during which failed login attempts are counted. In this case, we set it to 5 minutes.
sudo sed -i 's/# maxretry = 5/maxretry = 3/g' /etc/fail2ban/jail.local

# Set the number of failed login attempts that will trigger a ban. In this case, we set it to 3.
sudo sed -i 's/# backend = auto/backend = systemd/g' /etc/fail2ban/jail.local

# Set the method used by fail2ban to read log files. In this case, we set it to systemd.
sudo sed -i 's/# banaction = iptables-multiport/banaction = ufw/g' /etc/fail2ban/jail.local

# Set the action taken when an IP address is banned. In this case, we set it to ufw, which will add the IP address to the UFW firewall rules.
sudo sed -i 's/# action = %(action_)s/action = %(action_mwl)s/g' /etc/fail2ban/jail.local

# Set the action taken when a ban is triggered. In this case, we set it to send an email notification with the relevant log entries.

# Restart fail2ban service to apply changes
sudo systemctl restart fail2ban.service

# The bantime, findtime, maxretry, backend, banaction, and action options have been configured in the fail2ban jail.local file.

Much better, indeed. I believe the point is made. With the right nudge, BashSenpai evolves into a very powerful and indispensable tool indeed. Enjoy your scripting journey, and remember - the fun is just beginning. :)