Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Lugi's avatar
Level 21

DigitalOcean distribution for multiple Laravel projects

Hi, I decided that I will use DigitalOcean for multiple Laravel projects. (I'm tired of shared hosting :-)).

Please, give me a suggestion which distribution to use and why ? What about HTTP server - Apache or Nginx ?

And btw, what do you think to host different projects on the same droplet (few laravel projects, wordpres, static HTML site, etc.) ?

Any additional advice is welcome.

thanks

0 likes
12 replies
ejdelmonico's avatar

If you want it as "keep it simple", I would use forge and digital ocean. That will get you the standard Ubuntu server with nginx and php 7. That's the simple way.

Lugi's avatar
Level 21

Thanks. Yes, but for a start, I would like to use it without Forge. I would like to get some experience in server management before to go to Forge.

jekinney's avatar

Yes if you can afford it forge and envoyer pay for themselves.

Forge for sure, it basically installs homestead as your droplet. So if you develop with homestead easy as pie. Set env and conf nginx php Ini etc pretty easy along with deploying from source control and installing ssl certs.

Envoyer really shines if you update a lot and use source control (GitHub, bitbucket) and need hooks for composer and artisan commands. If you don't update etc a lot envoyer may not be worth it.

I use both. Forge to install and configure the droplet, envoyer for everything else. Only time I log into do is to change droplet size.

1 like
Lugi's avatar
Level 21

Forge and Envoyer definitely comes later. But for now, I would like to manage it myself.

@petrit so you suggest Ubuntu, Nginx ?

petrit's avatar

I personally use Ubuntu and nginx. It is also supported mainly by digitalocean community

kfirba's avatar
kfirba
Best Answer
Level 50

@Loogey Hey.

I would go with Ubuntu and install Nginx as my webserver. Ubuntu is so common and there are tons of material out there which simply targets Ubuntu. Also, don't forget the LTS versions which are just what you are looking for.

To be honest, setting up a website is really simple once you know what you are doing :).

Just to get you started, here are some tips:

  • Make sure you install nginx from the stable repository which will get you Nginx 1.8. There is also a "mainline" branch which is currently at 1.9.9 but I would still go with the stable branch. The mainline branch has some new features and bug fixes which aren't yet reflected in the stable branch. The mainline branch will, in turn, become the stable branch. In order to install stable branch Nginx just make sure to add the repository:
sudo add-apt-repository ppa:nginx/stable

sudo apt-get update

sudo apt-get install nginx
  • Install PHP 7 with PHP-FPM:
sudo add-apt-repository ppa:ondrej/php-7.0

sudo apt-get update

sudo apt-get install php7.0-fpm php7.0-cli php7.0-common php7.0-json php7.0-opcache  php7.0-mysql php7.0-phpdbg php7.0-dbg php7.0-gd php7.0-imap php7.0-ldap php7.0-pgsql php7.0-pspell php7.0-recode php7.0-snmp php7.0-tidy php7.0-dev php7.0-intl php7.0-gd php7.0-curl

The above will install PHP 7 and the most common extensions.

Please note, when adding the php7 repository, there is a common bug that's happening due to bad encoding because of the author name. If you get some error, before trying to re-add the repository, run:

sudo apt-get install -y language-pack-en-base

sudo LC_ALL=en_US.UTF-8 add-apt-repository ppa:ondrej/php-7.0

At this point you should have Nginx, PHP 7 and PHP7-FPM. Now you just need to install a DB. You can install the regular MySQL database:

sudo apt-get install mysql-server

To tighten the security on the server, just run:

sudo mysql_secure_installation

Please bear in mind that there are several drop-in replacements for MySQL which I don't see any reason not using them as they offer better performance and stability. Two of them are Percona Server and MariaDB. You probably have heard about MariaDB before. Percona Server is really my favorite (even tho I have to admit that I currently run a cluster of MariaDB instances just because Amazon RDS doesn't offer any support for Percona Server). Percona Server has proven itself to be much more stable and consistent on heavy load databases. It is also shows up to 40% better performance compared to MySQL.

If you want to use Percona Server, you can install it really easily:

wget https://repo.percona.com/apt/percona-release_0.1-3.$(lsb_release -sc)_all.deb

sudp dpkg -i percona-release_0.1-3.$(lsb_release -sc)_all.deb

sudo apt-get update

sudo apt-get install percona-server-server-5.5

Please note, if you have already installed MySQL, make sure to uninstall it first:

sudo apt-get remove mysql-server mysql-client mysql-common

sudo apt-get autoremove

Once you got Percona Server installed, you interact with it just like if you were interacting with MySQL (actually, it is just a MySQL fork) so you would connect to the server like:

mysql -umyuser -p

Ofcourse you can also interact with the service like:

service mysql stop
service mysql start
...

At this point you basically have all you need, Webserver, Server side programming language and a DB. Now we just need "glue" them together.

