- On your local machine generate a public key that will be exchanged with the remote servers you'll be deploying to. This will authorize your computer to connect and not require a password
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_abccompany -C "Comment to remember whos key"
also setup your ~/.ssh/config with this info to tie your key to which host
Host 192.168.1.5
Port 22
HostName 192.168.1.5
User myuser
AddKeysToAgent yes
IdentityFile ~/.ssh/id_rsa_abccompany
IdentitiesOnly yes
- Copy the public key to the remote system's user directory ssh authorized keys file. Create .ssh dir if its not already created
ssh [email protected] 'mkdir .ssh'
scp "/path/to/your/key/.ssh/id_rsa.pub" [email protected]:~/.ssh/TransferedKey.pub
ssh [email protected] < SetSSHDirPermissions.sh
cd ~/.ssh
cp authorized_keys authorized_keys_Backup
cat TransferedKey.pub >> authorized_keys
rm TransferedKey.pub
chmod go-w ~/
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
Special care is needed for symlinks and mounts inside your document root. You'll have to find our symlinks take note of these and figure out how you'll re-create them after deployment
- Find symlinks
ls -lR /var/www/html | grep ^l
Your site's document root will always be a symbolic link to a folder in the release directory which allows for clean switching to the new version of your site and quick rollback by switching the symlink to the previous version. Additionally it'll have a date-stamp and source control revision #
/var/www/html/site1.example.com -> /var/www/html/releases/site1.example.com/20170315_Rev2579
/var/www/html/site2.example.com -> /var/www/html/releases/site2.example.com/20170310_Rev2569
- Configuration and verify connection works
Project/App/Website Name: site1.example.com
Source Control: svn.example.com or git.example.com
Source Control branch to deploy: master
Source Control revision to deploy: head
Server: MyWebServer.example.com
IP: 64.64.64.201
SSH Connection Authentication: Pub Key
Project Path:/var/www/html/site1.example.com
Release Path:/var/www/html/releases/site1.example.com/
- Merge development branch to Main Branch and emit post-commit hooks
git checkout master
git merge devbranch
# Trigger Build and running of tests on CI Server
-
Run SQL promotion script
-
Auto-Run build scripts on CI server and generate source files (minify & combine JS and CSS, etc... )
java -jar yuicompressor-x.y.z.jar jsdir/*.js -o alljs-min.js --charset utf-8
java -jar yuicompressor-x.y.z.jar cssdir/*.css -o allcss-min.css --charset utf-8
- Auto-Run selenium tests/phpunit tests
java -jar selenium-server.jar -htmlSuite "*firefox" "http://example.com" "testsuite\testsuite.html" "testsuite\results.html"
grep testsuite\results.html "failed"
#if "failed" found then don't deploy
- Deploy if everything is successful. Generate tarball (.tar.gz) of generated source files with a filename of {git revision}-{build number}.tar.gz. Transfer tarball and uncompressed to a temporary location on deployment target system. Copy from temp directory a release directory (that is not currently live) via Rsync. Change the current symbolic link to the new release. Document root of Apache is /var/www/example.com/current, which is a symbolic link to /var/www/example.com/releases/A or /var/www/example.com/releases/B. Note: this also helps PHP Opcache not have to start from scratch if you did timestamps
#package the directory you want to promote
tar -zcvf example.com.2280-1.tar.gz example.com
#Send file over to machine
scp example.com.2280-1.tar.gz [email protected]:/example.com.2280-1.tar.gz
#Extract the tarball
tar -zxvf example.com.2280-1.tar.gz -C /tmp
#Copy from temp to release directories
rsync --recursive --checksum --perms --links --delete \ /tmp/example.com.2280-1/ \ /var/www/example.com/releases/B
- Switch the symbolic in an atomic way
ln -s /var/www/example.com/releases/B /var/www/example.com/releases/current.new
mv -T /var/www/example.com/releases/current.new /var/www/example.com/releases/current
-
If requested rollback A. DX make it easy to see history of deployments and which ones you can revert too rollback site1.example.com 2500 B. Switch the symlink to the previous version C. Revert any DB changes
-
Run other tests A) Can be reached internally B) Can be reached externally etc...
- Manually create 2 sql files
up{git revision}.sql
anddown{git revision}.sql
- Run
up{git revision}.sql
when promoting ordown{git revision}.sql
if you need to rollback - Copy the sql code over
scp -r "/sqlsource/migrations" [email protected]:/sqlsource/migrations
- Create 2 local shell scripts that we will send over remotely to be executed
PromoteSQL.sh
system -i "RUNSQLSTM SRCSTMF('/path/to/migrations/sql/up1.sql') COMMIT(*NONE) NAMING(*SQL)"
RollbackSQL.sh
system -i "RUNSQLSTM SRCSTMF('/path/to/migrations/sql/down1.sql') COMMIT(*NONE) NAMING(*SQL)"
- Promote the SQL by sending the PromoteSQL.sh script to the remote system to be ran.
ssh [email protected] < PromoteSQL.sh
- (If needed) Rollback the SQL by sending the RollbackSQL.sh script to the remote system to be ran.
ssh [email protected] < RollbackSQL.sh
- PHP file with IBM_DB2 connection, PDO or ODBC connection and Run up{git revision}.sql through that connection
- JDBC connection w/ JTOpen/JT400 driver through JDBC and Run up{git revision}.sql through that connection
- Clear unused files, db objects
- Tag a git version to signify when you went live with a release
- Verify the deployment server meets the application requirements (pre-deployment)
- Update your vendor folder (composer install --no-dev --optimize-autoloader)
- Add/edit cronjobs
- Deploy/Verify external files/services are working (CDNs)
- emit webhooks events for the different phases of deployment
#Settings
- Enable mod_realdoc so that when you switch deployments old requests continue to use the old release.
<IfModule mod_realdoc.c>
RealpathEvery 2
</IfModule>
if you configure Apache’s DOCUMENT_ROOT for your site to be /var/www/site/htdocs and then you have /var/www/site be a symlink to alternatingly /var/www/A and /var/www/B you need to check your code for any hardcoded instances of /var/www/site/htdocs. This includes your PHP include_path setting. One way of doing this is to set your include_path as the very first thing you do if you have a front controller in your application. You can use something like this:
ini_set('include_path', $_SERVER['DOCUMENT_ROOT'].'/../include');
That means once mod_realdoc has resolved /var/www/site/htdocs to /var/www/A/htdocs your include_path will be /var/www/A/htdocs/../include for the remainder of this PHP request and even if the symlink is switched to /var/www/B halfway through the request it won’t be visible to this request.
- https://en.wikipedia.org/wiki/Continuous_delivery
- https://medium.com/salesforce-engineering/tarball-is-not-a-dirty-word-3bd0af99e8fd#.8roru9d3n
- https://codeascraft.com/2013/07/01/atomic-deploys-at-etsy/
- https://docs.jelastic.com/php-zero-downtime-deploy
- https://github.com/etsy/mod_realdoc
- https://github.com/etsy/incpath
- http://stackoverflow.com/questions/305035/how-to-use-ssh-to-run-shell-script-on-a-remote-machine