But in a real-world environment, you might have to work with hundreds or thousands of servers at once, making it infeasible to log into each server to install packages or edit config. So somewhere along the way, tools got created that let you run 1 or many commands on many machines at once.
In this post I'll walk through how to use SaltStack to install LAMP (Linux, Apache, MySQL, PHP) and pull code from github to run a complete website on Ubuntu 18.04. Installing SaltStack Master and Minion is fairly simple — you can check it out here. Now let's get to the main event!!!
What can SaltStack do?
- Remote Execution: Run commands on minion machines (basically slaves) from the master machine.
- Configuration Management: Manage minion machines' config via state files. This is also commonly called Infrastructure as Code (IaC)
- File/Git Server: SaltStack can operate as a file server or Git Server for minions to pull files or source code from.
- ....
There are plenty more features I haven't gotten to explore yet.
Creating a State File to install LAMP + Clone Code
By default SaltStack's root file lives at /srv/salt/ — inside this folder, let's create a state file (.sls) named installLamp.sls. First, before doing anything on Linux I usually run Update + Upgrade — let's add this snippet:
updateSystem:
cmd.run:
- name: "apt update && apt upgrade -y"
'updateSystem': is the name of this piece of work — you can name it whatever you want.
'cmd.run': is the directive that runs a fixed command.
'name': the command's content.
Next, install the LampStack with this snippet:
install_LAMP_Packages:
pkg.installed:
- pkgs:
- apache2
- mysql-server
- php
- libapache2-mod-php
- php-mysql
This snippet installs all the packages needed for a LAMP Stack Server. Once installed, we need to make sure it's running with this snippet:
apache2:
pkg.installed: []
service.running:
- require:
- pkg: apache2
mysql-server:
pkg.installed: []
service.running:
- require:
- pkg: mysql-server
Now we have the services needed for the website to sit on — time to clone the code. The idea is to clone the code then copy it into the default webroot at /var/www/html. But sometimes /var/www/html hasn't been created yet, which could cause an error, so let's create this folder first to be safe.
create html_directory:
file.directory:
- name: /var/www/html
- user: www-data
- group: www-data
- mode: 735
Clone_git_Repo:
git.latest:
- name: https://github.com/MMA17/LapTrinhWeb.git
- target: /var/www/
- user: www-data
- force_clone: True
copy_all_web_files:
cmd.run:
- name: "cp -r /var/www/LapTrinhWeb/* /var/www/html/"
Now the web is online — one more thing left, importing the database. To import the database, add a super simple snippet to run pre-saved SQL statements from a file. Check out that file here:
Init_Database:
cmd.run:
- name: "mysql < /var/www/LapTrinhWeb/initdb.sql"
To be extra safe you could add a snippet to restart the services, but usually this is enough. Once written, the complete file looks like this:
updateSystem:
cmd.run:
- name: "apt update && apt upgrade -y"
install_LAMP_Packages:
pkg.installed:
- pkgs:
- apache2
- mysql-server
- php
- libapache2-mod-php
- php-mysql
copy_apache_config_file:
file.managed:
- name: /etc/apache2/apache2.conf
- source: salt://lampStack/apache2.conf
apache2:
pkg.installed: []
service.running:
- require:
- pkg: apache2
mysql-server:
pkg.installed: []
service.running:
- require:
- pkg: mysql-server
create html_directory:
file.directory:
- name: /var/www/html
- user: www-data
- group: www-data
- mode: 735
Clone_git_Repo:
git.latest:
- name: https://github.com/MMA17/LapTrinhWeb.git
- target: /var/www/
- user: www-data
- force_clone: True
copy_all_web_files:
cmd.run:
- name: "cp -r /var/www/LapTrinhWeb/* /var/www/html/"
Init_Database:
cmd.run:
- name: "mysql < /var/www/LapTrinhWeb/initdb.sql"
Running the State File
This is the part that'll get you excited once you've finished writing the State File. To run this State File on a Minion, we use a simple command:
salt '*' state.apply installLamp
to apply it to all minions, or replace * with a minion's name to apply it to a specific server.
Note: the State file's name, when used with state.apply, doesn't include the .sls extension.
Wrapping up
And that's it! Deploy a Website to as many servers as you want with 1 command. I've only scratched the surface myself, so the snippet will definitely have some mistakes or silly bits — if you spot any, feel free to help me fix them in the comments.
Hope you picked up a bit of knowledge. Have a nice day.
If you're running into technical challenges or need help with systems, DevOps tools, I'm confident I can help. Get in touch at hoangviet.io.vn