All of your website that you with them to be on that server should be configured in Nginx. You can go to /etc/nginx/sites-available to see all of your available websites. When you first go there you will see just a default file.

Now let's create our very first website (laravel project) which is going to listen on port 80 (non-https):

  1. Create mywebsitedomain.com file in /etc/nginx/sites-available (note that the mywebsitedomain.com naming is just a nice convention so you can easily remember which website the configuration file is for):
sudo vim /etc/nginx/sites-available/mywebsitedomain.com

Now let's paste some configurations in there:

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /home/user/mywebsitedomain.com/public;
    index index.php index.html index.htm;

    charset utf-8;

    server_name mywebsitedomain.com;
    
    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    access_log off;
    error_log  /var/log/nginx/mywebsitedomain.com.log error;

    location / {
        try_files $uri $uri/ /index.php?$query_string;;
    }

    location ~ \.php$ {
        try_files $uri /index.php =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

  location ~ /\.ht {
    deny  all;
  }
}

Note that right after we declare the server directive we are defining which port we want to listen on. We are specifying here that we want to listen to IPV4 and IPV6 on port 80. Please note that we are specifying the default_server; directive there. What it means that if nginx can't find a website to load based on the current configuration files, it will default to that website. Where can it meet you? when someone accesses your website through the direct IP of the server for example. (NOTE: the default file is also using this directive. Feel free to remove that file.)

the root directive simple points to the public folder of the website we want to show. In this example I assumed you store your files in /home/user/mywebsitedomain.com/public but it may change depends on you.

server_name is a VERY important configuration for your situation. You want to create multiple websites on your server and nginx has to somehow know which code to execute for each website but, how does it know that? It uses this directive. When someone accesses your website through mywebsitedomain.com nginx will know based on the server_name directive that it has to use this configuration file. If you have another domain pointing to that server which is example.com you should have another configuration file with server_name example.com and then nginx will know to pick this configuration file.

We define the error log in /var/log/nginx/mywebsitedomain.com.log in case you want to take a look at that.

The next directive (location /) just tells nginx which file order it should try. First, it tries to find the exact file. For example, if we access mywebsitedomain.com/someimage.jpeg it will look for /etc/user/mywebsitedomain.com/public/somefile.jpeg. If it cant find that, it will try to look for a folder with that name: /etc/user/mywebsitedomain.com/public/somefile.jpeg/ and if it can't find that, it will simply delegate that to the index.php file with the query string which is exactly what Laravel needs. We specify the other rules and don't default straight to the index.php file just because you may want to load css, js and images from your server (you obviously will do that...).

The next directive is just telling nginx that whenever it deals with a PHP file, it should pass it to a FastCGI (PHP-FPM) to execute that code and return the processed response as nginx doesn't know how to run PHP code natively (which is why we installed PHP-FPM).

The last directive just disables any .ht* files such as .htaccess file which may expose your website to some vulnerabilities.

Once we are done, save the file and make a symlink to /etc/nginx/sites-enabled in order to make the website "live":

sudo ln -s /etc/nginx/sites-available/mywebsitedomain.com /etc/nginx/sites-enabled

Before you restart Nginx, run this command to ensure that your configuration file is properly set and there are no syntax errors (which will prevent nginx from restarting and actually leaving it OFF)

sudo nginx -t

If everything is okay, just run.

sudo service nginx restart

Your website should be up and running at this point.


We haven't talked about configuring your server to get the most out of it like defining max connections, FPM settings, DB buffers etc. It is a little bit more advanced and it should not concern you right now. Make yourself comfortable with the basics first, try to run few websites on your server first and learn some nginx configurations (should be easy).

Good luck!

5 likes
Lugi's avatar
Level 21

Hey @kfirba thank you very much this really amazing post !!!

willem-aart's avatar

Excellent post @kfirba.

One thing you should consider using is a server provisioning tool such as Ansible. Instead of manually configuring and installing your server(s), a provisioning tool allows you to run a script (a playbook, in Ansible terminology) with which you can automate those tasks. These scripts are idempotent (which means you can run them over and over again) so they can also be used to check if your server is still set up properly. Ansible playbooks can even be used to deploy your applications. Furthermore, you can put these scripts into version control and have your complete infrastructure in code.

Vagrant has excellent integration with Ansible, so you can use one playbook for provisioning your development and production environment. This ensures you won't run into unexpected errors when deploying your application.

I'm not into server management at all, but it was very easy for me to learn the basics of Ansible. Much easier than writing shell scripts. You never want to manually install and configure servers again, believe me.

bashy's avatar

@kfirba Just a note on one of your commands, if you want to keep the names consistent, don't reference the file in the second param

This

sudo ln -s /etc/nginx/sites-available/mywebsitedomain.com /etc/nginx/sites-enabled/mywebsitedomain.com

should really be just

sudo ln -s /etc/nginx/sites-available/mywebsitedomain.com /etc/nginx/sites-enabled

Small tip :)

1 like

Please or to participate in this conversation.