Appearance
How to create a new server
2024 version
NOTE
This is an unfinished guide on how to create a new server with our new setup. The idea is to make this process smooth as just running some commands using Deployer or other tools. I also tried Ansible, but as nobody (incl. me) has experience with it, I decided to stick with Deployer for now (as we have very strict deadlines for the server migration). For this reason, this job is not fully done. Please, when you have a time, finish writing Deployer tasks for all required steps and then group them into a single command (or 2–3 commands, considering the waiting time).
[!NOTE] All these tasks are created with the assumption that we have a Load Balancer in place. The idea is that you can create a new server and then change the Load Balancer config to move traffic to the new server.
[!NOTE] In this doc we assume you have PHP and deployer.phar locally installed. If, for any reason, you don't have them, you can use an official Docker image: docker run --rm -it -v .:/app deployphp/deployer {task} {server}
Create a new web server on Forge
- Type: Web Server
- Circle: Development Team
- Region: New York 3
- Server Size: 32GB (Premium Intel) RAM - 16 CPU COre - 200Gb NVMe SSD
- Private Network: IxDF-web--NY3
- Server OS: latest available
- PHP Version: the version from
composer.json - Post-Provision Recipe: upgrade nginx (optional)
Copy a new sudo password to LastPass.
Add sever to deployer config
Update deploy.php. Example:
php
host('servername') // https://forge.laravel.com/servers/795724/sites
->setHostname('174.138.80.65')
->setRemoteUser('forge')
->setDeployPath('~/servername.ixdf.dev')
->set('env_type', 'staging');SSH
Add your public SSH key to the server (SSH Keys tab in Forge): cat ~/.ssh/id_rsa.pub | pbcopy.
Populate the known-hosts file:
shell
./deployer.phar ssh:populate-known-hosts servernamenetwork
Find server droplet on DigitalOcean and add tags. Based on tags, DigitalOcean will add firewall rules. For web server:
staging-weborproduction-web
PHP
Ensure the required PHP version is installed on the server using Forge UI (or API in the future).
Enable OPCache on php tab.
Setup PHP version by the configs stored in infrastructure/php.
shell
./deployer.phar php:setup servernameComposer
Run a deployer task and follow instructions:
shell
./deployer.phar composer:setup servername.env
Run a deployer task and follow instructions:
shell
./deployer.phar provision:setup-env-encryption servernamePrepare a new .env.{servername} file encrypted by LARAVEL_ENV_ENCRYPTION_KEY key.
Want to reuse a key from another server (e.g. server migration)?:
shell
./deployer.phar env:encrypt-key:show server-name-on-deployernode
./deployer.phar node:setup servername./deployer.phar node:remove_global servername
Nginx
This is the key section of the setup.
App vs. Load Balancer
When deciding which settings to move to the load balancer and which to keep on the app server level, the general rule of thumb is to handle common, overarching tasks at the load balancer level and more specific tasks at the app server level. This helps optimize performance and ensures better manageability.
General Guidelines:
- Load Balancer: Handle tasks like SSL termination, compression, global rate limiting, and caching. This offloads the processing from the app servers and centralizes control.
- App Server: Handle application-specific configurations, security headers, error handling, and file-specific rules. This allows for more fine-grained control over the application behavior.
Changes
- Create site using Forge UI (provide a name, e.g
servername.ixdf.dev, if you want to process few domains using the same app instance, add domains as aliases) - go to site settings and set Web Directory to
/current/public(to use Deployer) - Edit Nginx Configuration. Follow the steps described in the Nginx site config examples.
You will see an error, but the configuration will be saved. That's ok: it complains about missing files that we will upload soon.
deploy
23869 @todo remove current dir: deployer will create a symlink instead
Before doing this, please make sure you have a .env.{hostalias}.encrypted file in the root of the project (where hostalias host's alias in deployer config).
./deployer.phar deploy servername
Please take a look at output, it may report about some issues.
Setup load-balancer
For server replacement:
- Open load-balancer server on Forge and choose your site.
- Choose your new server and save,
For new server: @todo
Setup webhooks
If you create a new site using a new domain, you need to set up webhooks for all 3rd party services this application instance will use:
- Stripe
- PayPal
- etc.
Check routes/webhooks.php for the complete list of services we use with webhooks.
Also make sure webhook URLs are accessible by opening /api/webhooks/status URL (they should not be password-protected).
Horizon
./deployer.phar site:setup:supervisor-for-horizon servername
NewRelic
./deployer.phar newrelic:install servername -v
@todo Update App name in NewRelic settings.
Cron
Go to the scheduler tab on Forge UI (server level)
Forge should create 2 cron jobs:
29 8 * * * /usr/local/bin/composer self-update(as root)0 0 * * 0 apt-get autoremove && apt-get autoclean(as root)
You can keep them.
Please add new jobs:
* * * * * php ~/servername.ixdf.dev/current/artisan schedule:run -vvv(as forge)
For servername:
0 3 * * * cd ~/servername.ixdf.dev/current && ./scripts/servername/import_db_dump.sh servername(as forge)
For production:
30 0 * * * bash /home/forge/www.interaction-design.org/current/scripts/database/backup.sh(as forge)
Install tools
shell
./deployer.phar tools:install servername****_****_____
2019 version
NOTE
I kept this version as the 2024 version is not finished yet. Potentially, we can borrow some parts from here.
This document is a list of commands, tools, script and settings we should set up to run a new application server. ...
Note, we are automating both server and site provisioning via Deployer, please prioritize running existing Deployer tasks, adding new ones, updating existing instead of running commands manually. Deployer tasks are defined in:
- server: deploy_server_provision_tasks.php
- site: deploy_site_provision_tasks.php
Use proper tags on DigitalOcean
To allow a new server to connect to other private servers (e.g. MySQL and Redis).
Install the DigitalOcean Metrics Agent
How to Install the DigitalOcean Metrics Agent
Setup PHP
Install all required PHP modules
Some of them listed in our composer.json (direct dependencies). Some php packages we use also require PHP modules.
How to test: try to run composer install for our app (composer.json+composer.lock and an empty is enough for this sort of test).
Update php config files
Check the diff of your current config and config from previous setup. Files namely:
/etc/php/8.x/cli/php.ini/etc/php/8.x/fpm/php.ini/etc/php/8.x/fpm/php-fpm.conf/etc/php/8.x/fpm/pool.d/www.conf
If you do upgrading of PHP version, please check all params from the diff: there is a high chance that some params are removed or deprecated, and you don’t need to copy them from previous setup.
Setup LARAVEL_ENV_ENCRYPTION_KEY
We store encrypted versions of .env files in the repository and need to decrypt them on deployment. Do this, the deployment script should know an encryption key. By convention, we store it in the LARAVEL_ENV_ENCRYPTION_KEY OS-level env variable (/etc/environment file).
To check the value of the LARAVEL_ENV_ENCRYPTION_KEY env var on the server, run this command:
bash
./deployer.phar env:encrypt-key:show developOr login to the server and run this command:
bash
echo $LARAVEL_ENV_ENCRYPTION_KEYSetup New Relic
To set up NewRelic you need to obtain License Key from you New Relic control panel ( https://rpm.newrelic.com/accounts/1067389/servers/get_started ) and then put it into Forge’s interface. After that you need to configure settings for New Relic (at least appname), to do it connect to server via ssh and run sudo vim /etc/php/8.4/mods-available/newrelic.ini (you can use another editor, if you not familiar with vim). Find newrelic.appname and set it to you primary domain name (newrelic.appname = "staging.ixdf.dev"). After a few minutes information about the server and application should be shown up in New Relic Control Panel.
Install node.js
We use n: Node version manager and the latest LTS version. Installation guide.
Setup scripts permission
Using the root user, type visudo and add the following lines. They allow forge user to execute the specified sudo commands without password.
Failing to configure this will result in failures on the deploy.php script.
text
forge ALL=NOPASSWD: /usr/sbin/service php-fpm restart
forge ALL=NOPASSWD: /usr/sbin/service nginx restart
forge ALL=NOPASSWD: /bin/systemctl restart
forge ALL=NOPASSWD: /usr/sbin/service supervisor restart
ALL ALL=NOPASSWD: /usr/sbin/nginx -tInstall nginx with required modules
@todo @alies-dev #15485 add it
Edit hosts
Add server aliases to /etc/hosts file and use them aliases in .env files.
text
10.132.197.81 staging-redis-privatePlease also do the same for MySQL server.
FAQ
Q1: I want to map an existing server (e.g. staging) into another git branch. How to do it? A1: example: https://github.com/InteractionDesignFoundation/IxDF-web/commit/2d475c1b328977f069bef7a0253e070a62763749 (and ensure the commit pushed to all branches that may initiate deployment according to previous rules).